Merged from trunk -r13717:13733
authorFabian Groffen <grobian@gentoo.org>
Mon, 29 Jun 2009 19:09:45 +0000 (19:09 -0000)
committerFabian Groffen <grobian@gentoo.org>
Mon, 29 Jun 2009 19:09:45 +0000 (19:09 -0000)
   | 13723    | make sure etc-update sorts updates in the order (1) leading |
   | SpankMan | dir path (2) filename (3) cfg update                        |

   | 13724    | Bug #236786 - Warn about 'test?' USE conditionals in        |
   | zmedico  | RDEPEND. Thanks to Markus Meier <maekke@gentoo.org> for     |
   |          | this patch.                                                 |

   | 13725    | Check for redundant blank lines. Thanks to Markus Meier     |
   | zmedico  | <maekke@gentoo.org> for this patch.                         |

   | 13726    | Make Package.invalid suitable for use by repoman.           |
   | zmedico  |                                                             |

   | 13728    | Use Package.invalid to generate *.syntax repoman errors for |
   | zmedico  | LICENSE, PROPERTIES, PROVIDE, and RESTRICT.                 |

   | 13729    | Fix Package.metadata USE conditional evaluation so that     |
   | zmedico  | it's delayed until after config.setcpv() has calculated     |
   |          | PORTAGE_USE. Thanks to Arfrever for reporting.              |

   | 13730    | Bug #253467 - Fix regression in config._env_blacklist       |
   | zmedico  | handling.                                                   |

   | 13731    | Fix constructor to avoid TypeError when the "perms" keyword |
   | zmedico  | parameter is given.                                         |

   | 13732    | Add missing resume_depgraph import, and remove unused       |
   | zmedico  | imports.                                                    |

   | 13733    | Prepare 41 messages to localization.                        |
   | arfrever |                                                             |

svn path=/main/branches/prefix/; revision=13734

19 files changed:
bin/etc-update
bin/repoman
pym/_emerge/Package.py
pym/_emerge/Scheduler.py
pym/_emerge/depgraph.py
pym/portage/__init__.py
pym/portage/cache/metadata_overlay.py
pym/portage/elog/__init__.py
pym/portage/elog/messages.py
pym/portage/elog/mod_echo.py
pym/portage/elog/mod_mail.py
pym/portage/elog/mod_mail_summary.py
pym/portage/elog/mod_save_summary.py
pym/portage/env/loaders.py
pym/portage/sets/__init__.py
pym/portage/sets/dbapi.py
pym/portage/sets/files.py
pym/portage/sets/libs.py
pym/repoman/checks.py

index 4a8166b98dfed9e8fe6aad4756b3daa469866724..0e31a3e8ebce7a5976ae6b87cdfa2cca98a60baf 100755 (executable)
@@ -63,8 +63,8 @@ scan() {
                # The below set -f turns off file name globbing in the ${find_opts} expansion.
                for file in $(set -f ; find ${path}/ ${find_opts} \
                       ! -name '.*~' ! -iname '.*.bak' -print |
-                          sed -e "s:\(^.*/\)\(\._cfg[0-9]*_\)\(.*$\):\1\2\3\%\2\%\3:" |
-                          sort -t'%' -k3 -k2 | LANG=POSIX LC_ALL=POSIX cut -f1 -d'%'); do
+                          sed -e "s:\(^.*/\)\(\._cfg[0-9]*_\)\(.*$\):\1\2\3\%\1%\2\%\3:" |
+                          sort -t'%' -k2,2 -k4,4 -k3,3 | LANG=POSIX LC_ALL=POSIX cut -f1 -d'%'); do
 
                        rpath=$(echo "${file/\/\///}" | sed -e "s:/[^/]*$::")
                        rfile=$(echo "${file/\/\///}" | sed -e "s:^.*/::")
index 20c0308862e70c8ceaefbe392188aebe206ac71d..e921a0fe5bc6c9653a36b0ec8c27988e324b5865 100755 (executable)
@@ -1199,6 +1199,14 @@ for x in scanlist:
                        continue
 
                pkg = pkgs[y]
+
+               if pkg.invalid:
+                       for k, msgs in pkg.invalid.iteritems():
+                               for msg in msgs:
+                                       stats[k] = stats[k] + 1
+                                       fails[k].append("%s %s" % (relative_path, msg))
+                       continue
+
                myaux = pkg.metadata
                eapi = myaux["EAPI"]
                inherited = pkg.inherited
@@ -1232,21 +1240,9 @@ for x in scanlist:
                                        "%s: '%s' found in thirdpartymirrors" % \
                                        (relative_path, mirror))
 
-               # Test for negative logic and bad words in the RESTRICT var.
-               #for x in myaux[allvars.index("RESTRICT")].split():
-               #       if x.startswith("no"):
-               #               print "Bad RESTRICT value: %s" % x
-               try:
-                       portage.dep.use_reduce(
-                               portage.dep.paren_reduce(myaux["PROVIDE"]), matchall=1)
-               except portage.exception.InvalidDependString, e:
-                       stats["PROVIDE.syntax"] = stats["PROVIDE.syntax"] + 1
-                       fails["PROVIDE.syntax"].append(mykey+".ebuild PROVIDE: "+str(e))
-                       del e
-                       continue
-
                # The Package class automatically evaluates USE conditionals.
-               for myprovide in myaux["PROVIDE"].split():
+               for myprovide in portage.flatten(portage.dep.use_reduce(
+                       portage.dep.paren_reduce(pkg.metadata['PROVIDE']), matchall=1)):
                        prov_cp = portage.dep_getkey(myprovide)
                        if prov_cp != myprovide:
                                stats["virtual.versioned"]+=1
@@ -1404,7 +1400,11 @@ for x in scanlist:
                        if mytype in ("DEPEND", "RDEPEND", "PDEPEND"):
                                for token in mydepstr.split():
                                        if token in operator_tokens or \
-                                               token.endswith("?"):
+                                               token[-1:] == "?":
+                                               if token == "test?" and mytype == "RDEPEND":
+                                                       stats['RDEPEND.suspect'] += 1
+                                                       fails['RDEPEND.suspect'].append(relative_path + \
+                                                               ": 'test?' USE conditional in RDEPEND")
                                                continue
                                        try:
                                                atom = portage.dep.Atom(token)
index 45ed2c94fb11b76b998b86e676eeb5186ab5ea1f..bdb014f8fec714f118c89ed21b10eff10b6c46f4 100644 (file)
@@ -54,10 +54,14 @@ class Package(Task):
                self.cpv_split = portage.catpkgsplit(self.cpv)
                self.pv_split = self.cpv_split[1:]
 
-       def _invalid_metadata(self, msg):
+       def _invalid_metadata(self, msg_type, msg):
                if self.invalid is None:
-                       self.invalid = []
-               self.invalid.append(msg)
+                       self.invalid = {}
+               msgs = self.invalid.get(msg_type)
+               if msgs is None:
+                       msgs = []
+                       self.invalid[msg_type] = msgs
+               msgs.append(msg)
 
        class _use_class(object):
 
@@ -185,14 +189,10 @@ class _PackageMetadataWrapper(_PackageMetadataWrapperBase):
        def __getitem__(self, k):
                v = _PackageMetadataWrapperBase.__getitem__(self, k)
                if k in self._use_conditional_keys:
-                       if '?' in v:
+                       if self._pkg.root_config.settings.local_config and '?' in v:
                                try:
-                                       if self._pkg.root_config.settings.local_config:
-                                               v = paren_enclose(paren_normalize(use_reduce(
-                                                       paren_reduce(v), uselist=self._pkg.use.enabled)))
-                                       else:
-                                               v = paren_enclose(paren_normalize(use_reduce(
-                                                       paren_reduce(v), matchall=1)))
+                                       v = paren_enclose(paren_normalize(use_reduce(
+                                               paren_reduce(v), uselist=self._pkg.use.enabled)))
                                except portage.exception.InvalidDependString:
                                        # This error should already have been registered via
                                        # self._pkg._invalid_metadata().
@@ -219,7 +219,7 @@ class _PackageMetadataWrapper(_PackageMetadataWrapperBase):
                        try:
                                use_reduce(paren_reduce(v), matchall=1)
                        except portage.exception.InvalidDependString, e:
-                               self._pkg._invalid_metadata("%s: %s" % (k, e))
+                               self._pkg._invalid_metadata(k + ".syntax", "%s: %s" % (k, e))
 
        def _set_inherited(self, k, v):
                if isinstance(v, basestring):
index fa20b8019dca3ddae35362cf94efde9bbf2710dc..9b329a3355f2e26aa3c5394d3c179fe02b6e4c49 100644 (file)
@@ -33,7 +33,7 @@ from _emerge.clear_caches import clear_caches
 from _emerge.create_depgraph_params import create_depgraph_params
 from _emerge.create_world_atom import create_world_atom
 from _emerge.DepPriority import DepPriority
-from _emerge.depgraph import depgraph
+from _emerge.depgraph import depgraph, resume_depgraph
 from _emerge.EbuildFetcher import EbuildFetcher
 from _emerge.EbuildPhase import EbuildPhase
 from _emerge.emergelog import emergelog, _emerge_log_dir
@@ -47,7 +47,6 @@ from _emerge.PollScheduler import PollScheduler
 from _emerge.RootConfig import RootConfig
 from _emerge.SlotObject import SlotObject
 from _emerge.SequentialTaskQueue import SequentialTaskQueue
-from _emerge.show_invalid_depstring_notice import show_invalid_depstring_notice
 
 class Scheduler(PollScheduler):
 
@@ -323,8 +322,6 @@ class Scheduler(PollScheduler):
                return background
 
        def _get_interactive_tasks(self):
-               from portage import flatten
-               from portage.dep import use_reduce, paren_reduce
                interactive_tasks = []
                for task in self._mergelist:
                        if not (isinstance(task, Package) and \
index 58389aa1494daf8b511f1db6ba64c17b4f437b70..5ad75743df6c2d737c63ef27229c6a0aebe36127 100644 (file)
@@ -4900,8 +4900,9 @@ def get_masking_status(pkg, pkgsettings, root_config):
                        mreasons.append("CHOST: %s" % \
                                pkg.metadata["CHOST"])
                if pkg.invalid:
-                       for msg in pkg.invalid:
-                               mreasons.append("invalid: %s" % (msg,))
+                       for msg_type, msgs in pkg.invalid.iteritems():
+                               for msg in msgs:
+                                       mreasons.append("invalid: %s" % (msg,))
 
        if pkg.built and not pkg.installed:
                if not "EPREFIX" in pkg.metadata or not pkg.metadata["EPREFIX"]:
index 307574b350d5923b91ee3ef20b682be03d12982c..2f9bf07905cef2c094de78827ed29dc13b936c0c 100644 (file)
@@ -1605,6 +1605,7 @@ class config(object):
                        for blacklisted in self._env_blacklist:
                                for cfg in self.lookuplist:
                                        cfg.pop(blacklisted, None)
+                               self.backupenv.pop(blacklisted, None)
                        del blacklisted, cfg
 
                        self["PORTAGE_CONFIGROOT"] = config_root
@@ -2265,9 +2266,12 @@ class config(object):
                if mydb:
                        if not hasattr(mydb, "aux_get"):
                                for k in aux_keys:
-                                       v = mydb.get(k)
-                                       if v is not None:
-                                               pkg_configdict[k] = v
+                                       if k in mydb:
+                                               # Make these lazy, since __getitem__ triggers
+                                               # evaluation of USE conditionals which can't
+                                               # occur until PORTAGE_USE is calculated below.
+                                               pkg_configdict.addLazySingleton(k,
+                                                       mydb.__getitem__, k)
                        else:
                                for k, v in izip(aux_keys, mydb.aux_get(self.mycpv, aux_keys)):
                                        pkg_configdict[k] = v
index 027693605967fe7ce7135706b88e14051e20fdcf..84c5a9741ef5c6bea7009636a734567b827b1d5f 100644 (file)
@@ -16,6 +16,7 @@ class database(template.database):
                *args, **config):
                super_config = config.copy()
                super_config.pop("gid", None)
+               super_config.pop("perms", None)
                super(database, self).__init__(location, label, auxdbkeys,
                        *args, **super_config)
                self.db_rw = db_rw(location, label, auxdbkeys, **config)
index 5e8b11c8bb1f4e2a22b9c9252fccc1e35657a792..ad1ee805fa0fa946969a35167a50e9ca219caeea 100644 (file)
@@ -13,6 +13,7 @@ from portage.exception import PortageException
 from portage.process import atexit_register
 from portage.elog.messages import collect_ebuild_messages, collect_messages
 from portage.elog.filtering import filter_loglevels
+from portage.localization import _
 
 import os
 
@@ -157,8 +158,8 @@ def elog_process(cpv, mysettings, phasefilter=None):
                                        _elog_atexit_handlers.append(m.finalize)
                                        atexit_register(m.finalize)
                        except (ImportError, AttributeError), e:
-                               writemsg("!!! Error while importing logging modules " + \
-                                       "while loading \"mod_%s\":\n" % str(s))
+                               writemsg(_("!!! Error while importing logging modules "
+                                       "while loading \"mod_%s\":\n") % str(s))
                                writemsg("%s\n" % str(e), noiselevel=-1)
                        except PortageException, e:
                                writemsg("%s\n" % str(e), noiselevel=-1)
index 4fa73ba5ff57f84d8ce5642ed0f4c11f5af5e739..9832f26600f3b1bd3e7fed98b24b201e697bbcb8 100644 (file)
@@ -10,6 +10,7 @@ portage.proxy.lazyimport.lazyimport(globals(),
 )
 
 from portage.const import EBUILD_PHASES
+from portage.localization import _
 
 import os
 import sys
@@ -32,7 +33,7 @@ def collect_ebuild_messages(path):
        for msgfunction in mylogfiles:
                filename = os.path.join(path, msgfunction)
                if msgfunction not in EBUILD_PHASES:
-                       writemsg("!!! can't process invalid log file: %s\n" % filename,
+                       writemsg(_("!!! can't process invalid log file: %s\n") % filename,
                                noiselevel=-1)
                        continue
                if not msgfunction in logentries:
@@ -45,8 +46,8 @@ def collect_ebuild_messages(path):
                        try:
                                msgtype, msg = l.split(" ", 1)
                        except ValueError:
-                               writemsg("!!! malformed entry in " + \
-                                       "log file: '%s'\n" % filename, noiselevel=-1)
+                               writemsg(_("!!! malformed entry in "
+                                       "log file: '%s'\n") % filename, noiselevel=-1)
                                continue
 
                        if lastmsgtype is None:
index 30d88f005067224f973864f68af17a8231bd7747..fa6577dc6d59f8f397d56bd3208aaf22fb5f8544 100644 (file)
@@ -5,6 +5,7 @@
 
 from portage.output import EOutput, colorize
 from portage.const import EBUILD_PHASES
+from portage.localization import _
 
 _items = []
 def process(mysettings, key, logentries, fulltext):
@@ -18,12 +19,13 @@ def finalize(mysettings=None):
        global _items
        printer = EOutput()
        for mysettings, key, logentries in _items:
-               root_msg = ""
-               if mysettings["ROOT"] != "/":
-                       root_msg = " merged to %s" % mysettings["ROOT"]
                print
-               printer.einfo("Messages for package %s%s:" % \
-                       (colorize("INFORM", key), root_msg))
+               if mysettings["ROOT"] == "/":
+                       printer.einfo(_("Messages for package %s:") %
+                               colorize("INFORM", key))
+               else:
+                       printer.einfo(_("Messages for package %(pkg)s merged to %(root)s:") %
+                               {"pkg": colorize("INFORM", key), "root": mysettings["ROOT"]})
                print
                for phase in EBUILD_PHASES:
                        if phase not in logentries:
index d6383a4eb06b7bf2457cef5c7923a58c0d13eb16..841986b96ddd8fa47b20b6431f9c8e4461f26318 100644 (file)
@@ -5,6 +5,7 @@
 
 import portage.mail, socket
 from portage.exception import PortageException
+from portage.localization import _
 from portage.util import writemsg
 
 def process(mysettings, key, logentries, fulltext):
@@ -20,17 +21,17 @@ def process(mysettings, key, logentries, fulltext):
        mysubject = mysubject.replace("${HOST}", socket.getfqdn())
 
        # look at the phases listed in our logentries to figure out what action was performed
-       action = "merged"
+       action = _("merged")
        for phase in logentries.keys():
                # if we found a *rm phase assume that the package was unmerged
                if phase in ["postrm", "prerm"]:
-                       action = "unmerged"
+                       action = _("unmerged")
        # if we think that the package was unmerged, make sure there was no unexpected
        # phase recorded to avoid misinformation
-       if action == "unmerged":
+       if action == _("unmerged"):
                for phase in logentries.keys():
                        if phase not in ["postrm", "prerm", "other"]:
-                               action = "unknown"
+                               action = _("unknown")
 
        mysubject = mysubject.replace("${ACTION}", action)
 
index ed5147313ffbe567994731e873152dd1809eb358..90a6ed2f895f5828d217047f78bb539523cf4f84 100644 (file)
@@ -5,14 +5,15 @@
 
 import portage.mail, socket, os, time
 from portage.exception import PortageException
+from portage.localization import _
 from portage.util import writemsg
 from email.MIMEText import MIMEText as TextMessage
 
 _items = {}
 def process(mysettings, key, logentries, fulltext):
        global _items
-       header = ">>> Messages generated for package %s by process %d on %s:\n\n" % \
-               (key, os.getpid(), time.strftime("%Y%m%d-%H%M%S %Z", time.localtime(time.time())))
+       header = _(">>> Messages generated for package %(pkg)s by process %(pid)d on %(time)s:\n\n") % \
+               {"pkg": key, "pid": os.getpid(), "time": time.strftime("%Y%m%d-%H%M%S %Z", time.localtime(time.time()))}
        config_root = mysettings["PORTAGE_CONFIGROOT"]
        mysettings, items = _items.setdefault(config_root, (mysettings, {}))
        items[key] = header + fulltext
@@ -30,9 +31,9 @@ def _finalize(mysettings, items):
        if len(items) == 0:
                return
        elif len(items) == 1:
-               count = "one package"
+               count = _("one package")
        else:
-               count = "multiple packages"
+               count = _("multiple packages")
        if "PORTAGE_ELOG_MAILURI" in mysettings:
                myrecipient = mysettings["PORTAGE_ELOG_MAILURI"].split()[0]
        else:
@@ -44,8 +45,8 @@ def _finalize(mysettings, items):
        mysubject = mysubject.replace("${PACKAGE}", count)
        mysubject = mysubject.replace("${HOST}", socket.getfqdn())
 
-       mybody = "elog messages for the following packages generated by " + \
-               "process %d on host %s:\n" % (os.getpid(), socket.getfqdn())
+       mybody = _("elog messages for the following packages generated by "
+               "process %(pid)d on host %(host)s:\n") % {"pid": os.getpid(), "host": socket.getfqdn()}
        for key in items:
                 mybody += "- %s\n" % key
 
index eeb8fa0dacbd40d79c470f27893792832e947187..1b749f24b1289c6b636c7d6ae23dcaeb36a8c465 100644 (file)
@@ -5,6 +5,7 @@
 
 import os, time
 from portage.data import portage_uid, portage_gid
+from portage.localization import _
 from portage.util import ensure_dirs, apply_permissions
 from portage.const import EPREFIX
 
@@ -19,8 +20,8 @@ def process(mysettings, key, logentries, fulltext):
        elogfilename = elogdir+"/summary.log"
        elogfile = open(elogfilename, "a")
        apply_permissions(elogfilename, mode=060, mask=0)
-       elogfile.write(">>> Messages generated by process %d on %s for package %s:\n\n" % \
-                       (os.getpid(), time.strftime("%Y-%m-%d %H:%M:%S %Z", time.localtime(time.time())), key))
+       elogfile.write(_(">>> Messages generated by process %(pid)d on %(time)s for package %(pkg)s:\n\n") %
+                       {"pid": os.getpid(), "time": time.strftime("%Y-%m-%d %H:%M:%S %Z", time.localtime(time.time())), "pkg": key})
        elogfile.write(fulltext)
        elogfile.write("\n")
        elogfile.close()
index 400797c0c4d2d1c61fdc8cb2dd87f5009c400dd2..31d3b09aa6acb4e906c2fb28d2c21c00db0dd84b 100644 (file)
@@ -5,6 +5,7 @@
 
 import os
 import stat
+from portage.localization import _
 
 class LoaderError(Exception):
        
@@ -181,13 +182,13 @@ class ItemFileLoader(FileLoader):
                split = line.split()
                if not len(split):
                        errors.setdefault(self.fname, []).append(
-                               "Malformed data at line: %s, data: %s"
+                               _("Malformed data at line: %s, data: %s")
                                % (line_num + 1, line))
                        return
                key = split[0]
                if not self._validate(key):
                        errors.setdefault(self.fname, []).append(
-                               "Validation failed at line: %s, data %s"
+                               _("Validation failed at line: %s, data %s")
                                % (line_num + 1, key))
                        return
                data[key] = None
@@ -222,19 +223,19 @@ class KeyListFileLoader(FileLoader):
                split = line.split()
                if len(split) < 1:
                        errors.setdefault(self.fname, []).append(
-                               "Malformed data at line: %s, data: %s"
+                               _("Malformed data at line: %s, data: %s")
                                % (line_num + 1, line))
                        return
                key = split[0]
                value = split[1:]
                if not self._validate(key):
                        errors.setdefault(self.fname, []).append(
-                               "Key validation failed at line: %s, data %s"
+                               _("Key validation failed at line: %s, data %s")
                                % (line_num + 1, key))
                        return
                if not self._valueValidate(value):
                        errors.setdefault(self.fname, []).append(
-                               "Value validation failed at line: %s, data %s"
+                               _("Value validation failed at line: %s, data %s")
                                % (line_num + 1, value))
                        return
                if key in data:
@@ -276,24 +277,24 @@ class KeyValuePairFileLoader(FileLoader):
                split = line.split('=', 1)
                if len(split) < 2:
                        errors.setdefault(self.fname, []).append(
-                               "Malformed data at line: %s, data %s"
+                               _("Malformed data at line: %s, data %s")
                                % (line_num + 1, line))
                        return
                key = split[0].strip()
                value = split[1].strip()
                if not key:
                        errors.setdefault(self.fname, []).append(
-                               "Malformed key at line: %s, key %s"
+                               _("Malformed key at line: %s, key %s")
                                % (line_num + 1, key))
                        return
                if not self._validate(key):
                        errors.setdefault(self.fname, []).append(
-                               "Key validation failed at line: %s, data %s"
+                               _("Key validation failed at line: %s, data %s")
                                % (line_num + 1, key))
                        return
                if not self._valueValidate(value):
                        errors.setdefault(self.fname, []).append(
-                               "Value validation failed at line: %s, data %s"
+                               _("Value validation failed at line: %s, data %s")
                                % (line_num + 1, value))
                        return
                if key in data:
index ef7c1d9381105bf5983498e3f3013174b617b9c6..80aa608f68153a7557da9e9333060b378547b0f1 100644 (file)
@@ -10,6 +10,7 @@ from ConfigParser import SafeConfigParser, NoOptionError
 from portage import load_mod
 from portage.const import USER_CONFIG_PATH, GLOBAL_CONFIG_PATH
 from portage.exception import PackageSetNotFound
+from portage.localization import _
 
 SETPREFIX = "@"
 
@@ -21,7 +22,7 @@ def get_boolean(options, name, default):
        elif options[name].lower() in ("0", "no", "off", "false"):
                return False
        else:
-               raise SetConfigError("invalid value '%s' for option '%s'" % (options[name], name))
+               raise SetConfigError(_("invalid value '%(value)s' for option '%(option)s'") % {"value": options[name], "option": name})
 
 class SetConfigError(Exception):
        pass
@@ -56,7 +57,8 @@ class SetConfig(object):
                        section = self.psets[setname].creator
                        if parser.has_option(section, "multiset") and \
                                parser.getboolean(section, "multiset"):
-                               self.errors.append("Invalid request to reconfigure set '%s' generated by multiset section '%s'" % (setname, section))
+                               self.errors.append(_("Invalid request to reconfigure set '%(set)s' generated "
+                                       "by multiset section '%(section)s'") % {"set": setname, "section": section})
                                return
                        for k, v in options.items():
                                parser.set(section, k, v)
@@ -80,7 +82,8 @@ class SetConfig(object):
                                try:
                                        setclass = load_mod("portage.sets."+classname)
                                except (ImportError, AttributeError):
-                                       self.errors.append("Could not import '%s' for section '%s'" % (classname, sname))
+                                       self.errors.append(_("Could not import '%(class)s' for section "
+                                               "'%(section)s'") % {"class": classname, "section": sname})
                                        continue
                        # prepare option dict for the current section
                        optdict = {}
@@ -95,18 +98,19 @@ class SetConfig(object):
                                        try:
                                                newsets = setclass.multiBuilder(optdict, self.settings, self.trees)
                                        except SetConfigError, e:
-                                               self.errors.append("Configuration error in section '%s': %s" % (sname, str(e)))
+                                               self.errors.append(_("Configuration error in section '%s': %s") % (sname, str(e)))
                                                continue
                                        for x in newsets:
                                                if x in self.psets and not update:
-                                                       self.errors.append("Redefinition of set '%s' (sections: '%s', '%s')" % (x, self.psets[x].creator, sname))
+                                                       self.errors.append(_("Redefinition of set '%s' (sections: '%s', '%s')") % (x, self.psets[x].creator, sname))
                                                newsets[x].creator = sname
                                                if parser.has_option(sname, "world-candidate") and \
                                                        not parser.getboolean(sname, "world-candidate"):
                                                        newsets[x].world_candidate = False
                                        self.psets.update(newsets)
                                else:
-                                       self.errors.append("Section '%s' is configured as multiset, but '%s' doesn't support that configuration" % (sname, classname))
+                                       self.errors.append(_("Section '%(section)s' is configured as multiset, but '%(class)s' "
+                                               "doesn't support that configuration") % {"section": sname, "class": classname})
                                        continue
                        else:
                                try:
@@ -114,7 +118,7 @@ class SetConfig(object):
                                except NoOptionError:
                                        setname = sname
                                if setname in self.psets and not update:
-                                       self.errors.append("Redefinition of set '%s' (sections: '%s', '%s')" % (setname, self.psets[setname].creator, sname))
+                                       self.errors.append(_("Redefinition of set '%s' (sections: '%s', '%s')") % (setname, self.psets[setname].creator, sname))
                                if hasattr(setclass, "singleBuilder"):
                                        try:
                                                self.psets[setname] = setclass.singleBuilder(optdict, self.settings, self.trees)
@@ -123,10 +127,11 @@ class SetConfig(object):
                                                        not parser.getboolean(sname, "world-candidate"):
                                                        self.psets[setname].world_candidate = False
                                        except SetConfigError, e:
-                                               self.errors.append("Configuration error in section '%s': %s" % (sname, str(e)))
+                                               self.errors.append(_("Configuration error in section '%s': %s") % (sname, str(e)))
                                                continue
                                else:
-                                       self.errors.append("'%s' does not support individual set creation, section '%s' must be configured as multiset" % (classname, sname))
+                                       self.errors.append(_("'%(class)s' does not support individual set creation, section '%(section)s' "
+                                               "must be configured as multiset") % {"class": classname, "section": sname})
                                        continue
                self._parsed = True
        
index 65d05a2aefe8572dea1f6d6982eadc5aa56f10f8..d6e78bfb62c2cde3946d2e9badc74022346b2792 100644 (file)
@@ -4,6 +4,7 @@
 
 from portage.versions import catpkgsplit, catsplit, pkgcmp, best
 from portage.dep import Atom
+from portage.localization import _
 from portage.sets.base import PackageSet
 from portage.sets import SetConfigError, get_boolean
 
@@ -81,7 +82,7 @@ class OwnerSet(PackageSet):
 
        def singleBuilder(cls, options, settings, trees):
                if not "files" in options:
-                       raise SetConfigError("no files given")
+                       raise SetConfigError(_("no files given"))
 
                import shlex
                return cls(vardb=trees["vartree"].dbapi,
@@ -119,17 +120,17 @@ class VariableSet(EverythingSet):
 
                variable = options.get("variable")
                if variable is None:
-                       raise SetConfigError("missing required attribute: 'variable'")
+                       raise SetConfigError(_("missing required attribute: 'variable'"))
 
                includes = options.get("includes", "")
                excludes = options.get("excludes", "")
 
                if not (includes or excludes):
-                       raise SetConfigError("no includes or excludes given")
+                       raise SetConfigError(_("no includes or excludes given"))
                
                metadatadb = options.get("metadata-source", "vartree")
                if not metadatadb in trees.keys():
-                       raise SetConfigError("invalid value '%s' for option metadata-source" % metadatadb)
+                       raise SetConfigError(_("invalid value '%s' for option metadata-source") % metadatadb)
 
                return cls(trees["vartree"].dbapi,
                        metadatadb=trees[metadatadb].dbapi,
@@ -198,7 +199,7 @@ class UnavailableSet(EverythingSet):
 
                metadatadb = options.get("metadata-source", "porttree")
                if not metadatadb in trees:
-                       raise SetConfigError(("invalid value '%s' for option " + \
+                       raise SetConfigError(_("invalid value '%s' for option "
                                "metadata-source") % (metadatadb,))
 
                return cls(trees["vartree"].dbapi,
@@ -234,11 +235,11 @@ class CategorySet(PackageSet):
                
        def singleBuilder(cls, options, settings, trees):
                if not "category" in options:
-                       raise SetConfigError("no category given")
+                       raise SetConfigError(_("no category given"))
 
                category = options["category"]
                if not category in settings.categories:
-                       raise SetConfigError("invalid category name '%s'" % category)
+                       raise SetConfigError(_("invalid category name '%s'") % category)
 
                visible = cls._builderGetVisible(options)
                
@@ -252,7 +253,7 @@ class CategorySet(PackageSet):
                        categories = options["categories"].split()
                        invalid = set(categories).difference(settings.categories)
                        if invalid:
-                               raise SetConfigError("invalid categories: %s" % ", ".join(list(invalid)))
+                               raise SetConfigError(_("invalid categories: %s") % ", ".join(list(invalid)))
                else:
                        categories = settings.categories
        
@@ -260,7 +261,7 @@ class CategorySet(PackageSet):
                name_pattern = options.get("name_pattern", "$category/*")
        
                if not "$category" in name_pattern and not "${category}" in name_pattern:
-                       raise SetConfigError("name_pattern doesn't include $category placeholder")
+                       raise SetConfigError(_("name_pattern doesn't include $category placeholder"))
        
                for cat in categories:
                        myset = CategorySet(cat, trees["porttree"].dbapi, only_visible=visible)
@@ -293,11 +294,11 @@ class AgeSet(EverythingSet):
        def singleBuilder(cls, options, settings, trees):
                mode = options.get("mode", "older")
                if str(mode).lower() not in ["newer", "older"]:
-                       raise SetConfigError("invalid 'mode' value %s (use either 'newer' or 'older')" % mode)
+                       raise SetConfigError(_("invalid 'mode' value %s (use either 'newer' or 'older')") % mode)
                try:
                        age = int(options.get("age", "7"))
                except ValueError, e:
-                       raise SetConfigError("value of option 'age' is not an integer")
+                       raise SetConfigError(_("value of option 'age' is not an integer"))
                return AgeSet(vardb=trees["vartree"].dbapi, mode=mode, age=age)
 
        singleBuilder = classmethod(singleBuilder)
index fe256a79bd9a27c0664738f75e31040ff4c5e458..5e5f2bc1a529a1f877487ed8b932df1b72a76f2f 100644 (file)
@@ -8,6 +8,7 @@ from itertools import chain
 
 from portage.util import grabfile, write_atomic, ensure_dirs, normalize_path
 from portage.const import PRIVATE_PATH, USER_CONFIG_PATH, EPREFIX_LSTRIP
+from portage.localization import _
 from portage.locks import lockfile, unlockfile
 from portage import portage_gid
 from portage.sets.base import PackageSet, EditablePackageSet
@@ -30,7 +31,7 @@ class StaticFileSet(EditablePackageSet):
                self.description = "Package set loaded from file %s" % self._filename
                self.loader = ItemFileLoader(self._filename, self._validate)
                if greedy and not dbapi:
-                       self.errors.append("%s configured as greedy set, but no dbapi instance passed in constructor" % self._filename)
+                       self.errors.append(_("%s configured as greedy set, but no dbapi instance passed in constructor") % self._filename)
                        greedy = False
                self.greedy = greedy
                self.dbapi = dbapi
@@ -94,7 +95,7 @@ class StaticFileSet(EditablePackageSet):
                
        def singleBuilder(self, options, settings, trees):
                if not "filename" in options:
-                       raise SetConfigError("no filename specified")
+                       raise SetConfigError(_("no filename specified"))
                greedy = get_boolean(options, "greedy", False)
                filename = options["filename"]
                # look for repository path variables
@@ -103,7 +104,7 @@ class StaticFileSet(EditablePackageSet):
                        try:
                                filename = self._repopath_sub.sub(trees["porttree"].dbapi.treemap[match.groupdict()["reponame"]], filename)
                        except KeyError:
-                               raise SetConfigError("Could not find repository '%s'" % match.groupdict()["reponame"])
+                               raise SetConfigError(_("Could not find repository '%s'") % match.groupdict()["reponame"])
                return StaticFileSet(filename, greedy=greedy, dbapi=trees["vartree"].dbapi)
        singleBuilder = classmethod(singleBuilder)
        
@@ -112,7 +113,7 @@ class StaticFileSet(EditablePackageSet):
                directory = options.get("directory", os.path.join(settings["PORTAGE_CONFIGROOT"], USER_CONFIG_PATH.lstrip(os.sep), "sets"))
                name_pattern = options.get("name_pattern", "${name}")
                if not "$name" in name_pattern and not "${name}" in name_pattern:
-                       raise SetConfigError("name_pattern doesn't include ${name} placeholder")
+                       raise SetConfigError(_("name_pattern doesn't include ${name} placeholder"))
                greedy = get_boolean(options, "greedy", False)
                # look for repository path variables
                match = self._repopath_match.match(directory)
@@ -120,7 +121,7 @@ class StaticFileSet(EditablePackageSet):
                        try:
                                directory = self._repopath_sub.sub(trees["porttree"].dbapi.treemap[match.groupdict()["reponame"]], directory)
                        except KeyError:
-                               raise SetConfigError("Could not find repository '%s'" % match.groupdict()["reponame"])
+                               raise SetConfigError(_("Could not find repository '%s'") % match.groupdict()["reponame"])
                if os.path.isdir(directory):
                        directory = normalize_path(directory)
                        for parent, dirs, files in os.walk(directory):
@@ -155,7 +156,7 @@ class ConfigFileSet(PackageSet):
        
        def singleBuilder(self, options, settings, trees):
                if not "filename" in options:
-                       raise SetConfigError("no filename specified")
+                       raise SetConfigError(_("no filename specified"))
                return ConfigFileSet(options["filename"])
        singleBuilder = classmethod(singleBuilder)
        
@@ -164,7 +165,7 @@ class ConfigFileSet(PackageSet):
                directory = options.get("directory", os.path.join(settings["PORTAGE_CONFIGROOT"], USER_CONFIG_PATH.lstrip(os.sep)))
                name_pattern = options.get("name_pattern", "sets/package_$suffix")
                if not "$suffix" in name_pattern and not "${suffix}" in name_pattern:
-                       raise SetConfigError("name_pattern doesn't include $suffix placeholder")
+                       raise SetConfigError(_("name_pattern doesn't include $suffix placeholder"))
                for suffix in ["keywords", "use", "mask", "unmask"]:
                        myname = name_pattern.replace("$suffix", suffix)
                        myname = myname.replace("${suffix}", suffix)
index 1c5067ebc3933588c0041f05788ae30da978ecfd..806cb63f6faf7e74a9877625d71fd0e1b619e373 100644 (file)
@@ -2,6 +2,7 @@
 # Distributed under the terms of the GNU General Public License v2
 # $Id$
 
+from portage.localization import _
 from portage.sets.base import PackageSet
 from portage.sets import get_boolean
 from portage.versions import catpkgsplit
@@ -49,7 +50,7 @@ class LibraryFileConsumerSet(LibraryConsumerSet):
                import shlex
                files = tuple(shlex.split(options.get("files", "")))
                if not files:
-                       raise SetConfigError("no files given")
+                       raise SetConfigError(_("no files given"))
                debug = get_boolean(options, "debug", False)
                return LibraryFileConsumerSet(trees["vartree"].dbapi,
                        files, debug=debug)
index 915f989f2ce7894dbf7861c64d5b701c794ad0be..4c2bcd11359cce76e2ac69aadfd0e4adc270ef80 100644 (file)
@@ -82,6 +82,25 @@ class EbuildWhitespace(LineCheck):
                if self.trailing_whitespace.match(line) is None:
                        return errors.TRAILING_WHITESPACE_ERROR
 
+class EbuildBlankLine(LineCheck):
+       repoman_check_name = 'ebuild.minorsyn'
+       blank_line = re.compile(r'^$')
+
+       def new(self, pkg):
+               self.line_is_blank = False
+
+       def check(self, num, line):
+               if self.line_is_blank and self.blank_line.match(line):
+                       return 'Useless blank line on line: %d'
+               if self.blank_line.match(line):
+                       self.line_is_blank = True
+               else:
+                       self.line_is_blank = False
+
+       def end(self):
+               if self.line_is_blank:
+                       yield 'Useless blank line on last line'
+
 class EbuildQuote(LineCheck):
        """Ensure ebuilds have valid quoting around things like D,FILESDIR, etc..."""
 
@@ -471,7 +490,7 @@ class Eapi3GoneVars(LineCheck):
 
 
 _constant_checks = tuple((c() for c in (
-       EbuildHeader, EbuildWhitespace, EbuildQuote,
+       EbuildHeader, EbuildWhitespace, EbuildBlankLine, EbuildQuote,
        EbuildAssignment, EbuildUselessDodoc,
        EbuildUselessCdS, EbuildNestedDie,
        EbuildPatches, EbuildQuotedA, EapiDefinition,