From: Michael Vogt Date: Thu, 8 May 2014 12:29:30 +0000 (+0200) Subject: Merge remote-tracking branch 'mvo/feature/build-dep-dsc2' into debian/experimental X-Git-Tag: 1.1.exp1~25 X-Git-Url: https://git.saurik.com/apt.git/commitdiff_plain/070536e61cb203a9c74013be2a26322b582a9674?ds=inline;hp=-c Merge remote-tracking branch 'mvo/feature/build-dep-dsc2' into debian/experimental Conflicts: apt-pkg/deb/debindexfile.cc apt-pkg/deb/debindexfile.h apt-pkg/deb/debsrcrecords.cc --- 070536e61cb203a9c74013be2a26322b582a9674 diff --combined apt-pkg/deb/debindexfile.cc index 86ef92bfb,bb6884123..37efa05b0 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@@ -30,7 -30,6 +30,7 @@@ #include #include #include +#include #include #include @@@ -668,97 -667,42 +668,132 @@@ APT_CONST bool debStatusIndex::Exists( } /*}}}*/ +// debDebPkgFile - Single .deb file /*{{{*/ +// --------------------------------------------------------------------- +debDebPkgFileIndex::debDebPkgFileIndex(std::string DebFile) + : pkgIndexFile(true), DebFile(DebFile) +{ + DebFileFullPath = flAbsPath(DebFile); +} + +std::string debDebPkgFileIndex::ArchiveURI(std::string /*File*/) const +{ + return "file:" + DebFileFullPath; +} + +bool debDebPkgFileIndex::Exists() const +{ + return FileExists(DebFile); +} +bool debDebPkgFileIndex::Merge(pkgCacheGenerator& Gen, OpProgress* Prog) const +{ + if(Prog) + Prog->SubProgress(0, "Reading deb file"); + + // get the control data out of the deb file vid dpkg -I + // ... can I haz libdpkg? + const char *Args[5] = {"/usr/bin/dpkg", + "-I", + DebFile.c_str(), + "control", + NULL}; + FileFd PipeFd; + pid_t Child; + if(Popen(Args, PipeFd, Child, FileFd::ReadOnly) == false) + return _error->Error("Popen failed"); + // FIXME: static buffer + char buf[8*1024]; + unsigned long long n = 0; + if(PipeFd.Read(buf, sizeof(buf)-1, &n) == false) + return _error->Errno("read", "Failed to read dpkg pipe"); + ExecWait(Child, "Popen"); + + // now write the control data to a tempfile + SPtr DebControl = GetTempFile("deb-file-" + DebFile); + if(DebControl == NULL) + return false; + DebControl->Write(buf, n); + // append size of the file + FileFd Fd(DebFile, FileFd::ReadOnly); + string Size; + strprintf(Size, "Size: %llu\n", Fd.Size()); + DebControl->Write(Size.c_str(), Size.size()); + // and rewind for the listparser + DebControl->Seek(0); + + // and give it to the list parser + debDebFileParser Parser(DebControl, DebFile); + if(Gen.SelectFile(DebFile, "local", *this) == false) + return _error->Error("Problem with SelectFile %s", DebFile.c_str()); + + pkgCache::PkgFileIterator File = Gen.GetCurFile(); + File->Size = DebControl->Size(); + File->mtime = DebControl->ModificationTime(); + + if (Gen.MergeList(Parser) == false) + return _error->Error("Problem with MergeLister for %s", DebFile.c_str()); + + return true; +} +pkgCache::PkgFileIterator debDebPkgFileIndex::FindInCache(pkgCache &Cache) const +{ + // FIXME: we could simply always return pkgCache::PkgFileIterator(Cache); + // to indicate its never in the cache which will force a Merge() + pkgCache::PkgFileIterator File = Cache.FileBegin(); + for (; File.end() == false; ++File) + { + if (File.FileName() == NULL || DebFile != File.FileName()) + continue; + + return File; + } + + return File; +} +unsigned long debDebPkgFileIndex::Size() const +{ + struct stat buf; + if(stat(DebFile.c_str(), &buf) != 0) + return 0; + return buf.st_size; +} + /*}}}*/ + // debDscFileIndex stuff + debDscFileIndex::debDscFileIndex(std::string &DscFile) + : pkgIndexFile(true), DscFile(DscFile) + { + } + + bool debDscFileIndex::Exists() const + { + return FileExists(DscFile); + } + + unsigned long debDscFileIndex::Size() const + { + struct stat buf; + if(stat(DscFile.c_str(), &buf) == 0) + return buf.st_size; + return 0; + } + + // DscFileIndex::CreateSrcParser - Get a parser for the .dsc file /*{{{*/ + // --------------------------------------------------------------------- + /* */ + pkgSrcRecords::Parser *debDscFileIndex::CreateSrcParser() const + { + if (!FileExists(DscFile)) + return NULL; + + return new debDscRecordParser(DscFile,this); + } + /*}}}*/ + + + + + // --------------------------------------------------------------------- // Index File types for Debian /*{{{*/ class debIFTypeSrc : public pkgIndexFile::Type { @@@ -791,20 -735,32 +826,42 @@@ class debIFTypeStatus : public pkgIndex }; debIFTypeStatus() {Label = "Debian dpkg status file";}; }; +class debIFTypeDebPkgFile : public pkgIndexFile::Type +{ + public: + virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const + { + return new debDebFileRecordParser(File.FileName(),*File.Cache()); + }; + debIFTypeDebPkgFile() {Label = "deb Package file";}; +}; + class debIFTypeDscFile : public pkgIndexFile::Type + { + public: + virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string DscFile) const + { + return new debDscRecordParser(DscFile, NULL); + }; + debIFTypeDscFile() {Label = "dsc File Source Index";}; + }; + class debIFTypeDebianSourceDir : public pkgIndexFile::Type + { + public: + virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string SourceDir) const + { + return new debDscRecordParser(SourceDir + string("/debian/control"), NULL); + }; + debIFTypeDebianSourceDir() {Label = "debian/control File Source Index";}; + }; + static debIFTypeSrc _apt_Src; static debIFTypePkg _apt_Pkg; static debIFTypeTrans _apt_Trans; static debIFTypeStatus _apt_Status; +static debIFTypeDebPkgFile _apt_DebPkgFile; + // file based pseudo indexes + static debIFTypeDscFile _apt_DscFile; + static debIFTypeDebianSourceDir _apt_DebianSourceDir; const pkgIndexFile::Type *debSourcesIndex::GetType() const { @@@ -822,8 -778,13 +879,16 @@@ const pkgIndexFile::Type *debStatusInde { return &_apt_Status; } +const pkgIndexFile::Type *debDebPkgFileIndex::GetType() const +{ + return &_apt_DebPkgFile; ++} + const pkgIndexFile::Type *debDscFileIndex::GetType() const + { + return &_apt_DscFile; + } + const pkgIndexFile::Type *debDebianSourceDirIndex::GetType() const + { + return &_apt_DebianSourceDir; } - /*}}}*/ diff --combined apt-pkg/deb/debindexfile.h index 69754e79d,64ca558d2..18322dc1b --- a/apt-pkg/deb/debindexfile.h +++ b/apt-pkg/deb/debindexfile.h @@@ -164,35 -164,27 +164,57 @@@ class debSourcesIndex : public pkgIndex virtual ~debSourcesIndex() {}; }; +class debDebPkgFileIndex : public pkgIndexFile +{ + private: + void *d; + std::string DebFile; + std::string DebFileFullPath; + + public: + virtual const Type *GetType() const APT_CONST; + + virtual std::string Describe(bool /*Short*/) const { + return DebFile; + } + + // Interface for the Cache Generator + virtual bool Exists() const; + virtual bool HasPackages() const { + return true; + }; + virtual unsigned long Size() const; + virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const; + virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const; + + // Interface for acquire + virtual std::string ArchiveURI(std::string /*File*/) const; + + debDebPkgFileIndex(std::string DebFile); + virtual ~debDebPkgFileIndex() {}; - ++}; ++ + class debDscFileIndex : public pkgIndexFile + { + private: + std::string DscFile; + public: + virtual const Type *GetType() const APT_CONST; + virtual pkgSrcRecords::Parser *CreateSrcParser() const; + virtual bool Exists() const; + virtual bool HasPackages() const {return false;}; + virtual unsigned long Size() const; + virtual std::string Describe(bool /*Short*/) const { + return DscFile; + }; + + debDscFileIndex(std::string &DscFile); + virtual ~debDscFileIndex() {}; + }; + + class debDebianSourceDirIndex : public debDscFileIndex + { + virtual const Type *GetType() const APT_CONST; }; #endif diff --combined apt-pkg/deb/debmetaindex.cc index 56eecdca1,6fd12add8..b4839ada4 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@@ -471,15 -471,6 +471,15 @@@ class debSLTypeDebian : public pkgSourc } }; +debDebFileMetaIndex::debDebFileMetaIndex(std::string const &DebFile) + : metaIndex(DebFile, "local-uri", "deb-dist"), DebFile(DebFile) +{ + DebIndex = new debDebPkgFileIndex(DebFile); + Indexes = new vector(); + Indexes->push_back(DebIndex); +} + + class debSLTypeDeb : public debSLTypeDebian { public: @@@ -516,25 -507,5 +516,25 @@@ class debSLTypeDebSrc : public debSLTyp } }; +class debSLTypeDebFile : public pkgSourceList::Type +{ + public: + + bool CreateItem(vector &List, string const &URI, - string const &Dist, string const &Section, - std::map const &Options) const ++ string const &/*Dist*/, string const &/*Section*/, ++ std::map const &/*Options*/) const + { + metaIndex *mi = new debDebFileMetaIndex(URI); + List.push_back(mi); + return true; + } + + debSLTypeDebFile() + { + Name = "deb-file"; + Label = "Debian Deb File"; + } +}; debSLTypeDeb _apt_DebType; debSLTypeDebSrc _apt_DebSrcType; +debSLTypeDebFile _apt_DebFileType; diff --combined apt-pkg/deb/debsrcrecords.cc index 615f0f57d,8aad81e3c..7b9a828d3 --- a/apt-pkg/deb/debsrcrecords.cc +++ b/apt-pkg/deb/debsrcrecords.cc @@@ -18,7 -18,7 +18,8 @@@ #include #include #include +#include + #include #include #include @@@ -122,86 -122,64 +123,86 @@@ bool debSrcRecordParser::BuildDepends(s bool debSrcRecordParser::Files(std::vector &List) { List.erase(List.begin(),List.end()); + + // map from the Hashsum field to the hashsum function, + // unfortunately this is not a 1:1 mapping from + // Hashes::SupporedHashes as e.g. Files is a historic name for the md5 + const std::pair SourceHashFields[] = { + std::make_pair( "Checksums-Sha512", "SHA512"), + std::make_pair( "Checksums-Sha256", "SHA256"), + std::make_pair( "Checksums-Sha1", "SHA1"), + std::make_pair( "Files", "MD5Sum"), // historic Name + }; - string Files = Sect.FindS("Files"); - if (Files.empty() == true) - return false; - - // Stash the / terminated directory prefix - string Base = Sect.FindS("Directory"); - if (Base.empty() == false && Base[Base.length()-1] != '/') - Base += '/'; - - std::vector const compExts = APT::Configuration::getCompressorExtensions(); - - // Iterate over the entire list grabbing each triplet - const char *C = Files.c_str(); - while (*C != 0) - { - pkgSrcRecords::File F; - string Size; - - // Parse each of the elements - if (ParseQuoteWord(C,F.MD5Hash) == false || - ParseQuoteWord(C,Size) == false || - ParseQuoteWord(C,F.Path) == false) - return _error->Error("Error parsing file record"); - - // Parse the size and append the directory - F.Size = atoi(Size.c_str()); - F.Path = Base + F.Path; - - // Try to guess what sort of file it is we are getting. - string::size_type Pos = F.Path.length()-1; - while (1) - { - string::size_type Tmp = F.Path.rfind('.',Pos); - if (Tmp == string::npos) - break; - if (F.Type == "tar") { - // source v3 has extension 'debian.tar.*' instead of 'diff.*' - if (string(F.Path, Tmp+1, Pos-Tmp) == "debian") - F.Type = "diff"; - break; - } - F.Type = string(F.Path,Tmp+1,Pos-Tmp); - - if (std::find(compExts.begin(), compExts.end(), std::string(".").append(F.Type)) != compExts.end() || - F.Type == "tar") - { - Pos = Tmp-1; - continue; - } + for (unsigned int i=0; + i < sizeof(SourceHashFields)/sizeof(SourceHashFields[0]); + i++) + { + string Files = Sect.FindS(SourceHashFields[i].first); + if (Files.empty() == true) + continue; + + // Stash the / terminated directory prefix + string Base = Sect.FindS("Directory"); + if (Base.empty() == false && Base[Base.length()-1] != '/') + Base += '/'; + + std::vector const compExts = APT::Configuration::getCompressorExtensions(); + + // Iterate over the entire list grabbing each triplet + const char *C = Files.c_str(); + while (*C != 0) + { + pkgSrcRecords::File F; + string Size; + + // Parse each of the elements + std::string RawHash; + if (ParseQuoteWord(C, RawHash) == false || + ParseQuoteWord(C, Size) == false || + ParseQuoteWord(C, F.Path) == false) + return _error->Error("Error parsing '%s' record", + SourceHashFields[i].first); + // assign full hash string + F.Hash = HashString(SourceHashFields[i].second, RawHash).toStr(); + // API compat hack + if(strcmp(SourceHashFields[i].second, "MD5Sum") == 0) + F.MD5Hash = RawHash; + + // Parse the size and append the directory + F.Size = atoi(Size.c_str()); + F.Path = Base + F.Path; + + // Try to guess what sort of file it is we are getting. + string::size_type Pos = F.Path.length()-1; + while (1) + { + string::size_type Tmp = F.Path.rfind('.',Pos); + if (Tmp == string::npos) + break; + if (F.Type == "tar") { + // source v3 has extension 'debian.tar.*' instead of 'diff.*' + if (string(F.Path, Tmp+1, Pos-Tmp) == "debian") + F.Type = "diff"; + break; + } + F.Type = string(F.Path,Tmp+1,Pos-Tmp); + + if (std::find(compExts.begin(), compExts.end(), std::string(".").append(F.Type)) != compExts.end() || + F.Type == "tar") + { + Pos = Tmp-1; + continue; + } - break; - } + break; + } - List.push_back(F); + List.push_back(F); + } + break; } - - return true; + return (List.size() > 0); } /*}}}*/ // SrcRecordParser::~SrcRecordParser - Destructor /*{{{*/ @@@ -212,3 -190,21 +213,21 @@@ debSrcRecordParser::~debSrcRecordParser delete[] Buffer; } /*}}}*/ + + + debDscRecordParser::debDscRecordParser(std::string const &DscFile, pkgIndexFile const *Index) + : debSrcRecordParser(DscFile, Index) + { + // support clear signed files + if (OpenMaybeClearSignedFile(DscFile, Fd) == false) + { + _error->Error("Failed to open %s", DscFile.c_str()); + return; + } + + // re-init to ensure the updated Fd is used + Tags.Init(&Fd); + // read the first (and only) record + Step(); + + } diff --combined apt-pkg/sourcelist.h index 99e83f454,0ebf4e080..261dd8161 --- a/apt-pkg/sourcelist.h +++ b/apt-pkg/sourcelist.h @@@ -52,15 -52,7 +52,15 @@@ class pkgAcquire class pkgIndexFile; class metaIndex; -class pkgSourceList +class pkgSource +{ + protected: + + std::vector SrcList; + +}; + +class pkgSourceList : public pkgSource { public: @@@ -94,7 -86,7 +94,7 @@@ typedef std::vector::const_iterator const_iterator; - protected: + public: std::vector SrcList; diff --combined cmdline/apt-get.cc index f682074a7,6d6ba5ff9..1148dbbf3 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@@ -828,10 -828,13 +828,10 @@@ static bool DoSource(CommandLine &CmdL queued.insert(Last->Index().ArchiveURI(I->Path)); // check if we have a file with that md5 sum already localy - if(!I->MD5Hash.empty() && FileExists(flNotDir(I->Path))) + if(!I->Hash.empty() && FileExists(flNotDir(I->Path))) { - FileFd Fd(flNotDir(I->Path), FileFd::ReadOnly); - MD5Summation sum; - sum.AddFD(Fd.Fd(), Fd.Size()); - Fd.Close(); - if((string)sum.Result() == I->MD5Hash) + HashString hash_string = HashString(I->Hash); + if(hash_string.VerifyFile(flNotDir(I->Path))) { ioprintf(c1out,_("Skipping already downloaded file '%s'\n"), flNotDir(I->Path).c_str()); @@@ -840,7 -843,7 +840,7 @@@ } new pkgAcqFile(&Fetcher,Last->Index().ArchiveURI(I->Path), - I->MD5Hash,I->Size, + I->Hash,I->Size, Last->Index().SourceInfo(*Last,*I),Src); } } @@@ -1050,7 -1053,30 +1050,30 @@@ static bool DoBuildDep(CommandLine &Cmd for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++) { string Src; - pkgSrcRecords::Parser *Last = FindSrc(*I,Recs,SrcRecs,Src,Cache); + pkgSrcRecords::Parser *Last = 0; + + // a unpacked debian source tree + if (DirectoryExists(*I)) + { + // FIXME: how can we make this more elegant? + std::string TypeName = "debian/control File Source Index"; + pkgIndexFile::Type *Type = pkgIndexFile::Type::GetType(TypeName.c_str()); + if(Type != NULL) + Last = Type->CreateSrcPkgParser(*I); + } + // if its a local file (e.g. .dsc) use this + else if (FileExists(*I)) + { + // see if we can get a parser for this pkgIndexFile type + string TypeName = flExtension(*I) + " File Source Index"; + pkgIndexFile::Type *Type = pkgIndexFile::Type::GetType(TypeName.c_str()); + if(Type != NULL) + Last = Type->CreateSrcPkgParser(*I); + } else { + // normal case, search the cache for the source file + Last = FindSrc(*I,Recs,SrcRecs,Src,Cache); + } + if (Last == 0) return _error->Error(_("Unable to find a source package for %s"),Src.c_str()); @@@ -1068,7 -1094,7 +1091,7 @@@ } else if (Last->BuildDepends(BuildDeps, _config->FindB("APT::Get::Arch-Only", false), StripMultiArch) == false) return _error->Error(_("Unable to get build-dependency information for %s"),Src.c_str()); - + // Also ensure that build-essential packages are present Configuration::Item const *Opts = _config->Tree("APT::Build-Essential"); if (Opts) @@@ -1661,6 -1687,20 +1684,6 @@@ static bool ShowHelp(CommandLine & "pages for more information and options.\n" " This APT has Super Cow Powers.\n"); return true; -} - /*}}}*/ -// SigWinch - Window size change signal handler /*{{{*/ -// --------------------------------------------------------------------- -/* */ -static void SigWinch(int) -{ - // Riped from GNU ls -#ifdef TIOCGWINSZ - struct winsize ws; - - if (ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col >= 5) - ScreenWidth = ws.ws_col - 1; -#endif } /*}}}*/ int main(int argc,const char *argv[]) /*{{{*/ @@@ -1717,12 -1757,14 +1740,12 @@@ // see if we are in simulate mode CheckSimulateMode(CmdL); + // Init the signals + InitSignals(); + // Setup the output streams InitOutput(); - // Setup the signals - signal(SIGPIPE,SIG_IGN); - signal(SIGWINCH,SigWinch); - SigWinch(0); - // Match the operation CmdL.DispatchArg(Cmds);