From 994b6ec1c4d71a1a01038e79caa29d8b13deac80 Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Mon, 31 Jul 2006 15:55:15 +0000 Subject: Add a --force option for `ebuild digest` so that the user doesn't have to manually remove the Manifest and files/digest-* files when upstream changes the identity of distfiles. See bug #141843. This patch is from trunk r4040:4043 and r4044:4046. svn path=/main/branches/2.1/; revision=4060 --- bin/ebuild | 27 +++++++++++++++++++++++++-- pym/portage_manifest.py | 37 +++++++++++++++++++++---------------- 2 files changed, 46 insertions(+), 18 deletions(-) diff --git a/bin/ebuild b/bin/ebuild index a62585a5e..e6819b9da 100755 --- a/bin/ebuild +++ b/bin/ebuild @@ -12,9 +12,9 @@ if len(sys.argv) <= 2: sys.exit(1) -(opts, pargs) = getopt.getopt(sys.argv[1:], '', ['debug']) +opts, pargs = getopt.getopt(sys.argv[1:], '', ['debug', 'force']) debug = ("--debug",'') in opts - +force = ("--force",'') in opts if "merge" in pargs: print "Disabling noauto in features... merge disables it. (qmerge doesn't)" @@ -79,10 +79,33 @@ if len(pargs) > 1 and "config" in pargs: print "config must be called on it's own, not combined with any other phase" sys.exit(1) +def discard_digests(myebuild, mysettings, mydbapi): + """Discard all distfiles digests for the given ebuild. This is useful when + upstream has changed the identity of the distfiles and the user would + otherwise have to manually remove the Manifest and files/digest-* files in + order to ensure correct results.""" + pkgdir = os.path.dirname(myebuild) + fetchlist_dict = portage.FetchlistDict(pkgdir, mysettings, mydbapi) + cat, pkg = pkgdir.split(os.sep)[-2:] + cpv = cat + "/" + os.path.basename(myebuild)[:-7] + from portage_manifest import Manifest + mf = Manifest(pkgdir, mysettings["DISTDIR"], + fetchlist_dict=fetchlist_dict) + mf.create(requiredDistfiles=None, + assumeDistHashesSometimes=True, assumeDistHashesAlways=True) + distfiles = fetchlist_dict[cpv] + for myfile in distfiles: + try: + del mf.fhashdict["DIST"][myfile] + except KeyError: + pass + mf.write() for arg in pargs: try: tmpsettings = portage.config(clone=portage.settings) + if arg == "digest" and force: + discard_digests(ebuild, tmpsettings, portage.portdb) a = portage.doebuild(ebuild, arg, portage.root, tmpsettings, debug=debug, cleanup=("noauto" not in portage.features), tree=mytree) except KeyboardInterrupt: print "Interrupted." diff --git a/pym/portage_manifest.py b/pym/portage_manifest.py index ee9b4b833..687d7ca10 100644 --- a/pym/portage_manifest.py +++ b/pym/portage_manifest.py @@ -219,15 +219,14 @@ class Manifest(object): for cpv in cpvlist: dname = os.path.join(self.pkgdir, "files", "digest-%s" % self._catsplit(cpv)[1]) distlist = self._getCpvDistfiles(cpv) - have_all_checksums = True + missing_digests = set() for f in distlist: if f not in self.fhashdict["DIST"] or len(self.fhashdict["DIST"][f]) == 0: - have_all_checksums = False - break - if not have_all_checksums: - # We don't have all the required checksums to generate a proper - # digest, so we have to skip this cpv. - continue + missing_digests.add(f) + if missing_digests: + # This allows us to force remove of stale digests for the + # ebuild --force digest option. + distlist = [f for f in distlist if f not in missing_digests] update_digest = True if not force: try: @@ -236,13 +235,15 @@ class Manifest(object): f.close() if len(old_data) == 1 and "DIST" in old_data: new_data = self._getDigestData(distlist) - for myfile in new_data["DIST"]: - for hashname in new_data["DIST"][myfile].keys(): - if hashname != "size" and \ - hashname not in portage_const.MANIFEST1_HASH_FUNCTIONS: - del new_data["DIST"][myfile][hashname] - if new_data["DIST"] == old_data["DIST"]: - update_digest = False + if "DIST" in new_data: + for myfile in new_data["DIST"]: + for hashname in \ + new_data["DIST"][myfile].keys(): + if hashname != "size" and hashname not in \ + portage_const.MANIFEST1_HASH_FUNCTIONS: + del new_data["DIST"][myfile][hashname] + if new_data["DIST"] == old_data["DIST"]: + update_digest = False except (IOError, OSError), e: if errno.ENOENT == e.errno: pass @@ -402,7 +403,7 @@ class Manifest(object): return None def create(self, checkExisting=False, assumeDistHashesSometimes=False, - assumeDistHashesAlways=False, requiredDistfiles=None): + assumeDistHashesAlways=False, requiredDistfiles=[]): """ Recreate this Manifest from scratch. This will not use any existing checksums unless assumeDistHashesSometimes or assumeDistHashesAlways is true (assumeDistHashesSometimes will only @@ -444,7 +445,11 @@ class Manifest(object): distlist = set() for cpv in cpvlist: distlist.update(self._getCpvDistfiles(cpv)) - if requiredDistfiles is None or len(requiredDistfiles) == 0: + if requiredDistfiles is None: + # This allows us to force removal of stale digests for the + # ebuild --force digest option (no distfiles are required). + requiredDistfiles = set() + elif len(requiredDistfiles) == 0: # repoman passes in an empty list, which implies that all distfiles # are required. requiredDistfiles = distlist.copy() -- cgit v1.2.3-1-g7c22