Merged from trunk 9450:9460
authorFabian Groffen <grobian@gentoo.org>
Thu, 13 Mar 2008 18:12:17 +0000 (18:12 -0000)
committerFabian Groffen <grobian@gentoo.org>
Thu, 13 Mar 2008 18:12:17 +0000 (18:12 -0000)
   | 9451    | Make --prune and --depclean operate with missing             |
   | zmedico | dependencies when only asked to remove specific packages     |
   |         | since it's relatively safe in this case.                     |

   | 9452    | Convert PackageIndex.packages from a dict to a list so that  |
   | zmedico | in the future it will be possible to support multiple        |
   |         | packages with the same cpv.                                  |

   | 9453    | Make readpkgindex() and writepkgindex() private methods of   |
   | zmedico | PackageIndex.                                                |

   | 9455    | add some status messages, try to copy the tarball into       |
   | genone  | DISTDIR, use getopt for option parsing                       |

   | 9456    | Fix var_assign_re to recognize a call to the 'declare'       |
   | zmedico | builtin even when no options are given.                      |

   | 9457    | When all available ebuilds are masked, avoid producing       |
   | zmedico | warning message when the package does not need to be         |
   |         | reinstalled and the installed version is not masked.         |

   | 9458    | Bug #212882 - Fix lockfile() to handle errno.EACCES raised   |
   | zmedico | from the fcntl call since the spec says that it's equivalent |
   |         | to EAGAIN and it appears that CIFS returns EACCES in this    |
   |         | case.                                                        |

   | 9459    | - news bugfix from ferringb                                  |
   | solar   |                                                              |

   | 9460    | Make strip_empty() return a nedw list instead of working     |
   | zmedico | in-place. Thanks to RenĂ© Neumann <rene.neumann@necoro.net>  |
   |         | for the suggestion.                                          |

svn path=/main/branches/prefix/; revision=9461

bin/emaint
bin/filter-bash-environment.py
pym/_emerge/__init__.py
pym/portage/dbapi/bintree.py
pym/portage/dep.py
pym/portage/getbinpkg.py
pym/portage/locks.py
pym/portage/news.py

index 2f03202ce4f4d594ca9872d4edffa3dbc0745ac6..c2e3452902360163d0f314a9a09d9a5fb8b429e1 100755 (executable)
@@ -131,14 +131,17 @@ class BinhostHandler(object):
                        onProgress(maxval, 0)
                pkgindex = self._pkgindex
                missing = []
+               metadata = {}
+               for d in pkgindex.packages:
+                       metadata[d["CPV"]] = d
                for i, cpv in enumerate(cpv_all):
-                       d = pkgindex.packages.get(cpv)
+                       d = metadata.get(cpv)
                        if not d or "MD5" not in d:
                                missing.append(cpv)
                        if onProgress:
                                onProgress(maxval, i+1)
                errors = ["'%s' is not in Packages" % cpv for cpv in missing]
-               stale = set(pkgindex.packages).difference(cpv_all)
+               stale = set(metadata).difference(cpv_all)
                for cpv in stale:
                        errors.append("'%s' is not in the repository" % cpv)
                return errors
@@ -153,13 +156,16 @@ class BinhostHandler(object):
                        onProgress(maxval, 0)
                pkgindex = self._pkgindex
                missing = []
+               metadata = {}
+               for d in pkgindex.packages:
+                       metadata[d["CPV"]] = d
                for i, cpv in enumerate(cpv_all):
-                       d = pkgindex.packages.get(cpv)
+                       d = metadata.get(cpv)
                        if not d or "MD5" not in d:
                                bintree.inject(cpv)
                        if onProgress:
                                onProgress(maxval, i+1)
-               stale = set(pkgindex.packages).difference(cpv_all)
+               stale = set(metadata).difference(cpv_all)
                if stale:
                        from portage import locks
                        pkgindex_lock = locks.lockfile(
@@ -179,9 +185,11 @@ class BinhostHandler(object):
                                del bintree
                                portage.db[self._bintree.root]["bintree"] = self._bintree
                                self._bintree._populate()
-                               for cpv in set(self._pkgindex.packages).difference(
+                               for cpv in set(metadata).difference(
                                        self._bintree.dbapi.cpv_all()):
-                                       del self._pkgindex.packages[cpv]
+                                       del metadata[cpv]
+                               del pkgindex.packages[:]
+                               pkgindex.packages.extend(metadata.itervalues())
                                from portage.util import atomic_ofstream
                                f = atomic_ofstream(self._pkgindex_file)
                                try:
index 88ee400835211254841c1da07019e9b3547ccf33..323600916a03dac09b61c9a11d998ba9ee9a94ce 100755 (executable)
@@ -9,7 +9,7 @@ here_doc_re = re.compile(r'.*\s<<[-]?(\w+)$')
 func_start_re = re.compile(r'^[-\w]+\s*\(\)\s*$')
 func_end_re = re.compile(r'^\}$')
 
-var_assign_re = re.compile(r'(^|^declare\s+-\S+\s+|^export\s+)([^=\s]+)=("|\')?.*$')
+var_assign_re = re.compile(r'(^|^declare\s+-\S+\s+|^declare\s+|^export\s+)([^=\s]+)=("|\')?.*$')
 close_quote_re = re.compile(r'(\\"|"|\')\s*$')
 readonly_re = re.compile(r'^declare\s+-(\S*)r(\S*)\s+')
 
index 6f355935e69dde90778df572d3a64814b13b9107..d1f876065a53ee8caa9d43d2a841b14dc99aa57d 100644 (file)
@@ -1853,12 +1853,13 @@ class depgraph(object):
                        #    to prevent depclean from removing them
 
                        if arg_atoms:
+                               selective = "selective" in self.myparams
                                portdb = self.trees[pkg.root]["porttree"].dbapi
                                for arg, atom in arg_atoms:
                                        all_ebuilds_masked = bool(
                                                portdb.xmatch("match-all", atom) and
                                                not portdb.xmatch("bestmatch-visible", atom))
-                                       if all_ebuilds_masked:
+                                       if all_ebuilds_masked and not selective:
                                                self._missing_args.append((arg, atom))
 
                        if not visible(pkgsettings, pkg.cpv, pkg.metadata,
@@ -6415,6 +6416,14 @@ def action_depclean(settings, trees, ldpath_mtimes,
        # Kill packages that aren't explicitly merged or are required as a
        # dependency of another package. World file is explicit.
 
+       # Global depclean or prune operations are not very safe when there are
+       # missing dependencies since it's unknown how badly incomplete
+       # the dependency graph is, and we might accidentally remove packages
+       # that should have been pulled into the graph. On the other hand, it's
+       # relatively safe to ignore missing deps when only asked to remove
+       # specific packages.
+       allow_missing_deps = len(myfiles) > 0
+
        msg = []
        msg.append("Depclean may break link level dependencies.  Thus, it is\n")
        msg.append("recommended to use a tool such as " + good("`revdep-rebuild`") + " (from\n")
@@ -6629,13 +6638,13 @@ def action_depclean(settings, trees, ldpath_mtimes,
        if "--quiet" not in myopts:
                print "\b\b... done!\n"
 
-       if unresolveable:
+       if unresolveable and not allow_missing_deps:
                print "Dependencies could not be completely resolved due to"
                print "the following required packages not being installed:"
                print
                for atom in unresolveable:
                        print atom, "required by", " ".join(unresolveable[atom])
-       if unresolveable:
+       if unresolveable and not allow_missing_deps:
                print
                print "Have you forgotten to run " + good("`emerge --update --newuse --deep world`") + " prior to"
                print "%s?  It may be necessary to manually uninstall packages that no longer" % action
index a5ff09c5e67b32f492abf63139c98b418f46a29a..d634e816f8746ea0f340e88560c1bb5b715576fd 100644 (file)
@@ -387,7 +387,9 @@ class binarytree(object):
                        if not self._pkgindex_version_supported(pkgindex):
                                pkgindex = self._new_pkgindex()
                        header = pkgindex.header
-                       metadata = pkgindex.packages
+                       metadata = {}
+                       for d in pkgindex.packages:
+                               metadata[d["CPV"]] = d
                        update_pkgindex = False
                        for mydir in dirs:
                                for myfile in listdir(os.path.join(self.pkgdir, mydir)):
@@ -559,7 +561,8 @@ class binarytree(object):
                                stale = [cpv for cpv in metadata if cpv not in self._pkg_paths]
                                for cpv in stale:
                                        del metadata[cpv]
-                               #
+                               del pkgindex.packages[:]
+                               pkgindex.packages.extend(metadata.itervalues())
                                self._update_pkgindex_header(pkgindex.header)
                                from portage.util import atomic_ofstream
                                f = atomic_ofstream(self._pkgindex_file)
@@ -633,7 +636,9 @@ class binarytree(object):
                                finally:
                                        f.close()
                        if pkgindex:
-                               self._remotepkgs = pkgindex.packages
+                               self._remotepkgs = {}
+                               for d in pkgindex.packages:
+                                       self._remotepkgs[d["CPV"]] = d
                                self._remote_has_index = True
                                self._remote_base_uri = pkgindex.header.get("URI", base_url)
                                self.remotepkgs = {}
@@ -776,7 +781,14 @@ class binarytree(object):
                                self.dbapi.cpv_remove(cpv)
                                del self._pkg_paths[cpv]
                                return
-                       pkgindex.packages[cpv] = d
+                       # If found, remove package(s) with duplicate path.
+                       for i in xrange(len(pkgindex.packages) - 1, -1, -1):
+                               d2 = pkgindex.packages[i]
+                               if d2["CPV"] != cpv:
+                                       continue
+                               if d2.get("PATH") == d.get("PATH"):
+                                       del pkgindex.packages[i]
+                       pkgindex.packages.append(d)
                        self._update_pkgindex_header(pkgindex.header)
                        from portage.util import atomic_ofstream
                        f = atomic_ofstream(os.path.join(self.pkgdir, "Packages"))
index bf42d2ba85cfe70e0adbbf646f8b315e283a6158..2a1a3cfa59a8e090d4ada8687cf9ffc4081ba780 100644 (file)
@@ -63,11 +63,7 @@ def strip_empty(myarr):
        @rtype: Array
        @return: The array with empty elements removed
        """
-
-       for x in range(len(myarr)-1, -1, -1):
-               if not myarr[x]:
-                       del myarr[x]
-       return myarr
+       return [x for x in myarr if x]
 
 def paren_reduce(mystr,tokenize=1):
        """
index 6c2d32cdb7f83b040557f14ffc4166fac801afcf..c2fb48d031311bdca563e50d6d9a81959e7806a4 100644 (file)
@@ -656,25 +656,15 @@ def dir_get_metadata(baseurl, conn=None, chunk_size=3000, verbose=1, usingcache=
        
        return metadata[baseurl]["data"]
 
-def readpkgindex(pkgfile):
-       d = {}
-       for line in pkgfile:
-               line = line.rstrip("\n")
-               if not line:
-                       break
-               line = line.split(":", 1)
-               if not len(line) == 2:
-                       continue
-               k, v = line
-               if v:
-                       v = v[1:]
-               d[k] = v
-       return d
-
-def writepkgindex(pkgfile, items):
-       for k, v in items:
-               pkgfile.write("%s: %s\n" % (k, v))
-       pkgfile.write("\n")
+def _cmp_cpv(d1, d2):
+       cpv1 = d1["CPV"]
+       cpv2 = d2["CPV"]
+       if cpv1 > cpv2:
+               return 1
+       elif cpv1 == cpv2:
+               return 0
+       else:
+               return -1
 
 class PackageIndex(object):
 
@@ -682,19 +672,39 @@ class PackageIndex(object):
                self._default_pkg_data = default_pkg_data
                self._inherited_keys = inherited_keys
                self.header = {}
-               self.packages = {}
+               self.packages = []
                self.modified = True
 
+       def _readpkgindex(self, pkgfile):
+               d = {}
+               for line in pkgfile:
+                       line = line.rstrip("\n")
+                       if not line:
+                               break
+                       line = line.split(":", 1)
+                       if not len(line) == 2:
+                               continue
+                       k, v = line
+                       if v:
+                               v = v[1:]
+                       d[k] = v
+               return d
+       
+       def _writepkgindex(self, pkgfile, items):
+               for k, v in items:
+                       pkgfile.write("%s: %s\n" % (k, v))
+               pkgfile.write("\n")
+
        def read(self, pkgfile):
                self.readHeader(pkgfile)
                self.readBody(pkgfile)
 
        def readHeader(self, pkgfile):
-               self.header.update(readpkgindex(pkgfile))
+               self.header.update(self._readpkgindex(pkgfile))
 
        def readBody(self, pkgfile):
                while True:
-                       d = readpkgindex(pkgfile)
+                       d = self._readpkgindex(pkgfile)
                        if not d:
                                break
                        mycpv = d.get("CPV")
@@ -708,19 +718,18 @@ class PackageIndex(object):
                                        v = self.header.get(k)
                                        if v is not None:
                                                d.setdefault(k, v)
-                       self.packages[mycpv] = d
+                       self.packages.append(d)
 
        def write(self, pkgfile):
-               cpv_all = self.packages.keys()
-               cpv_all.sort()
                if self.modified:
                        self.header["TIMESTAMP"] = str(long(time.time()))
-                       self.header["PACKAGES"] = str(len(cpv_all))
+                       self.header["PACKAGES"] = str(len(self.packages))
                keys = self.header.keys()
                keys.sort()
-               writepkgindex(pkgfile, [(k, self.header[k]) for k in keys])
-               for cpv in cpv_all:
-                       metadata = self.packages[cpv].copy()
+               self._writepkgindex(pkgfile, [(k, self.header[k]) for k in keys])
+               for metadata in sorted(self.packages, _cmp_cpv):
+                       metadata = metadata.copy()
+                       cpv = metadata["CPV"]
                        if self._inherited_keys:
                                for k in self._inherited_keys:
                                        v = self.header.get(k)
@@ -732,5 +741,5 @@ class PackageIndex(object):
                                                metadata.pop(k, None)
                        keys = metadata.keys()
                        keys.sort()
-                       writepkgindex(pkgfile,
+                       self._writepkgindex(pkgfile,
                                [(k, metadata[k]) for k in keys if metadata[k]])
index 19762abbe80a1147284959866a50202f0000a395..49b1166a5a421964b91902f458521121fc89562b 100644 (file)
@@ -76,7 +76,7 @@ def lockfile(mypath, wantnewlockfile=0, unlinkfile=0, waiting_msg=None):
        except IOError, e:
                if "errno" not in dir(e):
                        raise
-               if e.errno == errno.EAGAIN:
+               if e.errno in (errno.EACCES, errno.EAGAIN):
                        # resource temp unavailable; eg, someone beat us to the lock.
                        if waiting_msg is None:
                                if isinstance(mypath, int):
index fe78c6d45aae7375ee0cbd9197daa837474ec65f..dd90f40d30350c1aaee3b45861bfc169f5469803 100644 (file)
@@ -89,6 +89,7 @@ class NewsManager(object):
                del path
                
                path = os.path.join(self.unread_path, 'news-%s.unread' % repoid)
+               unread_lock = None
                try:
                        unread_lock = lockfile(path)
                        if not os.path.exists(path):