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);
 	 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		/*{{{*/
 // SrcRecordParser::Binaries - Return the binaries field		/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* This member parses the binaries field into a pair of class arrays and
 /* 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)
 	       ParseQuoteWord(C, path) == false)
 	    return _error->Error("Error parsing file record in %s of source package %s", checksumField.c_str(), Package().c_str());
 	    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);
 	 HashString const hashString(*type, hash);
 	 if (Base.empty() == false)
 	 if (Base.empty() == false)
 	    path = Base + path;
 	    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 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 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 Version() const APT_OVERRIDE {return Sect.FindS("Version");};
    virtual std::string Maintainer() const APT_OVERRIDE {return Sect.FindS("Maintainer");};
    virtual std::string Maintainer() const APT_OVERRIDE {return Sect.FindS("Maintainer");};
    virtual std::string Section() const APT_OVERRIDE {return Sect.FindS("Section");};
    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/pkgcache.h>
 #include <apt-pkg/cacheiterators.h>
 #include <apt-pkg/cacheiterators.h>
 #include <apt-pkg/debindexfile.h>
 #include <apt-pkg/debindexfile.h>
+#include <apt-pkg/debsrcrecords.h>
 
 
 #include <ctype.h>
 #include <ctype.h>
 #include <stddef.h>
 #include <stddef.h>
@@ -543,7 +544,7 @@ void pkgSourceList::AddVolatileFile(pkgIndexFile * const File)		/*{{{*/
       VolatileFiles.push_back(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!
    // Note: FileExists matches directories and links, too!
    if (File.empty() || FileExists(File) == false)
    if (File.empty() || FileExists(File) == false)
@@ -556,13 +557,49 @@ bool pkgSourceList::AddVolatileFile(std::string const &File)		/*{{{*/
       AddVolatileFile(new debDscFileIndex(File));
       AddVolatileFile(new debDscFileIndex(File));
    else if (FileExists(flCombine(File, "debian/control")))
    else if (FileExists(flCombine(File, "debian/control")))
       AddVolatileFile(new debDscFileIndex(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
    else
       return false;
       return false;
 
 
+   if (VolatileCmdL != nullptr)
+      VolatileCmdL->push_back(File);
    return true;
    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) {
    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 (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);
    void AddVolatileFile(pkgIndexFile * const File);
    bool AddVolatileFile(std::string 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 */
    /** @return list of files registered with #AddVolatileFile */
    std::vector<pkgIndexFile*> GetVolatileFiles() const;
    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)
 bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache, int UpgradeMode)
 {
 {
-   std::vector<const char*> VolatileCmdL;
+   std::vector<std::string> VolatileCmdL;
    return DoCacheManipulationFromCommandLine(CmdL, VolatileCmdL, Cache, UpgradeMode);
    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;
    std::map<unsigned short, APT::VersionSet> verset;
    return DoCacheManipulationFromCommandLine(CmdL, VolatileCmdL, Cache, verset, UpgradeMode);
    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)
                                         std::map<unsigned short, APT::VersionSet> &verset, int UpgradeMode)
 {
 {
    // Enter the special broken fixing mode if the user specified arguments
    // Enter the special broken fixing mode if the user specified arguments
@@ -694,7 +694,7 @@ struct PkgIsExtraInstalled {
 bool DoInstall(CommandLine &CmdL)
 bool DoInstall(CommandLine &CmdL)
 {
 {
    CacheFile Cache;
    CacheFile Cache;
-   std::vector<char const *> VolatileCmdL;
+   std::vector<std::string> VolatileCmdL;
    Cache.GetSourceList()->AddVolatileFiles(CmdL, &VolatileCmdL);
    Cache.GetSourceList()->AddVolatileFiles(CmdL, &VolatileCmdL);
 
 
    // then open the cache
    // then open the cache

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

@@ -18,9 +18,9 @@ class pkgProblemResolver;
 
 
 APT_PUBLIC bool DoInstall(CommandLine &Cmd);
 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);
                                         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);
 bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache, int UpgradeMode);
 
 
 APT_PUBLIC bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
 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)
 bool DoBuildDep(CommandLine &CmdL)
 {
 {
    CacheFile Cache;
    CacheFile Cache;
-   std::vector<char const *> VolatileCmdL;
+   std::vector<std::string> VolatileCmdL;
    Cache.GetSourceList()->AddVolatileFiles(CmdL, &VolatileCmdL);
    Cache.GetSourceList()->AddVolatileFiles(CmdL, &VolatileCmdL);
 
 
    _config->Set("APT::Install-Recommends", false);
    _config->Set("APT::Install-Recommends", false);
@@ -702,18 +702,18 @@ bool DoBuildDep(CommandLine &CmdL)
       {
       {
 	 for (size_t i = 0; i < VolatileSources.size(); ++i)
 	 for (size_t i = 0; i < VolatileSources.size(); ++i)
 	 {
 	 {
-	    char const * const Src = VolatileCmdL[i];
+	    auto const Src = VolatileCmdL[i];
 	    if (DirectoryExists(Src))
 	    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
 	    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());
 	    std::unique_ptr<pkgSrcRecords::Parser> Last(VolatileSources[i]->CreateSrcParser());
 	    if (Last == nullptr)
 	    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;
 	    std::string const pseudo = std::string("builddeps:") + Src;
 	    WriteBuildDependencyPackage(buildDepsPkgFile, pseudo, pseudoArch,
 	    WriteBuildDependencyPackage(buildDepsPkgFile, pseudo, pseudoArch,
-		  GetBuildDeps(Last.get(), Src, StripMultiArch, hostArch));
+		  GetBuildDeps(Last.get(), Src.c_str(), StripMultiArch, hostArch));
 	    pseudoPkgs.emplace_back(pseudo, pseudoArch);
 	    pseudoPkgs.emplace_back(pseudo, pseudoArch);
 	 }
 	 }
       }
       }

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

@@ -19,7 +19,7 @@
 static bool UpgradeHelper(CommandLine &CmdL, int UpgradeFlags)
 static bool UpgradeHelper(CommandLine &CmdL, int UpgradeFlags)
 {
 {
    CacheFile Cache;
    CacheFile Cache;
-   std::vector<char const *> VolatileCmdL;
+   std::vector<std::string> VolatileCmdL;
    Cache.GetSourceList()->AddVolatileFiles(CmdL, &VolatileCmdL);
    Cache.GetSourceList()->AddVolatileFiles(CmdL, &VolatileCmdL);
 
 
    if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false)
    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-nodepends' 'Depends: unrelated'
 buildingpkg 'aptkeyuser-depends' 'Depends: gnupg'
 buildingpkg 'aptkeyuser-depends' 'Depends: gnupg'
 
 
-setupaptarchive
-
 insertinstalledpackage 'unrelated' 'native' '1'
 insertinstalledpackage 'unrelated' 'native' '1'
 insertinstalledpackage 'gnupg' '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
 cp rootdir/tmp/testsuccess.output apt.output
+testdpkginstalled 'aptkeyuser-depends'
 testfailure grep '^Warning: This will BREAK' apt.output
 testfailure grep '^Warning: This will BREAK' apt.output
 testsuccess grep '^Warning: apt-key' 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
 cp rootdir/tmp/testsuccess.output apt.output
+testdpkginstalled 'aptkeyuser-nodepends'
 testsuccess grep '^Warning: This will BREAK' apt.output
 testsuccess grep '^Warning: This will BREAK' apt.output
 testsuccess grep '^Warning: apt-key' apt.output
 testsuccess grep '^Warning: apt-key' apt.output