⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pkg.cc

📁 About: Paco (pacKAGE oRGANIZER) is a simple, yet powerful tool to aid package management when insta
💻 CC
字号:
//=======================================================================// Pkg.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 "Pkg.h"#include "PkgSet.h"#include "Options.h"#include <string>#include <iostream>#include <iomanip>#include <fstream>using std::endl;using std::cout;using std::string;using std::setw;using namespace Paco;// Forward declsstatic void cutPrint(string);static void removeDir(string const&);static void removeParentDir(string const&);static int getDigits(long);template <typename T, typename U> static T max(T const&, U const&);Pkg::Pkg(string const& aName):	BasePkg(aName){ }// [virtual]Pkg::~Pkg(){ }void Pkg::unlog() const{	if (!access(mLog.c_str(), W_OK)) {		if (!unlink(mLog.c_str()))			gOut.vrb("Package " + mName + " removed from the database\n");		else			gOut.vrb("unlink(" + mLog + ")", errno);	}}void Pkg::printInfo() const{	FileStream<std::ifstream> f(mLog);	string buf;	bool printed(false);		string line(mName.size() + 2, '-');	cout << line << "\n " << mName << " \n" << line << "\n" << endl;	while (getline(f, buf) && buf[0] == '#') {		if (buf == "#:Description")			cout << "Description:\n" << endl;		else if (!buf.find("#:")) {			cutPrint(buf.substr(2));			printed = true;		}	}	if (printed)		cout << endl;}bool Pkg::update() const{	gOut.vrb("Updating " + mName + "... ");	bool ret = updateLog(mLog);	gOut.vrb(ret ? "ok\n" : "no files logged (removed)\n");	return ret;}void Pkg::upgradeLog() const{	std::ifstream fLog(mLog.c_str());	if (!fLog)		return;	string buf;	getline(fLog, buf);	if (!buf.find("#!paco-2."))		return;		std::ostringstream s;	s << "#!paco-" PACKAGE_VERSION "\n";	string::size_type p = buf.rfind(" ");	if (p != string::npos)		s << "#d:" << str2num<int>(buf.substr(p)) << '\n';	string infoLog = Config::logdir() + "/_info/" + mName;	std::ifstream fInfoLog(infoLog.c_str());	if (fInfoLog) {		getline(fInfoLog, buf);		while (getline(fInfoLog, buf))			s << (buf[0] == '#' ? "" : "#:") << buf << '\n';	}	while (getline(fLog, buf)) {		if (buf[0] != '#' || !fInfoLog)			s << buf << '\n';	}	unlink(infoLog.c_str());	fLog.close();	FileStream<std::ofstream> fLog2(mLog);	fLog2 << s.str();}long Pkg::countShared(PkgSet& all){	long cnt(0);	for (iterator f = begin(); f != end(); ++f)		cnt += shares(*f, all);	return cnt;}void Pkg::printConfOpts(bool printPkgName) const{	if (printPkgName)		cout << mName << ":\n";	if (mConfOpts.size())		cout << mConfOpts << endl;	if (printPkgName)		cout << endl;}void Pkg::remove(Options& opt){	if (!opt.batch()) {		cout << "Remove package " << mName << " (y/N) ? ";		string buf;		if (!(getline(std::cin, buf) && (buf == "y" || buf == "yes")))			return;	}		PkgSet all;	if (!opt.removeShared()) {		all.getAllPkgs();		all.getFiles();	}	{		Out::Silencer s;		update();	}	getFiles();	struct stat s;	bool keepLog(false);	for (iterator f = begin(); f != end(); ++f) {		if (lstat((*f)->name().c_str(), &s) < 0)			continue;		else if (inPaths((*f)->name(), opt.skip())) {			gOut.vrb((*f)->name() + ": skipped\n");			keepLog = true;		}		else if (!opt.removeShared() && shares(*f, all)) {			gOut.vrb((*f)->name() + ": shared\n");			keepLog = true;		}		else if (!unlink((*f)->name().c_str())) {			if (S_ISLNK(s.st_mode))				gOut.vrb("Removed symlink '"  + (*f)->name() + "'\n");			else				gOut.vrb("Removed '"  + (*f)->name() + "'\n");			removeParentDir((*f)->name());		}		else {			gOut.vrb("unlink(" + (*f)->name() + ")", errno);			keepLog = true;		}	}		if (opt.unlog() || !keepLog)		unlog();	else {		Out::Silencer silencer;		update();	}}// [static]string Pkg::getVersion(string const& name){	for (string::size_type i = 1; i < name.size(); ++i) {		if (isdigit(name.at(i)) && name.at(i - 1) == '-')			return name.substr(i);	}	return "";}// [static]string Pkg::getBase(string const& name){	bool dash(false);	string::size_type i;	for (i = 1; i < name.size(); ++i) {		if (name.at(i) == '-')			dash = true;		else if (dash) {			if (isdigit(name.at(i)))				break;			dash = false;		}	}	return dash ? name.substr(0, i - 1) : name;}//-------------//// Pkg::Lister ////-------------//Pkg::Lister::Lister(Options& __opt, PkgSet& __set):	mOpt(__opt),	mSet(__set),	mAllPkgs(),	mSizeInstWidth(mOpt.size() ? getSizeInstWidth() : 0),	mSizeMissWidth(mOpt.sizeMiss() ? getSizeMissWidth() : 0),	mFilesInstWidth(mOpt.filesInst() ? getFilesInstWidth() : 0),	mFilesMissWidth(mOpt.filesMiss() ? getFilesMissWidth() : 0),	mFilesSharedWidth(mOpt.filesShared() ?		getDigits(mSet.filesInst() + mSet.filesMiss()) : 0){	if (mOpt.filesShared()) {		mAllPkgs.getAllPkgs();		mAllPkgs.getFiles();		mSet.getFiles();	}}	Pkg::Lister::~Lister(){	if (!mOpt.total())		return;	if (mOpt.size())		printSizeInst(mSet.sizeInst());	if (mOpt.sizeMiss())		printSizeMiss(mSet.sizeMiss());	if (mOpt.filesInst())		printFilesInst(mSet.filesInst());	if (mOpt.filesMiss())		printFilesMiss(mSet.filesMiss());	if (mOpt.filesShared())		cout << setw(mFilesSharedWidth + 4) << " ";	if (mOpt.day())		printDate(0);			cout << "TotaL" << endl;}int Pkg::Lister::getSizeMissWidth(){	int n = mOpt.total() ? sizeStr(mOpt.sizeUnit(), mSet.sizeMiss()).size() : 0;	for (PkgSet::iterator p = mSet.begin(); p != mSet.end(); ++p)		n = max(n, sizeStr(mOpt.sizeUnit(), (*p)->sizeMiss()).size());	return n;}int Pkg::Lister::getSizeInstWidth(){	int n = mOpt.total() ? sizeStr(mOpt.sizeUnit(), mSet.sizeInst()).size() : 0;	for (PkgSet::iterator p = mSet.begin(); p != mSet.end(); ++p)		n = max(n, sizeStr(mOpt.sizeUnit(), (*p)->sizeInst()).size());	return n;}int Pkg::Lister::getFilesInstWidth(){	if (mOpt.total())		return getDigits(mSet.filesInst());	int n = 0;	for (PkgSet::iterator p = mSet.begin(); p != mSet.end(); ++p)		n = max(n, (*p)->filesInst());	return getDigits(n);}int Pkg::Lister::getFilesMissWidth(){	if (mOpt.total())		return getDigits(mSet.filesMiss());	int n = 0;	for (PkgSet::iterator p = mSet.begin(); p != mSet.end(); ++p)		n = max(n, (*p)->filesMiss());	return getDigits(n);}void Pkg::Lister::printDate(int __time) const{	char dat[32] = "";	struct tm* t;	time_t timeT = static_cast<time_t>(__time);	if (!__time || !(t = localtime(&timeT)))		snprintf(dat, sizeof(dat), "%*c", mOpt.hour() ? 17 : 11, ' ');	else if (mOpt.hour())		strftime(dat, sizeof(dat) - 1, "%d-%b-%Y %H:%M", t);	else		strftime(dat, sizeof(dat) - 1, "%d-%b-%Y", t);			cout << dat << "  ";}void Pkg::Lister::printFilesInst(long n) const{	cout << setw(mFilesInstWidth) << n		<< ((mOpt.filesMiss() || mOpt.filesShared()) ? " " : "  ");}template <typename T>	// T = {float,long}void Pkg::Lister::printSizeInst(T size) const{	cout << setw(mSizeInstWidth) << sizeStr(mOpt.sizeUnit(), size)		<< (mOpt.sizeMiss() ? " " : "  ");}template <typename T>	// T = {float,long}void Pkg::Lister::printSizeMiss(T size) const{	cout << "[" << setw(mSizeMissWidth)		<< (size ? sizeStr(mOpt.sizeUnit(), size) : " ") << "]  ";}void Pkg::Lister::printFilesMiss(long n) const{	cout << "[" << setw(mFilesMissWidth);	if (n)		cout << n << "] ";	else		cout << " " << "] ";	if (!mOpt.filesShared())		cout << " ";}void Pkg::Lister::printFilesShared(long n) const{	cout << "(" << setw(mFilesSharedWidth);	if (n)		cout << n << ")  ";	else		cout << " " << ")  ";}Pkg* Pkg::Lister::operator()(Pkg* pkg){	if (mOpt.size())		printSizeInst(pkg->sizeInst());	if (mOpt.sizeMiss())		printSizeMiss(pkg->sizeMiss());	if (mOpt.filesInst())		printFilesInst(pkg->filesInst());	if (mOpt.filesMiss())		printFilesMiss(pkg->filesMiss());	if (mOpt.filesShared())		printFilesShared(pkg->countShared(mAllPkgs));	if (mOpt.day())		printDate(pkg->date());			cout << pkg->name() << endl;	return pkg;}//-----------------//// Pkg::FileLister ////-----------------//Pkg::FileLister::FileLister(Options& __opt, PkgSet& __set):	mOpt(__opt),	mSet(__set),	mSizeWidth(0),	mPrintTotal(mOpt.total() && mOpt.size()),	mTotalSize(0),	mAllPkgs(),	mPkgCnt(0),	mFileCnt(0){	if (mOpt.size()) {		mTotalSize = mOpt.filesInst() ? mSet.sizeInst() : 0;		if (mOpt.filesMiss())			mTotalSize += mSet.sizeMiss();		mSizeWidth = getSizeWidth();	}	if (mOpt.filesShared() || mOpt.filesNonShared()) {		mTotalSize = 0;		mAllPkgs.getAllPkgs();		mAllPkgs.getFiles();	}}Pkg::FileLister::~FileLister(){	if (mPrintTotal && mFileCnt) {		cout << endl << setw(mSizeWidth)			<< (mTotalSize < 0 ? "0" : sizeStr(mOpt.sizeUnit(), mTotalSize))			<< "  TotaL" << endl;	}}int Pkg::FileLister::getSizeWidth(){	int n = mOpt.total() ? sizeStr(mOpt.sizeUnit(), mTotalSize).size() : 0;	for (PkgSet::iterator p = mSet.begin(); p != mSet.end(); ++p) {		for (Pkg::iterator f = (*p)->begin(); f != (*p)->end(); ++f)			n = max(n, sizeStr(mOpt.sizeUnit(), (*f)->size()).size());	}	return n;}Pkg* Pkg::FileLister::operator()(Pkg* pkg){	if (mOpt.filesShared() || mOpt.filesNonShared()) {		if (!mOpt.noPkgName())			cout << pkg->name() << ":" << endl;		if (mOpt.filesShared())			listSharedFiles(pkg);		else			listNonSharedFiles(pkg);	}	else		listFiles(pkg);	if (++mPkgCnt < mSet.size() && !mOpt.noPkgName())		cout << endl;	return pkg;}inline void Pkg::FileLister::printFile(File* file){	if (mOpt.size()) {		cout << setw(mSizeWidth) << sizeStr(mOpt.sizeUnit(), file->size())			<< "  ";	}	cout << file->name();	if (file->symlink() && mOpt.symlinks()) {		char ln[4096];		int cnt = readlink(file->name().c_str(), ln, sizeof(ln) - 1);		if (cnt > 0)			ln[cnt] = 0;		else			memcpy(ln, "?", 2);		cout << " -> " << ln;	}		cout << "\n";	++mFileCnt;}void Pkg::FileLister::listFiles(Pkg* pkg){	if (!mOpt.noPkgName())		cout << pkg->name() << ":" << endl;	pkg->sort(mOpt.sortType(), mOpt.reverse());	for (iterator f = pkg->begin(); f != pkg->end(); ++f)		printFile(*f);}void Pkg::FileLister::listSharedFiles(Pkg* pkg){	for (PkgSet::iterator p = mAllPkgs.begin(); p != mAllPkgs.end(); ++p) {		if ((*p)->name() == pkg->name())			continue;		uint cnt = 0;		for (iterator f = pkg->begin(); f != pkg->end(); ++f) {			if (LIKELY(!(*p)->hasFile(*f)))				continue;			else if (mOpt.whoShares()) {				if (!cnt++)					cout << "(" << (*p)->name() << ")" << endl;			}			else if (!(*f)->shared())				(*f)->shared(true); // do not repeat files			else				continue;						printFile(*f);			mTotalSize += (*f)->size();		}	}}	void Pkg::FileLister::listNonSharedFiles(Pkg* pkg){	for (iterator f = pkg->begin(); f != pkg->end(); ++f) {		if (LIKELY(!pkg->shares(*f, mAllPkgs))) {			printFile(*f);			mTotalSize += (*f)->size();		}	}}	//-------------------//// static free funcs ////-------------------//template <typename T, typename U>inline static T max(T const& a, U const& b){	return static_cast<size_t>(a) > static_cast<size_t>(b) ? a : b;}//// Return the number of digits of a number//static int getDigits(long n){    int ret;    for (ret = 0; n; n /= 10, ret++);    return ret;}static void removeParentDir(string const& path){	string dir(path);	string::size_type i, j;	for (i = dir.size() - 1; i > 0 && dir.at(i) == '/'; --i)		dir.erase(i);	if ((j = dir.rfind('/', i)) && j != string::npos)		dir.erase(j);			removeDir(dir);}static void removeDir(string const& dir){	if (!rmdir(dir.c_str())) {		gOut.vrb("Removed directory '" + dir + "'\n");		removeParentDir(dir);	}	else if (errno != ENOTEMPTY)		gOut.vrb("rmdir(" + dir + ")", errno);}//// This function takes a string and prints it out in pieces not// longer than a given maximmum length. The cut points are not in the middle// of words if possible.//static void cutPrint(string buf){	uint width = Out::screenWidth();	// If the buffer is short enough, just print it and return	if (buf.size() <= width) {		cout << buf << endl;		return;	}	string out;	bool 	beggining = true,	// Leading spaces indicator			spaces = false;	// True if there are any space to cut at 	for (uint j, i = 0, len = 0; i < buf.size(); ) {		if (buf.at(i) == ' ')			spaces = !beggining;		else 			beggining = false;				if (len < width) {			++len;			out += buf.at(i++);			continue;		}        		// len >= width		else if (spaces && !beggining) {			for (j = out.size(); j && i && buf.at(i) != ' '; --j, --i);			++i;			out.erase(j);        }		for ( ; i < buf.size() && buf.at(i) == ' '; ++i);		cout << out << endl;		out.clear();		len = 0;		spaces = false;    }		// The remaining piece	cout << out << endl;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -