[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#122304: bug-fix patch



The problem we were having was that the order of the arguments specified
mattered.

If you tried to run:
apt-get install package1 package2
it put in a different package set than it did when you ran
apt-get install package2 package1

The problem came when package2 had a single dependency that was a
secondary member of an Or group for package1.

IE
Package: Package1
...
Depends: Package3 | Package4

Package: Package2
...
Depends: Package4, PackageX...

By the time it started processing dependencies for Package2 (the second
user-specified argument) it had already decided to install Package3 to
satisfy the (Package3 | Package4) Or group. Then when it saw that
Package2 depends on Package4, it marked that one for install but did not
un-mark Package3.

Since the problem was that the decision was being made to early, what I
did was postpone the decision. I modified
apt-pkg/depcache.cc::MarkInstall to skip Or groups instead of finding a
package to satisfy and recursing. Next I added a new function
apt-pkg/depcache.cc::MarkOrsInstall that is to be called after ALL of
the user-specified arguments had been through MarkInstall. At that point
I could tell if a secondary member of an Or group had already been
marked for install (in other words if it existed as a single dependency
elsewhere). Or groups that have a member already marked are considered
satisfied and only MarkOrsInstall is called for that package. Or groups
that do NOT have a member already marked are satisfied with their first
member and both MarkInstall and MarkOrsInstall are called for that
package.

In order to make this work I also had to make trivial modications to
cmdline/apt-get.cc. The loop in DoInstall now stores each package name
that it processes in a vector so that it may be passed to
TryToInstallOrs (made just for design-consistancy). TryToInstallOrs
calls MarkOrsInstall in apt-pkg/depcache.cc

At any rate, I've attached a diff file for your consideration.
Thank you.
diff --ignore-space-change -x '*~' -urN apt-0.5.25.orig/apt-pkg/depcache.cc apt-0.5.25.mine/apt-pkg/depcache.cc
--- apt-0.5.25.orig/apt-pkg/depcache.cc	2001-05-26 23:36:04.000000000 -0600
+++ apt-0.5.25.mine/apt-pkg/depcache.cc	2004-05-28 13:10:23.000000000 -0600
@@ -588,6 +588,92 @@
    Update(Pkg);
    AddSizes(Pkg);
 }
+
+void pkgDepCache::MarkOrsInstall(vector<PkgIterator> &packages)
+{
+	/*
+	 * This walks through a complete list of user-specified packages
+	 * and marks up the Ors.
+	 * Pre: All single-dependencies of each package in the vector are
+	 *      marked for install
+	 * Post: All dependencies are satisfied.
+	 */
+	 //if the passed-in vector is empty, return
+	 if (packages.size() == 0)
+	 	return;
+	 vector<PkgIterator>::iterator arguments = packages.begin();
+	 //this member function needs to be recursive so that all of
+	 //the Or groups in all of the packages are taken care of but
+	 //it accepts a vector<PkgIterator> so we need to create one
+	 //do pass when we recurse.
+	 vector<PkgIterator> PackagesWithOrsToResolve;
+	 for (; arguments != packages.end(); arguments++)
+	 {
+	 	//get a DepIterator for this package's dependency linked list
+	 	DepIterator Dep = PkgState[(*arguments)->ID].InstVerIter(*this).DependsList();
+		while (Dep.end() != true)
+		{
+			DepIterator endOfOrIterator = Dep;
+			//move the endOfOrIterator to the last member of the Or group
+			//or fail to move it if the dependency is not part of such a
+			//group
+			while ((endOfOrIterator->CompareOp & Dep::Or) == Dep::Or)
+				endOfOrIterator++;
+			//if this wasn't an or it's already been taken care of
+			if (endOfOrIterator == Dep)
+			{
+				Dep++;
+				continue;
+			}
+			//actually the end iterator should be one beyond the end of the group
+			//set it now
+			endOfOrIterator++;
+			//If a member of an Or group has already been selected that means
+			//that it exists as a single-dependency of another package.
+			//Find out if that's the case.
+			bool memberIsInstalled = false;
+			DepIterator choice;
+			for (choice = Dep; choice != endOfOrIterator; choice++)
+			{
+				PkgIterator Res;
+				if (CheckDep(choice, choice->Type, Res))
+				{
+					PackagesWithOrsToResolve.push_back(Res);
+					memberIsInstalled = true;
+					break;
+				}
+			}
+			//if there is a member installed this group is satisfied, move on.
+			if (memberIsInstalled)
+			{
+				Dep = endOfOrIterator;
+				continue;
+			}
+			//at this point nothing odd was found and the correct satisfaction
+			//for this Or group is the first member. Reset choice.
+			choice = Dep;
+			//first check to see if it needs to be installed at all
+			if (IsImportantDep(choice) == false)
+			{
+				Dep = endOfOrIterator;
+				continue;
+			}
+			if ((*arguments)->CurrentVer != 0 && choice.IsCritical() == false)
+			{
+				Dep = endOfOrIterator;
+				continue;
+			}
+			//install the chosen package with autoinstalling enabled
+			MarkInstall(choice.TargetPkg(),true);
+			//push the package on to the vector to recurse on it
+			PackagesWithOrsToResolve.push_back(choice.TargetPkg());
+			//set Dep to the package just after the last dependency
+			Dep = endOfOrIterator;
+		}
+	 }
+	 //recurse
+	 MarkOrsInstall(PackagesWithOrsToResolve); 
+}
 									/*}}}*/
 // DepCache::MarkInstall - Put the package in the install state		/*{{{*/
 // ---------------------------------------------------------------------
@@ -667,11 +753,9 @@
 	 continue;
       if (Pkg->CurrentVer != 0 && Start.IsCritical() == false)
 	 continue;
-      
-      /* If we are in an or group locate the first or that can 
-         succeed. We have already cached this.. */
-      for (; Ors > 1 && (DepState[Start->ID] & DepCVer) != DepCVer; Ors--)
-	 Start++;
+      //skip Or groups, we'll deal with them later
+      if (Ors > 1) //because > 1 or means it's an Or group that needs to be skipped.
+	continue;
 
       /* This bit is for processing the possibilty of an install/upgrade
          fixing the problem */
@@ -715,7 +799,6 @@
 	    if (P->CurrentVer == 0)
 	       PkgState[InstPkg->ID].Flags |= Flag::Auto;
 	 }
-	 
 	 continue;
       }
       
diff --ignore-space-change -x '*~' -urN apt-0.5.25.orig/apt-pkg/depcache.h apt-0.5.25.mine/apt-pkg/depcache.h
--- apt-0.5.25.orig/apt-pkg/depcache.h	2001-02-20 00:03:17.000000000 -0700
+++ apt-0.5.25.mine/apt-pkg/depcache.h	2004-05-28 12:53:07.000000000 -0600
@@ -44,6 +44,8 @@
 
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/progress.h>
+#include <vector>
+using std::vector;
 
 class pkgDepCache : protected pkgCache::Namespace
 {
@@ -187,6 +189,7 @@
    void MarkDelete(PkgIterator const &Pkg,bool Purge = false);
    void MarkInstall(PkgIterator const &Pkg,bool AutoInst = true,
 		    unsigned long Depth = 0);
+   void MarkOrsInstall(vector<PkgIterator> &packages);
    void SetReInstall(PkgIterator const &Pkg,bool To);
    void SetCandidateVersion(VerIterator TargetVer);
    
diff --ignore-space-change -x '*~' -urN apt-0.5.25.orig/cmdline/apt-get.cc apt-0.5.25.mine/cmdline/apt-get.cc
--- apt-0.5.25.orig/cmdline/apt-get.cc	2004-02-26 12:17:55.000000000 -0700
+++ apt-0.5.25.mine/cmdline/apt-get.cc	2004-05-28 13:38:08.000000000 -0600
@@ -1321,6 +1321,16 @@
    
    return InstallPackages(Cache,true);
 }
+void TryToInstallOrs(vector<pkgCache::PkgIterator> arguments, pkgDepCache &Cache)
+{
+	/*
+	 * for consistency's sake this is basically a wrapper for
+	 * a call to Cache.MarkOrsInstall
+	 */
+	 Cache.MarkOrsInstall(arguments);
+}
+									
+									
 									/*}}}*/
 // DoInstall - Install packages from the command line			/*{{{*/
 // ---------------------------------------------------------------------
@@ -1345,6 +1355,8 @@
    if (strcasecmp(CmdL.FileList[0],"remove") == 0)
       DefRemove = true;
 
+   vector<pkgCache::PkgIterator> arguments;
+
    for (const char **I = CmdL.FileList + 1; *I != 0; I++)
    {
       // Duplicate the string
@@ -1396,6 +1408,7 @@
       
       // Locate the package
       pkgCache::PkgIterator Pkg = Cache->FindPkg(S);
+      arguments.push_back (Pkg);
       Packages++;
       if (Pkg.end() == true)
       {
@@ -1453,6 +1466,8 @@
 	    return false;
       }      
    }
+   //satisfy the Or groups
+   TryToInstallOrs(arguments, Cache);
 
    /* If we are in the Broken fixing mode we do not attempt to fix the
       problems. This is if the user invoked install without -f and gave
diff --ignore-space-change -x '*~' -urN apt-0.5.25.orig/po/apt-all.pot apt-0.5.25.mine/po/apt-all.pot
--- apt-0.5.25.orig/po/apt-all.pot	2004-05-08 13:41:36.000000000 -0600
+++ apt-0.5.25.mine/po/apt-all.pot	2004-05-28 13:45:41.000000000 -0600
@@ -7,7 +7,7 @@
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2004-04-29 21:56-0700\n"
+"POT-Creation-Date: 2004-05-28 13:45-0600\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -148,7 +148,7 @@
 
 #: cmdline/apt-cache.cc:1646 cmdline/apt-cdrom.cc:731 cmdline/apt-config.cc:70
 #: cmdline/apt-extracttemplates.cc:225 ftparchive/apt-ftparchive.cc:545
-#: cmdline/apt-get.cc:2260 cmdline/apt-sortpkgs.cc:144
+#: cmdline/apt-get.cc:2275 cmdline/apt-sortpkgs.cc:144
 #, c-format
 msgid "%s %s for %s %s compiled on %s %s\n"
 msgstr ""
@@ -518,7 +518,7 @@
 msgid "Y"
 msgstr ""
 
-#: cmdline/apt-get.cc:140 cmdline/apt-get.cc:1422
+#: cmdline/apt-get.cc:140 cmdline/apt-get.cc:1435
 #, c-format
 msgid "Regex compilation error - %s"
 msgstr ""
@@ -649,11 +649,11 @@
 msgid "Packages need to be removed but Remove is disabled."
 msgstr ""
 
-#: cmdline/apt-get.cc:744 cmdline/apt-get.cc:1716 cmdline/apt-get.cc:1749
+#: cmdline/apt-get.cc:744 cmdline/apt-get.cc:1731 cmdline/apt-get.cc:1764
 msgid "Unable to lock the download directory"
 msgstr ""
 
-#: cmdline/apt-get.cc:754 cmdline/apt-get.cc:1797 cmdline/apt-get.cc:2008
+#: cmdline/apt-get.cc:754 cmdline/apt-get.cc:1812 cmdline/apt-get.cc:2023
 #: apt-pkg/cachefile.cc:67
 msgid "The list of sources could not be read."
 msgstr ""
@@ -711,7 +711,7 @@
 msgid "Do you want to continue? [Y/n] "
 msgstr ""
 
-#: cmdline/apt-get.cc:911 cmdline/apt-get.cc:1281 cmdline/apt-get.cc:1906
+#: cmdline/apt-get.cc:911 cmdline/apt-get.cc:1281 cmdline/apt-get.cc:1921
 #, c-format
 msgid "Failed to fetch %s  %s\n"
 msgstr ""
@@ -720,7 +720,7 @@
 msgid "Some files failed to download"
 msgstr ""
 
-#: cmdline/apt-get.cc:930 cmdline/apt-get.cc:1915
+#: cmdline/apt-get.cc:930 cmdline/apt-get.cc:1930
 msgid "Download complete and in download only mode"
 msgstr ""
 
@@ -830,27 +830,27 @@
 msgid "Internal Error, AllUpgrade broke stuff"
 msgstr ""
 
-#: cmdline/apt-get.cc:1409 cmdline/apt-get.cc:1445
+#: cmdline/apt-get.cc:1422 cmdline/apt-get.cc:1458
 #, c-format
 msgid "Couldn't find package %s"
 msgstr ""
 
-#: cmdline/apt-get.cc:1432
+#: cmdline/apt-get.cc:1445
 #, c-format
 msgid "Note, selecting %s for regex '%s'\n"
 msgstr ""
 
-#: cmdline/apt-get.cc:1462
+#: cmdline/apt-get.cc:1477
 msgid "You might want to run `apt-get -f install' to correct these:"
 msgstr ""
 
-#: cmdline/apt-get.cc:1465
+#: cmdline/apt-get.cc:1480
 msgid ""
 "Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a "
 "solution)."
 msgstr ""
 
-#: cmdline/apt-get.cc:1477
+#: cmdline/apt-get.cc:1492
 msgid ""
 "Some packages could not be installed. This may mean that you have\n"
 "requested an impossible situation or if you are using the unstable\n"
@@ -858,149 +858,149 @@
 "or been moved out of Incoming."
 msgstr ""
 
-#: cmdline/apt-get.cc:1485
+#: cmdline/apt-get.cc:1500
 msgid ""
 "Since you only requested a single operation it is extremely likely that\n"
 "the package is simply not installable and a bug report against\n"
 "that package should be filed."
 msgstr ""
 
-#: cmdline/apt-get.cc:1490
+#: cmdline/apt-get.cc:1505
 msgid "The following information may help to resolve the situation:"
 msgstr ""
 
-#: cmdline/apt-get.cc:1493
+#: cmdline/apt-get.cc:1508
 msgid "Broken packages"
 msgstr ""
 
-#: cmdline/apt-get.cc:1519
+#: cmdline/apt-get.cc:1534
 msgid "The following extra packages will be installed:"
 msgstr ""
 
-#: cmdline/apt-get.cc:1590
+#: cmdline/apt-get.cc:1605
 msgid "Suggested packages:"
 msgstr ""
 
-#: cmdline/apt-get.cc:1591
+#: cmdline/apt-get.cc:1606
 msgid "Recommended packages:"
 msgstr ""
 
-#: cmdline/apt-get.cc:1611
+#: cmdline/apt-get.cc:1626
 msgid "Calculating Upgrade... "
 msgstr ""
 
-#: cmdline/apt-get.cc:1614 methods/ftp.cc:702 methods/connect.cc:99
+#: cmdline/apt-get.cc:1629 methods/ftp.cc:702 methods/connect.cc:99
 msgid "Failed"
 msgstr ""
 
-#: cmdline/apt-get.cc:1619
+#: cmdline/apt-get.cc:1634
 msgid "Done"
 msgstr ""
 
-#: cmdline/apt-get.cc:1792
+#: cmdline/apt-get.cc:1807
 msgid "Must specify at least one package to fetch source for"
 msgstr ""
 
-#: cmdline/apt-get.cc:1819 cmdline/apt-get.cc:2026
+#: cmdline/apt-get.cc:1834 cmdline/apt-get.cc:2041
 #, c-format
 msgid "Unable to find a source package for %s"
 msgstr ""
 
-#: cmdline/apt-get.cc:1866
+#: cmdline/apt-get.cc:1881
 #, c-format
 msgid "You don't have enough free space in %s"
 msgstr ""
 
-#: cmdline/apt-get.cc:1871
+#: cmdline/apt-get.cc:1886
 #, c-format
 msgid "Need to get %sB/%sB of source archives.\n"
 msgstr ""
 
-#: cmdline/apt-get.cc:1874
+#: cmdline/apt-get.cc:1889
 #, c-format
 msgid "Need to get %sB of source archives.\n"
 msgstr ""
 
-#: cmdline/apt-get.cc:1880
+#: cmdline/apt-get.cc:1895
 #, c-format
 msgid "Fetch Source %s\n"
 msgstr ""
 
-#: cmdline/apt-get.cc:1911
+#: cmdline/apt-get.cc:1926
 msgid "Failed to fetch some archives."
 msgstr ""
 
-#: cmdline/apt-get.cc:1939
+#: cmdline/apt-get.cc:1954
 #, c-format
 msgid "Skipping unpack of already unpacked source in %s\n"
 msgstr ""
 
-#: cmdline/apt-get.cc:1951
+#: cmdline/apt-get.cc:1966
 #, c-format
 msgid "Unpack command '%s' failed.\n"
 msgstr ""
 
-#: cmdline/apt-get.cc:1968
+#: cmdline/apt-get.cc:1983
 #, c-format
 msgid "Build command '%s' failed.\n"
 msgstr ""
 
-#: cmdline/apt-get.cc:1987
+#: cmdline/apt-get.cc:2002
 msgid "Child process failed"
 msgstr ""
 
-#: cmdline/apt-get.cc:2003
+#: cmdline/apt-get.cc:2018
 msgid "Must specify at least one package to check builddeps for"
 msgstr ""
 
-#: cmdline/apt-get.cc:2031
+#: cmdline/apt-get.cc:2046
 #, c-format
 msgid "Unable to get build-dependency information for %s"
 msgstr ""
 
-#: cmdline/apt-get.cc:2051
+#: cmdline/apt-get.cc:2066
 #, c-format
 msgid "%s has no build depends.\n"
 msgstr ""
 
-#: cmdline/apt-get.cc:2103
+#: cmdline/apt-get.cc:2118
 #, c-format
 msgid ""
 "%s dependency for %s cannot be satisfied because the package %s cannot be "
 "found"
 msgstr ""
 
-#: cmdline/apt-get.cc:2155
+#: cmdline/apt-get.cc:2170
 #, c-format
 msgid ""
 "%s dependency for %s cannot be satisfied because no available versions of "
 "package %s can satisfy version requirements"
 msgstr ""
 
-#: cmdline/apt-get.cc:2190
+#: cmdline/apt-get.cc:2205
 #, c-format
 msgid "Failed to satisfy %s dependency for %s: Installed package %s is too new"
 msgstr ""
 
-#: cmdline/apt-get.cc:2215
+#: cmdline/apt-get.cc:2230
 #, c-format
 msgid "Failed to satisfy %s dependency for %s: %s"
 msgstr ""
 
-#: cmdline/apt-get.cc:2229
+#: cmdline/apt-get.cc:2244
 #, c-format
 msgid "Build-dependencies for %s could not be satisfied."
 msgstr ""
 
-#: cmdline/apt-get.cc:2233
+#: cmdline/apt-get.cc:2248
 msgid "Failed to process build dependencies"
 msgstr ""
 
-#: cmdline/apt-get.cc:2265
+#: cmdline/apt-get.cc:2280
 msgid "Supported Modules:"
 msgstr ""
 
-#: cmdline/apt-get.cc:2306
+#: cmdline/apt-get.cc:2321
 msgid ""
 "Usage: apt-get [options] command\n"
 "       apt-get [options] install|remove pkg1 [pkg2 ...]\n"
@@ -1544,7 +1544,7 @@
 msgid "Unable to accept connection"
 msgstr ""
 
-#: methods/ftp.cc:864 methods/http.cc:912 methods/rsh.cc:303
+#: methods/ftp.cc:864 methods/http.cc:916 methods/rsh.cc:303
 msgid "Problem hashing file"
 msgstr ""
 
@@ -1638,76 +1638,76 @@
 msgid "Read error from %s process"
 msgstr ""
 
-#: methods/http.cc:340
+#: methods/http.cc:344
 msgid "Waiting for headers"
 msgstr ""
 
-#: methods/http.cc:486
+#: methods/http.cc:490
 #, c-format
 msgid "Got a single header line over %u chars"
 msgstr ""
 
-#: methods/http.cc:494
+#: methods/http.cc:498
 msgid "Bad header line"
 msgstr ""
 
-#: methods/http.cc:513 methods/http.cc:520
+#: methods/http.cc:517 methods/http.cc:524
 msgid "The http server sent an invalid reply header"
 msgstr ""
 
-#: methods/http.cc:549
+#: methods/http.cc:553
 msgid "The http server sent an invalid Content-Length header"
 msgstr ""
 
-#: methods/http.cc:564
+#: methods/http.cc:568
 msgid "The http server sent an invalid Content-Range header"
 msgstr ""
 
-#: methods/http.cc:566
+#: methods/http.cc:570
 msgid "This http server has broken range support"
 msgstr ""
 
-#: methods/http.cc:590
+#: methods/http.cc:594
 msgid "Unknown date format"
 msgstr ""
 
-#: methods/http.cc:733
+#: methods/http.cc:737
 msgid "Select failed"
 msgstr ""
 
-#: methods/http.cc:738
+#: methods/http.cc:742
 msgid "Connection timed out"
 msgstr ""
 
-#: methods/http.cc:761
+#: methods/http.cc:765
 msgid "Error writing to output file"
 msgstr ""
 
-#: methods/http.cc:789
+#: methods/http.cc:793
 msgid "Error writing to file"
 msgstr ""
 
-#: methods/http.cc:814
+#: methods/http.cc:818
 msgid "Error writing to the file"
 msgstr ""
 
-#: methods/http.cc:828
+#: methods/http.cc:832
 msgid "Error reading from server Remote end closed connection"
 msgstr ""
 
-#: methods/http.cc:830
+#: methods/http.cc:834
 msgid "Error reading from server"
 msgstr ""
 
-#: methods/http.cc:1061
+#: methods/http.cc:1065
 msgid "Bad header Data"
 msgstr ""
 
-#: methods/http.cc:1078
+#: methods/http.cc:1082
 msgid "Connection failed"
 msgstr ""
 
-#: methods/http.cc:1169
+#: methods/http.cc:1173
 msgid "Internal error"
 msgstr ""
 

Reply to: