#include <apt-pkg/error.h>
#include <apt-pkg/fileutl.h>
#include <apt-pkg/indexfile.h>
-#include <apt-pkg/indexrecords.h>
#include <apt-pkg/init.h>
#include <apt-pkg/md5.h>
#include <apt-pkg/metaindex.h>
#include <apt-pkg/pkgcache.h>
#include <apt-pkg/cacheiterators.h>
#include <apt-pkg/upgrade.h>
+#include <apt-pkg/sptr.h>
#include <apt-private/acqprogress.h>
#include <apt-private/private-cacheset.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
-#include <sys/statfs.h>
-#include <sys/statvfs.h>
-#include <sys/wait.h>
#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+
#include <algorithm>
#include <fstream>
#include <iostream>
+#include <sstream>
#include <set>
#include <string>
#include <vector>
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();
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 /*{{{*/
// ---------------------------------------------------------------------
/* */
-static pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs,
+static pkgSrcRecords::Parser *FindSrc(const char *Name,
pkgSrcRecords &SrcRecs,string &Src,
CacheFile &CacheFile)
{
(VF.File().Archive() != 0 && VF.File().Archive() == RelTag) ||
(VF.File().Codename() != 0 && VF.File().Codename() == RelTag))
{
- pkgRecords::Parser &Parse = Recs.Lookup(VF);
- Src = Parse.SourcePkg();
- // no SourcePkg name, so it is the "binary" name
- if (Src.empty() == true)
- Src = TmpSrc;
// the Version we have is possibly fuzzy or includes binUploads,
// so we use the Version of the SourcePkg (empty if same as package)
- VerTag = Parse.SourceVer();
- if (VerTag.empty() == true)
- VerTag = Ver.VerStr();
+ Src = Ver.SourcePkgName();
+ VerTag = Ver.SourceVerStr();
break;
}
}
pkgCache::VerIterator Ver = Cache->GetCandidateVer(Pkg);
if (Ver.end() == false)
{
- pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
- Src = Parse.SourcePkg();
- if (VerTag.empty() == true)
- VerTag = Parse.SourceVer();
+ if (strcmp(Ver.SourcePkgName(),Ver.ParentPkg().Name()) != 0)
+ Src = Ver.SourcePkgName();
+ if (VerTag.empty() == true && strcmp(Ver.SourceVerStr(),Ver.VerStr()) != 0)
+ VerTag = Ver.SourceVerStr();
}
}
}
// 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;
+ }
}
}
}
// Now upgrade everything
- if (pkgAllUpgrade(Cache) == false)
+ if (APT::Upgrade::Upgrade(Cache, APT::Upgrade::FORBID_REMOVE_PACKAGES | APT::Upgrade::FORBID_INSTALL_NEW_PACKAGES) == false)
{
ShowBroken(c1out,Cache,false);
return _error->Error(_("Internal error, problem resolver broke stuff"));
static bool DoClean(CommandLine &)
{
std::string const archivedir = _config->FindDir("Dir::Cache::archives");
- std::string const pkgcache = _config->FindFile("Dir::cache::pkgcache");
- std::string const srcpkgcache = _config->FindFile("Dir::cache::srcpkgcache");
+ std::string const listsdir = _config->FindDir("Dir::state::lists");
if (_config->FindB("APT::Get::Simulate") == true)
{
+ std::string const pkgcache = _config->FindFile("Dir::cache::pkgcache");
+ std::string const srcpkgcache = _config->FindFile("Dir::cache::srcpkgcache");
cout << "Del " << archivedir << "* " << archivedir << "partial/*"<< endl
+ << "Del " << listsdir << "partial/*" << endl
<< "Del " << pkgcache << " " << srcpkgcache << endl;
return true;
}
-
- // Lock the archive directory
- FileFd Lock;
- if (_config->FindB("Debug::NoLocking",false) == false)
- {
- int lock_fd = GetLock(archivedir + "lock");
- if (lock_fd < 0)
- return _error->Error(_("Unable to lock the download directory"));
- Lock.Fd(lock_fd);
- }
-
+
pkgAcquire Fetcher;
+ Fetcher.GetLock(archivedir);
Fetcher.Clean(archivedir);
Fetcher.Clean(archivedir + "partial/");
+ Fetcher.GetLock(listsdir);
+ Fetcher.Clean(listsdir + "partial/");
+
pkgCacheFile::RemoveCaches();
return true;
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;
if (Cache.ReadOnlyOpen() == false)
return false;
- APT::CacheSetHelper helper(c0out);
+ APT::CacheSetHelper helper;
APT::VersionSet verset = APT::VersionSet::FromCommandLine(Cache,
- CmdL.FileList + 1, APT::VersionSet::CANDIDATE, helper);
+ CmdL.FileList + 1, APT::CacheSetHelper::CANDIDATE, helper);
if (verset.empty() == true)
return false;
- AcqTextStatus Stat(ScreenWidth, _config->FindI("quiet", 0));
- pkgAcquire Fetcher;
- if (Fetcher.Setup(&Stat) == false)
- return false;
-
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<std::string> storefile(verset.size());
std::string const cwd = SafeGetCWD();
_config->Set("Dir::Cache::Archives", cwd);
Ver != verset.end(); ++Ver, ++i)
{
pkgAcquire::Item *I = new pkgAcqArchive(&Fetcher, SrcList, &Recs, *Ver, storefile[i]);
+ if (storefile[i].empty())
+ continue;
std::string const filename = cwd + flNotDir(storefile[i]);
storefile[i].assign(filename);
I->DestFile.assign(filename);
{
pkgAcquire::UriIterator I = Fetcher.UriBegin();
for (; I != Fetcher.UriEnd(); ++I)
- cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
+ cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
I->Owner->FileSize << ' ' << I->Owner->HashSum() << endl;
return true;
}
pkgSourceList *List = Cache.GetSourceList();
// Create the text record parsers
- pkgRecords Recs(Cache);
pkgSrcRecords SrcRecs(*List);
if (_error->PendingError() == true)
return false;
- // Create the download object
- AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
- pkgAcquire Fetcher;
- Fetcher.SetLog(&Stat);
-
- SPtrArray<DscFile> Dsc = new DscFile[CmdL.FileSize()];
+ std::unique_ptr<DscFile[]> Dsc(new DscFile[CmdL.FileSize()]);
// insert all downloaded uris into this set to avoid downloading them
// twice
bool const dscOnly = _config->FindB("APT::Get::Dsc-Only", false);
// Load the requestd sources into the fetcher
+ aptAcquireWithTextStatus Fetcher;
unsigned J = 0;
+ std::vector<std::string> UntrustedList;
for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
{
string Src;
- pkgSrcRecords::Parser *Last = FindSrc(*I,Recs,SrcRecs,Src,Cache);
-
+ 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.push_back(Src);
+
string srec = Last->AsStr();
string::size_type pos = srec.find("\nVcs-");
while (pos != string::npos)
}
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<pkgSrcRecords::File> Lst;
- if (Last->Files(Lst) == false) {
+ vector<pkgSrcRecords::File2> Lst;
+ if (Last->Files2(Lst) == false) {
return false;
}
// Load them into the fetcher
- for (vector<pkgSrcRecords::File>::const_iterator I = Lst.begin();
+ for (vector<pkgSrcRecords::File2>::const_iterator I = Lst.begin();
I != Lst.end(); ++I)
{
// Try to guess what sort of file it is we are getting.
queued.insert(Last->Index().ArchiveURI(I->Path));
// check if we have a file with that md5 sum already localy
- if(!I->MD5Hash.empty() && FileExists(flNotDir(I->Path)))
- {
- FileFd Fd(flNotDir(I->Path), FileFd::ReadOnly);
- MD5Summation sum;
- sum.AddFD(Fd.Fd(), Fd.Size());
- Fd.Close();
- if((string)sum.Result() == I->MD5Hash)
+ std::string localFile = flNotDir(I->Path);
+ if (FileExists(localFile) == true)
+ if(I->Hashes.VerifyFile(localFile) == true)
{
ioprintf(c1out,_("Skipping already downloaded file '%s'\n"),
- flNotDir(I->Path).c_str());
+ localFile.c_str());
continue;
}
+
+ // see if we have a hash (Acquire::ForceHash is the only way to have none)
+ if (I->Hashes.usable() == false && _config->FindB("APT::Get::AllowUnauthenticated",false) == false)
+ {
+ ioprintf(c1out, "Skipping download of file '%s' as requested hashsum is not available for authentication\n",
+ localFile.c_str());
+ continue;
}
new pkgAcqFile(&Fetcher,Last->Index().ArchiveURI(I->Path),
- I->MD5Hash,I->Size,
- Last->Index().SourceInfo(*Last,*I),Src);
+ I->Hashes, I->FileSize, Last->Index().SourceInfo(*Last,*I), Src);
}
}
-
+
// Display statistics
unsigned long long FetchBytes = Fetcher.FetchNeeded();
unsigned long long FetchPBytes = Fetcher.PartialPresent();
unsigned long long DebBytes = Fetcher.TotalNeeded();
- // Check for enough free space
- struct statvfs Buf;
- string OutputDir = ".";
- if (statvfs(OutputDir.c_str(),&Buf) != 0) {
- if (errno == EOVERFLOW)
- return _error->WarningE("statvfs",_("Couldn't determine free space in %s"),
- OutputDir.c_str());
- else
- return _error->Errno("statvfs",_("Couldn't determine free space in %s"),
- OutputDir.c_str());
- } else if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
- {
- struct statfs Stat;
- if (statfs(OutputDir.c_str(),&Stat) != 0
-#if HAVE_STRUCT_STATFS_F_TYPE
- || unsigned(Stat.f_type) != RAMFS_MAGIC
-#endif
- ) {
- return _error->Error(_("You don't have enough free space in %s"),
- OutputDir.c_str());
- }
- }
-
+ if (CheckFreeSpaceBeforeDownload(".", (FetchBytes - FetchPBytes)) == false)
+ return false;
+
// Number of bytes
if (DebBytes != FetchBytes)
//TRANSLATOR: The required space between number and unit is already included
ioprintf(cout,_("Fetch source %s\n"),Dsc[I].Package.c_str());
return true;
}
-
+
// Just print out the uris an exit if the --print-uris flag was used
if (_config->FindB("APT::Get::Print-URIs") == true)
{
return true;
}
+ // check authentication status of the source as well
+ if (UntrustedList.empty() == false && AuthPrompt(UntrustedList, false) == false)
+ return false;
+
// Run it
bool Failed = false;
if (AcquireRun(Fetcher, 0, &Failed, NULL) == false || Failed == true)
else
{
// Call dpkg-source
- char S[500];
- snprintf(S,sizeof(S),"%s -x %s",
+ std::string const sourceopts = _config->Find("DPkg::Source-Options", "-x");
+ std::string S;
+ strprintf(S, "%s %s %s",
_config->Find("Dir::Bin::dpkg-source","dpkg-source").c_str(),
- Dsc[I].Dsc.c_str());
- if (system(S) != 0)
+ sourceopts.c_str(), Dsc[I].Dsc.c_str());
+ if (system(S.c_str()) != 0)
{
- fprintf(stderr,_("Unpack command '%s' failed.\n"),S);
- fprintf(stderr,_("Check if the 'dpkg-dev' package is installed.\n"));
+ fprintf(stderr, _("Unpack command '%s' failed.\n"), S.c_str());
+ fprintf(stderr, _("Check if the 'dpkg-dev' package is installed.\n"));
_exit(1);
- }
+ }
}
-
+
// Try to compile it with dpkg-buildpackage
if (_config->FindB("APT::Get::Compile",false) == true)
{
buildopts.append(_config->Find("DPkg::Build-Options","-b -uc"));
// Call dpkg-buildpackage
- char S[500];
- snprintf(S,sizeof(S),"cd %s && %s %s",
+ std::string S;
+ strprintf(S, "cd %s && %s %s",
Dir.c_str(),
_config->Find("Dir::Bin::dpkg-buildpackage","dpkg-buildpackage").c_str(),
buildopts.c_str());
-
- if (system(S) != 0)
+
+ if (system(S.c_str()) != 0)
{
- fprintf(stderr,_("Build command '%s' failed.\n"),S);
+ fprintf(stderr, _("Build command '%s' failed.\n"), S.c_str());
_exit(1);
- }
- }
+ }
+ }
}
-
- _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");
+ _exit(0);
}
- 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 /*{{{*/
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)
pkgSourceList *List = Cache.GetSourceList();
// Create the text record parsers
- pkgRecords Recs(Cache);
pkgSrcRecords SrcRecs(*List);
if (_error->PendingError() == true)
return false;
- // Create the download object
- AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
- pkgAcquire Fetcher;
- if (Fetcher.Setup(&Stat) == false)
- return false;
-
bool StripMultiArch;
string hostArch = _config->Find("APT::Get::Host-Architecture");
if (hostArch.empty() == false)
for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
{
string Src;
- pkgSrcRecords::Parser *Last = FindSrc(*I,Recs,SrcRecs,Src,Cache);
+ pkgSrcRecords::Parser *Last = 0;
+ std::unique_ptr<pkgSrcRecords::Parser> LastOwner;
+
+ // an unpacked debian source tree
+ using APT::String::Startswith;
+ if ((Startswith(*I, "./") || Startswith(*I, "/")) &&
+ DirectoryExists(*I))
+ {
+ 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";
+ pkgIndexFile::Type *Type = pkgIndexFile::Type::GetType(TypeName.c_str());
+ if(Type != NULL)
+ LastOwner.reset(Last = Type->CreateSrcPkgParser(*I));
+ }
+ // if its a local file (e.g. .dsc) use this
+ else if (FileExists(*I))
+ {
+ 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 = "Debian " + flExtension(*I) + " file";
+ pkgIndexFile::Type *Type = pkgIndexFile::Type::GetType(TypeName.c_str());
+ if(Type != NULL)
+ LastOwner.reset(Last = Type->CreateSrcPkgParser(*I));
+ } else {
+ // normal case, search the cache for the source file
+ Last = FindSrc(*I,SrcRecs,Src,Cache);
+ }
+
if (Last == 0)
return _error->Error(_("Unable to find a source package for %s"),Src.c_str());
}
else if (Last->BuildDepends(BuildDeps, _config->FindB("APT::Get::Arch-Only", false), StripMultiArch) == false)
return _error->Error(_("Unable to get build-dependency information for %s"),Src.c_str());
-
+
// Also ensure that build-essential packages are present
Configuration::Item const *Opts = _config->Tree("APT::Build-Essential");
if (Opts)
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");
}
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::PkgIterator Pkg,
- pkgCache::VerIterator Ver)
-{
- string path;
-
- pkgRecords Recs(Cache);
- pkgRecords::Parser &rec=Recs.Lookup(Ver.FileList());
- string srcpkg = rec.SourcePkg().empty() ? Pkg.Name() : rec.SourcePkg();
- string ver = Ver.VerStr();
- // if there is a source version it always wins
- if (rec.SourceVer() != "")
- ver = rec.SourceVer();
- path = flNotFile(rec.FileName());
- path += srcpkg + "_" + StripEpoch(ver);
- 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::PkgIterator Pkg,
- 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, Pkg, 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)
- */
-{
- string path;
- string descr;
- string server;
- string changelog_uri;
-
- // data structures we need
- pkgCache::PkgIterator Pkg = Ver.ParentPkg();
-
- // make the server root configurable
- server = _config->Find("Apt::Changelogs::Server",
- "http://packages.debian.org/changelogs");
- path = GetChangelogPath(CacheFile, Pkg, Ver);
- 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);
}
- strprintf(descr, _("Changelog for %s (%s)"), Pkg.Name(), changelog_uri.c_str());
- // queue it
- new pkgAcqFile(&Fetcher, changelog_uri, "", 0, descr, Pkg.Name(), "ignored", targetfile);
+ 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 (!FileExists(targetfile))
+ if (downOnly == false || printOnly == true)
{
- string third_party_uri;
- if (GuessThirdPartyChangelogUri(CacheFile, Pkg, 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());
- 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 (FileExists(targetfile))
- 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::VersionList::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.Setup(&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::vector<IndexTarget> const targets = (*S)->GetIndexTargets();
+ std::map<std::string, string> AddOptions;
+ if (ReleaseInfo)
+ {
+ 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<IndexTarget>::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<std::string,std::string>::const_iterator O = AddOptions.begin(); O != AddOptions.end(); ++O)
+ stanza << format_key(O->first) << ": " << O->second << "\n";
+ for (std::map<std::string,std::string>::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<std::string,std::string>::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 &)
+bool ShowHelp(CommandLine &, aptDispatchWithHelp 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];
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++)
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"
return true;
}
/*}}}*/
+std::vector<aptDispatchWithHelp> GetCommands() /*{{{*/
+{
+ return {
+ {"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}
+ };
+}
+ /*}}}*/
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<CommandLine::Args> Args = getCommandArgs("apt-get", CommandLine::GetCommand(Cmds, argc, argv));
-
- // Set up gettext support
- setlocale(LC_ALL,"");
- textdomain(PACKAGE);
+ InitLocale();
// 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;
+ auto const Cmds = ParseCommandLine(CmdL, APT_CMD::APT_GET, &_config, &_system, argc, argv);
- // 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);
}
/*}}}*/