From: Fabian Groffen Date: Thu, 31 May 2007 15:54:40 +0000 (-0000) Subject: Merged from trunk 6675:6695 X-Git-Url: http://git.tremily.us/gitweb.cgi?a=commitdiff_plain;h=9af1e642ebf5b77303cf6fdda510cd4acef0d639;p=portage.git Merged from trunk 6675:6695 +------------------------------------------------------------------------+ | 6676 | Show deprecation warnings if the "clone" parameters are used | | zmedico | for the binartree, vartree, or portagetree constructors. | |---------+--------------------------------------------------------------| | 6678 | For bug #180399, raise an appropriate InvalidDependString | | zmedico | exception if there is no flag attached directly to a '?' | | | token. | |---------+--------------------------------------------------------------| | 6680 | Fix an IndexError in get_operator() that occurs when | | zmedico | isvalidatom() passes it an empty string. | |---------+--------------------------------------------------------------| | 6682 | remove pointless $PORTDIR lock | | genone | | |---------+--------------------------------------------------------------| | 6684 | catch GetoptError | | genone | | |---------+--------------------------------------------------------------| | 6685 | Only check ChangeLog if we're dealing with an ebuild (bug | | genone | #170604) | |---------+--------------------------------------------------------------| | 6686 | Create one unified dbapi.update_ents() method and use it for | | zmedico | both fixpackages and the emaint move{inst,bin} targets. | |---------+--------------------------------------------------------------| | 6687 | Make automatic "global updates" always use the config | | zmedico | instance that's associated with /, since the rest of the | | | code is targeted at /. | |---------+--------------------------------------------------------------| | 6688 | Create one unified dbapi.move_slot_ent() method to replace | | zmedico | the corresponding binarytree and vardbapi methods. | |---------+--------------------------------------------------------------| | 6689 | Allow dbapi.aux_update() to prune empty metadata values from | | zmedico | storage. | |---------+--------------------------------------------------------------| | 6690 | Trigger an update of the Packages index when a package is | | zmedico | moved or aux_update() is called. | |---------+--------------------------------------------------------------| | 6691 | Don't try to perform global updates on binary packages | | zmedico | unless $PKGDIR is writable. | |---------+--------------------------------------------------------------| | 6692 | Don't define bindbapi.move_slot_ent() since the inherited | | zmedico | one works fine. Override cp_all() instead of cpv_all() since | | | the latter calls the former. | |---------+--------------------------------------------------------------| | 6693 | Implement bindbapi.cpv_all() since the one from fakedbapi | | zmedico | won't populate the tree. | |---------+--------------------------------------------------------------| | 6694 | Add PORTAGE_BINHOST support for fetching a remote Packages | | zmedico | index. If the index is not found then it falls back to the | | | old directory listing method. | |---------+--------------------------------------------------------------| | 6695 | Fix typos. | | zmedico | | +------------------------------------------------------------------------+ svn path=/main/branches/prefix/; revision=6696 --- diff --git a/bin/ebuild b/bin/ebuild index 48420d78e..d29333ef1 100755 --- a/bin/ebuild +++ b/bin/ebuild @@ -12,7 +12,11 @@ if len(sys.argv) <= 2: sys.exit(1) -opts, pargs = getopt.getopt(sys.argv[1:], '', ['debug', 'force']) +try: + opts, pargs = getopt.getopt(sys.argv[1:], '', ['debug', 'force']) +except getopt.GetoptError, e: + print e + sys.exit(1) debug = ("--debug",'') in opts force = ("--force",'') in opts diff --git a/bin/emaint b/bin/emaint index 70ccb775b..25b0be450 100755 --- a/bin/emaint +++ b/bin/emaint @@ -246,23 +246,7 @@ class MoveHandler(object): # Searching for updates in all the metadata is relatively slow, so this # is where the progress bar comes out of indeterminate mode. - cpv_all = self._tree.dbapi.cpv_all() - cpv_all.sort() - maxval = len(cpv_all) - aux_get = self._tree.dbapi.aux_get - aux_update = self._tree.dbapi.aux_update - update_keys = self._update_keys - from itertools import izip - from portage.update import update_dbentries - if onProgress: - onProgress(maxval, 0) - for i, cpv in enumerate(cpv_all): - metadata = dict(izip(update_keys, aux_get(cpv, update_keys))) - metadata_updates = update_dbentries(updates, metadata) - if metadata_updates: - aux_update(cpv, metadata_updates) - if onProgress: - onProgress(maxval, i+1) + self._tree.dbapi.update_ents(updates, onProgress=onProgress) return errors class MoveInstalled(MoveHandler): diff --git a/bin/fixpackages b/bin/fixpackages index 9d05826cf..49320e839 100755 --- a/bin/fixpackages +++ b/bin/fixpackages @@ -24,7 +24,7 @@ except (OSError, ValueError), e: portage.writemsg("!!! %s\n" % str(e)) del e -portage.global_updates(mysettings, mytrees, mtimedb["updates"]) +portage._global_updates(mytrees, mtimedb["updates"]) print print "Done." diff --git a/pym/emerge/__init__.py b/pym/emerge/__init__.py index f64d1dd07..623bf48ca 100644 --- a/pym/emerge/__init__.py +++ b/pym/emerge/__init__.py @@ -2810,10 +2810,14 @@ class depgraph: sys.stderr.write("".join(msg)) def calc_changelog(self,ebuildpath,current,next): + if ebuildpath == None or not os.path.exists(ebuildpath): + return [] current = '-'.join(portage.catpkgsplit(current)[1:]) - if current.endswith('-r0'): current = current[:-3] + if current.endswith('-r0'): + current = current[:-3] next = '-'.join(portage.catpkgsplit(next)[1:]) - if next.endswith('-r0'): next = next[:-3] + if next.endswith('-r0'): + next = next[:-3] changelogpath = os.path.join(os.path.split(ebuildpath)[0],'ChangeLog') try: changelog = open(changelogpath).read() @@ -4382,7 +4386,7 @@ def action_sync(settings, trees, mtimedb, myopts, myaction): if os.path.exists(myportdir+"/metadata/cache") and updatecache_flg: action_metadata(settings, portdb, myopts) - if portage.global_updates(settings, trees, mtimedb["updates"]): + if portage._global_updates(trees, mtimedb["updates"]): mtimedb.commit() # Reload the whole config from scratch. settings, trees, mtimedb = load_emerge_config(trees=trees) @@ -5429,7 +5433,7 @@ def emerge_main(): portage.writemsg("!!! %s\n" % str(e)) del e - if portage.global_updates(settings, trees, mtimedb["updates"]): + if portage._global_updates(trees, mtimedb["updates"]): mtimedb.commit() # Reload the whole config from scratch. settings, trees, mtimedb = load_emerge_config(trees=trees) diff --git a/pym/portage/__init__.py b/pym/portage/__init__.py index 7f2108cc6..67a3a709e 100644 --- a/pym/portage/__init__.py +++ b/pym/portage/__init__.py @@ -5021,12 +5021,10 @@ def portageexit(): atexit_register(portageexit) -def global_updates(mysettings, trees, prev_mtimes): +def _global_updates(trees, prev_mtimes): """ Perform new global updates if they exist in $PORTDIR/profiles/updates/. - @param mysettings: A config instance for ROOT="/". - @type mysettings: config @param trees: A dictionary containing portage trees. @type trees: dict @param prev_mtimes: A dictionary containing mtimes of files located in @@ -5040,6 +5038,7 @@ def global_updates(mysettings, trees, prev_mtimes): global secpass if secpass < 2 or "SANDBOX_ACTIVE" in os.environ: return + mysettings = trees["/"]["vartree"].settings updpath = os.path.join(mysettings["PORTDIR"], "profiles", "updates") try: @@ -5080,21 +5079,25 @@ def global_updates(mysettings, trees, prev_mtimes): settings=mysettings) vardb = trees["/"]["vartree"].dbapi bindb = trees["/"]["bintree"].dbapi + if not os.access(bindb.bintree.pkgdir, os.W_OK): + bindb = None for update_cmd in myupd: if update_cmd[0] == "move": moves = vardb.move_ent(update_cmd) if moves: writemsg_stdout(moves * "@") - moves = bindb.move_ent(update_cmd) - if moves: - writemsg_stdout(moves * "%") + if bindb: + moves = bindb.move_ent(update_cmd) + if moves: + writemsg_stdout(moves * "%") elif update_cmd[0] == "slotmove": moves = vardb.move_slot_ent(update_cmd) if moves: writemsg_stdout(moves * "s") - moves = bindb.move_slot_ent(update_cmd) - if moves: - writemsg_stdout(moves * "S") + if bindb: + moves = bindb.move_slot_ent(update_cmd) + if moves: + writemsg_stdout(moves * "S") # The above global updates proceed quickly, so they # are considered a single mtimedb transaction. @@ -5109,7 +5112,11 @@ def global_updates(mysettings, trees, prev_mtimes): # We gotta do the brute force updates for these now. if mysettings["PORTAGE_CALLER"] == "fixpackages" or \ "fixpackages" in mysettings.features: - trees["/"]["bintree"].update_ents(myupd) + def onProgress(maxval, curval): + writemsg_stdout("*") + vardb.update_ents(myupd, onProgress=onProgress) + if bindb: + bindb.update_ents(myupd, onProgress=onProgress) else: do_upgrade_packagesmessage = 1 @@ -5119,8 +5126,8 @@ def global_updates(mysettings, trees, prev_mtimes): print print - if do_upgrade_packagesmessage and \ - listdir(os.path.join(mysettings["PKGDIR"], "All"), EmptyOnError=1): + if do_upgrade_packagesmessage and bindb and \ + bindb.cpv_all(): writemsg_stdout(" ** Skipping packages. Run 'fixpackages' or set it in FEATURES to fix the") writemsg_stdout("\n tbz2's in the packages directory. "+bold("Note: This can take a very long time.")) writemsg_stdout("\n") diff --git a/pym/portage/dbapi/__init__.py b/pym/portage/dbapi/__init__.py index b4ec89e53..ef91d4de1 100644 --- a/pym/portage/dbapi/__init__.py +++ b/pym/portage/dbapi/__init__.py @@ -53,3 +53,46 @@ class dbapi(object): else: writemsg("!!! Invalid db entry: %s\n" % mypath, noiselevel=-1) + def update_ents(self, updates, onProgress=None): + """ + Update metadata of all packages for packages moves. + @param updates: A list of move commands + @type updates: List + @param onProgress: A progress callback function + @type onProgress: a callable that takes 2 integer arguments: maxval and curval + """ + cpv_all = self.cpv_all() + cpv_all.sort() + maxval = len(cpv_all) + aux_get = self.aux_get + aux_update = self.aux_update + update_keys = ["DEPEND", "RDEPEND", "PDEPEND", "PROVIDE"] + from itertools import izip + from portage.update import update_dbentries + if onProgress: + onProgress(maxval, 0) + for i, cpv in enumerate(cpv_all): + metadata = dict(izip(update_keys, aux_get(cpv, update_keys))) + metadata_updates = update_dbentries(updates, metadata) + if metadata_updates: + aux_update(cpv, metadata_updates) + if onProgress: + onProgress(maxval, i+1) + + def move_slot_ent(self, mylist): + pkg = mylist[1] + origslot = mylist[2] + newslot = mylist[3] + origmatches = self.match(pkg) + moves = 0 + if not origmatches: + return moves + from portage.versions import catsplit + for mycpv in origmatches: + slot = self.aux_get(mycpv, ["SLOT"])[0] + if slot != origslot: + continue + moves += 1 + mydata = {"SLOT": newslot+"\n"} + self.aux_update(mycpv, mydata) + return moves diff --git a/pym/portage/dbapi/bintree.py b/pym/portage/dbapi/bintree.py index ab4b88ae9..51d565489 100644 --- a/pym/portage/dbapi/bintree.py +++ b/pym/portage/dbapi/bintree.py @@ -16,7 +16,6 @@ class bindbapi(fakedbapi): def __init__(self, mybintree=None, settings=None): self.bintree = mybintree self.move_ent = mybintree.move_ent - self.move_slot_ent = mybintree.move_slot_ent self.cpvdict={} self.cpdict={} if settings is None: @@ -78,23 +77,33 @@ class bindbapi(fakedbapi): mytbz2 = portage.xpak.tbz2(tbz2path) mydata = mytbz2.get_data() mydata.update(values) + for k, v in mydata.items(): + if not v: + del mydata[k] mytbz2.recompose_mem(portage.xpak.xpak_mem(mydata)) + self.bintree.inject(cpv) def cp_list(self, *pargs, **kwargs): if not self.bintree.populated: self.bintree.populate() return fakedbapi.cp_list(self, *pargs, **kwargs) + def cp_all(self): + if not self.bintree.populated: + self.bintree.populate() + return fakedbapi.cp_all(self) + def cpv_all(self): if not self.bintree.populated: self.bintree.populate() return fakedbapi.cpv_all(self) - class binarytree(object): "this tree scans for a list of all packages available in PKGDIR" def __init__(self, root, pkgdir, virtual=None, settings=None, clone=None): if clone: + writemsg("binartree.__init__(): deprecated " + \ + "use of clone parameter\n", noiselevel=-1) # XXX This isn't cloning. It's an instance of the same thing. self.root = clone.root self.pkgdir = clone.pkgdir @@ -109,9 +118,13 @@ class binarytree(object): #self.pkgdir=settings["PKGDIR"] self.pkgdir = normalize_path(pkgdir) self.dbapi = bindbapi(self, settings=settings) + self.update_ents = self.dbapi.update_ents + self.move_slot_ent = self.dbapi.move_slot_ent self.populated = 0 self.tree = {} - self.remotepkgs = {} + self._remote_has_index = False + self._remotepkgs = None # remote metadata indexed by cpv + self.remotepkgs = {} # indexed by tbz2 name (deprecated) self.invalids = [] self.settings = settings self._pkg_paths = {} @@ -184,7 +197,7 @@ class binarytree(object): self._remove_symlink(mycpv) if new_path.split(os.path.sep)[-2] == "All": self._create_symlink(mynewcpv) - self.dbapi.cpv_inject(mynewcpv) + self.inject(mynewcpv) return moves @@ -226,67 +239,6 @@ class binarytree(object): del e os.symlink(os.path.join("..", "All", mypkg + ".tbz2"), full_path) - def move_slot_ent(self, mylist): - if not self.populated: - self.populate() - pkg = mylist[1] - origslot = mylist[2] - newslot = mylist[3] - - if not isvalidatom(pkg): - raise InvalidAtom(pkg) - - origmatches = self.dbapi.match(pkg) - moves = 0 - if not origmatches: - return moves - for mycpv in origmatches: - mycpsplit = catpkgsplit(mycpv) - myoldpkg = mycpv.split("/")[1] - tbz2path = self.getname(mycpv) - if os.path.exists(tbz2path) and not os.access(tbz2path,os.W_OK): - writemsg("!!! Cannot update readonly binary: "+mycpv+"\n", - noiselevel=-1) - continue - - #print ">>> Updating data in:",mycpv - mytbz2 = portage.xpak.tbz2(tbz2path) - mydata = mytbz2.get_data() - - slot = mydata["SLOT"] - if (not slot): - continue - - if (slot[0] != origslot): - continue - - moves += 1 - mydata["SLOT"] = newslot+"\n" - mytbz2.recompose_mem(portage.xpak.xpak_mem(mydata)) - return moves - - def update_ents(self, update_iter): - if len(update_iter) == 0: - return - if not self.populated: - self.populate() - - for mycpv in self.dbapi.cp_all(): - tbz2path = self.getname(mycpv) - if os.path.exists(tbz2path) and not os.access(tbz2path,os.W_OK): - writemsg("!!! Cannot update readonly binary: "+mycpv+"\n", - noiselevel=-1) - continue - #print ">>> Updating binary data:",mycpv - writemsg_stdout("*") - mytbz2 = portage.xpak.tbz2(tbz2path) - mydata = mytbz2.get_data() - updated_items = update_dbentries(update_iter, mydata) - if len(updated_items) > 0: - mydata.update(updated_items) - mytbz2.recompose_mem(portage.xpak.xpak_mem(mydata)) - return 1 - def prevent_collision(self, cpv): """Make sure that the file location ${PKGDIR}/All/${PF}.tbz2 is safe to use for a given cpv. If a collision will occur with an existing @@ -528,15 +480,77 @@ class binarytree(object): noiselevel=-1) if getbinpkgs and \ - self.settings["PORTAGE_BINHOST"] and not self.remotepkgs: + "PORTAGE_BINHOST" in self.settings and \ + not self._remotepkgs: + + base_url = self.settings["PORTAGE_BINHOST"] + from portage.const import CACHE_PATH + from urlparse import urlparse + urldata = urlparse(base_url) + pkgindex_file = os.path.join(CACHE_PATH, "binhost", + urldata[1] + urldata[2], "Packages") + pkgindex = portage.getbinpkg.PackageIndex() + try: + f = open(pkgindex_file) + try: + pkgindex.read(f) + finally: + f.close() + except EnvironmentError, e: + if e.errno != errno.ENOENT: + raise + local_timestamp = pkgindex.header.get("TIMESTAMP", None) + import urllib, urlparse + rmt_idx = portage.getbinpkg.PackageIndex() + try: + f = urllib.urlopen(urlparse.urljoin(base_url, "Packages")) + try: + rmt_idx.readHeader(f) + remote_timestamp = rmt_idx.header.get("TIMESTAMP", None) + if not remote_timestamp: + # no timestamp in the header, something's wrong + pkgindex = None + else: + if local_timestamp != remote_timestamp: + rmt_idx.readBody(f) + pkgindex = rmt_idx + finally: + f.close() + except EnvironmentError, e: + writemsg("\n\n!!! Error fetching binhost package" + \ + " info from '%s'\n" % base_url) + writemsg("!!! %s\n\n" % str(e)) + del e + pkgindex = None + if pkgindex is rmt_idx: + pkgindex.modified = False # don't update the header + from portage.util import atomic_ofstream, ensure_dirs + ensure_dirs(os.path.dirname(pkgindex_file)) + f = atomic_ofstream(pkgindex_file) + try: + pkgindex.write(f) + finally: + f.close() + if pkgindex: + self._remotepkgs = pkgindex.packages + self._remote_has_index = True + self.remotepkgs = {} + for cpv, metadata in self._remotepkgs.iteritems(): + self.dbapi.cpv_inject(cpv) + cat, pf = catsplit(cpv) + # backward compat + self.remotepkgs[pf+".tbz2"] = metadata + metadata["CATEGORY"] = cat + self.populated = 1 + return + self._remotepkgs = {} try: chunk_size = long(self.settings["PORTAGE_BINHOST_CHUNKSIZE"]) if chunk_size < 8: chunk_size = 8 except (ValueError, KeyError): chunk_size = 3000 - - writemsg(green("Fetching binary packages info...\n")) + writemsg_stdout(green("Fetching binary packages info...\n")) self.remotepkgs = portage.getbinpkg.dir_get_metadata( self.settings["PORTAGE_BINHOST"], chunk_size=chunk_size) writemsg(green(" -- DONE!\n\n")) @@ -563,6 +577,10 @@ class binarytree(object): # invalid tbz2's can hurt things. #print "cpv_inject("+str(fullpkg)+")" self.dbapi.cpv_inject(fullpkg) + metadata = self.remotepkgs[mypkg] + for k, v in metadata.items(): + metadata[k] = v.strip() + self._remotepkgs[fullpkg] = metadata #print " -- Injected" except SystemExit, e: raise @@ -748,10 +766,25 @@ class binarytree(object): os.makedirs(mydest, 0775) except (OSError, IOError): pass - success = portage.getbinpkg.file_get( - self.settings["PORTAGE_BINHOST"] + "/" + tbz2name, - mydest, fcmd=self.settings["RESUMECOMMAND"]) - self.inject(pkgname) + from urlparse import urljoin + base_url = self.settings["PORTAGE_BINHOST"] + fcmd = self.settings["RESUMECOMMAND"] + if self._remote_has_index: + url = urljoin(base_url, pkgname+".tbz2") + success = portage.getbinpkg.file_get(url, mydest, fcmd=fcmd) + if not success: + try: + os.unlink(self.getname(pkgname)) + except OSError: + pass + # Fall back to the "All" directory + url = urljoin(base_url, "All/"+tbz2name) + success = portage.getbinpkg.file_get(url, mydest, fcmd=fcmd) + else: + url = urljoin(base_url, tbz2name) + success = portage.getbinpkg.file_get(url, mydest, fcmd=fcmd) + if success: + self.inject(pkgname) return success def getslot(self, mycatpkg): diff --git a/pym/portage/dbapi/porttree.py b/pym/portage/dbapi/porttree.py index 86d70416f..c99b0193c 100644 --- a/pym/portage/dbapi/porttree.py +++ b/pym/portage/dbapi/porttree.py @@ -727,6 +727,8 @@ class portagetree(object): """ if clone: + writemsg("portagetree.__init__(): deprecated " + \ + "use of clone parameter\n", noiselevel=-1) self.root = clone.root self.portroot = clone.portroot self.pkglines = clone.pkglines diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py index 7c5736a75..41147df4d 100644 --- a/pym/portage/dbapi/vartree.py +++ b/pym/portage/dbapi/vartree.py @@ -316,47 +316,6 @@ class vardbapi(dbapi): fixdbentries([mylist], newpath) return moves - def update_ents(self, update_iter): - """Run fixdbentries on all installed packages (time consuming). Like - fixpackages, this should be run from a helper script and display - a progress indicator.""" - dbdir = os.path.join(self.root, VDB_PATH) - for catdir in listdir(dbdir): - catdir = dbdir+"/"+catdir - if os.path.isdir(catdir): - for pkgdir in listdir(catdir): - pkgdir = catdir+"/"+pkgdir - if os.path.isdir(pkgdir): - fixdbentries(update_iter, pkgdir) - - def move_slot_ent(self, mylist): - pkg = mylist[1] - origslot = mylist[2] - newslot = mylist[3] - - if not isvalidatom(pkg): - raise InvalidAtom(pkg) - - origmatches = self.match(pkg, use_cache=0) - moves = 0 - if not origmatches: - return moves - for mycpv in origmatches: - origpath = self.getpath(mycpv) - if not os.path.exists(origpath): - continue - - slot = grabfile(os.path.join(origpath, "SLOT")); - if (not slot): - continue - - if (slot[0] != origslot): - continue - - moves += 1 - write_atomic(os.path.join(origpath, "SLOT"), newslot+"\n") - return moves - def cp_list(self, mycp, use_cache=1): mysplit=catsplit(mycp) if mysplit[0] == '*': @@ -592,7 +551,13 @@ class vardbapi(dbapi): if not mylink.exists(): raise KeyError(cpv) for k, v in values.iteritems(): - mylink.setfile(k, v) + if v: + mylink.setfile(k, v) + else: + try: + os.unlink(os.path.join(self.getpath(cpv), k)) + except EnvironmentError: + pass def counter_tick(self, myroot, mycpv=None): return self.counter_tick_core(myroot, incrementing=1, mycpv=mycpv) @@ -669,6 +634,8 @@ class vartree(object): def __init__(self, root="/", virtual=None, clone=None, categories=None, settings=None): if clone: + writemsg("vartree.__init__(): deprecated " + \ + "use of clone parameter\n", noiselevel=-1) self.root = clone.root[:] self.dbapi = copy.deepcopy(clone.dbapi) self.populated = 1 diff --git a/pym/portage/dep.py b/pym/portage/dep.py index 848e4902e..866e575a0 100644 --- a/pym/portage/dep.py +++ b/pym/portage/dep.py @@ -241,10 +241,17 @@ def use_reduce(deparray, uselist=[], masklist=[], matchall=0, excludeall=[]): # Check that each flag matches ismatch = True + missing_flag = False for head in newdeparray[:-1]: head = head[:-1] - if head[0] == "!": + if not head: + missing_flag = True + break + if head.startswith("!"): head_key = head[1:] + if not head_key: + missing_flag = True + break if not matchall and head_key in uselist or \ head_key in excludeall: ismatch = False @@ -255,6 +262,10 @@ def use_reduce(deparray, uselist=[], masklist=[], matchall=0, excludeall=[]): break else: ismatch = False + if missing_flag: + raise portage_exception.InvalidDependString( + "Conditional without flag: \"" + \ + paren_enclose([head+"?", newdeparray[-1]])+"\"") # If they all match, process the target if ismatch: @@ -324,6 +335,8 @@ def get_operator(mydep): """ if mydep: mydep = remove_slot(mydep) + if not mydep: + return None if mydep[0] == "~": operator = "~" elif mydep[0] == "=": diff --git a/pym/portage/getbinpkg.py b/pym/portage/getbinpkg.py index 320e95a00..79ddca545 100644 --- a/pym/portage/getbinpkg.py +++ b/pym/portage/getbinpkg.py @@ -597,9 +597,16 @@ class PackageIndex(object): def __init__(self): self.header = {} self.packages = {} + self.modified = True def read(self, pkgfile): + self.readHeader(pkgfile) + self.readBody(pkgfile) + + def readHeader(self, pkgfile): self.header.update(readpkgindex(pkgfile)) + + def readBody(self, pkgfile): while True: d = readpkgindex(pkgfile) if not d: @@ -613,9 +620,10 @@ class PackageIndex(object): def write(self, pkgfile): cpv_all = self.packages.keys() cpv_all.sort() - import time - self.header["TIMESTAMP"] = str(long(time.time())) - self.header["PACKAGES"] = str(len(cpv_all)) + if self.modified: + import time + self.header["TIMESTAMP"] = str(long(time.time())) + self.header["PACKAGES"] = str(len(cpv_all)) keys = self.header.keys() keys.sort() writepkgindex(pkgfile, [(k, self.header[k]) for k in keys]) diff --git a/pym/portage/news.py b/pym/portage/news.py index 327fe15f4..3cfb5de12 100644 --- a/pym/portage/news.py +++ b/pym/portage/news.py @@ -64,32 +64,22 @@ class NewsManager(object): timestamp = 0 path = os.path.join(self.portdb.getRepositoryPath(repoid), self.NEWS_PATH) - newsdir_lock = None - try: - repo_path = self.portdb.getRepositoryPath(repoid) - if os.access(os.path.dirname(repo_path), os.W_OK): - # This lock file should really be mapped into /var somewhere - # since the repo_path or it's parent directory may not even be - # writable. - newsdir_lock = lockdir(repo_path) - # Skip reading news for repoid if the news dir does not exist. Requested by - # NightMorph :) - if not os.path.exists(path): - return None - news = os.listdir(path) - updates = [] - for itemid in news: - try: - filename = os.path.join(path, itemid, itemid + "." + self.LANGUAGE_ID + ".txt") - item = NewsItem(filename, itemid, timestamp) - except (TypeError, ValueError), e: - continue - if item.isRelevant(profile=os.readlink(PROFILE_PATH), config=config, vardb=self.vdb): - updates.append(item) - finally: - if newsdir_lock: - unlockdir(newsdir_lock) - + + repo_path = self.portdb.getRepositoryPath(repoid) + # Skip reading news for repoid if the news dir does not exist. Requested by + # NightMorph :) + if not os.path.exists(path): + return None + news = os.listdir(path) + updates = [] + for itemid in news: + try: + filename = os.path.join(path, itemid, itemid + "." + self.LANGUAGE_ID + ".txt") + item = NewsItem(filename, itemid, timestamp) + except (TypeError, ValueError), e: + continue + if item.isRelevant(profile=os.readlink(PROFILE_PATH), config=config, vardb=self.vdb): + updates.append(item) del path path = os.path.join(self.UNREAD_PATH, "news-"+repoid+".unread")