Logo Search packages:      
Sourcecode: packagesearch version File versions

dumpavailpackagedb.cpp

//
// C++ Implementation: %{MODULE}
//
// Description:
//
//
// Author: %{AUTHOR} <%{EMAIL}>, (C) %{YEAR}
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "dumpavailpackagedb.h"

#include <stdio.h>

#include <iostream>

#include <qdatetime.h>
#include <qfile.h>
#include <qstringlist.h>

#include <singlehandlemaker.h>
#include <helpers.h>

// NApplication
#include <runcommandforoutput.h>

// NPlugin
#include <iprovider.h>
#include <iprogressobserver.h>
#include <packagenotfoundexception.h>


namespace NApt
{

00037 DumpAvailPackageDB::DumpAvailPackageDB(NUtil::IProgressObserver* pObserver, uint estimatedPackageNum)
{
      _estimatedPackageNum = estimatedPackageNum;
      reloadPackageInformation(pObserver);
}


DumpAvailPackageDB::~DumpAvailPackageDB()
{
      qDebug("Deleting DumpAvailPackageDB");
}

00049 const Package& DumpAvailPackageDB::getPackageRecord(const QString& pkg, const QString& linebreak) const
{
      int packageHandle = SingleHandleMaker::instance()->getHandle(pkg);
      PackageMap::const_iterator it = _packages.find(packageHandle);
      if (it == _packages.end())
            throw NPlugin::PackageNotFoundException(packageHandle);
      return it->second;
}


00059 const Package& DumpAvailPackageDB::getPackageRecord(int packageHandle, const QString& linebreak) const
{
      PackageMap::const_iterator it = _packages.find(packageHandle);
      if (it == _packages.end())
            throw NPlugin::PackageNotFoundException(packageHandle);
      return it->second;
}


00068 const QString DumpAvailPackageDB::getShortDescription(int packageHandle) const
{
      PackageMap::const_iterator it = _packages.find(packageHandle);
      if (it == _packages.end())
            throw NPlugin::PackageNotFoundException(packageHandle);
      return it->second.shortDescription;
}

00076 Package::InstalledState DumpAvailPackageDB::getState(int packageHandle) const
{
      PackageMap::const_iterator it = _packages.find(packageHandle);
      if (it == _packages.end())
            throw NPlugin::PackageNotFoundException(packageHandle);
      return it->second.installedState;
}

00084 void DumpAvailPackageDB::reloadPackageInformation(NUtil::IProgressObserver* pObserver)
{
      _packages.clear();
      {
            if (pObserver)
                  pObserver->setText("reading package information");
            
            QString command("apt-cache dumpavail");
            #ifdef __DEBUG
            qDebug("running " + command);
            QTime t;
            t.start();
            #endif
            
            // setup the data for progress infromation
            double increment;
            if ( _estimatedPackageNum == 0 )
                  increment = 0;
            else
                  increment = 80.0 / _estimatedPackageNum;  // update the progress every 1%
            double count = 0;
            int dbgCount = 0;
            int progress = 0;
            
            FILE* pipe = popen(command, "r");
            // current maximum line length of apt-cache dumpavail is around 1700 so 10000 should offer enough safety
            int maximumLineLength = 10000;
            char* chars = new char[maximumLineLength];
            QStringList packageLines;
            while (fgets(chars, maximumLineLength, pipe) != 0)
            {
                  QString line(chars);
                  line.truncate(line.length()-1);     // remove the trailing newline
                  if (!line.isEmpty()) 
                  {
                        packageLines.append(line);
                  } 
                  else 
                  {
                        Package p(packageLines);
                        _packages[SingleHandleMaker::instance()->getHandle(toString(p.name))] = p;
                        packageLines.clear();
                        if (pObserver)
                        {
                              count += increment;
                              ++dbgCount;
                              if (count >= 1)
                              {
                                    ++progress;
                                    pObserver->setProgress(progress);
                                    count -= 1;
                              }
                        }
                  }
            }
            qDebug("size: %d, debug-count: %d", _estimatedPackageNum, dbgCount);
            delete[] chars;
            int exitStatus = pclose(pipe);
            #ifdef __DEBUG
            qDebug( "Time elapsed: %d ms", t.elapsed() );   
            #endif
      }
      // 80% done
      {     
            // reading the status file
            #ifdef __DEBUG
            QTime t;
            t.start();
            #endif
            
            if (pObserver)
            {
                  pObserver->setProgress(80);
                  pObserver->setText("parsing status information");
            }
            
            // setup the data for progress infromation
            double increment;
            if ( _estimatedPackageNum == 0 )
                  increment = 0;
            else
                  increment = 20.0 / _estimatedPackageNum;  // update the progress every 1%
            double count = 0;
            int dbgCount = 0;
            int progress = 80;

            FILE* statusFile = fopen("/var/lib/dpkg/status", "r");
            // current maximum line length of apt-cache dumpavail is around 1700 so 10000 should offer enough safety
            int maximumLineLength = 10000;
            char* chars = new char[maximumLineLength];
            QStringList packageLines;
            Package* pP = 0;
            while (fgets(chars, maximumLineLength, statusFile) != 0)
            {
                  QString line(chars);
                  line.truncate(line.length()-1);     // remove the trailing newline
                  if ( line.isEmpty() )   // package ended
                  {
                        if (pObserver)
                        {
                              count += increment;
                              ++dbgCount;
                              if (count >= 1)
                              {
                                    ++progress;
                                    pObserver->setProgress(progress);
                                    count -= 1;
                              }
                        }
                        // if we gathered some information
                        if (!packageLines.empty())
                        {
                              pP->parseInformation(packageLines);
                        }
                        packageLines.clear();
                  }
                  else if ( line.startsWith("Package: ") )
                  {
                        QString pkg = (line.mid(9));
                        int pkgHandle = SingleHandleMaker::instance()->getHandle(pkg);
                        PackageMap::iterator jt = _packages.find(pkgHandle);
                        if (jt == _packages.end())
                              // insert a new package and return the iterator to it
                              jt = _packages.insert(make_pair(pkgHandle, Package(pkg))).first;
                        pP = &((*jt).second);
                  }
                  else if (line.startsWith("Status: "))
                  {
                        // QString status = (line.mid(8));
                        if (pP != 0)
                        {
                              if (line.endsWith(" installed"))
                                    pP->installedState = Package::INSTALLED;
                        }
                  }
                  else if (line.startsWith("Version: "))
                  {
                        if (pP != 0)
                        {
                              QString installedVersion = (line.mid(9));
                              pP->installedVersion = installedVersion;
                        }
                  }
                  else
                        packageLines.push_back(line);
            }
            qDebug("size: %d, debug-count: %d", _estimatedPackageNum, dbgCount);
            delete[] chars;
            int exitStatus = fclose(statusFile);
      
            // collect the information needed by the package here
            #ifdef __DEBUG
            qDebug( "Time elapsed for /var/lib/dpkg/status: %d ms", t.elapsed() );  
            #endif
      }
      if (pObserver)
            pObserver->setProgress(100);
      _estimatedPackageNum = _packages.size();
}


00245 bool DumpAvailPackageDB::search(Tagcoll::OpSet<int>& result, Tagcoll::HandleMaker<string>& handleMaker, 
            const string& pattern, bool searchDescr) const
{
      for (PackageMap::const_iterator it = _packages.begin(); it!=_packages.end(); ++it)
      {
            const Package& package(it->second);
            if ( package.name.contains(pattern.c_str(), false) || 
                        (searchDescr && package.description.contains(pattern.c_str(), false))
            )
                  result.insert(it->first);
      }
      return result.empty();
}


00260 bool DumpAvailPackageDB::search(Tagcoll::OpSet<int>& result, Tagcoll::HandleMaker<string>& handleMaker,
            const PackageContainer& includePatterns, const PackageContainer& excludePatterns, bool searchDescr) const
{
      for (PackageMap::const_iterator it = _packages.begin(); it!=_packages.end(); ++it)
      {
            const Package& package(it->second);
            // holds if the search matches the package
            bool included = true;
            // check if each included pattern occurs in the package
            for (PackageContainer::const_iterator jt = includePatterns.begin(); jt != includePatterns.end(); ++jt)
            {
                  if ( !  ( package.name.contains(*jt, false) ||
                                  (searchDescr && package.description.contains(*jt, false))
                                ) 
                        )
                  {
                        included = false;
                        break;
                  }
            }
            if (!included)
                  continue;
            // check if each excluded pattern does not occur in the package
            for (PackageContainer::const_iterator jt = excludePatterns.begin(); jt != excludePatterns.end(); ++jt)
            {
                  if ( package.name.contains(*jt, false) ||
                          (searchDescr && package.description.contains(*jt, false))
                        )
                  {
                        included = false;
                        break;
                  }
            }
            if (included)
                  result.insert(it->first);
      }
      return result.empty();
}


}     // namespace NApt


Generated by  Doxygen 1.6.0   Back to index