X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/3e68f7e41022790619c698a32390a5256fadba7c..2b0660b537581e9e65180e4cf1a94d763fd66847:/cmdline/apt-get.cc diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index b6786faf8..2a19360c8 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include @@ -56,6 +55,7 @@ #include #include #include +#include #include #include @@ -78,7 +78,6 @@ #include #include #include -#include #include #include #include @@ -86,6 +85,7 @@ #include #include #include +#include #include #include #include @@ -136,33 +136,9 @@ static bool TryToInstallBuildDep(pkgCache::PkgIterator Pkg,pkgCacheFile &Cache, return true; } /*}}}*/ - - -// helper that can go wit hthe next ABI break -#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR < 13) -static std::string MetaIndexFileNameOnDisk(metaIndex *metaindex) -{ - // FIXME: this cast is the horror, the horror - debReleaseIndex *r = (debReleaseIndex*)metaindex; - - // see if we have a InRelease file - std::string PathInRelease = r->MetaIndexFile("InRelease"); - if (FileExists(PathInRelease)) - return PathInRelease; - - // and if not return the normal one - if (FileExists(PathInRelease)) - return r->MetaIndexFile("Release"); - - return ""; -} -#endif - -// GetReleaseForSourceRecord - Return Suite for the given srcrecord /*{{{*/ -// --------------------------------------------------------------------- -/* */ -static std::string GetReleaseForSourceRecord(pkgSourceList *SrcList, - pkgSrcRecords::Parser *Parse) +// GetReleaseFileForSourceRecord - Return Suite for the given srcrecord /*{{{*/ +static pkgCache::RlsFileIterator GetReleaseFileForSourceRecord(CacheFile &CacheFile, + pkgSourceList *SrcList, pkgSrcRecords::Parser *Parse) { // try to find release const pkgIndexFile& CurrentIndexFile = Parse->Index(); @@ -175,22 +151,10 @@ static std::string GetReleaseForSourceRecord(pkgSourceList *SrcList, IF != Indexes->end(); ++IF) { if (&CurrentIndexFile == (*IF)) - { -#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR < 13) - std::string path = MetaIndexFileNameOnDisk(*S); -#else - std::string path = (*S)->LocalFileName(); -#endif - if (path != "") - { - indexRecords records; - records.Load(path); - return records.GetSuite(); - } - } + return (*S)->FindInCache(CacheFile, false); } } - return ""; + return pkgCache::RlsFileIterator(CacheFile); } /*}}}*/ // FindSrc - Find a source record /*{{{*/ @@ -304,9 +268,9 @@ static pkgSrcRecords::Parser *FindSrc(const char *Name, (VF.File().Archive() != 0 && VF.File().Archive() == RelTag) || (VF.File().Codename() != 0 && VF.File().Codename() == RelTag)) { - Src = Ver.SourcePkgName(); // the Version we have is possibly fuzzy or includes binUploads, - // so we use the Version of the SourcePkg + // so we use the Version of the SourcePkg (empty if same as package) + Src = Ver.SourcePkgName(); VerTag = Ver.SourceVerStr(); break; } @@ -382,13 +346,16 @@ static pkgSrcRecords::Parser *FindSrc(const char *Name, // See if we need to look for a specific release tag if (RelTag != "" && UserRequestedVerTag == "") { - const string Rel = GetReleaseForSourceRecord(SrcList, Parse); - - if (Rel == RelTag) + pkgCache::RlsFileIterator const Rls = GetReleaseFileForSourceRecord(CacheFile, SrcList, Parse); + if (Rls.end() == false) { - Last = Parse; - Offset = Parse->Offset(); - Version = Ver; + if ((Rls->Archive != 0 && RelTag == Rls.Archive()) || + (Rls->Codename != 0 && RelTag == Rls.Codename())) + { + Last = Parse; + Offset = Parse->Offset(); + Version = Ver; + } } } @@ -562,30 +529,12 @@ static bool DoClean(CommandLine &) return true; } - bool const NoLocking = _config->FindB("Debug::NoLocking",false); - // Lock the archive directory - FileFd Lock; - if (NoLocking == false) - { - int lock_fd = GetLock(archivedir + "lock"); - if (lock_fd < 0) - return _error->Error(_("Unable to lock directory %s"), archivedir.c_str()); - Lock.Fd(lock_fd); - } - pkgAcquire Fetcher; + Fetcher.GetLock(archivedir); Fetcher.Clean(archivedir); Fetcher.Clean(archivedir + "partial/"); - if (NoLocking == false) - { - Lock.Close(); - int lock_fd = GetLock(listsdir + "lock"); - if (lock_fd < 0) - return _error->Error(_("Unable to lock directory %s"), listsdir.c_str()); - Lock.Fd(lock_fd); - } - + Fetcher.GetLock(listsdir); Fetcher.Clean(listsdir + "partial/"); pkgCacheFile::RemoveCaches(); @@ -600,7 +549,7 @@ static bool DoClean(CommandLine &) class LogCleaner : public pkgArchiveCleaner { protected: - virtual void Erase(const char *File,string Pkg,string Ver,struct stat &St) + virtual void Erase(const char *File,string Pkg,string Ver,struct stat &St) APT_OVERRIDE { c1out << "Del " << Pkg << " " << Ver << " [" << SizeToStr(St.st_size) << "B]" << endl; @@ -639,21 +588,19 @@ static bool DoDownload(CommandLine &CmdL) if (Cache.ReadOnlyOpen() == false) return false; - APT::CacheSetHelper helper(c0out); + APT::CacheSetHelper helper; APT::VersionSet verset = APT::VersionSet::FromCommandLine(Cache, CmdL.FileList + 1, APT::CacheSetHelper::CANDIDATE, helper); if (verset.empty() == true) return false; - AcqTextStatus Stat(ScreenWidth, _config->FindI("quiet", 0)); - pkgAcquire Fetcher(&Stat); - pkgRecords Recs(Cache); pkgSourceList *SrcList = Cache.GetSourceList(); // reuse the usual acquire methods for deb files, but don't drop them into // the usual directories - keep everything in the current directory + aptAcquireWithTextStatus Fetcher; std::vector storefile(verset.size()); std::string const cwd = SafeGetCWD(); _config->Set("Dir::Cache::Archives", cwd); @@ -679,9 +626,6 @@ static bool DoDownload(CommandLine &CmdL) return true; } - // Disable drop-privs if "_apt" can not write to the target dir - CheckDropPrivsMustBeDisabled(Fetcher); - if (_error->PendingError() == true || CheckAuth(Fetcher, false) == false) return false; @@ -747,11 +691,7 @@ static bool DoSource(CommandLine &CmdL) if (_error->PendingError() == true) return false; - // Create the download object - AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0)); - pkgAcquire Fetcher(&Stat); - - SPtrArray Dsc = new DscFile[CmdL.FileSize()]; + std::unique_ptr Dsc(new DscFile[CmdL.FileSize()]); // insert all downloaded uris into this set to avoid downloading them // twice @@ -765,20 +705,20 @@ static bool DoSource(CommandLine &CmdL) bool const dscOnly = _config->FindB("APT::Get::Dsc-Only", false); // Load the requestd sources into the fetcher + aptAcquireWithTextStatus Fetcher; unsigned J = 0; - std::string UntrustedList; + std::vector UntrustedList; for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++) { string Src; pkgSrcRecords::Parser *Last = FindSrc(*I,SrcRecs,Src,Cache); - if (Last == 0) { return _error->Error(_("Unable to find a source package for %s"),Src.c_str()); } if (Last->Index().IsTrusted() == false) - UntrustedList += Src + " "; - + UntrustedList.push_back(Src); + string srec = Last->AsStr(); string::size_type pos = srec.find("\nVcs-"); while (pos != string::npos) @@ -792,28 +732,33 @@ static bool DoSource(CommandLine &CmdL) } pos += vcs.length()+2; string::size_type epos = srec.find("\n", pos); - string uri = srec.substr(pos,epos-pos).c_str(); + string const uri = srec.substr(pos,epos-pos); ioprintf(c1out, _("NOTICE: '%s' packaging is maintained in " "the '%s' version control system at:\n" "%s\n"), Src.c_str(), vcs.c_str(), uri.c_str()); - if(vcs == "Bzr") - ioprintf(c1out,_("Please use:\n" - "bzr branch %s\n" - "to retrieve the latest (possibly unreleased) " - "updates to the package.\n"), - uri.c_str()); + std::string vcscmd; + if (vcs == "Bzr") + vcscmd = "bzr branch " + uri; + else if (vcs == "Git") + vcscmd = "git clone " + uri; + + if (vcscmd.empty() == false) + ioprintf(c1out,_("Please use:\n%s\n" + "to retrieve the latest (possibly unreleased) " + "updates to the package.\n"), + vcscmd.c_str()); break; } // Back track - vector Lst; - if (Last->Files(Lst) == false) { + vector Lst; + if (Last->Files2(Lst) == false) { return false; } // Load them into the fetcher - for (vector::const_iterator I = Lst.begin(); + for (vector::const_iterator I = Lst.begin(); I != Lst.end(); ++I) { // Try to guess what sort of file it is we are getting. @@ -860,7 +805,7 @@ static bool DoSource(CommandLine &CmdL) } new pkgAcqFile(&Fetcher,Last->Index().ArchiveURI(I->Path), - I->Hashes, I->Size, Last->Index().SourceInfo(*Last,*I), Src); + I->Hashes, I->FileSize, Last->Index().SourceInfo(*Last,*I), Src); } } @@ -901,11 +846,8 @@ static bool DoSource(CommandLine &CmdL) return true; } - // Disable drop-privs if "_apt" can not write to the target dir - CheckDropPrivsMustBeDisabled(Fetcher); - // check authentication status of the source as well - if (UntrustedList != "" && !AuthPrompt(UntrustedList, false)) + if (UntrustedList.empty() == false && AuthPrompt(UntrustedList, false) == false) return false; // Run it @@ -993,19 +935,7 @@ static bool DoSource(CommandLine &CmdL) _exit(0); } - // Wait for the subprocess - int Status = 0; - while (waitpid(Process,&Status,0) != Process) - { - if (errno == EINTR) - continue; - return _error->Errno("waitpid","Couldn't wait for subprocess"); - } - - if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0) - return _error->Error(_("Child process failed")); - - return true; + return ExecWait(Process, "dpkg-source"); } /*}}}*/ // DoBuildDep - Install/removes packages to satisfy build dependencies /*{{{*/ @@ -1017,8 +947,10 @@ static bool DoBuildDep(CommandLine &CmdL) CacheFile Cache; _config->Set("APT::Install-Recommends", false); + + bool WantLock = _config->FindB("APT::Get::Print-URIs", false) == false; - if (Cache.Open(true) == false) + if (Cache.Open(WantLock) == false) return false; if (CmdL.FileSize() <= 1) @@ -1051,6 +983,7 @@ static bool DoBuildDep(CommandLine &CmdL) { string Src; pkgSrcRecords::Parser *Last = 0; + std::unique_ptr LastOwner; // an unpacked debian source tree using APT::String::Startswith; @@ -1059,10 +992,10 @@ static bool DoBuildDep(CommandLine &CmdL) { ioprintf(c1out, _("Note, using directory '%s' to get the build dependencies\n"), *I); // FIXME: how can we make this more elegant? - std::string TypeName = "debian/control File Source Index"; + std::string TypeName = "Debian control file"; pkgIndexFile::Type *Type = pkgIndexFile::Type::GetType(TypeName.c_str()); if(Type != NULL) - Last = Type->CreateSrcPkgParser(*I); + LastOwner.reset(Last = Type->CreateSrcPkgParser(*I)); } // if its a local file (e.g. .dsc) use this else if (FileExists(*I)) @@ -1070,13 +1003,13 @@ static bool DoBuildDep(CommandLine &CmdL) ioprintf(c1out, _("Note, using file '%s' to get the build dependencies\n"), *I); // see if we can get a parser for this pkgIndexFile type - string TypeName = flExtension(*I) + " File Source Index"; + string TypeName = "Debian " + flExtension(*I) + " file"; pkgIndexFile::Type *Type = pkgIndexFile::Type::GetType(TypeName.c_str()); if(Type != NULL) - Last = Type->CreateSrcPkgParser(*I); + LastOwner.reset(Last = Type->CreateSrcPkgParser(*I)); } else { // normal case, search the cache for the source file - Last = FindSrc(*I,SrcRecs,Src,Cache); + Last = FindSrc(*I,SrcRecs,Src,Cache); } if (Last == 0) @@ -1221,12 +1154,12 @@ static bool DoBuildDep(CommandLine &CmdL) for (; Ver != verlist.end(); ++Ver) { forbidden.clear(); - if (Ver->MultiArch == pkgCache::Version::None || Ver->MultiArch == pkgCache::Version::All) + if (Ver->MultiArch == pkgCache::Version::No || Ver->MultiArch == pkgCache::Version::All) { if (colon == string::npos) Pkg = Ver.ParentPkg().Group().FindPkg(hostArch); else if (strcmp(D->Package.c_str() + colon, ":any") == 0) - forbidden = "Multi-Arch: none"; + forbidden = "Multi-Arch: no"; else if (strcmp(D->Package.c_str() + colon, ":native") == 0) Pkg = Ver.ParentPkg().Group().FindPkg("native"); } @@ -1418,202 +1351,192 @@ static bool DoBuildDep(CommandLine &CmdL) return true; } /*}}}*/ -// GetChangelogPath - return a path pointing to a changelog file or dir /*{{{*/ -// --------------------------------------------------------------------- -/* This returns a "path" string for the changelog url construction. - * Please note that its not complete, it either needs a "/changelog" - * appended (for the packages.debian.org/changelogs site) or a - * ".changelog" (for third party sites that store the changelog in the - * pool/ next to the deb itself) - * Example return: "pool/main/a/apt/apt_0.8.8ubuntu3" - */ -static string GetChangelogPath(CacheFile &Cache, - pkgCache::VerIterator Ver) -{ - pkgRecords Recs(Cache); - pkgRecords::Parser &rec=Recs.Lookup(Ver.FileList()); - string path = flNotFile(rec.FileName()); - path.append(Ver.SourcePkgName()); - path.append("_"); - path.append(StripEpoch(Ver.SourceVerStr())); - return path; -} - /*}}}*/ -// GuessThirdPartyChangelogUri - return url /*{{{*/ -// --------------------------------------------------------------------- -/* Contruct a changelog file path for third party sites that do not use - * packages.debian.org/changelogs - * This simply uses the ArchiveURI() of the source pkg and looks for - * a .changelog file there, Example for "mediabuntu": - * apt-get changelog mplayer-doc: - * http://packages.medibuntu.org/pool/non-free/m/mplayer/mplayer_1.0~rc4~try1.dsfg1-1ubuntu1+medibuntu1.changelog - */ -static bool GuessThirdPartyChangelogUri(CacheFile &Cache, - pkgCache::VerIterator Ver, - string &out_uri) +// DoChangelog - Get changelog from the command line /*{{{*/ +static bool DoChangelog(CommandLine &CmdL) { - // get the binary deb server path - pkgCache::VerFileIterator Vf = Ver.FileList(); - if (Vf.end() == true) + CacheFile Cache; + if (Cache.ReadOnlyOpen() == false) return false; - pkgCache::PkgFileIterator F = Vf.File(); - pkgIndexFile *index; - pkgSourceList *SrcList = Cache.GetSourceList(); - if(SrcList->FindIndex(F, index) == false) + + APT::CacheSetHelper helper; + APT::VersionList verset = APT::VersionList::FromCommandLine(Cache, + CmdL.FileList + 1, APT::CacheSetHelper::CANDIDATE, helper); + if (verset.empty() == true) return false; - // get archive uri for the binary deb - string path_without_dot_changelog = GetChangelogPath(Cache, Ver); - out_uri = index->ArchiveURI(path_without_dot_changelog + ".changelog"); + bool const downOnly = _config->FindB("APT::Get::Download-Only", false); + bool const printOnly = _config->FindB("APT::Get::Print-URIs", false); - // now strip away the filename and add srcpkg_srcver.changelog - return true; -} - /*}}}*/ -// DownloadChangelog - Download the changelog /*{{{*/ -// --------------------------------------------------------------------- -static bool DownloadChangelog(CacheFile &CacheFile, pkgAcquire &Fetcher, - pkgCache::VerIterator Ver, string targetfile) -/* Download a changelog file for the given package version to - * targetfile. This will first try the server from Apt::Changelogs::Server - * (http://packages.debian.org/changelogs by default) and if that gives - * a 404 tries to get it from the archive directly (see - * GuessThirdPartyChangelogUri for details how) - */ -{ - // make the server root configurable - string const server = _config->Find("Apt::Changelogs::Server", - "http://packages.debian.org/changelogs"); - string const path = GetChangelogPath(CacheFile, Ver); - string changelog_uri; - if (APT::String::Endswith(server, "/") == true) - strprintf(changelog_uri, "%s%s/changelog", server.c_str(), path.c_str()); - else - strprintf(changelog_uri, "%s/%s/changelog", server.c_str(), path.c_str()); - if (_config->FindB("APT::Get::Print-URIs", false) == true) + aptAcquireWithTextStatus Fetcher; + for (APT::VersionList::const_iterator Ver = verset.begin(); + Ver != verset.end(); + ++Ver) { - std::cout << '\'' << changelog_uri << '\'' << std::endl; - return true; + if (printOnly) + new pkgAcqChangelog(&Fetcher, Ver, "/dev/null"); + else if (downOnly) + new pkgAcqChangelog(&Fetcher, Ver, "."); + else + new pkgAcqChangelog(&Fetcher, Ver); } - pkgCache::PkgIterator const Pkg = Ver.ParentPkg(); - - string descr; - strprintf(descr, _("Changelog for %s (%s)"), Pkg.Name(), changelog_uri.c_str()); - // queue it - pkgAcquire::Item const * itm = new pkgAcqFile(&Fetcher, changelog_uri, "", 0, descr, Pkg.Name(), "ignored", targetfile); - // Disable drop-privs if "_apt" can not write to the target dir - CheckDropPrivsMustBeDisabled(Fetcher); + if (printOnly == false) + { + bool Failed = false; + if (AcquireRun(Fetcher, 0, &Failed, NULL) == false || Failed == true) + return false; + } - // try downloading it, if that fails, try third-party-changelogs location - // FIXME: Fetcher.Run() is "Continue" even if I get a 404?!? - Fetcher.Run(); - if (itm->Status != pkgAcquire::Item::StatDone) + if (downOnly == false || printOnly == true) { - string third_party_uri; - if (GuessThirdPartyChangelogUri(CacheFile, Ver, third_party_uri)) + bool Failed = false; + for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); ++I) { - strprintf(descr, _("Changelog for %s (%s)"), Pkg.Name(), third_party_uri.c_str()); - itm = new pkgAcqFile(&Fetcher, third_party_uri, "", 0, descr, Pkg.Name(), "ignored", targetfile); - Fetcher.Run(); + if (printOnly) + { + if ((*I)->ErrorText.empty() == false) + { + Failed = true; + _error->Error("%s", (*I)->ErrorText.c_str()); + } + else + cout << '\'' << (*I)->DescURI() << "' " << flNotDir((*I)->DestFile) << std::endl; + } + else + DisplayFileInPager((*I)->DestFile); } + return Failed == false; } - if (itm->Status == pkgAcquire::Item::StatDone) - return true; - - // error - return _error->Error("changelog download failed"); + return true; } /*}}}*/ -// DoChangelog - Get changelog from the command line /*{{{*/ -// --------------------------------------------------------------------- -static bool DoChangelog(CommandLine &CmdL) +// DoIndexTargets - Lists all IndexTargets /*{{{*/ +static std::string format_key(std::string key) { - CacheFile Cache; - if (Cache.ReadOnlyOpen() == false) - return false; - - APT::CacheSetHelper helper(c0out); - APT::VersionList verset = APT::VersionList::FromCommandLine(Cache, - CmdL.FileList + 1, APT::CacheSetHelper::CANDIDATE, helper); - if (verset.empty() == true) - return false; - pkgAcquire Fetcher; - - if (_config->FindB("APT::Get::Print-URIs", false) == true) + // deb822 is case-insensitive, but the human eye prefers candy + std::transform(key.begin(), key.end(), key.begin(), ::tolower); + key[0] = ::toupper(key[0]); + size_t found = key.find("_uri"); + if (found != std::string::npos) + key.replace(found, 4, "-URI"); + while ((found = key.find('_')) != std::string::npos) { - bool Success = true; - for (APT::VersionList::const_iterator Ver = verset.begin(); - Ver != verset.end(); ++Ver) - Success &= DownloadChangelog(Cache, Fetcher, Ver, ""); - return Success; + key[found] = '-'; + key[found + 1] = ::toupper(key[found + 1]); } + return key; +} +static bool DoIndexTargets(CommandLine &CmdL) +{ + pkgCacheFile CacheFile; + pkgSourceList *SrcList = CacheFile.GetSourceList(); - AcqTextStatus Stat(ScreenWidth, _config->FindI("quiet",0)); - Fetcher.SetLog(&Stat); - - bool const downOnly = _config->FindB("APT::Get::Download-Only", false); + if (SrcList == NULL) + return false; - char tmpname[100]; - const char* tmpdir = NULL; - if (downOnly == false) + std::string const Format = _config->Find("APT::Get::IndexTargets::Format"); + bool const ReleaseInfo = _config->FindB("APT::Get::IndexTargets::ReleaseInfo", true); + bool Filtered = CmdL.FileSize() > 1; + for (pkgSourceList::const_iterator S = SrcList->begin(); S != SrcList->end(); ++S) { - std::string systemTemp = GetTempDir(); - snprintf(tmpname, sizeof(tmpname), "%s/apt-changelog-XXXXXX", - systemTemp.c_str()); - tmpdir = mkdtemp(tmpname); - if (tmpdir == NULL) - return _error->Errno("mkdtemp", "mkdtemp failed"); - - std::string const SandboxUser = _config->Find("APT::Sandbox::User"); - if (getuid() == 0 && SandboxUser.empty() == false) // if we aren't root, we can't chown, so don't try it + std::vector const targets = (*S)->GetIndexTargets(); + std::map AddOptions; + if (ReleaseInfo) { - struct passwd const * const pw = getpwnam(SandboxUser.c_str()); - struct group const * const gr = getgrnam("root"); - if (pw != NULL && gr != NULL) - { - // chown the tmp dir directory we use to the sandbox user - if(chown(tmpdir, pw->pw_uid, gr->gr_gid) != 0) - _error->WarningE("DoChangelog", "chown to %s:%s of directory %s failed", SandboxUser.c_str(), "root", tmpdir); - } + AddOptions.insert(std::make_pair("TRUSTED", ((*S)->IsTrusted() ? "yes" : "no"))); + pkgCache &Cache = *CacheFile.GetPkgCache(); + pkgCache::RlsFileIterator const RlsFile = (*S)->FindInCache(Cache, false); + if (RlsFile.end()) + continue; +#define APT_RELEASE(X,Y) if (RlsFile.Y() != NULL) AddOptions.insert(std::make_pair(X, RlsFile.Y())) + APT_RELEASE("CODENAME", Codename); + APT_RELEASE("SUITE", Archive); + APT_RELEASE("VERSION", Version); + APT_RELEASE("ORIGIN", Origin); + APT_RELEASE("LABEL", Label); +#undef APT_RELEASE } - } - for (APT::VersionList::const_iterator Ver = verset.begin(); - Ver != verset.end(); - ++Ver) - { - string changelogfile; - if (downOnly == false) - changelogfile.append(tmpname).append("/changelog"); - else - changelogfile.append(Ver.ParentPkg().Name()).append(".changelog"); - if (DownloadChangelog(Cache, Fetcher, Ver, changelogfile) && downOnly == false) + for (std::vector::const_iterator T = targets.begin(); T != targets.end(); ++T) { - DisplayFileInPager(changelogfile); - // cleanup temp file - unlink(changelogfile.c_str()); + std::string filename = T->Option(ReleaseInfo ? IndexTarget::EXISTING_FILENAME : IndexTarget::FILENAME); + if (filename.empty()) + continue; + + std::ostringstream stanza; + if (Filtered || Format.empty()) + { + stanza << "MetaKey: " << T->MetaKey << "\n" + << "ShortDesc: " << T->ShortDesc << "\n" + << "Description: " << T->Description << "\n" + << "URI: " << T->URI << "\n" + << "Filename: " << filename << "\n" + << "Optional: " << (T->IsOptional ? "yes" : "no") << "\n" + << "KeepCompressed: " << (T->KeepCompressed ? "yes" : "no") << "\n"; + for (std::map::const_iterator O = AddOptions.begin(); O != AddOptions.end(); ++O) + stanza << format_key(O->first) << ": " << O->second << "\n"; + for (std::map::const_iterator O = T->Options.begin(); O != T->Options.end(); ++O) + { + if (O->first == "PDIFFS") + stanza << "PDiffs: " << O->second << "\n"; + else if (O->first == "COMPRESSIONTYPES") + stanza << "CompressionTypes: " << O->second << "\n"; + else if (O->first == "DEFAULTENABLED") + stanza << "DefaultEnabled: " << O->second << "\n"; + else + stanza << format_key(O->first) << ": " << O->second << "\n"; + } + stanza << "\n"; + + if (Filtered) + { + // that is a bit crude, but good enough for now + bool found = true; + std::string haystack = std::string("\n") + stanza.str() + "\n"; + std::transform(haystack.begin(), haystack.end(), haystack.begin(), ::tolower); + size_t const filesize = CmdL.FileSize() - 1; + for (size_t i = 0; i != filesize; ++i) + { + std::string needle = std::string("\n") + CmdL.FileList[i + 1] + "\n"; + std::transform(needle.begin(), needle.end(), needle.begin(), ::tolower); + if (haystack.find(needle) != std::string::npos) + continue; + found = false; + break; + } + if (found == false) + continue; + } + } + + if (Format.empty()) + cout << stanza.str(); + else + { + std::string out = SubstVar(Format, "$(FILENAME)", filename); + out = T->Format(out); + for (std::map::const_iterator O = AddOptions.begin(); O != AddOptions.end(); ++O) + out = SubstVar(out, std::string("$(") + O->first + ")", O->second); + cout << out << std::endl; + } } } - // clenaup tmp dir - if (tmpdir != NULL) - rmdir(tmpdir); + return true; } /*}}}*/ // ShowHelp - Show a help screen /*{{{*/ // --------------------------------------------------------------------- /* */ -static bool ShowHelp(CommandLine &) +static bool ShowHelp(CommandLine &, CommandLine::DispatchWithHelp const * Cmds) { - ioprintf(cout,_("%s %s for %s compiled on %s %s\n"),PACKAGE,PACKAGE_VERSION, - COMMON_ARCH,__DATE__,__TIME__); - + ioprintf(cout, "%s %s (%s)\n", PACKAGE, PACKAGE_VERSION, COMMON_ARCH); + if (_config->FindB("version") == true) { cout << _("Supported modules:") << endl; - + for (unsigned I = 0; I != pkgVersioningSystem::GlobalListLen; I++) { pkgVersioningSystem *VS = pkgVersioningSystem::GlobalList[I]; @@ -1622,7 +1545,7 @@ static bool ShowHelp(CommandLine &) else cout << ' '; cout << "Ver: " << VS->Label << endl; - + /* Print out all the packaging systems that will work with this VS */ for (unsigned J = 0; J != pkgSystem::GlobalListLen; J++) @@ -1651,34 +1574,26 @@ static bool ShowHelp(CommandLine &) return true; } - - cout << + + std::cout << _("Usage: apt-get [options] command\n" " apt-get [options] install|remove pkg1 [pkg2 ...]\n" " apt-get [options] source pkg1 [pkg2 ...]\n" "\n" "apt-get is a simple command line interface for downloading and\n" "installing packages. The most frequently used commands are update\n" - "and install.\n" - "\n" - "Commands:\n" - " update - Retrieve new lists of packages\n" - " upgrade - Perform an upgrade\n" - " install - Install new packages (pkg is libc6 not libc6.deb)\n" - " remove - Remove packages\n" - " autoremove - Remove automatically all unused packages\n" - " purge - Remove packages and config files\n" - " source - Download source archives\n" - " build-dep - Configure build-dependencies for source packages\n" - " dist-upgrade - Distribution upgrade, see apt-get(8)\n" - " dselect-upgrade - Follow dselect selections\n" - " clean - Erase downloaded archive files\n" - " autoclean - Erase old downloaded archive files\n" - " check - Verify that there are no broken dependencies\n" - " changelog - Download and display the changelog for the given package\n" - " download - Download the binary package into the current directory\n" - "\n" - "Options:\n" + "and install.\n") + << std::endl + << _("Commands:") << std::endl; + for (; Cmds->Handler != nullptr; ++Cmds) + { + if (Cmds->Help == nullptr) + continue; + std::cout << " " << Cmds->Match << " - " << Cmds->Help << std::endl; + } + + std::cout << std::endl << + _("Options:\n" " -h This help text.\n" " -q Loggable output - no progress indicator\n" " -qq No output except for errors\n" @@ -1700,73 +1615,43 @@ static bool ShowHelp(CommandLine &) /*}}}*/ int main(int argc,const char *argv[]) /*{{{*/ { - CommandLine::Dispatch Cmds[] = {{"update",&DoUpdate}, - {"upgrade",&DoUpgrade}, - {"install",&DoInstall}, - {"remove",&DoInstall}, - {"purge",&DoInstall}, - {"autoremove",&DoInstall}, - {"markauto",&DoMarkAuto}, - {"unmarkauto",&DoMarkAuto}, - {"dist-upgrade",&DoDistUpgrade}, - {"dselect-upgrade",&DoDSelectUpgrade}, - {"build-dep",&DoBuildDep}, - {"clean",&DoClean}, - {"autoclean",&DoAutoClean}, - {"check",&DoCheck}, - {"source",&DoSource}, - {"download",&DoDownload}, - {"changelog",&DoChangelog}, - {"moo",&DoMoo}, - {"help",&ShowHelp}, - {0,0}}; - - std::vector Args = getCommandArgs("apt-get", CommandLine::GetCommand(Cmds, argc, argv)); - - // Set up gettext support - setlocale(LC_ALL,""); - textdomain(PACKAGE); + InitLocale(); + + CommandLine::DispatchWithHelp Cmds[] = { + {"update", &DoUpdate, _("Retrieve new lists of packages")}, + {"upgrade", &DoUpgrade, _("Perform an upgrade")}, + {"install", &DoInstall, _("Install new packages (pkg is libc6 not libc6.deb)")}, + {"remove", &DoInstall, _("Remove packages")}, + {"purge", &DoInstall, _("Remove packages and config files")}, + {"autoremove", &DoInstall, _("Remove automatically all unused packages")}, + {"auto-remove", &DoInstall, nullptr}, + {"markauto", &DoMarkAuto, nullptr}, + {"unmarkauto", &DoMarkAuto, nullptr}, + {"dist-upgrade", &DoDistUpgrade, _("Distribution upgrade, see apt-get(8)")}, + {"full-upgrade", &DoDistUpgrade, nullptr}, + {"dselect-upgrade", &DoDSelectUpgrade, _("Follow dselect selections")}, + {"build-dep", &DoBuildDep, _("Configure build-dependencies for source packages")}, + {"clean", &DoClean, _("Erase downloaded archive files")}, + {"autoclean", &DoAutoClean, _("Erase old downloaded archive files")}, + {"auto-clean", &DoAutoClean, nullptr}, + {"check", &DoCheck, _("Verify that there are no broken dependencies")}, + {"source", &DoSource, _("Download source archives")}, + {"download", &DoDownload, _("Download the binary package into the current directory")}, + {"changelog", &DoChangelog, _("Download and display the changelog for the given package")}, + {"indextargets", &DoIndexTargets, nullptr}, + {"moo", &DoMoo, nullptr}, + {nullptr, nullptr, nullptr} + }; // Parse the command line and initialize the package library - CommandLine CmdL(Args.data(),_config); - if (pkgInitConfig(*_config) == false || - CmdL.Parse(argc,argv) == false || - pkgInitSystem(*_config,_system) == false) - { - if (_config->FindB("version") == true) - ShowHelp(CmdL); - - _error->DumpErrors(); - return 100; - } + CommandLine CmdL; + ParseCommandLine(CmdL, Cmds, "apt-get", &_config, &_system, argc, argv, ShowHelp); - // See if the help should be shown - if (_config->FindB("help") == true || - _config->FindB("version") == true || - CmdL.FileSize() == 0) - { - ShowHelp(CmdL); - return 0; - } - - // see if we are in simulate mode - CheckSimulateMode(CmdL); - - // Init the signals InitSignals(); - - // Setup the output streams InitOutput(); - // Match the operation - CmdL.DispatchArg(Cmds); + CheckIfSimulateMode(CmdL); - // Print any errors or warnings found during parsing - bool const Errors = _error->PendingError(); - if (_config->FindI("quiet",0) > 0) - _error->DumpErrors(); - else - _error->DumpErrors(GlobalError::DEBUG); - return Errors == true ? 100 : 0; + return DispatchCommandLine(CmdL, Cmds); } /*}}}*/