Explorar el Código

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
David Kalnischkies hace 13 años
padre
commit
8ba17539a3

+ 51 - 28
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)
 	 {

+ 1 - 5
debian/changelog

@@ -9,6 +9,7 @@ apt (0.9.8.3) UNRELEASED; urgency=low
   * fix priority sorting by prefering higher in MarkInstall
   * try all providers in order if uninstallable in MarkInstall
   * do unpacks before configures in SmartConfigure (Closes: #707578)
+  * fix support for multiple patterns in apt-cache search (Closes: #691453)
 
  -- David Kalnischkies <kalnischkies@gmail.com>  Sun, 09 Jun 2013 15:06:24 +0200
 
@@ -31,11 +32,6 @@ apt (0.9.8.2) unstable; urgency=low
   * Fix crash when the "mirror" method does not find any entry
     (closes: #699303)
 
-  [ Johan Kiviniemi ]
-  * cmdline/apt-key:
-    - Create new keyrings with mode 0644 instead of 0600.
-    - Accept a nonexistent --keyring file with the adv subcommand as well.
-
  -- Michael Vogt <mvo@debian.org>  Thu, 06 Jun 2013 19:15:14 +0200
 
 apt (0.9.8.1) unstable; urgency=low

+ 9 - 3
test/integration/framework

@@ -483,6 +483,7 @@ insertpackage() {
 	local VERSION="$4"
 	local DEPENDENCIES="$5"
 	local PRIORITY="${6:-optional}"
+	local DESCRIPTION="${7}"
 	local ARCHS=""
 	for arch in $(echo "$ARCH" | sed -e 's#,#\n#g' | sed -e "s#^native\$#$(getarchitecture 'native')#"); do
 		if [ "$arch" = 'all' -o "$arch" = 'none' ]; then
@@ -504,11 +505,16 @@ Maintainer: Joe Sixpack <joe@example.org>" >> $FILE
 			echo "Version: $VERSION
 Filename: pool/main/${NAME}/${NAME}_${VERSION}_${arch}.deb" >> $FILE
 			test -z "$DEPENDENCIES" || echo "$DEPENDENCIES" >> $FILE
-			echo "Description: an autogenerated dummy ${NAME}=${VERSION}/${RELEASE}
+			echo -n 'Description: ' >> $FILE
+			if [ -z "$DESCRIPTION" ]; then
+				echo "an autogenerated dummy ${NAME}=${VERSION}/${RELEASE}
  If you find such a package installed on your system,
  YOU did something horribly wrong! They are autogenerated
- und used only by testcases for APT and surf no other propose…
-" >> $FILE
+ und used only by testcases for APT and surf no other propose…" >> $FILE
+			else
+				echo "$DESCRIPTION" >> $FILE
+			fi
+			echo >> $FILE
 		done
 	done
 }

+ 33 - 0
test/integration/test-bug-691453-apt-cache-search-multi-pattern

@@ -0,0 +1,33 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+setupenvironment
+configarchitecture 'native'
+
+insertpackage 'unstable' 'foobar' 'native' '1' '' '' 'funky tool'
+insertpackage 'unstable' 'coolstuff' 'native' '1' '' '' 'funky tool just like foo and bar'
+insertpackage 'unstable' 'foo' 'native' '1' '' '' 'tool best used with bar'
+insertpackage 'unstable' 'bar' 'native' '1' '' '' 'tool best used with foo'
+insertpackage 'unstable' 'baz' 'native' '1' 'Provides: bar' '' 'alternative tool best used with foo'
+
+setupaptarchive
+
+# in this special case the following queries should be equal
+FOOBAR='foobar - funky tool
+coolstuff - funky tool just like foo and bar
+foo - tool best used with bar
+bar - tool best used with foo
+baz - alternative tool best used with foo'
+
+testequal "$FOOBAR" aptcache search foo
+testequal "$FOOBAR" aptcache search bar
+testequal "$FOOBAR" aptcache search foo bar
+
+testequal 'foobar - funky tool
+foo - tool best used with bar' aptcache search -n foo
+testequal 'foobar - funky tool
+bar - tool best used with foo
+baz - alternative tool best used with foo' aptcache search -n bar
+testequal 'foobar - funky tool' aptcache search -n foo bar