diff options
Diffstat (limited to 'pym/portage.py')
-rw-r--r-- | pym/portage.py | 145 |
1 files changed, 51 insertions, 94 deletions
diff --git a/pym/portage.py b/pym/portage.py index d52a6da57..0719aa23d 100644 --- a/pym/portage.py +++ b/pym/portage.py @@ -3891,6 +3891,8 @@ def movefile(src,dest,newmtime=None,sstat=None,mysettings=None): else: os.symlink(target,dest) lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID]) + # utime() only works on the target of a symlink, so it's not + # possible to perserve mtime on symlinks. return os.lstat(dest)[stat.ST_MTIME] except SystemExit, e: raise @@ -6827,9 +6829,9 @@ class dblink: mysettings.get("CONFIG_PROTECT","").split(), mysettings.get("CONFIG_PROTECT_MASK","").split()) self.updateprotect = protect_obj.updateprotect - self._config_protect = protect_obj + self.isprotected = protect_obj.isprotected self._installed_instance = None - self.contentscache=[] + self.contentscache = None self._contents_inodes = None def lockdb(self): @@ -6894,7 +6896,7 @@ class dblink: """ if not os.path.exists(self.dbdir+"/CONTENTS"): return None - if self.contentscache != []: + if self.contentscache is not None: return self.contentscache pkgfiles={} myc=open(self.dbdir+"/CONTENTS","r") @@ -6953,7 +6955,7 @@ class dblink: return pkgfiles def unmerge(self, pkgfiles=None, trimworld=1, cleanup=1, - ldpath_mtimes=None): + ldpath_mtimes=None, new_contents=None): """ Calls prerm Unmerges a given package (CPV) @@ -6969,6 +6971,8 @@ class dblink: @type cleanup: Boolean @param ldpath_mtimes: mtimes to pass to env_update (see env_update) @type ldpath_mtimes: Dictionary + @param new_contents: contents from a new instance that will replace this one + @type new_contents: Dictionary @rtype: Integer @returns: 1. os.EX_OK if everything went well. @@ -7032,7 +7036,7 @@ class dblink: writemsg("!!! FAILED prerm: %s\n" % retval, noiselevel=-1) return retval - self._unmerge_pkgfiles(pkgfiles) + self._unmerge_pkgfiles(pkgfiles, new_contents=new_contents) if myebuildpath: retval = doebuild(myebuildpath, "postrm", self.myroot, @@ -7071,7 +7075,7 @@ class dblink: contents=contents) return os.EX_OK - def _unmerge_pkgfiles(self, pkgfiles): + def _unmerge_pkgfiles(self, pkgfiles, new_contents=None): """ Unmerges the contents of a package from the liveFS @@ -7079,6 +7083,8 @@ class dblink: @param pkgfiles: typically self.getcontents() @type pkgfiles: Dictionary { filename: [ 'type', '?', 'md5sum' ] } + @param new_contents: contents from a new instance that will replace this one + @type new_contents: Dictionary @rtype: None """ global dircache @@ -7088,6 +7094,28 @@ class dblink: writemsg_stdout("No package files given... Grabbing a set.\n") pkgfiles=self.getcontents() + if not new_contents: + counter = self.vartree.dbapi.cpv_counter(self.mycpv) + slot = self.vartree.dbapi.aux_get(self.mycpv, ["SLOT"])[0] + slot_matches = self.vartree.dbapi.match( + "%s:%s" % (dep_getkey(self.mycpv), slot)) + new_cpv = None + if slot_matches: + max_counter = -1 + for cur_cpv in slot_matches: + cur_counter = self.vartree.dbapi.cpv_counter(cur_cpv) + if cur_counter == counter and \ + cur_cpv == self.mycpv: + continue + if cur_counter > max_counter: + max_counter = cur_counter + new_cpv = cur_cpv + if new_cpv: + # The current instance has been replaced by a newer instance. + new_cat, new_pkg = catsplit(new_cpv) + new_contents = dblink(new_cat, new_pkg, self.vartree.root, + self.settings, vartree=self.vartree).getcontents() + if pkgfiles: mykeys=pkgfiles.keys() mykeys.sort() @@ -7098,8 +7126,12 @@ class dblink: modprotect="/lib/modules/" for objkey in mykeys: obj = normalize_path(objkey) - if obj[:2]=="//": - obj=obj[1:] + if new_contents and obj in new_contents: + # A new instance of this package claims the file, so don't + # unmerge it. + writemsg_stdout("--- !owned %s %s\n" % \ + (pkgfiles[objkey][0], obj)) + continue statobj = None try: statobj = os.stat(obj) @@ -7233,31 +7265,6 @@ class dblink: return False - def isprotected(self, filename): - """In cases where an installed package in the same slot owns a - protected file that will be merged, bump the mtime on the installed - file in order to ensure that it isn't unmerged.""" - if not self._config_protect.isprotected(filename): - return False - if self._installed_instance is None: - return True - mydata = self._installed_instance.getcontents().get(filename, None) - if mydata is None: - return True - - # Bump the mtime in order to ensure that the old config file doesn't - # get unmerged. The user will have an opportunity to merge the new - # config with the old one. - try: - os.utime(filename, None) - except OSError, e: - if e.errno != errno.ENOENT: - raise - del e - # The file has disappeared, so it's not protected. - return False - return True - def treewalk(self, srcroot, destroot, inforoot, myebuild, cleanup=0, mydbapi=None, prev_mtimes=None): """ @@ -7442,9 +7449,6 @@ class dblink: raise del e - # get old contents info for later unmerging - oldcontents = self.getcontents() - self.dbdir = self.dbtmpdir self.delete() if not os.path.exists(self.dbtmpdir): @@ -7490,12 +7494,11 @@ class dblink: else: cfgfiledict["IGNORE"]=0 - # Timestamp for files being merged. Use time() - 1 in order to prevent - # a collision with timestamps that are bumped by the utime() call - # inside isprotected(). This ensures that the new and old config have - # different timestamps (for the benefit of programs like rsync that - # that need distiguishable timestamps to detect file changes). - mymtime = long(time.time() - 1) + # Don't bump mtimes on merge since some application require + # preservation of timestamps. This means that the unmerge phase must + # check to see if file belongs to an installed instance in the same + # slot. + mymtime = None # set umask to 0 for merging; back up umask, save old one in prevmask (since this is a global change) prevmask = os.umask(0) @@ -7534,12 +7537,14 @@ class dblink: #if we opened it, close it outfile.flush() outfile.close() + self.contentscache = None + new_contents = self.getcontents() if os.path.exists(self.dbpkgdir): writemsg_stdout(">>> Safely unmerging already-installed instance...\n") - self.dbdir = self.dbpkgdir - self.unmerge(oldcontents, trimworld=0, ldpath_mtimes=prev_mtimes) - self.dbdir = self.dbtmpdir + dblink(self.cat, self.pkg, destroot, self.settings, + vartree=self.vartree).unmerge(trimworld=0, + ldpath_mtimes=prev_mtimes, new_contents=new_contents) writemsg_stdout(">>> Original instance of package unmerged safely.\n") # We hold both directory locks. @@ -7805,9 +7810,7 @@ class dblink: destmd5=portage_checksum.perform_md5(mydest,calc_prelink=1) if mymd5==destmd5: #file already in place; simply update mtimes of destination - os.utime(mydest,(thismtime,thismtime)) - zing="---" - moveme=0 + moveme = 1 else: if mymd5 == cfgfiledict.get(myrealdest, [None])[0]: """ An identical update has previously been @@ -7836,52 +7839,6 @@ class dblink: if mymtime is None: sys.exit(1) zing=">>>" - else: - mymtime = long(time.time()) - # We need to touch the destination so that on --update the - # old package won't yank the file with it. (non-cfgprot related) - os.utime(mydest, (mymtime, mymtime)) - zing="---" - if self.settings["USERLAND"] == "Darwin" and myrealdest[-2:] == ".a": - - # XXX kludge, can be killed when portage stops relying on - # md5+mtime, and uses refcounts - # alright, we've fooled w/ mtime on the file; this pisses off static archives - # basically internal mtime != file's mtime, so the linker (falsely) thinks - # the archive is stale, and needs to have it's toc rebuilt. - - myf = open(mydest, "r+") - - # ar mtime field is digits padded with spaces, 12 bytes. - lms=str(thismtime+5).ljust(12) - myf.seek(0) - magic=myf.read(8) - if magic != "!<arch>\n": - # not an archive (dolib.a from portage.py makes it here fex) - myf.close() - else: - st = os.stat(mydest) - while myf.tell() < st.st_size - 12: - # skip object name - myf.seek(16,1) - - # update mtime - myf.write(lms) - - # skip uid/gid/mperm - myf.seek(20,1) - - # read the archive member's size - x=long(myf.read(10)) - - # skip the trailing newlines, and add the potential - # extra padding byte if it's not an even size - myf.seek(x + 2 + (x % 2),1) - - # and now we're at the end. yay. - myf.close() - mymd5 = portage_checksum.perform_md5(mydest, calc_prelink=1) - os.utime(mydest,(thismtime,thismtime)) if mymtime!=None: zing=">>>" |