Explorar el Código

support "install ./foo.changes"

We support installing ./foo.deb (and ./foo.dsc for source) for a while
now, but it can be a bit clunky to work with those directly if you e.g.
build packages locally in a 'central' build-area.

The changes files also include hashsums and can be signed, so this can
also be considered an enhancement in terms of security as a user "just"
has to verify the signature on the changes file then rather than
checking all deb files individually in these manual installation
procedures.
David Kalnischkies hace 10 años
padre
commit
92296fe4b0

+ 18 - 1
apt-pkg/deb/debsrcrecords.cc

@@ -41,7 +41,15 @@ debSrcRecordParser::debSrcRecordParser(std::string const &File,pkgIndexFile cons
 	 Tags.Init(&Fd, 102400);
    }
 }
-
+std::string debSrcRecordParser::Package() const				/*{{{*/
+{
+   auto const name = Sect.FindS("Package");
+   if (iIndex == nullptr)
+      return name.empty() ? Sect.FindS("Source") : name;
+   else
+      return name;
+}
+									/*}}}*/
 // SrcRecordParser::Binaries - Return the binaries field		/*{{{*/
 // ---------------------------------------------------------------------
 /* This member parses the binaries field into a pair of class arrays and
@@ -190,6 +198,15 @@ bool debSrcRecordParser::Files2(std::vector<pkgSrcRecords::File2> &List)
 	       ParseQuoteWord(C, path) == false)
 	    return _error->Error("Error parsing file record in %s of source package %s", checksumField.c_str(), Package().c_str());
 
+	 if (iIndex == nullptr && checksumField == "Files")
+	 {
+	    // the Files field has a different format than the rest in deb-changes files
+	    std::string ignore;
+	    if (ParseQuoteWord(C, ignore) == false ||
+		  ParseQuoteWord(C, path) == false)
+	       return _error->Error("Error parsing file record in %s of source package %s", checksumField.c_str(), Package().c_str());
+	 }
+
 	 HashString const hashString(*type, hash);
 	 if (Base.empty() == false)
 	    path = Base + path;

+ 1 - 1
apt-pkg/deb/debsrcrecords.h

@@ -40,7 +40,7 @@ class APT_HIDDEN debSrcRecordParser : public pkgSrcRecords::Parser
    virtual bool Step() APT_OVERRIDE {iOffset = Tags.Offset(); return Tags.Step(Sect);};
    virtual bool Jump(unsigned long const &Off) APT_OVERRIDE {iOffset = Off; return Tags.Jump(Sect,Off);};
 
-   virtual std::string Package() const APT_OVERRIDE {return Sect.FindS("Package");};
+   virtual std::string Package() const APT_OVERRIDE;
    virtual std::string Version() const APT_OVERRIDE {return Sect.FindS("Version");};
    virtual std::string Maintainer() const APT_OVERRIDE {return Sect.FindS("Maintainer");};
    virtual std::string Section() const APT_OVERRIDE {return Sect.FindS("Section");};

+ 39 - 2
apt-pkg/sourcelist.cc

@@ -22,6 +22,7 @@
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/cacheiterators.h>
 #include <apt-pkg/debindexfile.h>
+#include <apt-pkg/debsrcrecords.h>
 
 #include <ctype.h>
 #include <stddef.h>
@@ -543,7 +544,7 @@ void pkgSourceList::AddVolatileFile(pkgIndexFile * const File)		/*{{{*/
       VolatileFiles.push_back(File);
 }
 									/*}}}*/
-bool pkgSourceList::AddVolatileFile(std::string const &File)		/*{{{*/
+bool pkgSourceList::AddVolatileFile(std::string const &File, std::vector<std::string> * const VolatileCmdL)/*{{{*/
 {
    // Note: FileExists matches directories and links, too!
    if (File.empty() || FileExists(File) == false)
@@ -556,13 +557,49 @@ bool pkgSourceList::AddVolatileFile(std::string const &File)		/*{{{*/
       AddVolatileFile(new debDscFileIndex(File));
    else if (FileExists(flCombine(File, "debian/control")))
       AddVolatileFile(new debDscFileIndex(flCombine(File, "debian/control")));
+   else if (ext == "changes")
+   {
+      debDscRecordParser changes(File, nullptr);
+      std::vector<pkgSrcRecords::File2> fileslst;
+      if (changes.Files2(fileslst) == false || fileslst.empty())
+	 return false;
+      auto const basedir = flNotFile(File);
+      for (auto && file: fileslst)
+      {
+	 auto const name = flCombine(basedir, file.Path);
+	 AddVolatileFile(name, VolatileCmdL);
+	 if (file.Hashes.VerifyFile(name) == false)
+	    return _error->Error("The file %s does not match with the hashes in the %s file!", name.c_str(), File.c_str());
+      }
+      return true;
+   }
    else
       return false;
 
+   if (VolatileCmdL != nullptr)
+      VolatileCmdL->push_back(File);
    return true;
+}
+bool pkgSourceList::AddVolatileFile(std::string const &File)
+{
+   return AddVolatileFile(File, nullptr);
 }
 									/*}}}*/
-void pkgSourceList::AddVolatileFiles(CommandLine &CmdL, std::vector<const char*> * const VolatileCmdL)/*{{{*/
+void pkgSourceList::AddVolatileFiles(CommandLine &CmdL, std::vector<std::string> * const VolatileCmdL)/*{{{*/
+{
+   std::remove_if(CmdL.FileList + 1, CmdL.FileList + 1 + CmdL.FileSize(), [&](char const * const I) {
+      if (I != nullptr && (I[0] == '/' || (I[0] == '.' && ((I[1] == '.' && I[2] == '/') || I[1] == '/'))))
+      {
+	 if (AddVolatileFile(I, VolatileCmdL))
+	    ;
+	 else
+	    _error->Error(_("Unsupported file %s given on commandline"), I);
+	 return true;
+      }
+      return false;
+   });
+}
+void pkgSourceList::AddVolatileFiles(CommandLine &CmdL, std::vector<const char*> * const VolatileCmdL)
 {
    std::remove_if(CmdL.FileList + 1, CmdL.FileList + 1 + CmdL.FileSize(), [&](char const * const I) {
       if (I != nullptr && (I[0] == '/' || (I[0] == '.' && ((I[1] == '.' && I[2] == '/') || I[1] == '/'))))

+ 3 - 1
apt-pkg/sourcelist.h

@@ -131,7 +131,9 @@ class pkgSourceList
     */
    void AddVolatileFile(pkgIndexFile * const File);
    bool AddVolatileFile(std::string const &File);
-   void AddVolatileFiles(CommandLine &CmdL, std::vector<const char*> * const VolatileCmdL);
+   bool AddVolatileFile(std::string const &File, std::vector<std::string> * const VolatileCmdL);
+   APT_DEPRECATED_MSG("Use the overload with string-vector") void AddVolatileFiles(CommandLine &CmdL, std::vector<const char*> * const VolatileCmdL);
+   void AddVolatileFiles(CommandLine &CmdL, std::vector<std::string> * const VolatileCmdL);
 
    /** @return list of files registered with #AddVolatileFile */
    std::vector<pkgIndexFile*> GetVolatileFiles() const;

+ 4 - 4
apt-private/private-install.cc

@@ -540,15 +540,15 @@ static const unsigned short MOD_INSTALL = 2;
 
 bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache, int UpgradeMode)
 {
-   std::vector<const char*> VolatileCmdL;
+   std::vector<std::string> VolatileCmdL;
    return DoCacheManipulationFromCommandLine(CmdL, VolatileCmdL, Cache, UpgradeMode);
 }
-bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, std::vector<const char*> &VolatileCmdL, CacheFile &Cache, int UpgradeMode)
+bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, std::vector<std::string> &VolatileCmdL, CacheFile &Cache, int UpgradeMode)
 {
    std::map<unsigned short, APT::VersionSet> verset;
    return DoCacheManipulationFromCommandLine(CmdL, VolatileCmdL, Cache, verset, UpgradeMode);
 }
-bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, std::vector<const char*> &VolatileCmdL, CacheFile &Cache,
+bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, std::vector<std::string> &VolatileCmdL, CacheFile &Cache,
                                         std::map<unsigned short, APT::VersionSet> &verset, int UpgradeMode)
 {
    // Enter the special broken fixing mode if the user specified arguments
@@ -694,7 +694,7 @@ struct PkgIsExtraInstalled {
 bool DoInstall(CommandLine &CmdL)
 {
    CacheFile Cache;
-   std::vector<char const *> VolatileCmdL;
+   std::vector<std::string> VolatileCmdL;
    Cache.GetSourceList()->AddVolatileFiles(CmdL, &VolatileCmdL);
 
    // then open the cache

+ 2 - 2
apt-private/private-install.h

@@ -18,9 +18,9 @@ class pkgProblemResolver;
 
 APT_PUBLIC bool DoInstall(CommandLine &Cmd);
 
-bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, std::vector<const char*> &VolatileCmdL, CacheFile &Cache,
+bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, std::vector<std::string> &VolatileCmdL, CacheFile &Cache,
                                         std::map<unsigned short, APT::VersionSet> &verset, int UpgradeMode);
-bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, std::vector<const char*> &VolatileCmdL, CacheFile &Cache, int UpgradeMode);
+bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, std::vector<std::string> &VolatileCmdL, CacheFile &Cache, int UpgradeMode);
 bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache, int UpgradeMode);
 
 APT_PUBLIC bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,

+ 6 - 6
apt-private/private-source.cc

@@ -644,7 +644,7 @@ static void WriteBuildDependencyPackage(std::ostringstream &buildDepsPkgFile,
 bool DoBuildDep(CommandLine &CmdL)
 {
    CacheFile Cache;
-   std::vector<char const *> VolatileCmdL;
+   std::vector<std::string> VolatileCmdL;
    Cache.GetSourceList()->AddVolatileFiles(CmdL, &VolatileCmdL);
 
    _config->Set("APT::Install-Recommends", false);
@@ -702,18 +702,18 @@ bool DoBuildDep(CommandLine &CmdL)
       {
 	 for (size_t i = 0; i < VolatileSources.size(); ++i)
 	 {
-	    char const * const Src = VolatileCmdL[i];
+	    auto const Src = VolatileCmdL[i];
 	    if (DirectoryExists(Src))
-	       ioprintf(c1out, _("Note, using directory '%s' to get the build dependencies\n"), Src);
+	       ioprintf(c1out, _("Note, using directory '%s' to get the build dependencies\n"), Src.c_str());
 	    else
-	       ioprintf(c1out, _("Note, using file '%s' to get the build dependencies\n"), Src);
+	       ioprintf(c1out, _("Note, using file '%s' to get the build dependencies\n"), Src.c_str());
 	    std::unique_ptr<pkgSrcRecords::Parser> Last(VolatileSources[i]->CreateSrcParser());
 	    if (Last == nullptr)
-	       return _error->Error(_("Unable to find a source package for %s"), Src);
+	       return _error->Error(_("Unable to find a source package for %s"), Src.c_str());
 
 	    std::string const pseudo = std::string("builddeps:") + Src;
 	    WriteBuildDependencyPackage(buildDepsPkgFile, pseudo, pseudoArch,
-		  GetBuildDeps(Last.get(), Src, StripMultiArch, hostArch));
+		  GetBuildDeps(Last.get(), Src.c_str(), StripMultiArch, hostArch));
 	    pseudoPkgs.emplace_back(pseudo, pseudoArch);
 	 }
       }

+ 1 - 1
apt-private/private-upgrade.cc

@@ -19,7 +19,7 @@
 static bool UpgradeHelper(CommandLine &CmdL, int UpgradeFlags)
 {
    CacheFile Cache;
-   std::vector<char const *> VolatileCmdL;
+   std::vector<std::string> VolatileCmdL;
    Cache.GetSourceList()->AddVolatileFiles(CmdL, &VolatileCmdL);
 
    if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false)

+ 5 - 4
test/integration/test-apt-key-used-in-maintainerscript

@@ -22,18 +22,19 @@ apt-key list >/dev/null' > "${BUILDDIR}/debian/postinst"
 buildingpkg 'aptkeyuser-nodepends' 'Depends: unrelated'
 buildingpkg 'aptkeyuser-depends' 'Depends: gnupg'
 
-setupaptarchive
-
 insertinstalledpackage 'unrelated' 'native' '1'
 insertinstalledpackage 'gnupg' 'native' '1'
+testdpkgnotinstalled 'aptkeyuser-depends' 'aptkeyuser-nodepends'
 
-testsuccess apt install aptkeyuser-depends -y
+testsuccess apt install ./incoming/aptkeyuser-depends_*.changes -y
 cp rootdir/tmp/testsuccess.output apt.output
+testdpkginstalled 'aptkeyuser-depends'
 testfailure grep '^Warning: This will BREAK' apt.output
 testsuccess grep '^Warning: apt-key' apt.output
 
-testsuccess apt install aptkeyuser-nodepends -y
+testsuccess apt install ./incoming/aptkeyuser-nodepends_*.changes -y
 cp rootdir/tmp/testsuccess.output apt.output
+testdpkginstalled 'aptkeyuser-nodepends'
 testsuccess grep '^Warning: This will BREAK' apt.output
 testsuccess grep '^Warning: apt-key' apt.output