📄 pkgset.cc
字号:
//=======================================================================// PkgSet.cc//-----------------------------------------------------------------------// This file is part of the package paco// Copyright (C) 2004-2007 David Rosal <david.3r@gmail.com>// For more information visit http://paco.sourceforge.net//=======================================================================#include "config.h"#include "global.h"#include "PkgSet.h"#include "Options.h"#include "Pkg.h"#include "paco/Dir.h"#include <fstream>#include <iostream>#include <string>#include <cctype>#include <algorithm>#include <iomanip>#include <vector>using std::string;using std::vector;using std::cout;using std::endl;using std::setw;using std::for_each;using std::mem_fun;using namespace Paco;// Forward declsstatic bool matchPkg(string const& s, string const& pkg);PkgSet::PkgSet(): mSizeInst(0), mSizeMiss(0), mFilesInst(0), mFilesMiss(0){ }PkgSet::PkgSet(vector<string> const& args): mSizeInst(0), mSizeMiss(0), mFilesInst(0), mFilesMiss(0){ getPkgs(args);}// [virtual]PkgSet::~PkgSet(){ for (PkgSet::iterator p = begin(); p != end(); ++p) { assert(*p != NULL); if (*p) { delete *p; *p = NULL; } }}void PkgSet::update(bool allPkgs){ if (allPkgs && Config::version().find("2") != 0) { gOut.vrb("Detected paco-1 database. Upgrading to paco-2...\n"); for_each(begin(), end(), mem_fun(&Pkg::upgradeLog)); string infoDir(Config::logdir() + "/_info"); if (!rmdir(infoDir.c_str())) gOut.vrb("Directory " + infoDir + " has been removed\n"); else if (errno != ENOENT) gOut.vrb("rmdir(\"" + infoDir + "\")", errno); } for_each(begin(), end(), mem_fun(&Pkg::update)); if (allPkgs) Config::touchStamp();}void PkgSet::remove(Options& opt){ apply(*this, &Pkg::remove, opt);}void PkgSet::unlog(){ for_each(begin(), end(), mem_fun(&Pkg::unlog));}void PkgSet::printConfOpts(){ apply(*this, &Pkg::printConfOpts, (size() > 1));}void PkgSet::printInfo(){ for_each(begin(), end(), mem_fun(&Pkg::printInfo));}void PkgSet::getFiles(int fType /* = Pkg::ALL_FILES */){ apply(*this, &Pkg::getFiles, fType);}void PkgSet::getAllPkgs(){ Dir dir(Config::logdir()); string name; while (dir.read(name)) { try { add(new Pkg(name)); } catch (Pkg::ConstructorError&) { } } if (empty()) gOut.vrb("paco: No packages logged in directory " + Config::logdir() + "\n");}//// Get all logged packages that match any name in 'args'.//void PkgSet::getPkgs(vector<string> const& args){ Dir dir(Config::logdir()); bool logged; string name; for (uint i = 0; i < args.size(); ++i, dir.rewind()) { if (!isalnum(args[i][0]) && args[i][1]) { gExitStatus = EXIT_FAILURE; gOut.vrb("paco: " + args[i] + ": invalid package name\n"); continue; } for (logged = false; dir.read(name); ) { if (matchPkg(args[i], name)) { try { add(new Pkg(name)); logged = true; } catch (Pkg::ConstructorError&) { } } } if (!logged) { gExitStatus = EXIT_FAILURE; gOut.vrb("paco: " + args[i] + ": package not logged\n"); } }}void PkgSet::queryFiles(vector<string> const& args){ gExitStatus = EXIT_FAILURE; getFiles(); for (uint i = 0; i < args.size(); ++i) { string real = realDir(args[i]); cout << real << ":"; for (iterator p = begin(); p != end(); ++p) { if ((*p)->hasFile(real)) { gExitStatus = EXIT_SUCCESS; cout << '\t' << (*p)->name(); } } cout << "\n"; }}void PkgSet::add(Pkg* pkg){ push_back(pkg); mSizeInst += pkg->sizeInst(); mSizeMiss += pkg->sizeMiss(); mFilesInst += pkg->filesInst(); mFilesMiss += pkg->filesMiss();}//// Print the packages in an ls' style//void PkgSet::lsPkgs(){ size_t maxlen = 0, cols; PkgSet::iterator p; for (p = begin(); p != end(); ++p) maxlen = std::max(maxlen, (*p)->name().size()); maxlen += 2; if (!(cols = Out::screenWidth() / maxlen)) cols = 1; int rows = size() / cols + ((size() % cols) != 0); if (rows == 1) { uint cnt = 0; for (p = begin(); p != end(); ++p) cout << (cnt++ ? " " : "") << (*p)->name(); cout << endl; return; } for (int k = 0; k < rows; ++k) { for (p = begin() + k; p < end(); p += rows) cout << (*p)->name() << setw(maxlen - (*p)->name().size()) << " "; cout << endl; }}void PkgSet::listPkgs(Options& opt){ assert(empty() == false); std::sort(begin(), end(), Sorter(opt.sortType())); if (opt.reverse()) std::reverse(begin(), end()); if (opt.oneColumn()) transform(begin(), end(), begin(), Pkg::Lister(opt, *this)); else lsPkgs();}void PkgSet::listFiles(Options& opt){ assert(empty() == false); int type = opt.filesInst() ? Pkg::INSTALLED_FILES : 0; if (opt.filesMiss()) type |= Pkg::MISSING_FILES; getFiles(type); transform(begin(), end(), begin(), Pkg::FileLister(opt, *this));}//----------------//// PkgSet::Sorter ////----------------//PkgSet::Sorter::Sorter(SortType type): mSortFunc(){ switch (type) { case SORT_SIZE_INST: mSortFunc = &Sorter::sortBySizeInst; break; case SORT_SIZE_MISS: mSortFunc = &Sorter::sortBySizeMiss; break; case SORT_FILES_INST: mSortFunc = &Sorter::sortByFilesInst; break; case SORT_FILES_MISS: mSortFunc = &Sorter::sortByFilesMiss; break; case SORT_DATE: mSortFunc = &Sorter::sortByDate; break; default: mSortFunc = &Sorter::sortByName; }}inline bool PkgSet::Sorter::operator()(Pkg* left, Pkg* right) const{ return (this->*mSortFunc)(right, left);}inline bool PkgSet::Sorter::sortByName(Pkg* left, Pkg* right) const{ return strcasecmp(right->name().c_str(), left->name().c_str()) < 0;}inline bool PkgSet::Sorter::sortBySizeInst(Pkg* left, Pkg* right) const{ return left->sizeInst() > right->sizeInst();}inline bool PkgSet::Sorter::sortBySizeMiss(Pkg* left, Pkg* right) const{ return left->sizeMiss() > right->sizeMiss();}inline bool PkgSet::Sorter::sortByFilesMiss(Pkg* left, Pkg* right) const{ return left->filesMiss() > right->filesMiss();}inline bool PkgSet::Sorter::sortByFilesInst(Pkg* left, Pkg* right) const{ return left->filesInst() > right->filesInst();}inline bool PkgSet::Sorter::sortByDate(Pkg* left, Pkg* right) const{ return left->date() > right->date();}//--------------//// Static funcs ////--------------////// Check whether the string 's' is a valid reference to the 'pkg'.// Example: given the pkg 'foo-bar-1.0', the string 'foo-bar' matches,// but not 'foo' or 'foo-bar-2.0'.// This provides a kind of automatic pkg name completion for the command// line arguments, whose targets are the names of the logged pkgs.//static bool matchPkg(string const& s, string const& pkg){ string sBase = Pkg::getBase(s); string pkgBase = Pkg::getBase(pkg); string sVersion = Pkg::getVersion(s); string pkgVersion = Pkg::getVersion(pkg); if (Config::caseSensitive()) { if (sBase != pkgBase) return false; } else if (strcasecmp(pkgBase.c_str(), sBase.c_str())) return false; if (sVersion.empty() || sVersion == pkgVersion) return true; else if (sVersion.compare(0, sVersion.size(), pkgVersion.c_str(), sVersion.size())) return false; return ispunct(pkgVersion.at(sVersion.size()));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -