From: Fabian Groffen Date: Thu, 13 Mar 2008 18:12:17 +0000 (-0000) Subject: Merged from trunk 9450:9460 X-Git-Url: http://git.tremily.us/gitweb.cgi?a=commitdiff_plain;h=afc8562b0c3a54d94141d6e860e5ba578d424531;p=portage.git Merged from trunk 9450:9460 | 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 | | | for the suggestion. | svn path=/main/branches/prefix/; revision=9461 --- diff --git a/bin/emaint b/bin/emaint index 2f03202ce..c2e345290 100755 --- a/bin/emaint +++ b/bin/emaint @@ -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: diff --git a/bin/filter-bash-environment.py b/bin/filter-bash-environment.py index 88ee40083..323600916 100755 --- a/bin/filter-bash-environment.py +++ b/bin/filter-bash-environment.py @@ -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+') diff --git a/pym/_emerge/__init__.py b/pym/_emerge/__init__.py index 6f355935e..d1f876065 100644 --- a/pym/_emerge/__init__.py +++ b/pym/_emerge/__init__.py @@ -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 diff --git a/pym/portage/dbapi/bintree.py b/pym/portage/dbapi/bintree.py index a5ff09c5e..d634e816f 100644 --- a/pym/portage/dbapi/bintree.py +++ b/pym/portage/dbapi/bintree.py @@ -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")) diff --git a/pym/portage/dep.py b/pym/portage/dep.py index bf42d2ba8..2a1a3cfa5 100644 --- a/pym/portage/dep.py +++ b/pym/portage/dep.py @@ -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): """ diff --git a/pym/portage/getbinpkg.py b/pym/portage/getbinpkg.py index 6c2d32cdb..c2fb48d03 100644 --- a/pym/portage/getbinpkg.py +++ b/pym/portage/getbinpkg.py @@ -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]]) diff --git a/pym/portage/locks.py b/pym/portage/locks.py index 19762abbe..49b1166a5 100644 --- a/pym/portage/locks.py +++ b/pym/portage/locks.py @@ -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): diff --git a/pym/portage/news.py b/pym/portage/news.py index fe78c6d45..dd90f40d3 100644 --- a/pym/portage/news.py +++ b/pym/portage/news.py @@ -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):