Merged from trunk 6675:6695
authorFabian Groffen <grobian@gentoo.org>
Thu, 31 May 2007 15:54:40 +0000 (15:54 -0000)
committerFabian Groffen <grobian@gentoo.org>
Thu, 31 May 2007 15:54:40 +0000 (15:54 -0000)
   +------------------------------------------------------------------------+
   | 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

12 files changed:
bin/ebuild
bin/emaint
bin/fixpackages
pym/emerge/__init__.py
pym/portage/__init__.py
pym/portage/dbapi/__init__.py
pym/portage/dbapi/bintree.py
pym/portage/dbapi/porttree.py
pym/portage/dbapi/vartree.py
pym/portage/dep.py
pym/portage/getbinpkg.py
pym/portage/news.py

index 48420d78e237917d8d080bb3c65fbd0dee55c187..d29333ef13665c231e643cade3e224d51eeea38d 100755 (executable)
@@ -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
 
index 70ccb775bb9ac56db6d04e6051f9299c8038d3ab..25b0be4508d7ab2f54077d5058491720c3cc88f5 100755 (executable)
@@ -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):
index 9d05826cf6ba7c593022c176fe817d1ff75116aa..49320e839949d9e0aca22072eeeb89bd66bcf99a 100755 (executable)
@@ -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."
index f64d1dd074f872f7b6a4cfc33911293d81dd2639..623bf48cacd0005f1c55f578a1676566ddbcc7e4 100644 (file)
@@ -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)
index 7f2108cc65b73581f5c6e225cc4b2aa6e13b7be1..67a3a709e7a62be9953ba1a5fb2ec916f96034ba 100644 (file)
@@ -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")
index b4ec89e53fb45473b38a6526ed76ac4eb6c7368b..ef91d4de1cd553399a2f90b8a99782e4e34fa5d2 100644 (file)
@@ -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
index ab4b88ae91067dfca374ffe3fac6d5053bbe1c7b..51d565489a8f2eed31e1acc8f385f0288ba37dab 100644 (file)
@@ -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):
index 86d70416f2635f625d71808ca9b87eb714db82a3..c99b0193c2cc8328a42dc31b8f437d65b823b497 100644 (file)
@@ -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
index 7c5736a75b75b87c87a847bc03b7c8895a699ead..41147df4d236ce731220e9c23cce5e672899044e 100644 (file)
@@ -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
index 848e4902e0116fe97aa918b7e49d55877f81614c..866e575a091fe175563f0f95dc1b29a34cf48946 100644 (file)
@@ -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] == "=":
index 320e95a002b05e2075599b96e4a54caaa1362b98..79ddca5451c07df11a0ae9b5b00408764b4faca6 100644 (file)
@@ -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])
index 327fe15f4d9377e04be50f85dfd42c94f34b4530..3cfb5de12b966cf82d4f6da478d358637cf3be99 100644 (file)
@@ -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")