From 8ba17539a3ec33abc283ca382cca6e59876a0f07 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 25 May 2013 19:57:48 +0200 Subject: fix support for multiple patterns in apt-cache search Patterns can appear in the name as well as in the description, they don't have to match all in the name/description only. Closes: 691453 --- cmdline/apt-cache.cc | 79 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 28 deletions(-) (limited to 'cmdline') diff --git a/cmdline/apt-cache.cc b/cmdline/apt-cache.cc index de263a300..bda09a5a1 100644 --- a/cmdline/apt-cache.cc +++ b/cmdline/apt-cache.cc @@ -1203,7 +1203,7 @@ bool DisplayRecord(pkgCacheFile &CacheFile, pkgCache::VerIterator V) struct ExDescFile { pkgCache::DescFile *Df; - bool NameMatch; + map_ptrloc ID; }; // Search - Perform a search /*{{{*/ @@ -1246,37 +1246,48 @@ bool Search(CommandLine &CmdL) return false; } - ExDescFile *DFList = new ExDescFile[Cache->HeaderP->GroupCount+1]; - memset(DFList, 0, sizeof(*DFList) * (Cache->HeaderP->GroupCount + 1)); + size_t const descCount = Cache->HeaderP->GroupCount + 1; + ExDescFile *DFList = new ExDescFile[descCount]; + memset(DFList,0,sizeof(*DFList) * descCount); + + bool PatternMatch[descCount * NumPatterns]; + memset(PatternMatch,false,sizeof(PatternMatch)); // Map versions that we want to write out onto the VerList array. for (pkgCache::GrpIterator G = Cache->GrpBegin(); G.end() == false; ++G) { - if (DFList[G->ID].NameMatch == true) - continue; - - DFList[G->ID].NameMatch = true; - for (unsigned I = 0; I != NumPatterns; I++) + size_t const PatternOffset = G->ID * NumPatterns; + size_t unmatched = 0, matched = 0; + for (unsigned I = 0; I < NumPatterns; ++I) { - if (regexec(&Patterns[I],G.Name(),0,0,0) == 0) - continue; - DFList[G->ID].NameMatch = false; - break; + if (PatternMatch[PatternOffset + I] == true) + ++matched; + else if (regexec(&Patterns[I],G.Name(),0,0,0) == 0) + PatternMatch[PatternOffset + I] = true; + else + ++unmatched; } - - // Doing names only, drop any that dont match.. - if (NamesOnly == true && DFList[G->ID].NameMatch == false) + + // already dealt with this package? + if (matched == NumPatterns) continue; - + + // Doing names only, drop any that don't match.. + if (NamesOnly == true && unmatched == NumPatterns) + continue; + // Find the proper version to use pkgCache::PkgIterator P = G.FindPreferredPkg(); if (P.end() == true) continue; pkgCache::VerIterator V = Plcy->GetCandidateVer(P); if (V.end() == false) + { DFList[G->ID].Df = V.TranslatedDescription().FileList(); + DFList[G->ID].ID = G->ID; + } - if (DFList[G->ID].NameMatch == false) + if (unmatched == NumPatterns) continue; // Include all the packages that provide matching names too @@ -1288,33 +1299,45 @@ bool Search(CommandLine &CmdL) unsigned long id = Prv.OwnerPkg().Group()->ID; DFList[id].Df = V.TranslatedDescription().FileList(); - DFList[id].NameMatch = true; + DFList[id].ID = id; + + size_t const PrvPatternOffset = id * NumPatterns; + for (unsigned I = 0; I < NumPatterns; ++I) + PatternMatch[PrvPatternOffset + I] = PatternMatch[PatternOffset + I]; } } - + LocalitySort(&DFList->Df,Cache->HeaderP->GroupCount,sizeof(*DFList)); // Create the text record parser pkgRecords Recs(*Cache); // Iterate over all the version records and check them - for (ExDescFile *J = DFList; J->Df != 0; J++) + for (ExDescFile *J = DFList; J->Df != 0; ++J) { pkgRecords::Parser &P = Recs.Lookup(pkgCache::DescFileIterator(*Cache,J->Df)); + size_t const PatternOffset = J->ID * NumPatterns; - if (J->NameMatch == false && NamesOnly == false) + if (NamesOnly == false) { string const LongDesc = P.LongDesc(); - J->NameMatch = true; - for (unsigned I = 0; I != NumPatterns; I++) + for (unsigned I = 0; I < NumPatterns; ++I) { - if (regexec(&Patterns[I],LongDesc.c_str(),0,0,0) == 0) + if (PatternMatch[PatternOffset + I] == true) continue; - J->NameMatch = false; - break; + else if (regexec(&Patterns[I],LongDesc.c_str(),0,0,0) == 0) + PatternMatch[PatternOffset + I] = true; } } - - if (J->NameMatch == true) + + bool matchedAll = true; + for (unsigned I = 0; I < NumPatterns; ++I) + if (PatternMatch[PatternOffset + I] == false) + { + matchedAll = false; + break; + } + + if (matchedAll == true) { if (ShowFull == true) { -- cgit v1.2.3