From 8881b11eacd735148d087c8c0f53827cb537b582 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 11 Jun 2015 16:40:45 +0200 Subject: implement 'apt-get files' to access index targets Downloading additional files is only half the job. We still need a way to allow external tools to know where the files are they requested for download given that we don't want them to choose their own location. 'apt-get files' is our answer to this showing by default in a deb822 format information about each IndexTarget with the potential to filter the records based on lines and an option to change the output format. The command serves also as an example on how to get to this information via libapt. --- doc/apt-get.8.xml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'doc/apt-get.8.xml') diff --git a/doc/apt-get.8.xml b/doc/apt-get.8.xml index a372a0d30..da077afa7 100644 --- a/doc/apt-get.8.xml +++ b/doc/apt-get.8.xml @@ -243,6 +243,21 @@ + + Displays by default a deb822 formatted listing of + information about all data files apt-get + update would download. Supports a + option to modify the output format as + well as accepts lines of the default output to filter the records + by. The command is mainly used as an interface for external tools + working with APT to get information as well as filenames for + downloaded files so they can use them as well instead of + downloading them again on their own. Detailed documentation is + omitted here and can instead be found in the source tree in + doc/acquire-additional-files.txt. + + + -- cgit v1.2.3-70-g09d2 From d56e2917f27a722b54685de13aeb1bb7592fc61b Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 13 Jun 2015 11:13:45 +0200 Subject: provide a public interface for acquiring changelogs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Provided is a specialized acquire item which given a version can figure out the correct URI to try by itself and if not provides an error message alongside with static methods to get just the URI it would try to download if it should just be displayed or similar such. The URI is constructed as follows: Release files can provide an URI template in the "Changelogs" field, otherwise we lookup a configuration item based on the "Label" or "Origin" of the Release file to get a (hopefully known) default value for now. This template should contain the string CHANGEPATH which is replaced with the information about the version we want the changelog for (e.g. main/a/apt/apt_1.1). This middleway was choosen as this path part was consistent over the three known implementations (+1 defunct), while the rest of the URI varies widely between them. The benefit of this construct is that it is now easy to get changelogs for Debian packages on Ubuntu and vice versa – even at the moment where the Changelogs field is present nowhere. Strictly better than what apt-get had before as it would even fail to get changelogs from security… Now it will notice that security identifies as Origin: Debian and pick this setting (assuming again that no Changelogs field exists). If on the other hand security would ship its changelogs in a different location we could set it via the Label option overruling Origin. Closes: 687147, 739854, 784027, 787190 --- apt-pkg/acquire-item.cc | 211 +++++++++++++++++++++ apt-pkg/acquire-item.h | 114 +++++++++++ apt-pkg/init.cc | 4 + cmdline/apt-get.cc | 204 ++++---------------- doc/apt-get.8.xml | 16 +- doc/apt.conf.5.xml | 27 +++ doc/examples/configure-index | 11 +- test/integration/framework | 24 ++- test/integration/test-apt-get-changelog | 104 +++++++--- .../test-bug-722207-print-uris-even-if-very-quiet | 3 +- test/integration/test-bug-738785-switch-protocol | 7 +- vendor/ubuntu/apt.conf-01-vendor-ubuntu | 6 - 12 files changed, 507 insertions(+), 224 deletions(-) (limited to 'doc/apt-get.8.xml') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index d6e9ccbe0..4bf4e62f8 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -2836,6 +2837,216 @@ std::string pkgAcqArchive::ShortDesc() const /*{{{*/ } /*}}}*/ +// AcqChangelog::pkgAcqChangelog - Constructors /*{{{*/ +pkgAcqChangelog::pkgAcqChangelog(pkgAcquire * const Owner, pkgCache::VerIterator const &Ver, + std::string const &DestDir, std::string const &DestFilename) : + pkgAcquire::Item(Owner), d(NULL), SrcName(Ver.SourcePkgName()), SrcVersion(Ver.SourceVerStr()) +{ + Desc.URI = URI(Ver); + Init(DestDir, DestFilename); +} +// some parameters are char* here as they come likely from char* interfaces – which can also return NULL +pkgAcqChangelog::pkgAcqChangelog(pkgAcquire * const Owner, pkgCache::RlsFileIterator const &RlsFile, + char const * const Component, char const * const SrcName, char const * const SrcVersion, + const string &DestDir, const string &DestFilename) : + pkgAcquire::Item(Owner), d(NULL), SrcName(SrcName), SrcVersion(SrcVersion) +{ + Desc.URI = URI(RlsFile, Component, SrcName, SrcVersion); + Init(DestDir, DestFilename); +} +pkgAcqChangelog::pkgAcqChangelog(pkgAcquire * const Owner, + std::string const &URI, char const * const SrcName, char const * const SrcVersion, + const string &DestDir, const string &DestFilename) : + pkgAcquire::Item(Owner), d(NULL), SrcName(SrcName), SrcVersion(SrcVersion) +{ + Desc.URI = URI; + Init(DestDir, DestFilename); +} +void pkgAcqChangelog::Init(std::string const &DestDir, std::string const &DestFilename) +{ + if (Desc.URI.empty()) + { + Status = StatError; + // TRANSLATOR: %s=%s is sourcename=sourceversion, e.g. apt=1.1 + strprintf(ErrorText, _("Changelog unavailable for %s=%s"), SrcName.c_str(), SrcVersion.c_str()); + // Let the error message print something sensible rather than "Failed to fetch /" + if (DestFilename.empty()) + DestFile = SrcName + ".changelog"; + else + DestFile = DestFilename; + Desc.URI = "changelog:/" + DestFile; + return; + } + + if (DestDir.empty()) + { + std::string const systemTemp = GetTempDir(); + char tmpname[100]; + snprintf(tmpname, sizeof(tmpname), "%s/apt-changelog-XXXXXX", systemTemp.c_str()); + if (NULL == mkdtemp(tmpname)) + { + _error->Errno("mkdtemp", "mkdtemp failed in changelog acquire of %s %s", SrcName.c_str(), SrcVersion.c_str()); + Status = StatError; + return; + } + DestFile = TemporaryDirectory = tmpname; + } + else + DestFile = DestDir; + + if (DestFilename.empty()) + DestFile = flCombine(DestFile, SrcName + ".changelog"); + else + DestFile = flCombine(DestFile, DestFilename); + + Desc.ShortDesc = "Changelog"; + strprintf(Desc.Description, "%s %s %s Changelog", URI::SiteOnly(Desc.URI).c_str(), SrcName.c_str(), SrcVersion.c_str()); + Desc.Owner = this; + QueueURI(Desc); + + if (Status == StatDone) // this happens if we queue the same changelog two times + { + Complete = true; + for (pkgAcquire::UriIterator I = Owner->UriBegin(); I != Owner->UriEnd(); ++I) + if (I->URI == Desc.URI) + if (DestFile != I->Owner->DestFile) + if (symlink(I->Owner->DestFile.c_str(), DestFile.c_str()) != 0) + { + ; // ignore error, there isn't anthing we could do to handle the edgecase of an edgecase + } + } +} + /*}}}*/ +std::string pkgAcqChangelog::URI(pkgCache::VerIterator const &Ver) /*{{{*/ +{ + char const * const SrcName = Ver.SourcePkgName(); + char const * const SrcVersion = Ver.SourceVerStr(); + pkgCache::PkgFileIterator PkgFile; + // find the first source for this version which promises a changelog + for (pkgCache::VerFileIterator VF = Ver.FileList(); VF.end() == false; ++VF) + { + pkgCache::PkgFileIterator const PF = VF.File(); + if (PF.Flagged(pkgCache::Flag::NotSource) || PF->Release == 0) + continue; + PkgFile = PF; + pkgCache::RlsFileIterator const RF = PF.ReleaseFile(); + std::string const uri = URI(RF, PF.Component(), SrcName, SrcVersion); + if (uri.empty()) + continue; + return uri; + } + return ""; +} +std::string pkgAcqChangelog::URITemplate(pkgCache::RlsFileIterator const &Rls) +{ + if (Rls.end() == true || (Rls->Label == 0 && Rls->Origin == 0)) + return ""; + std::string const serverConfig = "Acquire::Changelogs::URI"; + std::string server; +#define APT_EMPTY_SERVER \ + if (server.empty() == false) \ + { \ + if (server != "no") \ + return server; \ + return ""; \ + } +#define APT_CHECK_SERVER(X, Y) \ + if (Rls->X != 0) \ + { \ + std::string const specialServerConfig = serverConfig + "::" + Y + #X + "::" + Rls.X(); \ + server = _config->Find(specialServerConfig); \ + APT_EMPTY_SERVER \ + } + // this way e.g. Debian-Security can fallback to Debian + APT_CHECK_SERVER(Label, "Override::") + APT_CHECK_SERVER(Origin, "Override::") + + if (RealFileExists(Rls.FileName())) + { + _error->PushToStack(); + FileFd rf; + /* This can be costly. A caller wanting to get millions of URIs might + want to do this on its own once and use Override settings. + We don't do this here as Origin/Label are not as unique as they + should be so this could produce request order-dependent anomalies */ + if (OpenMaybeClearSignedFile(Rls.FileName(), rf) == true) + { + pkgTagFile TagFile(&rf, rf.Size()); + pkgTagSection Section; + if (TagFile.Step(Section) == true) + server = Section.FindS("Changelogs"); + } + _error->RevertToStack(); + APT_EMPTY_SERVER + } + + APT_CHECK_SERVER(Label, "") + APT_CHECK_SERVER(Origin, "") +#undef APT_CHECK_SERVER +#undef APT_EMPTY_SERVER + return ""; +} +std::string pkgAcqChangelog::URI(pkgCache::RlsFileIterator const &Rls, + char const * const Component, char const * const SrcName, + char const * const SrcVersion) +{ + return URI(URITemplate(Rls), Component, SrcName, SrcVersion); +} +std::string pkgAcqChangelog::URI(std::string const &Template, + char const * const Component, char const * const SrcName, + char const * const SrcVersion) +{ + if (Template.find("CHANGEPATH") == std::string::npos) + return ""; + + // the path is: COMPONENT/SRC/SRCNAME/SRCNAME_SRCVER, e.g. main/a/apt/1.1 or contrib/liba/libapt/2.0 + std::string Src = SrcName; + std::string path = APT::String::Startswith(SrcName, "lib") ? Src.substr(0, 4) : Src.substr(0,1); + path.append("/").append(Src).append("/"); + path.append(Src).append("_").append(StripEpoch(SrcVersion)); + // we omit component for releases without one (= flat-style repositories) + if (Component != NULL && strlen(Component) != 0) + path = std::string(Component) + "/" + path; + + return SubstVar(Template, "CHANGEPATH", path); +} + /*}}}*/ +// AcqChangelog::Failed - Failure handler /*{{{*/ +void pkgAcqChangelog::Failed(string const &Message, pkgAcquire::MethodConfig const * const Cnf) +{ + Item::Failed(Message,Cnf); + + std::string errText; + // TRANSLATOR: %s=%s is sourcename=sourceversion, e.g. apt=1.1 + strprintf(errText, _("Changelog unavailable for %s=%s"), SrcName.c_str(), SrcVersion.c_str()); + + // Error is probably something techy like 404 Not Found + if (ErrorText.empty()) + ErrorText = errText; + else + ErrorText = errText + " (" + ErrorText + ")"; + return; +} + /*}}}*/ +// AcqChangelog::Done - Item downloaded OK /*{{{*/ +void pkgAcqChangelog::Done(string const &Message,HashStringList const &CalcHashes, + pkgAcquire::MethodConfig const * const Cnf) +{ + Item::Done(Message,CalcHashes,Cnf); + + Complete = true; +} + /*}}}*/ +pkgAcqChangelog::~pkgAcqChangelog() /*{{{*/ +{ + if (TemporaryDirectory.empty() == false) + { + unlink(DestFile.c_str()); + rmdir(TemporaryDirectory.c_str()); + } +} + /*}}}*/ + // AcqFile::pkgAcqFile - Constructor /*{{{*/ pkgAcqFile::pkgAcqFile(pkgAcquire * const Owner,string const &URI, HashStringList const &Hashes, unsigned long long const Size,string const &Dsc,string const &ShortDesc, diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index b6d569737..606fd4173 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -1031,6 +1031,120 @@ class pkgAcqArchive : public pkgAcquire::Item std::string &StoreFilename); }; /*}}}*/ +/** \brief Retrieve the changelog for the given version {{{ + * + * Downloads the changelog to a temporary file it will also remove again + * while it is deconstructed or downloads it to a named location. + */ +class pkgAcqChangelog : public pkgAcquire::Item +{ + void *d; + std::string TemporaryDirectory; + std::string const SrcName; + std::string const SrcVersion; + + public: + // we will never have hashes for changelogs. + // If you need verified ones, download the deb and extract the changelog. + virtual HashStringList GetExpectedHashes() const { return HashStringList(); } + virtual bool HashesRequired() const { return false; } + + // Specialized action members + virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf); + virtual void Done(std::string const &Message, HashStringList const &CalcHashes, + pkgAcquire::MethodConfig const * const Cnf); + virtual std::string DescURI() const {return Desc.URI;}; + + /** returns the URI to the changelog of this version + * + * @param Ver is the version to get the changelog for + * @return the URI which will be used to acquire the changelog + */ + static std::string URI(pkgCache::VerIterator const &Ver); + + /** returns the URI to the changelog of this version + * + * \param Rls is the Release file the package comes from + * \param Component in which the package resides, can be empty + * \param SrcName is the source package name + * \param SrcVersion is the source package version + * @return the URI which will be used to acquire the changelog + */ + static std::string URI(pkgCache::RlsFileIterator const &Rls, + char const * const Component, char const * const SrcName, + char const * const SrcVersion); + + /** returns the URI to the changelog of this version + * + * \param Template URI where CHANGEPATH has to be filled in + * \param Component in which the package resides, can be empty + * \param SrcName is the source package name + * \param SrcVersion is the source package version + * @return the URI which will be used to acquire the changelog + */ + static std::string URI(std::string const &Template, + char const * const Component, char const * const SrcName, + char const * const SrcVersion); + + /** returns the URI template for this release file + * + * \param Rls is a Release file + * @return the URI template to use for this release file + */ + static std::string URITemplate(pkgCache::RlsFileIterator const &Rls); + + /** \brief Create a new pkgAcqChangelog object. + * + * \param Owner The pkgAcquire object with which this object is + * associated. + * \param Ver is the version to get the changelog for + * \param DestDir The directory the file should be downloaded into. + * Will be an autocreated (and cleaned up) temporary directory if not set. + * \param DestFilename The filename the file should have in #DestDir + * Defaults to sourcepackagename.changelog if not set. + */ + pkgAcqChangelog(pkgAcquire * const Owner, pkgCache::VerIterator const &Ver, + std::string const &DestDir="", std::string const &DestFilename=""); + + /** \brief Create a new pkgAcqChangelog object. + * + * \param Owner The pkgAcquire object with which this object is + * associated. + * \param Rls is the Release file the package comes from + * \param Component in which the package resides, can be empty + * \param SrcName is the source package name + * \param SrcVersion is the source package version + * \param DestDir The directory the file should be downloaded into. + * Will be an autocreated (and cleaned up) temporary directory if not set. + * \param DestFilename The filename the file should have in #DestDir + * Defaults to sourcepackagename.changelog if not set. + */ + pkgAcqChangelog(pkgAcquire * const Owner, pkgCache::RlsFileIterator const &Rls, + char const * const Component, char const * const SrcName, char const * const SrcVersion, + std::string const &DestDir="", std::string const &DestFilename=""); + + /** \brief Create a new pkgAcqChangelog object. + * + * \param Owner The pkgAcquire object with which this object is + * associated. + * \param URI is to be used to get the changelog + * \param SrcName is the source package name + * \param SrcVersion is the source package version + * \param DestDir The directory the file should be downloaded into. + * Will be an autocreated (and cleaned up) temporary directory if not set. + * \param DestFilename The filename the file should have in #DestDir + * Defaults to sourcepackagename.changelog if not set. + */ + pkgAcqChangelog(pkgAcquire * const Owner, std::string const &URI, + char const * const SrcName, char const * const SrcVersion, + std::string const &DestDir="", std::string const &DestFilename=""); + + virtual ~pkgAcqChangelog(); + +private: + APT_HIDDEN void Init(std::string const &DestDir, std::string const &DestFilename); +}; + /*}}}*/ /** \brief Retrieve an arbitrary file to the current directory. {{{ * * The file is retrieved even if it is accessed via a URL type that diff --git a/apt-pkg/init.cc b/apt-pkg/init.cc index e2239a906..96966b249 100644 --- a/apt-pkg/init.cc +++ b/apt-pkg/init.cc @@ -119,6 +119,10 @@ bool pkgInitConfig(Configuration &Cnf) Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::flatDescription", "$(SITE) $(RELEASE) Sources"); Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::Optional", false); + Cnf.CndSet("Acquire::Changelogs::URI::Origin::Debian", "http://metadata.ftp-master.debian.org/changelogs/CHANGEPATH_changelog"); + Cnf.CndSet("Acquire::Changelogs::URI::Origin::Ubuntu", "http://changelogs.ubuntu.com/changelogs/pool/CHANGEPATH/changelog"); + Cnf.CndSet("Acquire::Changelogs::URI::Origin::Ultimedia", "http://packages.ultimediaos.com/changelogs/pool/CHANGEPATH/changelog.txt"); + bool Res = true; // Read an alternate config file diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index a4cd3c377..184b51d23 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -1410,196 +1410,70 @@ 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()); -#if APT_PKG_ABI >= 413 - path.append(Ver.SourcePkgName()); - path.append("_"); - path.append(StripEpoch(Ver.SourceVerStr())); -#else - string srcpkg = rec.SourcePkg().empty() ? Ver.ParentPkg().Name() : rec.SourcePkg(); - string ver = Ver.VerStr(); - // if there is a source version it always wins - if (rec.SourceVer() != "") - ver = rec.SourceVer(); - path += srcpkg + "_" + StripEpoch(ver); -#endif - 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) -{ - // get the binary deb server path - pkgCache::VerFileIterator Vf = Ver.FileList(); - if (Vf.end() == true) - return false; - pkgCache::PkgFileIterator F = Vf.File(); - pkgIndexFile *index; - pkgSourceList *SrcList = Cache.GetSourceList(); - if(SrcList->FindIndex(F, index) == false) - 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"); - - // 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) - { - std::cout << '\'' << changelog_uri << '\'' << std::endl; - return true; - } - 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); - - // 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) - { - string third_party_uri; - if (GuessThirdPartyChangelogUri(CacheFile, Ver, third_party_uri)) - { - 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 (itm->Status == pkgAcquire::Item::StatDone) - return true; - - // error - return _error->Error("changelog download failed"); -} - /*}}}*/ // DoChangelog - Get changelog from the command line /*{{{*/ -// --------------------------------------------------------------------- static bool DoChangelog(CommandLine &CmdL) { CacheFile Cache; if (Cache.ReadOnlyOpen() == false) return false; - + APT::CacheSetHelper helper; APT::VersionList verset = APT::VersionList::FromCommandLine(Cache, CmdL.FileList + 1, APT::CacheSetHelper::CANDIDATE, helper); if (verset.empty() == true) return false; pkgAcquire Fetcher; + AcqTextStatus Stat(std::cout, ScreenWidth,_config->FindI("quiet",0)); + Fetcher.SetLog(&Stat); - if (_config->FindB("APT::Get::Print-URIs", false) == true) + bool const downOnly = _config->FindB("APT::Get::Download-Only", false); + bool const printOnly = _config->FindB("APT::Get::Print-URIs", false); + + for (APT::VersionList::const_iterator Ver = verset.begin(); + Ver != verset.end(); + ++Ver) { - bool Success = true; - for (APT::VersionList::const_iterator Ver = verset.begin(); - Ver != verset.end(); ++Ver) - Success &= DownloadChangelog(Cache, Fetcher, Ver, ""); - return Success; + if (printOnly) + new pkgAcqChangelog(&Fetcher, Ver, "/dev/null"); + else if (downOnly) + new pkgAcqChangelog(&Fetcher, Ver, "."); + else + new pkgAcqChangelog(&Fetcher, Ver); } - AcqTextStatus Stat(std::cout, ScreenWidth,_config->FindI("quiet",0)); - Fetcher.SetLog(&Stat); + if (printOnly == false) + { + // Disable drop-privs if "_apt" can not write to the target dir + CheckDropPrivsMustBeDisabled(Fetcher); + if (_error->PendingError() == true) + return false; - bool const downOnly = _config->FindB("APT::Get::Download-Only", false); + bool Failed = false; + if (AcquireRun(Fetcher, 0, &Failed, NULL) == false || Failed == true) + return false; + } - char tmpname[100]; - const char* tmpdir = NULL; - if (downOnly == false) + if (downOnly == false || printOnly == true) { - 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 + bool Failed = false; + for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); ++I) { - struct passwd const * const pw = getpwnam(SandboxUser.c_str()); - struct group const * const gr = getgrnam("root"); - if (pw != NULL && gr != NULL) + if (printOnly) { - // 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); + 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; } - 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) - { - DisplayFileInPager(changelogfile); - // cleanup temp file - unlink(changelogfile.c_str()); - } - } - // clenaup tmp dir - if (tmpdir != NULL) - rmdir(tmpdir); return true; } /*}}}*/ diff --git a/doc/apt-get.8.xml b/doc/apt-get.8.xml index da077afa7..5b6788ed4 100644 --- a/doc/apt-get.8.xml +++ b/doc/apt-get.8.xml @@ -230,16 +230,12 @@ - changelog downloads a package changelog and displays - it through sensible-pager. The server name and base - directory is defined in the APT::Changelogs::Server - variable (e.g. packages.debian.org/changelogs for - Debian or changelogs.ubuntu.com/changelogs for - Ubuntu). - By default it displays the changelog for the version that is - installed. However, you can specify the same options as for - the command. - + changelog tries to download the + changelog of a package and displays it through + sensible-pager. By default it + displays the changelog for the version that is installed. + However, you can specify the same options as for the + command. diff --git a/doc/apt.conf.5.xml b/doc/apt.conf.5.xml index efe986ea8..7d5f7e9b3 100644 --- a/doc/apt.conf.5.xml +++ b/doc/apt.conf.5.xml @@ -618,6 +618,33 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";}; + scope + + Acquiring changelogs can only be done if an URI is known from where to get them. + Preferable the Release file indicates this in a 'Changelogs' field. If this isn't + available the Label/Origin field of the Release file is used to check if a + Acquire::Changelogs::URI::Label::LABEL or + Acquire::Changelogs::URI::Origin::ORIGIN option + exists and if so this value is taken. The value in the Release file can be overridden + with Acquire::Changelogs::URI::Override::Label::LABEL + or Acquire::Changelogs::URI::Override::Origin::ORIGIN. + + The value should be a normal URI to a text file, expect that package specific data is + replaced with the placeholder CHANGEPATH. The + value for it is: 1. if the package is from a component (e.g. main) + this is the first part otherwise it is omitted, 2. the first letter of source package name, + expect if the source package name starts with 'lib' in which case it will + be the first four letters. 3. The complete source package name. 4. the complete name again and + 5. the source version. + The first (if present), second, third and fourth part are separated by a slash ('/') + and between the fourth and fifth part is an underscore ('_'). + + The special value 'no' is available for this option indicating that + this source can't be used to acquire changelog files from. Another source will be tried + if available in this case. + + + diff --git a/doc/examples/configure-index b/doc/examples/configure-index index ef1ae056d..1339335fa 100644 --- a/doc/examples/configure-index +++ b/doc/examples/configure-index @@ -117,14 +117,6 @@ APT // does a ExecFork) Keep-Fds {}; - Changelogs - { - // server the provides the changelogs, the code will assume - // the changlogs are in the pool/ under a srcpkg_ver directory - // with the name "changelog" - Server "http://packages.debian.org/changelogs"; - }: - // control parameters for cron jobs by /etc/cron.daily/apt Periodic { @@ -305,6 +297,9 @@ Acquire "none"; "fr"; }; + + // Location of the changelogs with the placeholder CHANGEPATH (e.g. "main/a/apt/apt_1.1") + Changelogs::URI::Origin::Debian "http://metadata.ftp-master.debian.org/changelogs/CHANGEPATH_changelog"; }; // Directory layout diff --git a/test/integration/framework b/test/integration/framework index 7b03c09ef..1b99929e2 100644 --- a/test/integration/framework +++ b/test/integration/framework @@ -520,6 +520,12 @@ Package: $NAME" > debian/control buildsimplenativepackage() { local NAME="$1" + local NM + if [ "$(echo "$NAME" | cut -c 1-3)" = 'lib' ]; then + NM="$(echo "$NAME" | cut -c 1-4)" + else + NM="$(echo "$NAME" | cut -c 1)" + fi local ARCH="$2" local VERSION="$3" local RELEASE="${4:-unstable}" @@ -600,15 +606,15 @@ Package: $NAME" >> ${BUILDDIR}/debian/control (cd ${BUILDDIR}; dpkg-gencontrol -DArchitecture=$arch) (cd ${BUILDDIR}/debian/tmp; md5sum $(find usr/ -type f) > DEBIAN/md5sums) local LOG="${BUILDDIR}/../${NAME}_${VERSION}_${arch}.dpkg-deb.log" - # ensure the right permissions as dpkg-deb ensists + # ensure the right permissions as dpkg-deb insists chmod 755 ${BUILDDIR}/debian/tmp/DEBIAN testsuccess --nomsg dpkg-deb -Z${COMPRESS_TYPE} --build ${BUILDDIR}/debian/tmp ${BUILDDIR}/.. echo "pool/${NAME}_${VERSION}_${arch}.deb" >> ${BUILDDIR}/../${RELEASE}.${DISTSECTION}.pkglist done - mkdir -p ${BUILDDIR}/../${NAME}_${VERSION} - cp ${BUILDDIR}/debian/changelog ${BUILDDIR}/../${NAME}_${VERSION}/ - cp ${BUILDDIR}/debian/changelog ${BUILDDIR}/../${NAME}_${VERSION}.changelog + local CHANGEPATH="${BUILDDIR}/../${DISTSECTION}/${NM}/${NAME}/${NAME}_${VERSION}" + mkdir -p $CHANGEPATH + cp ${BUILDDIR}/debian/changelog $CHANGEPATH rm -rf "${BUILDDIR}" msgdone "info" } @@ -876,6 +882,7 @@ getcodenamefromsuite() { } getreleaseversionfromsuite() { true; } getlabelfromsuite() { true; } +getoriginfromsuite() { true; } generatereleasefiles() { # $1 is the Date header and $2 is the ValidUntil header to be set @@ -887,16 +894,21 @@ generatereleasefiles() { local CODENAME="$(getcodenamefromsuite $SUITE)" local VERSION="$(getreleaseversionfromsuite $SUITE)" local LABEL="$(getlabelfromsuite $SUITE)" + local ORIGIN="$(getoriginfromsuite $SUITE)" if [ -n "$VERSION" ]; then VERSION="-o APT::FTPArchive::Release::Version=${VERSION}" fi if [ -n "$LABEL" ]; then LABEL="-o APT::FTPArchive::Release::Label=${LABEL}" fi + if [ -n "$ORIGIN" ]; then + ORIGIN="-o APT::FTPArchive::Release::Origin=${ORIGIN}" + fi aptftparchive -qq release $dir \ -o APT::FTPArchive::Release::Suite="${SUITE}" \ -o APT::FTPArchive::Release::Codename="${CODENAME}" \ ${LABEL} \ + ${ORIGIN} \ ${VERSION} \ | sed -e '/0 Release$/ d' > $dir/Release # remove the self reference if [ "$SUITE" = "experimental" -o "$SUITE" = "experimental2" ]; then @@ -1450,9 +1462,9 @@ testfilestats() { msgpass else echo >&2 - ls -ld >&2 "$1" + ls -ld >&2 "$1" || true echo -n >&2 "stat(1) reports for $2: " - stat --format "$2" "$1" + stat --format "$2" "$1" || true msgfail fi } diff --git a/test/integration/test-apt-get-changelog b/test/integration/test-apt-get-changelog index 7e81c71b6..5fa8543b9 100755 --- a/test/integration/test-apt-get-changelog +++ b/test/integration/test-apt-get-changelog @@ -5,44 +5,98 @@ TESTDIR=$(readlink -f $(dirname $0)) . $TESTDIR/framework setupenvironment -configarchitecture "i386" +configarchitecture 'native' -buildsimplenativepackage 'apt' 'all' '1.0' 'stable' +buildsimplenativepackage 'foo' 'all' '1.0' 'stable' +buildsimplenativepackage 'libbar' 'all' '1.0' 'stable' + +getlabelfromsuite() { echo 'Testcases'; } +getoriginfromsuite() { echo 'Debian'; } setupaptarchive --no-update changetowebserver testsuccess aptget update -# simulate normal user with non-existent root-owned directories -rm -rf rootdir/var/cache/apt/archives/ -mkdir rootdir/var/cache/apt/archives/ -addtrap 'prefix' "chmod -f -R +w $PWD/rootdir/var/cache/apt/archives || true;" -chmod -R -w rootdir/var/cache/apt/archives +testsuccessequal "'http://metadata.ftp-master.debian.org/changelogs/main/f/foo/foo_1.0_changelog' foo.changelog +'http://metadata.ftp-master.debian.org/changelogs/main/libb/libbar/libbar_1.0_changelog' libbar.changelog" aptget changelog foo libbar --print-uris + +releasechanger() { + # modifying the Release files in lists… bad stuff. Good that this is only a test… + sed -i "s#^${1}: .*#${1}: ${2}#" $(find rootdir/var/lib/apt/lists -name '*Release') + rm -f rootdir/var/cache/apt/*.bin +} +releasechanger 'Origin' 'Ubuntu' +testsuccessequal "'http://changelogs.ubuntu.com/changelogs/pool/main/f/foo/foo_1.0/changelog' foo.changelog +'http://changelogs.ubuntu.com/changelogs/pool/main/libb/libbar/libbar_1.0/changelog' libbar.changelog" aptget changelog foo libbar --print-uris + +releasechanger 'Label' 'Debian' +testsuccessequal "'http://changelogs.ubuntu.com/changelogs/pool/main/f/foo/foo_1.0/changelog' foo.changelog +'http://changelogs.ubuntu.com/changelogs/pool/main/libb/libbar/libbar_1.0/changelog' libbar.changelog" aptget changelog foo libbar --print-uris + +testsuccessequal "'http://localhost:8080/main/f/foo/foo_1.0.changelog' foo.changelog +'http://localhost:8080/main/libb/libbar/libbar_1.0.changelog' libbar.changelog" aptget changelog foo libbar --print-uris -o Acquire::Changelogs::URI::Label::Debian='http://localhost:8080/CHANGEPATH.changelog' + +sed -i '/^Origin: / a\ +Changelogs: http://example.org/CHANGEPATH-changelog' $(find rootdir/var/lib/apt/lists -name '*Release') +rm -f rootdir/var/cache/apt/*.bin -echo 'Apt::Changelogs::Server "http://localhost:8080/";' > rootdir/etc/apt/apt.conf.d/changelog.conf +testsuccessequal "'http://example.org/main/f/foo/foo_1.0-changelog' foo.changelog +'http://example.org/main/libb/libbar/libbar_1.0-changelog' libbar.changelog" aptget changelog foo libbar --print-uris -o Acquire::Changelogs::URI::Label::Debian='http://localhost:8080/CHANGEPATH.changelog' -testsuccessequal "'http://localhost:8080/pool/apt_1.0/changelog'" aptget changelog apt --print-uris +testsuccessequal "'http://localhost:8080/main/f/foo/foo_1.0.changelog' foo.changelog +'http://localhost:8080/main/libb/libbar/libbar_1.0.changelog' libbar.changelog" aptget changelog foo libbar --print-uris -o Acquire::Changelogs::URI::Override::Label::Debian='http://localhost:8080/CHANGEPATH.changelog' -testsuccessequal "'http://localhost:8080/pool/apt_1.0/changelog' -'http://localhost:8080/pool/apt_1.0/changelog'" aptget changelog apt apt --print-uris +releasechanger 'Changelogs' 'no' +testequal 'E: Failed to fetch changelog:/foo.changelog Changelog unavailable for foo=1.0 +' aptget changelog foo -qq -d + +sed -i '/^Changelogs: / d' $(find rootdir/var/lib/apt/lists -name '*Release') +releasechanger 'Label' 'Testcases' + +echo 'Acquire::Changelogs::URI::Label::Testcases "http://localhost:8080/CHANGEPATH/change.txt";' > rootdir/etc/apt/apt.conf.d/changelog.conf +testsuccessequal "'http://localhost:8080/main/f/foo/foo_1.0/change.txt' foo.changelog +'http://localhost:8080/main/libb/libbar/libbar_1.0/change.txt' libbar.changelog" aptget changelog foo libbar --print-uris + +echo 'Acquire::Changelogs::URI::Label::Testcases "http://localhost:8080/pool/CHANGEPATH/changelog";' > rootdir/etc/apt/apt.conf.d/changelog.conf +testsuccessequal "'http://localhost:8080/pool/main/f/foo/foo_1.0/changelog' foo.changelog" aptget changelog foo --print-uris cd downloaded -testsuccess aptget changelog apt -qq -testfileequal '../rootdir/tmp/testsuccess.output' "$(cat ../aptarchive/pool/apt_1.0/changelog)" +testsuccess aptget changelog foo -qq +testfileequal '../rootdir/tmp/testsuccess.output' "$(cat ../aptarchive/pool/main/f/foo/foo_1.0/changelog)" + +testsuccess aptget changelog foo libbar -qq +testfileequal '../rootdir/tmp/testsuccess.output' "$(cat ../aptarchive/pool/main/f/foo/foo_1.0/changelog) +$(cat ../aptarchive/pool/main/libb/libbar/libbar_1.0/changelog)" + +testsuccess aptget changelog foo -d +testfilestats 'foo.changelog' '%U:%G:%a' '=' "${TEST_DEFAULT_USER}:${TEST_DEFAULT_GROUP}:644" +testfileequal 'foo.changelog' "$(cat ../aptarchive/pool/main/f/foo/foo_1.0/changelog)" +rm -f foo.changelog -testsuccess aptget changelog apt -d -testfileequal 'apt.changelog' "$(cat ../aptarchive/pool/apt_1.0/changelog)" -testfilestats 'apt.changelog' '%U:%G:%a' '=' "${TEST_DEFAULT_USER}:${TEST_DEFAULT_GROUP}:644" -rm -f apt.changelog ../aptarchive/pool/apt_1.0/changelog +testsuccess aptget changelog libbar foo -d +testfilestats 'libbar.changelog' '%U:%G:%a' '=' "${TEST_DEFAULT_USER}:${TEST_DEFAULT_GROUP}:644" +testfilestats 'foo.changelog' '%U:%G:%a' '=' "${TEST_DEFAULT_USER}:${TEST_DEFAULT_GROUP}:644" +testfileequal 'libbar.changelog' "$(cat ../aptarchive/pool/main/libb/libbar/libbar_1.0/changelog)" +testfileequal 'foo.changelog' "$(cat ../aptarchive/pool/main/f/foo/foo_1.0/changelog)" +rm -f libbar.changelog foo.changelog -testequal "$(cat ../aptarchive/pool/apt_1.0.changelog)" aptget changelog apt \ - -qq -o APT::Changelogs::Server='http://not-on-the-main-server:8080/' +# as such bogus, but can happen with multiple binaries from the same source +testsuccessequal "'http://localhost:8080/pool/main/f/foo/foo_1.0/changelog' foo.changelog +'http://localhost:8080/pool/main/f/foo/foo_1.0/changelog' foo.changelog" aptget changelog foo foo --print-uris +testsuccess aptget changelog foo foo -qq +testfileequal '../rootdir/tmp/testsuccess.output' "$(cat ../aptarchive/pool/main/f/foo/foo_1.0/changelog) +$(cat ../aptarchive/pool/main/f/foo/foo_1.0/changelog)" +testsuccess aptget changelog foo foo -d +testfilestats 'foo.changelog' '%U:%G:%a' '=' "${TEST_DEFAULT_USER}:${TEST_DEFAULT_GROUP}:644" +testfileequal 'foo.changelog' "$(cat ../aptarchive/pool/main/f/foo/foo_1.0/changelog)" +rm -f foo.changelog -testsuccess aptget changelog apt -d -testfileequal 'apt.changelog' "$(cat ../aptarchive/pool/apt_1.0.changelog)" -testfilestats 'apt.changelog' '%U:%G:%a' '=' "${TEST_DEFAULT_USER}:${TEST_DEFAULT_GROUP}:644" -rm -f apt.changelog ../aptarchive/pool/apt_1.0.changelog +# no CHANGEPATH in the URI +testequal 'E: Failed to fetch changelog:/foo.changelog Changelog unavailable for foo=1.0 +' aptget changelog foo -qq -d -o Acquire::Changelogs::URI::Label::Testcases='http://localhost:8080/change.txt' +testfailure test -e foo.changelog -testequal 'E: changelog download failed' aptget changelog apt -qq -d -o APT::Changelogs::Server='http://not-on-the-main-server:8080/' -testfailure test -e apt.changelog +testequal 'E: Failed to fetch http://localhost:8080/does/not/exist/main/f/foo/foo_1.0/change.txt Changelog unavailable for foo=1.0 (404 Not Found) +' aptget changelog foo -qq -d -o Acquire::Changelogs::URI::Label::Testcases='http://localhost:8080/does/not/exist/CHANGEPATH/change.txt' +testfailure test -e foo.changelog diff --git a/test/integration/test-bug-722207-print-uris-even-if-very-quiet b/test/integration/test-bug-722207-print-uris-even-if-very-quiet index 2cad929cc..e51d72ccd 100755 --- a/test/integration/test-bug-722207-print-uris-even-if-very-quiet +++ b/test/integration/test-bug-722207-print-uris-even-if-very-quiet @@ -12,6 +12,7 @@ insertpackage 'unstable' 'apt' 'all' '2' insertsource 'unstable' 'apt' 'all' '2' insertsource 'unstable' 'apt2' 'all' '1' +getoriginfromsuite() { echo 'Debian'; } setupaptarchive APTARCHIVE=$(readlink -f ./aptarchive) @@ -22,7 +23,7 @@ testsuccessequal "'file://${APTARCHIVE}/pool/main/apt/apt_2_all.deb' apt_2_all.d testsuccessequal "'file://${APTARCHIVE}/pool/main/apt/apt_2_all.deb' apt_2_all.deb 0 " aptget download apt -qq --print-uris testsuccessequal "'file://${APTARCHIVE}/apt_2.dsc' apt_2.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e 'file://${APTARCHIVE}/apt_2.tar.gz' apt_2.tar.gz 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e" aptget source apt -qq --print-uris -testsuccessequal "'http://packages.debian.org/changelogs/pool/main/apt/apt_2/changelog'" aptget changelog apt -qq --print-uris +testsuccessequal "'http://metadata.ftp-master.debian.org/changelogs/main/a/apt/apt_2_changelog' apt.changelog" aptget changelog apt -qq --print-uris testsuccessequal "'file://${APTARCHIVE}/apt_2.dsc' apt_2.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e 'file://${APTARCHIVE}/apt_2.tar.gz' apt_2.tar.gz 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e diff --git a/test/integration/test-bug-738785-switch-protocol b/test/integration/test-bug-738785-switch-protocol index f6336ffe3..539080200 100755 --- a/test/integration/test-bug-738785-switch-protocol +++ b/test/integration/test-bug-738785-switch-protocol @@ -10,6 +10,7 @@ configarchitecture "i386" buildsimplenativepackage 'apt' 'all' '1.0' 'stable' # setup http redirecting to https +getlabelfromsuite() { echo 'Testcases'; } setupaptarchive --no-update changetowebserver -o 'aptwebserver::redirect::replace::/redirectme/=https://localhost:4433/' \ -o 'aptwebserver::redirect::replace::/downgrademe/=http://localhost:8080/' \ @@ -20,10 +21,10 @@ sed -i -e 's#:4433/#:8080/redirectme#' -e 's# https:# http:#' rootdir/etc/apt/so testsuccess aptget update -o Debug::Acquire::http=1 -o Debug::Acquire::https=1 -o Debug::pkgAcquire::Worker=1 msgtest 'Test that the webserver does not answer' 'http requests' -downloadfile 'http://localhost:8080/pool/apt_1.0/changelog' changelog >/dev/null 2>&1 && msgfail || msgpass +downloadfile 'http://localhost:8080/pool/main/a/apt/apt_1.0/changelog' changelog >/dev/null 2>&1 && msgfail || msgpass -echo 'Apt::Changelogs::Server "http://localhost:8080/redirectme";' > rootdir/etc/apt/apt.conf.d/changelog.conf -testsuccessequal "'http://localhost:8080/redirectme/pool/apt_1.0/changelog'" aptget changelog apt --print-uris +echo 'Acquire::Changelogs::URI::Label::Testcases "http://localhost:8080/redirectme/pool/CHANGEPATH/changelog";' > rootdir/etc/apt/apt.conf.d/changelog.conf +testsuccessequal "'http://localhost:8080/redirectme/pool/main/a/apt/apt_1.0/changelog' apt.changelog" aptget changelog apt --print-uris cd downloaded testsuccess aptget changelog apt -d diff --git a/vendor/ubuntu/apt.conf-01-vendor-ubuntu b/vendor/ubuntu/apt.conf-01-vendor-ubuntu index c4092ff44..e69de29bb 100644 --- a/vendor/ubuntu/apt.conf-01-vendor-ubuntu +++ b/vendor/ubuntu/apt.conf-01-vendor-ubuntu @@ -1,6 +0,0 @@ -// Server information for apt-changelog -APT { - Changelogs { - Server "http://changelogs.ubuntu.com/changelogs"; - }; -}; -- cgit v1.2.3-70-g09d2 From 0741daeb7ab870b4dd62a93fa12a1cf6330f9a72 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 23 Jun 2015 17:26:57 +0200 Subject: add sources.list Check-Valid-Until and Valid-Until-{Max,Min} options MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These options could be set via configuration before, but the connection to the actual sources is so strong that they should really be set in the sources.list instead – especially as this can be done a lot more specific rather than e.g. disabling Valid-Until for all sources at once. Valid-Until-* names are chosen instead of the Min/Max-ValidTime as this seems like a better name and their use in the wild is probably low enough that this isn't going to confuse anyone if we have to names for the same thing in different areas. In the longrun, the config options should be removed, but for now documentation hinting at the new options is good enough as these are the kind of options you set once across many systems with different apt versions, so the new way should work everywhere first before we deprecate the old way. --- apt-pkg/acquire-item.cc | 4 +- apt-pkg/deb/debmetaindex.cc | 134 ++++++++++++++++++-------- apt-pkg/deb/debmetaindex.h | 3 + apt-pkg/sourcelist.cc | 3 + doc/apt-get.8.xml | 10 +- doc/apt.conf.5.xml | 8 +- doc/sources.list.5.xml | 55 +++++++++-- test/integration/test-releasefile-valid-until | 9 ++ 8 files changed, 170 insertions(+), 56 deletions(-) (limited to 'doc/apt-get.8.xml') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 100199bc1..a30a5d154 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -1041,8 +1041,8 @@ bool pkgAcqMetaBase::VerifyVendor(string const &Message) /*{{{*/ Transformed = ""; } - if (_config->FindB("Acquire::Check-Valid-Until", true) == true && - TransactionManager->MetaIndexParser->GetValidUntil() > 0) { + if (TransactionManager->MetaIndexParser->GetValidUntil() > 0) + { time_t const invalid_since = time(NULL) - TransactionManager->MetaIndexParser->GetValidUntil(); if (invalid_since > 0) { diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index f0b859eb4..5d7e539c7 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -44,7 +44,11 @@ class APT_HIDDEN debReleaseIndexPrivate /*{{{*/ std::vector DebEntries; std::vector DebSrcEntries; - debReleaseIndexPrivate() {} + metaIndex::TriState CheckValidUntil; + time_t ValidUntilMin; + time_t ValidUntilMax; + + debReleaseIndexPrivate() : CheckValidUntil(metaIndex::TRI_UNSET), ValidUntilMin(0), ValidUntilMax(0) {} }; /*}}}*/ // ReleaseIndex::MetaIndex* - display helpers /*{{{*/ @@ -283,43 +287,56 @@ bool debReleaseIndex::Load(std::string const &Filename, std::string * const Erro return false; } - std::string const Label = Section.FindS("Label"); - std::string const StrValidUntil = Section.FindS("Valid-Until"); + bool CheckValidUntil = _config->FindB("Acquire::Check-Valid-Until", true); + if (d->CheckValidUntil == metaIndex::TRI_NO) + CheckValidUntil = false; + else if (d->CheckValidUntil == metaIndex::TRI_YES) + CheckValidUntil = true; - // if we have a Valid-Until header in the Release file, use it as default - if (StrValidUntil.empty() == false) + if (CheckValidUntil == true) { - if(RFC1123StrToTime(StrValidUntil.c_str(), ValidUntil) == false) + std::string const Label = Section.FindS("Label"); + std::string const StrValidUntil = Section.FindS("Valid-Until"); + + // if we have a Valid-Until header in the Release file, use it as default + if (StrValidUntil.empty() == false) { - if (ErrorText != NULL) - strprintf(*ErrorText, _("Invalid 'Valid-Until' entry in Release file %s"), Filename.c_str()); - return false; + if(RFC1123StrToTime(StrValidUntil.c_str(), ValidUntil) == false) + { + if (ErrorText != NULL) + strprintf(*ErrorText, _("Invalid 'Valid-Until' entry in Release file %s"), Filename.c_str()); + return false; + } + } + // get the user settings for this archive and use what expires earlier + time_t MaxAge = d->ValidUntilMax; + if (MaxAge == 0) + { + MaxAge = _config->FindI("Acquire::Max-ValidTime", 0); + if (Label.empty() == false) + MaxAge = _config->FindI(("Acquire::Max-ValidTime::" + Label).c_str(), MaxAge); + } + time_t MinAge = d->ValidUntilMin; + if (MinAge == 0) + { + MinAge = _config->FindI("Acquire::Min-ValidTime", 0); + if (Label.empty() == false) + MinAge = _config->FindI(("Acquire::Min-ValidTime::" + Label).c_str(), MinAge); } - } - // get the user settings for this archive and use what expires earlier - int MaxAge = _config->FindI("Acquire::Max-ValidTime", 0); - if (Label.empty() == false) - MaxAge = _config->FindI(("Acquire::Max-ValidTime::" + Label).c_str(), MaxAge); - int MinAge = _config->FindI("Acquire::Min-ValidTime", 0); - if (Label.empty() == false) - MinAge = _config->FindI(("Acquire::Min-ValidTime::" + Label).c_str(), MinAge); - - LoadedSuccessfully = TRI_YES; - if(MaxAge == 0 && - (MinAge == 0 || ValidUntil == 0)) // No user settings, use the one from the Release file - return true; - if (MinAge != 0 && ValidUntil != 0) { - time_t const min_date = Date + MinAge; - if (ValidUntil < min_date) - ValidUntil = min_date; - } - if (MaxAge != 0) { - time_t const max_date = Date + MaxAge; - if (ValidUntil == 0 || ValidUntil > max_date) - ValidUntil = max_date; + if (MinAge != 0 && ValidUntil != 0) { + time_t const min_date = Date + MinAge; + if (ValidUntil < min_date) + ValidUntil = min_date; + } + if (MaxAge != 0) { + time_t const max_date = Date + MaxAge; + if (ValidUntil == 0 || ValidUntil > max_date) + ValidUntil = max_date; + } } + LoadedSuccessfully = TRI_YES; return true; } /*}}}*/ @@ -411,7 +428,7 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll)/*{{{*/ return true; } /*}}}*/ -// ReleaseIndex::IsTrusted /*{{{*/ +// ReleaseIndex::Set* TriState options /*{{{*/ bool debReleaseIndex::SetTrusted(TriState const pTrusted) { if (Trusted == TRI_UNSET) @@ -421,6 +438,32 @@ bool debReleaseIndex::SetTrusted(TriState const pTrusted) return _error->Error(_("Conflicting values set for option %s concerning source %s %s"), "Trusted", URI.c_str(), Dist.c_str()); return true; } +bool debReleaseIndex::SetCheckValidUntil(TriState const pCheckValidUntil) +{ + if (d->CheckValidUntil == TRI_UNSET) + d->CheckValidUntil = pCheckValidUntil; + else if (d->CheckValidUntil != pCheckValidUntil) + return _error->Error(_("Conflicting values set for option %s concerning source %s %s"), "Check-Valid-Until", URI.c_str(), Dist.c_str()); + return true; +} +bool debReleaseIndex::SetValidUntilMin(time_t const Valid) +{ + if (d->ValidUntilMin == 0) + d->ValidUntilMin = Valid; + else if (d->ValidUntilMin != Valid) + return _error->Error(_("Conflicting values set for option %s concerning source %s %s"), "Min-ValidTime", URI.c_str(), Dist.c_str()); + return true; +} +bool debReleaseIndex::SetValidUntilMax(time_t const Valid) +{ + if (d->ValidUntilMax == 0) + d->ValidUntilMax = Valid; + else if (d->ValidUntilMax != Valid) + return _error->Error(_("Conflicting values set for option %s concerning source %s %s"), "Max-ValidTime", URI.c_str(), Dist.c_str()); + return true; +} + /*}}}*/ +// ReleaseIndex::IsTrusted /*{{{*/ bool debReleaseIndex::IsTrusted() const { if (Trusted == TRI_YES) @@ -601,6 +644,22 @@ static std::vector parsePlusMinusOptions(std::string const &Name, / /*}}}*/ class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type /*{{{*/ { + metaIndex::TriState GetTriStateOption(std::mapconst &Options, char const * const name) const + { + std::map::const_iterator const opt = Options.find(name); + if (opt != Options.end()) + return StringToBool(opt->second, false) ? metaIndex::TRI_YES : metaIndex::TRI_NO; + return metaIndex::TRI_DONTCARE; + } + + time_t GetTimeOption(std::mapconst &Options, char const * const name) const + { + std::map::const_iterator const opt = Options.find(name); + if (opt == Options.end()) + return 0; + return strtoull(opt->second.c_str(), NULL, 10); + } + protected: bool CreateItemInternal(std::vector &List, std::string const &URI, @@ -641,13 +700,10 @@ class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type /*{{{*/ parsePlusMinusOptions("lang", Options, APT::Configuration::getLanguages(true)) ); - std::map::const_iterator const trusted = Options.find("trusted"); - if (trusted != Options.end()) - { - if (Deb->SetTrusted(StringToBool(trusted->second, false) ? debReleaseIndex::TRI_YES : debReleaseIndex::TRI_NO) == false) - return false; - } - else if (Deb->SetTrusted(debReleaseIndex::TRI_DONTCARE) == false) + if (Deb->SetTrusted(GetTriStateOption(Options, "trusted")) == false || + Deb->SetCheckValidUntil(GetTriStateOption(Options, "check-valid-until")) == false || + Deb->SetValidUntilMax(GetTimeOption(Options, "valid-until-max")) == false || + Deb->SetValidUntilMin(GetTimeOption(Options, "valid-until-min")) == false) return false; return true; diff --git a/apt-pkg/deb/debmetaindex.h b/apt-pkg/deb/debmetaindex.h index 19fe6806c..879eb3bfc 100644 --- a/apt-pkg/deb/debmetaindex.h +++ b/apt-pkg/deb/debmetaindex.h @@ -53,6 +53,9 @@ class APT_HIDDEN debReleaseIndex : public metaIndex virtual std::vector *GetIndexFiles(); bool SetTrusted(TriState const Trusted); + bool SetCheckValidUntil(TriState const Trusted); + bool SetValidUntilMin(time_t const Valid); + bool SetValidUntilMax(time_t const Valid); virtual bool IsTrusted() const; diff --git a/apt-pkg/sourcelist.cc b/apt-pkg/sourcelist.cc index 0502f0e1d..0d65558ed 100644 --- a/apt-pkg/sourcelist.cc +++ b/apt-pkg/sourcelist.cc @@ -103,6 +103,9 @@ bool pkgSourceList::Type::ParseStanza(vector &List, /*{{{*/ APT_PLUSMINUS("Targets", "target"); #undef APT_PLUSMINUS mapping.insert(std::make_pair("Trusted", "trusted")); + mapping.insert(std::make_pair("Check-Valid-Until", "check-valid-until")); + mapping.insert(std::make_pair("Valid-Until-Min", "valid-until-min")); + mapping.insert(std::make_pair("Valid-Until-Max", "valid-until-max")); for (std::map::const_iterator m = mapping.begin(); m != mapping.end(); ++m) if (Tags.Exists(m->first)) diff --git a/doc/apt-get.8.xml b/doc/apt-get.8.xml index 5b6788ed4..b0fe390df 100644 --- a/doc/apt-get.8.xml +++ b/doc/apt-get.8.xml @@ -531,9 +531,13 @@ - Ignore if packages can't be authenticated and don't prompt about it. - This is useful for tools like pbuilder. - Configuration Item: APT::Get::AllowUnauthenticated. + Ignore if packages can't be authenticated and don't prompt + about it. This can be useful while working with local repositories, + but is a huge security risk if data authenticity isn't ensured in + another way by the user itself. The usage of the + option for &sources-list; entries should + usually be preferred over this global override. Configuration Item: + APT::Get::AllowUnauthenticated. diff --git a/doc/apt.conf.5.xml b/doc/apt.conf.5.xml index 7d5f7e9b3..103d0622c 100644 --- a/doc/apt.conf.5.xml +++ b/doc/apt.conf.5.xml @@ -301,6 +301,8 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";}; Valid-Until header, but if they don't or a stricter value is desired the Max-ValidTime option below can be used. + The option of &sources-list; entries should be + preferred to disable the check selectively instead of using this global override. @@ -312,7 +314,8 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";}; the earlier date of the two is used as the expiration date. The default value is 0 which stands for "valid forever". Archive specific settings can be made by appending the label of the archive - to the option name. + to the option name. Preferably, the same can be achieved for specific + &sources-list; entries by using the option there. @@ -324,7 +327,8 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";}; frequently updated archive with a Valid-Until header instead of completely disabling the expiration date checking. Archive specific settings can and should be used by appending the label of - the archive to the option name. + the archive to the option name. Preferably, the same can be achieved for specific + &sources-list; entries by using the option there. diff --git a/doc/sources.list.5.xml b/doc/sources.list.5.xml index f87dcda23..aded8ecef 100644 --- a/doc/sources.list.5.xml +++ b/doc/sources.list.5.xml @@ -202,26 +202,26 @@ deb-src [ option1=value1 option2=value2 ] uri suite [component1] [component2] [. APT versions. - Architectures - (arch) is a multivalue option defining for + + () is a multivalue option defining for which architectures information should be downloaded. If this option isn't set the default is all architectures as defined by - the APT::Architectures config option. + the config option. - Languages - (lang) is a multivalue option defining for + + () is a multivalue option defining for which languages information like translated package descriptions should be downloaded. If this option isn't set the default is all languages as defined by the - Acquire::Languages config option. + config option. - Targets - (target) is a multivalue option defining + + () is a multivalue option defining which download targets apt will try to acquire from this source. If not specified, the default set is defined by the - APT::Acquire::Targets configuration scope. + configuration scope. @@ -232,7 +232,7 @@ deb-src [ option1=value1 option2=value2 ] uri suite [component1] [component2] [. anomalies. - Trusted (trusted) + () is a tri-state value which defaults to APT deciding if a source is considered trusted or if warnings should be raised before e.g. packages are installed from this source. This option can be used @@ -245,6 +245,41 @@ deb-src [ option1=value1 option2=value2 ] uri suite [component1] [component2] [. as untrusted even if the authentication checks passed successfully. The default value can't be set explicitly. + + () + is a yes/no value which controls if APT should try to detect + replay attacks. A repository creator can declare until then the + data provided in the repository should be considered valid and + if this time is reached, but no new data is provided the data + is considered expired and an error is raised. Beside + increasing security as a malicious attacker can't sent old data + forever denying a user to be able to upgrade to a new version, + this also helps users identify mirrors which are no longer + updated. Some repositories like historic archives aren't + updated anymore by design through, so this check can be + disabled by setting this option to no. + Defaults to the value of configuration option + which itself + defaults to yes. + + + + () and + + () can be used to raise or + lower the time period in seconds in which the data from this + repository is considered valid. -Max can be especially useful + if the repository provides no Valid-Until field on its Release + file to set your own value, while -Min can be used to increase + the valid time on seldomly updated (local) mirrors of a more + frequently updated but less accessible archive (which is in the + sources.list as well) instead of disabling the check entirely. + Default to the value of the configuration options + and + which are both unset by + default. + + diff --git a/test/integration/test-releasefile-valid-until b/test/integration/test-releasefile-valid-until index e000abf5d..43574ec3e 100755 --- a/test/integration/test-releasefile-valid-until +++ b/test/integration/test-releasefile-valid-until @@ -46,3 +46,12 @@ runtest 'accepted' 'good Min-Valid (bad Until, good Max-Valid) <' 'now - 7 days' runtest 'rejected' 'bad Max-Valid (bad Until, good Min-Valid) >' 'now - 7 days' 'now - 2 days' -o Acquire::Max-ValidTime=12096 -o Acquire::Min-ValidTime=2419200 runtest 'rejected' 'bad Max-Valid (bad Until, bad Min-Valid) <' 'now - 7 days' 'now - 2 days' -o Acquire::Min-ValidTime=12096 -o Acquire::Max-ValidTime=241920 runtest 'rejected' 'bad Max-Valid (bad Until, bad Min-Valid) >' 'now - 7 days' 'now - 2 days' -o Acquire::Max-ValidTime=12096 -o Acquire::Min-ValidTime=241920 + +sed -i -e 's#\(deb\(-src\)\?\) #\1 [check-valid-until=no] #' rootdir/etc/apt/sources.list.d/* +runtest 'accepted' 'bad Until but overriden by sources option' 'now - 7 days' 'now - 4 days' + +sed -i -e 's#\(deb\(-src\)\?\) \[check-valid-until=no\] #\1 [valid-until-max=86400] #' rootdir/etc/apt/sources.list.d/* +runtest 'rejected' 'bad Max-Valid (good Until) via sources option' 'now - 7 days' 'now + 4 days' + +sed -i -e 's#\(deb\(-src\)\?\) \[valid-until-max=86400\] #\1 [valid-until-min=1209600] #' rootdir/etc/apt/sources.list.d/* +runtest 'accepted' 'good Min-Valid (bad Until) via sources option' 'now - 7 days' 'now - 4 days' -- cgit v1.2.3-70-g09d2 From c2a4a8dded2dfb56dbcab9689b6cb4b96c9999b6 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 10 Jul 2015 00:07:37 +0200 Subject: rename 'apt-get files' to 'apt-get indextargets' 'files' is a bit too generic as a name for a command usually only used programmatically (if at all) by developers, so instead of "wasting" this generic name for this we use "indextargets" which is actually the name of the datastructure the displayed data is stored in. Along with this rename the config options are renamed accordingly. --- apt-pkg/deb/debmetaindex.cc | 10 +++---- apt-pkg/init.cc | 34 +++++++++++----------- apt-private/private-cmndline.cc | 6 ++-- cmdline/apt-get.cc | 10 +++---- doc/acquire-additional-files.txt | 18 +++++++----- doc/apt-get.8.xml | 24 +++++++-------- doc/sources.list.5.xml | 2 +- .../test-acquire-same-repository-multiple-times | 2 +- test/integration/test-apt-acquire-additional-files | 26 ++++++++--------- .../integration/test-apt-get-update-unauth-warning | 2 +- .../test-sourceslist-lang-plusminus-options | 4 +-- 11 files changed, 70 insertions(+), 68 deletions(-) (limited to 'doc/apt-get.8.xml') diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index 46a7181fc..480317db3 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -128,12 +128,12 @@ static void GetIndexTargetsFor(char const * const Type, std::string const &URI, { for (std::vector::const_iterator T = E->Targets.begin(); T != E->Targets.end(); ++T) { -#define APT_T_CONFIG(X) _config->Find(std::string("APT::Acquire::Targets::") + Type + "::" + *T + "::" + (X)) +#define APT_T_CONFIG(X) _config->Find(std::string("Acquire::IndexTargets::") + Type + "::" + *T + "::" + (X)) std::string const tplMetaKey = APT_T_CONFIG(flatArchive ? "flatMetaKey" : "MetaKey"); std::string const tplShortDesc = APT_T_CONFIG("ShortDescription"); - std::string const tplLongDesc = APT_T_CONFIG(flatArchive ? "flatDescription" : "Description"); - bool const IsOptional = _config->FindB(std::string("APT::Acquire::Targets::") + Type + "::" + *T + "::Optional", true); - bool const KeepCompressed = _config->FindB(std::string("APT::Acquire::Targets::") + Type + "::" + *T + "::KeepCompressed", GzipIndex); + std::string const tplLongDesc = "$(SITE) " + APT_T_CONFIG(flatArchive ? "flatDescription" : "Description"); + bool const IsOptional = _config->FindB(std::string("Acquire::IndexTargets::") + Type + "::" + *T + "::Optional", true); + bool const KeepCompressed = _config->FindB(std::string("Acquire::IndexTargets::") + Type + "::" + *T + "::KeepCompressed", GzipIndex); #undef APT_T_CONFIG if (tplMetaKey.empty()) continue; @@ -721,7 +721,7 @@ class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type /*{{{*/ Deb->AddComponent( IsSrc, Section, - parsePlusMinusOptions("target", Options, _config->FindVector(std::string("APT::Acquire::Targets::") + Name, "", true)), + parsePlusMinusOptions("target", Options, _config->FindVector(std::string("Acquire::IndexTargets::") + Name, "", true)), parsePlusMinusOptions("arch", Options, APT::Configuration::getArchitectures()), parsePlusMinusOptions("lang", Options, APT::Configuration::getLanguages(true)) ); diff --git a/apt-pkg/init.cc b/apt-pkg/init.cc index 1fbb035f7..858bcec43 100644 --- a/apt-pkg/init.cc +++ b/apt-pkg/init.cc @@ -99,23 +99,23 @@ bool pkgInitConfig(Configuration &Cnf) // The default user we drop to in the methods Cnf.CndSet("APT::Sandbox::User", "_apt"); - Cnf.CndSet("APT::Acquire::Targets::deb::Packages::MetaKey", "$(COMPONENT)/binary-$(ARCHITECTURE)/Packages"); - Cnf.CndSet("APT::Acquire::Targets::deb::Packages::flatMetaKey", "Packages"); - Cnf.CndSet("APT::Acquire::Targets::deb::Packages::ShortDescription", "Packages"); - Cnf.CndSet("APT::Acquire::Targets::deb::Packages::Description", "$(SITE) $(RELEASE)/$(COMPONENT) $(ARCHITECTURE) Packages"); - Cnf.CndSet("APT::Acquire::Targets::deb::Packages::flatDescription", "$(SITE) $(RELEASE) Packages"); - Cnf.CndSet("APT::Acquire::Targets::deb::Packages::Optional", false); - Cnf.CndSet("APT::Acquire::Targets::deb::Translations::MetaKey", "$(COMPONENT)/i18n/Translation-$(LANGUAGE)"); - Cnf.CndSet("APT::Acquire::Targets::deb::Translations::flatMetaKey", "$(LANGUAGE)"); - Cnf.CndSet("APT::Acquire::Targets::deb::Translations::ShortDescription", "Translation-$(LANGUAGE)"); - Cnf.CndSet("APT::Acquire::Targets::deb::Translations::Description", "$(SITE) $(RELEASE)/$(COMPONENT) Translation-$(LANGUAGE)"); - Cnf.CndSet("APT::Acquire::Targets::deb::Translations::flatDescription", "$(SITE) $(RELEASE) Translation-$(LANGUAGE)"); - Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::MetaKey", "$(COMPONENT)/source/Sources"); - Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::flatMetaKey", "Sources"); - Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::ShortDescription", "Sources"); - Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::Description", "$(SITE) $(RELEASE)/$(COMPONENT) Sources"); - Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::flatDescription", "$(SITE) $(RELEASE) Sources"); - Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::Optional", false); + Cnf.CndSet("Acquire::IndexTargets::deb::Packages::MetaKey", "$(COMPONENT)/binary-$(ARCHITECTURE)/Packages"); + Cnf.CndSet("Acquire::IndexTargets::deb::Packages::flatMetaKey", "Packages"); + Cnf.CndSet("Acquire::IndexTargets::deb::Packages::ShortDescription", "Packages"); + Cnf.CndSet("Acquire::IndexTargets::deb::Packages::Description", "$(RELEASE)/$(COMPONENT) $(ARCHITECTURE) Packages"); + Cnf.CndSet("Acquire::IndexTargets::deb::Packages::flatDescription", "$(RELEASE) Packages"); + Cnf.CndSet("Acquire::IndexTargets::deb::Packages::Optional", false); + Cnf.CndSet("Acquire::IndexTargets::deb::Translations::MetaKey", "$(COMPONENT)/i18n/Translation-$(LANGUAGE)"); + Cnf.CndSet("Acquire::IndexTargets::deb::Translations::flatMetaKey", "$(LANGUAGE)"); + Cnf.CndSet("Acquire::IndexTargets::deb::Translations::ShortDescription", "Translation-$(LANGUAGE)"); + Cnf.CndSet("Acquire::IndexTargets::deb::Translations::Description", "$(RELEASE)/$(COMPONENT) Translation-$(LANGUAGE)"); + Cnf.CndSet("Acquire::IndexTargets::deb::Translations::flatDescription", "$(RELEASE) Translation-$(LANGUAGE)"); + Cnf.CndSet("Acquire::IndexTargets::deb-src::Sources::MetaKey", "$(COMPONENT)/source/Sources"); + Cnf.CndSet("Acquire::IndexTargets::deb-src::Sources::flatMetaKey", "Sources"); + Cnf.CndSet("Acquire::IndexTargets::deb-src::Sources::ShortDescription", "Sources"); + Cnf.CndSet("Acquire::IndexTargets::deb-src::Sources::Description", "$(RELEASE)/$(COMPONENT) Sources"); + Cnf.CndSet("Acquire::IndexTargets::deb-src::Sources::flatDescription", "$(RELEASE) Sources"); + Cnf.CndSet("Acquire::IndexTargets::deb-src::Sources::Optional", false); Cnf.CndSet("Acquire::Changelogs::URI::Origin::Debian", "http://metadata.ftp-master.debian.org/changelogs/CHANGEPATH_changelog"); Cnf.CndSet("Acquire::Changelogs::URI::Origin::Ubuntu", "http://changelogs.ubuntu.com/changelogs/pool/CHANGEPATH/changelog"); diff --git a/apt-private/private-cmndline.cc b/apt-private/private-cmndline.cc index 11e88b1e7..71dceb559 100644 --- a/apt-private/private-cmndline.cc +++ b/apt-private/private-cmndline.cc @@ -163,10 +163,10 @@ static bool addArgumentsAPTGet(std::vector &Args, char const // once sbuild is fixed, this option can be removed addArg('f', "fix-broken", "APT::Get::Fix-Broken", 0); } - else if (CmdMatches("files")) + else if (CmdMatches("indextargets")) { - addArg(0,"format","APT::Get::Files::Format", CommandLine::HasArg); - addArg(0,"release-info","APT::Get::Files::ReleaseInfo", 0); + addArg(0,"format","APT::Get::IndexTargets::Format", CommandLine::HasArg); + addArg(0,"release-info","APT::Get::IndexTargets::ReleaseInfo", 0); } else if (CmdMatches("clean", "autoclean", "check", "download", "changelog") || CmdMatches("markauto", "unmarkauto")) // deprecated commands diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 9232e1505..a69f5418a 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -1468,7 +1468,7 @@ static bool DoChangelog(CommandLine &CmdL) return true; } /*}}}*/ -// DoFiles - Lists all IndexTargets /*{{{*/ +// DoIndexTargets - Lists all IndexTargets /*{{{*/ static std::string format_key(std::string key) { // deb822 is case-insensitive, but the human eye prefers candy @@ -1484,7 +1484,7 @@ static std::string format_key(std::string key) } return key; } -static bool DoFiles(CommandLine &CmdL) +static bool DoIndexTargets(CommandLine &CmdL) { pkgCacheFile CacheFile; pkgSourceList *SrcList = CacheFile.GetSourceList(); @@ -1492,8 +1492,8 @@ static bool DoFiles(CommandLine &CmdL) if (SrcList == NULL) return false; - std::string const Format = _config->Find("APT::Get::Files::Format"); - bool const ReleaseInfo = _config->FindB("APT::Get::Files::ReleaseInfo", true); + 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) { @@ -1687,7 +1687,7 @@ int main(int argc,const char *argv[]) /*{{{*/ {"source",&DoSource}, {"download",&DoDownload}, {"changelog",&DoChangelog}, - {"files",&DoFiles}, + {"indextargets",&DoIndexTargets}, {"moo",&DoMoo}, {"help",&ShowHelp}, {0,0}}; diff --git a/doc/acquire-additional-files.txt b/doc/acquire-additional-files.txt index f9a16318d..71ce7b0cb 100644 --- a/doc/acquire-additional-files.txt +++ b/doc/acquire-additional-files.txt @@ -26,7 +26,7 @@ they would be written in a configuration file the configuration instructing the Acquire system to download the Packages files would look like this (see also apt.conf(5) manpage for configuration file syntax): - APT::Acquire::Targets::deb::Packages { + Acquire::IndexTargets::deb::Packages { MetaKey "$(COMPONENT)/binary-$(ARCHITECTURE)/Packages"; ShortDescription "Packages"; Description "$(SITE) $(RELEASE)/$(COMPONENT) $(ARCHITECTURE) Packages"; @@ -38,7 +38,7 @@ like this (see also apt.conf(5) manpage for configuration file syntax): }; All files which should be downloaded (nicknamed 'Targets') are mentioned -below the APT::Acquire::Targets scope. 'deb' is here the type of the +below the Acquire::IndexTargets scope. 'deb' is here the type of the sources.list entry the file should be acquired for. The only other supported value is hence 'deb-src'. Beware: You can't specify multiple types here and you can't download the same (evaluated) MetaKey from @@ -47,7 +47,7 @@ multiple types! After the type you can pick any valid and unique string which preferable refers to the file it downloads (In the example we picked 'Packages'). This string is used as identifier for the target class and accessible as -'Created-By' e.g. in the "apt-get files" output as detailed below. +'Created-By' e.g. in the "apt-get indextargets" output as detailed below. All targets have three main properties you can define: * MetaKey: The identifier of the file to be downloaded as used in the @@ -92,7 +92,7 @@ NO properties have to be set to enable this. The stanzas for Translation-* files as well as for Sources files would look like this: -APT::Acquire::Targets { +Acquire::IndexTargets { deb::Translations { MetaKey "$(COMPONENT)/i18n/Translation-$(LANGUAGE)"; ShortDescription "Translation-$(LANGUAGE)"; @@ -152,7 +152,7 @@ design so multiple applications can download and use the same file rather than each and every one of them potentially downloads and uses its own copy somewhere on disk. -"apt-get files" can be used to get the location as well as other +"apt-get indextargets" can be used to get the location as well as other information about all files downloaded (aka: you will see Packages, Sources and Translation-* files here as well). Provide a line of the default output format as parameter to filter out all entries which do @@ -161,12 +161,16 @@ own output style. The variables are what you see in the output, just all uppercase and wrapped in $(), as in the configuration file. To get all the filenames of all Translation-en files you can e.g. call: - apt-get files --format '$(FILENAME)' "Created-By: Translations" "Language: en" + apt-get indextargets --format '$(FILENAME)' "Created-By: Translations" "Language: en" + +The line-based filtering and the formating is rather crude and feature- +less by design, so it is recommend to use dedicated and more powerful +tools like 'grep-dctrl'. Accessing this information via libapt is done by reading the sources.lists (pkgSourceList), iterating over the metaIndex objects this creates and calling GetIndexTargets() on them. See the sourcecode of -"apt-get files" for a complete example. +"apt-get indextargets" for a complete example. Note that by default targets are not listed if they weren't downloaded. If you want to see all targets, you can use the --no-release-info, which diff --git a/doc/apt-get.8.xml b/doc/apt-get.8.xml index b0fe390df..81a9036c4 100644 --- a/doc/apt-get.8.xml +++ b/doc/apt-get.8.xml @@ -239,9 +239,9 @@ - + Displays by default a deb822 formatted listing of - information about all data files apt-get + information about all data files (aka index targets) apt-get update would download. Supports a option to modify the output format as well as accepts lines of the default output to filter the records @@ -327,17 +327,15 @@ - No action; perform a simulation of events that would occur but do not - actually change the system. - Configuration Item: APT::Get::Simulate. - - Simulated runs performed as a user will automatically deactivate locking - (Debug::NoLocking), and if the option - APT::Get::Show-User-Simulation-Note is set - (as it is by default) a notice will also be displayed indicating that - this is only a simulation. Runs performed as root do not trigger either - NoLocking or the notice - superusers should know what they are doing - without further warnings from apt-get. + No action; perform a simulation of events that would occur + based on the current system state but do not actually change the + system. Locking will be disabled () + so the system state could change while apt-get is + running. Simulations can also be executed by non-root users which might + not have read access to all apt configuration distorting the simulation. + A notice expressing this warning is also shown by default for non-root + users (). + Configuration Item: APT::Get::Simulate. Simulated runs print out a series of lines, each representing a dpkg operation: configure (Conf), remove (Remv) diff --git a/doc/sources.list.5.xml b/doc/sources.list.5.xml index 12a7773f5..3bc8a94ac 100644 --- a/doc/sources.list.5.xml +++ b/doc/sources.list.5.xml @@ -221,7 +221,7 @@ deb-src [ option1=value1 option2=value2 ] uri suite [component1] [component2] [. () is a multivalue option defining which download targets apt will try to acquire from this source. If not specified, the default set is defined by the - configuration scope. + configuration scope. diff --git a/test/integration/test-acquire-same-repository-multiple-times b/test/integration/test-acquire-same-repository-multiple-times index ad9cd6d7e..d3cb46c14 100755 --- a/test/integration/test-acquire-same-repository-multiple-times +++ b/test/integration/test-acquire-same-repository-multiple-times @@ -43,7 +43,7 @@ tworepos() { testsuccess --nomsg aptget update -o Debug::pkgAcquire::Worker=1 cp rootdir/tmp/testsuccess.output download.log #cat download.log - aptget files --format '$(FILENAME)' --no-release-info | sort > file.lst + aptget indextargets --format '$(FILENAME)' --no-release-info | sort > file.lst testequal "$(find $(readlink -f ./rootdir/var/lib/apt/lists) -name '*_dists_*' \( ! -name '*InRelease' \) -type f | sort)" cat file.lst testsuccess aptcache policy testequal "foo: diff --git a/test/integration/test-apt-acquire-additional-files b/test/integration/test-apt-acquire-additional-files index fecdf30bf..ee7908a2d 100755 --- a/test/integration/test-apt-acquire-additional-files +++ b/test/integration/test-apt-acquire-additional-files @@ -30,18 +30,18 @@ Reading package lists..." aptget update testempty find rootdir/var/lib/apt/lists -name '*Contents*' cat > rootdir/etc/apt/apt.conf.d/content-target.conf <> rootdir/etc/apt/apt.conf.d/content-target.conf +echo 'Acquire::IndexTargets::deb::Contents::KeepCompressed "true";' >> rootdir/etc/apt/apt.conf.d/content-target.conf testsuccessequal "Hit:1 http://localhost:8080 unstable InRelease Get:2 http://localhost:8080 unstable/main amd64 Contents [$(stat -c%s aptarchive/dists/unstable/main/Contents-amd64.gz) B] Reading package lists..." aptget update testequal 'rootdir/var/lib/apt/lists/localhost:8080_dists_unstable_main_Contents-amd64.gz' find rootdir/var/lib/apt/lists -name '*Contents*' -testequal "$(readlink -f ./rootdir/var/lib/apt/lists/localhost:8080_dists_unstable_main_Contents-amd64.gz)" aptget files --format '$(FILENAME)' 'Created-By: Contents' +testequal "$(readlink -f ./rootdir/var/lib/apt/lists/localhost:8080_dists_unstable_main_Contents-amd64.gz)" aptget indextargets --format '$(FILENAME)' 'Created-By: Contents' testsuccess cmp 'rootdir/var/lib/apt/lists/localhost:8080_dists_unstable_main_Contents-amd64.gz' 'aptarchive/dists/unstable/main/Contents-amd64.gz' rm ./rootdir/var/lib/apt/lists/localhost:8080_dists_unstable_main_Contents-amd64.gz -testempty aptget files --format '$(FILENAME)' 'Created-By: Contents' +testempty aptget indextargets --format '$(FILENAME)' 'Created-By: Contents' # and no automatic uncompress based on the name please, # only if we downloaded a compressed file, but target was uncompressed cat > rootdir/etc/apt/apt.conf.d/content-target.conf < gotlangs.list + aptget indextargets --no-release-info 'Created-By: Translations' "$@" --format '$(LANGUAGE)' | sort -u > gotlangs.list if [ -z "$LANGS" ]; then echo -n | tr ',' '\n' | sort | checkdiff - gotlangs.list && msgpass || msgfail else @@ -44,7 +44,7 @@ testlangs 'lang=de_DE' 'de_DE' echo 'deb [lang=none] http://example.org/debian stable rocks' > rootdir/etc/apt/sources.list testlangs 'lang=none' '' -testequal 'amd64' aptget files --no-release-info 'Created-By: Packages' --format '$(ARCHITECTURE)' +testequal 'amd64' aptget indextargets --no-release-info 'Created-By: Packages' --format '$(ARCHITECTURE)' echo 'deb [lang+=pt] http://example.org/debian stable rocks' > rootdir/etc/apt/sources.list testlangs 'lang+=pt' 'en,de,de_DE,pt' -- cgit v1.2.3-70-g09d2 From b381a482eab0fc7b65b63cf0512ef1f97d775e34 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Fri, 14 Aug 2015 11:49:45 +0200 Subject: Replace --force-yes by various options starting with --allow This enables more fine grained control over such exceptions. --- apt-private/private-cmndline.cc | 3 + apt-private/private-download.cc | 6 +- apt-private/private-install.cc | 43 ++++++---- doc/apt-get.8.xml | 26 +++++- test/integration/test-allow | 98 ++++++++++++++++++++++ .../integration/test-apt-get-update-unauth-warning | 2 +- test/integration/test-apt-never-markauto-sections | 2 +- test/integration/test-apt-update-nofallback | 2 +- test/integration/test-apt-update-rollback | 4 +- ...bug-712116-dpkg-pre-install-pkgs-hook-multiarch | 2 +- test/integration/test-releasefile-verification | 4 +- 11 files changed, 167 insertions(+), 25 deletions(-) create mode 100755 test/integration/test-allow (limited to 'doc/apt-get.8.xml') diff --git a/apt-private/private-cmndline.cc b/apt-private/private-cmndline.cc index fa8416824..487349c8c 100644 --- a/apt-private/private-cmndline.cc +++ b/apt-private/private-cmndline.cc @@ -202,6 +202,9 @@ static bool addArgumentsAPTGet(std::vector &Args, char const addArg(0,"ignore-hold","APT::Ignore-Hold",0); addArg(0,"upgrade","APT::Get::upgrade",0); addArg(0,"only-upgrade","APT::Get::Only-Upgrade",0); + addArg(0,"allow-change-held-packages","APT::Get::allow-change-held-packages",CommandLine::Boolean); + addArg(0,"allow-remove-essential","APT::Get::allow-remove-essential",CommandLine::Boolean); + addArg(0,"allow-downgrades","APT::Get::allow-downgrades",CommandLine::Boolean); addArg(0,"force-yes","APT::Get::force-yes",0); addArg(0,"print-uris","APT::Get::Print-URIs",0); addArg(0,"trivial-only","APT::Get::Trivial-Only",0); diff --git a/apt-private/private-download.cc b/apt-private/private-download.cc index 099146187..18a9b1fbc 100644 --- a/apt-private/private-download.cc +++ b/apt-private/private-download.cc @@ -114,10 +114,12 @@ bool AuthPrompt(std::vector const &UntrustedList, bool const Prompt return true; } - else if (_config->FindB("APT::Get::Force-Yes",false) == true) + else if (_config->FindB("APT::Get::Force-Yes",false) == true) { + _error->Warning(_("--force-yes is deprecated, use one of the options starting with --allow instead.")); return true; + } - return _error->Error(_("There are problems and -y was used without --force-yes")); + return _error->Error(_("There were unauthenticated packages and -y was used without --allow-unauthenticated")); } /*}}}*/ bool AcquireRun(pkgAcquire &Fetcher, int const PulseInterval, bool * const Failure, bool * const TransientNetworkFailure)/*{{{*/ diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc index d2b4bed51..96e33f7de 100644 --- a/apt-private/private-install.cc +++ b/apt-private/private-install.cc @@ -58,7 +58,8 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety) } } - bool Fail = false; + bool Hold = false; + bool Downgrade = false; bool Essential = false; // Show all the various warning indicators @@ -66,13 +67,17 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety) ShowNew(c1out,Cache); if (ShwKept == true) ShowKept(c1out,Cache); - Fail |= !ShowHold(c1out,Cache); + Hold = !ShowHold(c1out,Cache); if (_config->FindB("APT::Get::Show-Upgraded",true) == true) ShowUpgraded(c1out,Cache); - Fail |= !ShowDowngraded(c1out,Cache); + Downgrade = !ShowDowngraded(c1out,Cache); + if (_config->FindB("APT::Get::Download-Only",false) == false) Essential = !ShowEssential(c1out,Cache); - Fail |= Essential; + + // All kinds of failures + bool Fail = (Essential || Downgrade || Hold); + Stats(c1out,Cache); // Sanity check @@ -89,7 +94,25 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety) // No remove flag if (Cache->DelCount() != 0 && _config->FindB("APT::Get::Remove",true) == false) return _error->Error(_("Packages need to be removed but remove is disabled.")); - + + // Fail safe check + if (_config->FindI("quiet",0) >= 2 || + _config->FindB("APT::Get::Assume-Yes",false) == true) + { + if (_config->FindB("APT::Get::Force-Yes",false) == true) { + _error->Warning(_("--force-yes is deprecated, use one of the options starting with --allow instead.")); + } + + if (Fail == true && _config->FindB("APT::Get::Force-Yes",false) == false) { + if (Essential == true && _config->FindB("APT::Get::allow-remove-essential", false) == false) + return _error->Error(_("Essential packages were removed and -y was used without --allow-remove-essential.")); + if (Downgrade == true && _config->FindB("APT::Get::allow-downgrades", false) == false) + return _error->Error(_("Packages were downgraded and -y was used without --allow-downgrades.")); + if (Hold == true && _config->FindB("APT::Get::allow-change-held-packages", false) == false) + return _error->Error(_("Held packages were changed and -y was used without --allow-change-held-packages.")); + } + } + // Run the simulator .. if (_config->FindB("APT::Get::Simulate") == true) { @@ -173,15 +196,7 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety) if (CheckFreeSpaceBeforeDownload(_config->FindDir("Dir::Cache::Archives"), (FetchBytes - FetchPBytes)) == false) return false; - // Fail safe check - if (_config->FindI("quiet",0) >= 2 || - _config->FindB("APT::Get::Assume-Yes",false) == true) - { - if (Fail == true && _config->FindB("APT::Get::Force-Yes",false) == false) - return _error->Error(_("There are problems and -y was used without --force-yes")); - } - - if (Essential == true && Safety == true) + if (Essential == true && Safety == true && _config->FindB("APT::Get::allow-remove-essential", false) == false) { if (_config->FindB("APT::Get::Trivial-Only",false) == true) return _error->Error(_("Trivial Only specified but this is not a trivial operation.")); diff --git a/doc/apt-get.8.xml b/doc/apt-get.8.xml index 81a9036c4..76a53aec2 100644 --- a/doc/apt-get.8.xml +++ b/doc/apt-get.8.xml @@ -429,12 +429,36 @@ Configuration Item: APT::Get::Only-Upgrade. + + This is a dangerous option that will cause apt to continue + without prompting if it is doing downgrades. It + should not be used except in very special situations. Using + it can potentially destroy your system! + Configuration Item: APT::Get::allow-downgrades. Introduced in APT 1.1. + + + + Force yes; this is a dangerous option that will cause apt to continue + without prompting if it is removing essentials. It + should not be used except in very special situations. Using + it can potentially destroy your system! + Configuration Item: APT::Get::allow-remove-essential. Introduced in APT 1.1. + + + + Force yes; this is a dangerous option that will cause apt to continue + without prompting if it is changing held packages. It + should not be used except in very special situations. Using + it can potentially destroy your system! + Configuration Item: APT::Get::allow-change-held-packages. Introduced in APT 1.1. + + Force yes; this is a dangerous option that will cause apt to continue without prompting if it is doing something potentially harmful. It should not be used except in very special situations. Using force-yes can potentially destroy your system! - Configuration Item: APT::Get::force-yes. + Configuration Item: APT::Get::force-yes. This is deprecated and replaced by , , in 1.1. diff --git a/test/integration/test-allow b/test/integration/test-allow new file mode 100755 index 000000000..3d773ee95 --- /dev/null +++ b/test/integration/test-allow @@ -0,0 +1,98 @@ +#!/bin/sh +# +# Test for --allow-remove-essential and friends replacing --force-yes +# +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework +setupenvironment +configarchitecture 'amd64' + +insertpackage 'unstable' 'downgrade' 'all' '1' +insertinstalledpackage 'downgrade' 'all' '2' + +insertpackage 'unstable' 'hold' 'all' '2' +insertinstalledpackage 'hold' 'all' '1' + +insertinstalledpackage 'essential' 'all' '1' 'Essential: yes' + +setupaptarchive + +testsuccess aptmark hold hold + +# Test --allow-remove--essential + +testfailureequal 'Reading package lists... +Building dependency tree... +The following packages will be REMOVED: + essential +WARNING: The following essential packages will be removed. +This should NOT be done unless you know exactly what you are doing! + essential +0 upgraded, 0 newly installed, 1 to remove and 1 not upgraded. +E: Essential packages were removed and -y was used without --allow-remove-essential.' aptget remove essential -y -s + +testsuccessequal 'Reading package lists... +Building dependency tree... +The following packages will be REMOVED: + essential +WARNING: The following essential packages will be removed. +This should NOT be done unless you know exactly what you are doing! + essential +0 upgraded, 0 newly installed, 1 to remove and 1 not upgraded. +Remv essential [1]' aptget remove essential -y --allow-remove-essential -s + +# Test --allow-change-held-packages (should not influence dist-upgrade, but an install) + +testsuccessequal 'Reading package lists... +Building dependency tree... +Calculating upgrade... +The following packages have been kept back: + hold +0 upgraded, 0 newly installed, 0 to remove and 1 not upgraded.' aptget dist-upgrade --allow-change-held-packages -s + +testfailureequal 'Reading package lists... +Building dependency tree... +The following held packages will be changed: + hold +The following packages will be upgraded: + hold +1 upgraded, 0 newly installed, 0 to remove and 0 not upgraded. +E: Held packages were changed and -y was used without --allow-change-held-packages.' aptget install hold -y -s + +testfailureequal 'Reading package lists... +Building dependency tree... +The following held packages will be changed: + hold +The following packages will be upgraded: + hold +1 upgraded, 0 newly installed, 0 to remove and 0 not upgraded. +E: Held packages were changed and -y was used without --allow-change-held-packages.' aptget install hold -y -s + +testsuccessequal 'Reading package lists... +Building dependency tree... +The following held packages will be changed: + hold +The following packages will be upgraded: + hold +1 upgraded, 0 newly installed, 0 to remove and 0 not upgraded. +Inst hold [1] (2 unstable [all]) +Conf hold (2 unstable [all])' aptget install hold -y -s --allow-change-held-packages + +# Test --allow-downgrades + +testfailureequal 'Reading package lists... +Building dependency tree... +The following packages will be DOWNGRADED: + downgrade +0 upgraded, 0 newly installed, 1 downgraded, 0 to remove and 1 not upgraded. +E: Packages were downgraded and -y was used without --allow-downgrades.' aptget install downgrade=1 -y -s + +testsuccessequal 'Reading package lists... +Building dependency tree... +The following packages will be DOWNGRADED: + downgrade +0 upgraded, 0 newly installed, 1 downgraded, 0 to remove and 1 not upgraded. +Inst downgrade [2] (1 unstable [all]) +Conf downgrade (1 unstable [all])' aptget install downgrade=1 --allow-downgrades -y -s diff --git a/test/integration/test-apt-get-update-unauth-warning b/test/integration/test-apt-get-update-unauth-warning index bc8e6d3ea..4c45f8f26 100755 --- a/test/integration/test-apt-get-update-unauth-warning +++ b/test/integration/test-apt-get-update-unauth-warning @@ -81,4 +81,4 @@ W: The repository 'file:$APTARCHIVE unstable Release' does not have a Release fi # ensure we can not install the package testfailureequal "WARNING: The following packages cannot be authenticated! foo -E: There are problems and -y was used without --force-yes" aptget install -qq -y foo +E: There were unauthenticated packages and -y was used without --allow-unauthenticated" aptget install -qq -y foo diff --git a/test/integration/test-apt-never-markauto-sections b/test/integration/test-apt-never-markauto-sections index a469b4c15..9f490a1bd 100755 --- a/test/integration/test-apt-never-markauto-sections +++ b/test/integration/test-apt-never-markauto-sections @@ -65,7 +65,7 @@ testmarkedauto # test that installed/upgraded auto-pkgs are not set to manual -testsuccess aptget install browser=41 -y --force-yes +testsuccess aptget install browser=41 -y --allow-downgrades testmarkedmanual 'browser' 'dpkg' 'foreignpkg:i386' 'nosection' testmarkedauto diff --git a/test/integration/test-apt-update-nofallback b/test/integration/test-apt-update-nofallback index 2f4ddc016..6e9db2cae 100755 --- a/test/integration/test-apt-update-nofallback +++ b/test/integration/test-apt-update-nofallback @@ -101,7 +101,7 @@ test_from_inrelease_to_unsigned_with_override() # but that the individual packages are still considered untrusted testfailureequal "WARNING: The following packages cannot be authenticated! evil -E: There are problems and -y was used without --force-yes" aptget install -qq -y evil +E: There were unauthenticated packages and -y was used without --allow-unauthenticated" aptget install -qq -y evil } test_cve_2012_0214() diff --git a/test/integration/test-apt-update-rollback b/test/integration/test-apt-update-rollback index 646484e7b..503b81985 100755 --- a/test/integration/test-apt-update-rollback +++ b/test/integration/test-apt-update-rollback @@ -120,7 +120,7 @@ test_unauthenticated_to_invalid_inrelease() { listcurrentlistsdirectory > lists.before testfailureequal "WARNING: The following packages cannot be authenticated! old -E: There are problems and -y was used without --force-yes" aptget install -qq -y old +E: There were unauthenticated packages and -y was used without --allow-unauthenticated" aptget install -qq -y old # go to authenticated but not correct add_new_package '+1hour' @@ -133,7 +133,7 @@ E: Some index files failed to download. They have been ignored, or old ones used testfailure ls rootdir/var/lib/apt/lists/*_InRelease testfailureequal "WARNING: The following packages cannot be authenticated! old -E: There are problems and -y was used without --force-yes" aptget install -qq -y old +E: There were unauthenticated packages and -y was used without --allow-unauthenticated" aptget install -qq -y old } test_inrelease_to_unauth_inrelease() { diff --git a/test/integration/test-bug-712116-dpkg-pre-install-pkgs-hook-multiarch b/test/integration/test-bug-712116-dpkg-pre-install-pkgs-hook-multiarch index 62355a6b5..93a33d30f 100755 --- a/test/integration/test-bug-712116-dpkg-pre-install-pkgs-hook-multiarch +++ b/test/integration/test-bug-712116-dpkg-pre-install-pkgs-hook-multiarch @@ -48,7 +48,7 @@ DPkg::Tools::options::\"./${hook}-v${1}.sh\"::Version \"$1\";" > rootdir/etc/apt observehook() { rm -f ${hook}-v2.list ${hook}-v3.list msgtest 'Observe hooks while' "$*" - testsuccess --nomsg aptget "$@" -y --force-yes + testsuccess --nomsg aptget "$@" -y --allow-downgrades } testrun() { diff --git a/test/integration/test-releasefile-verification b/test/integration/test-releasefile-verification index 06701c623..c4d1455eb 100755 --- a/test/integration/test-releasefile-verification +++ b/test/integration/test-releasefile-verification @@ -69,7 +69,7 @@ The following NEW packages will be installed: After this operation, 5370 kB of additional disk space will be used. WARNING: The following packages cannot be authenticated! apt -E: There are problems and -y was used without --force-yes' aptget install apt -dy +E: There were unauthenticated packages and -y was used without --allow-unauthenticated' aptget install apt -dy } failaptnew() { @@ -83,7 +83,7 @@ The following NEW packages will be installed: After this operation, 5808 kB of additional disk space will be used. WARNING: The following packages cannot be authenticated! apt -E: There are problems and -y was used without --force-yes' aptget install apt -dy +E: There were unauthenticated packages and -y was used without --allow-unauthenticated' aptget install apt -dy } # fake our downloadable file -- cgit v1.2.3-70-g09d2 From f66738d7fb8978eaa30a179ae4f3bcc4ca7aa58f Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Fri, 14 Aug 2015 18:27:24 +0200 Subject: Make auto-remove and auto-clean aliases for the versions without - Some people type them instead of autoremove and autoclean, so make them happy. Closes: #274159 Makes-Happy: Ansgar --- apt-private/private-cmndline.cc | 4 ++-- apt-private/private-install.cc | 3 ++- cmdline/apt-get.cc | 2 ++ doc/apt-get.8.xml | 4 ++-- 4 files changed, 8 insertions(+), 5 deletions(-) (limited to 'doc/apt-get.8.xml') diff --git a/apt-private/private-cmndline.cc b/apt-private/private-cmndline.cc index 487349c8c..3a1564b23 100644 --- a/apt-private/private-cmndline.cc +++ b/apt-private/private-cmndline.cc @@ -169,14 +169,14 @@ static bool addArgumentsAPTGet(std::vector &Args, char const addArg(0,"format","APT::Get::IndexTargets::Format", CommandLine::HasArg); addArg(0,"release-info","APT::Get::IndexTargets::ReleaseInfo", 0); } - else if (CmdMatches("clean", "autoclean", "check", "download", "changelog") || + else if (CmdMatches("clean", "autoclean", "auto-clean", "check", "download", "changelog") || CmdMatches("markauto", "unmarkauto")) // deprecated commands ; else if (CmdMatches("moo")) addArg(0, "color", "APT::Moo::Color", 0); if (CmdMatches("install", "remove", "purge", "upgrade", "dist-upgrade", - "dselect-upgrade", "autoremove", "clean", "autoclean", "check", + "dselect-upgrade", "autoremove", "auto-remove", "clean", "autoclean", "auto-clean", "check", "build-dep", "full-upgrade", "source")) { addArg('s', "simulate", "APT::Get::Simulate", 0); diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc index 96e33f7de..e61c4ca51 100644 --- a/apt-private/private-install.cc +++ b/apt-private/private-install.cc @@ -519,7 +519,8 @@ bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache, _config->Set("APT::Get::Purge", true); fallback = MOD_REMOVE; } - else if (strcasecmp(CmdL.FileList[0], "autoremove") == 0) + else if (strcasecmp(CmdL.FileList[0], "autoremove") == 0 || + strcasecmp(CmdL.FileList[0], "auto-remove") == 0) { _config->Set("APT::Get::AutomaticRemove", "true"); fallback = MOD_REMOVE; diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 61ed41164..80e344740 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -1643,6 +1643,7 @@ int main(int argc,const char *argv[]) /*{{{*/ {"remove",&DoInstall}, {"purge",&DoInstall}, {"autoremove",&DoInstall}, + {"auto-remove",&DoInstall}, {"markauto",&DoMarkAuto}, {"unmarkauto",&DoMarkAuto}, {"dist-upgrade",&DoDistUpgrade}, @@ -1650,6 +1651,7 @@ int main(int argc,const char *argv[]) /*{{{*/ {"build-dep",&DoBuildDep}, {"clean",&DoClean}, {"autoclean",&DoAutoClean}, + {"auto-clean",&DoAutoClean}, {"check",&DoCheck}, {"source",&DoSource}, {"download",&DoDownload}, diff --git a/doc/apt-get.8.xml b/doc/apt-get.8.xml index 76a53aec2..785b4e9a8 100644 --- a/doc/apt-get.8.xml +++ b/doc/apt-get.8.xml @@ -214,7 +214,7 @@ &cachedir;/archives/partial/. - + (and the alias since 1.1) Like clean, autoclean clears out the local repository of retrieved package files. The difference is that it only removes package files that can no longer be downloaded, and are largely @@ -224,7 +224,7 @@ erased if it is set to off. - + (and the alias since 1.1) autoremove is used to remove packages that were automatically installed to satisfy dependencies for other packages and are now no longer needed. -- cgit v1.2.3-70-g09d2