# Then, check to make sure deps are satisfiable (to avoid "can't find match for" problems)
# that last one is tricky because multiple profiles need to be checked.
+from __future__ import print_function
+
import codecs
-import commands
+try:
+ from subprocess import getstatusoutput as subprocess_getstatusoutput
+except ImportError:
+ from commands import getstatusoutput as subprocess_getstatusoutput
import errno
import formatter
import logging
import optparse
-import os
import re
import signal
import stat
import time
import platform
-from itertools import chain, izip
+from io import StringIO
+from itertools import chain
from stat import S_ISDIR, ST_CTIME
-try:
- from cStringIO import StringIO
-except ImportError:
- from StringIO import StringIO
-
if not hasattr(__builtins__, "set"):
from sets import Set as set
sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
import portage
portage._disable_legacy_globals()
+from portage import os
+from portage import _encodings
+from portage import _unicode_encode
try:
from repoman.checks import run_checks
from repoman.checks import run_checks
from repoman import utilities
-from _emerge import Package, RootConfig
-from portage.sets import load_default_config
+from _emerge.Package import Package
+from _emerge.RootConfig import RootConfig
+from portage._sets import load_default_config
import portage.checksum
import portage.const
from portage.output import ConsoleStyleFile, StyleWriter
from portage.util import cmp_sort_key, writemsg_level
+if sys.hexversion >= 0x3000000:
+ basestring = str
+
util.initialize_logger()
# 14 is the length of DESCRIPTION=""
bad = create_color_func("BAD")
# A sane umask is needed for files that portage creates.
-os.umask(022)
+os.umask(0o22)
repoman_settings = portage.config(local_config=False,
config_incrementals=portage.const.INCREMENTALS)
repoman_settings.lock()
nocolor()
def warn(txt):
- print "repoman: " + txt
+ print("repoman: " + txt)
def err(txt):
warn(txt)
'scan' : 'Scan directory tree for QA issues'
}
- mode_keys = modes.keys()
+ mode_keys = list(modes)
mode_keys.sort()
parser = RepomanOptionParser(formatter=RepomanHelpFormatter(), usage="%prog [options] [mode]")
parser.add_option('--without-mask', dest='without_mask', action='store_true',
default=False, help='behave as if no package.mask entries exist (not allowed with commit mode)')
- parser.add_option('--mode', type='choice', dest='mode', choices=modes.keys(),
+ parser.add_option('--mode', type='choice', dest='mode', choices=list(modes),
help='specify which mode repoman will run in (default=full)')
parser.on_tail("\n " + green("Modes".ljust(20) + " Description\n"))
parser.on_tail("\n " + green("QA keyword".ljust(20) + " Description\n"))
- sorted_qa = qahelp.keys()
+ sorted_qa = list(qahelp)
sorted_qa.sort()
for k in sorted_qa:
parser.on_tail(" %s %s\n" % (k.ljust(20), qahelp[k]))
"changelog.notadded":"ChangeLogs that exist but have not been added to cvs",
"filedir.missing":"Package lacks a files directory",
"file.executable":"Ebuilds, digests, metadata.xml, Manifest, and ChangeLog do note need the executable bit",
- "file.size":"Files in the files directory must be under 20k",
+ "file.size":"Files in the files directory must be under 20 KiB",
+ "file.size.fatal":"Files in the files directory must be under 60 KiB",
"file.name":"File/dir name must be composed of only the following chars: %s " % allowed_filename_chars,
"file.UTF8":"File is not UTF8 compliant",
"inherit.autotools":"Ebuild inherits autotools but does not call eautomake, eautoconf or eautoreconf",
"LICENSE.missing":"Ebuilds that have a missing or empty LICENSE variable",
"DESCRIPTION.missing":"Ebuilds that have a missing or empty DESCRIPTION variable",
"DESCRIPTION.toolong":"DESCRIPTION is over %d characters" % max_desc_len,
+ "EAPI.definition":"EAPI is defined after an inherit call (must be defined before)",
"EAPI.incompatible":"Ebuilds that use features that are only available with a different EAPI",
"EAPI.unsupported":"Ebuilds that have an unsupported EAPI version (you must upgrade portage)",
"SLOT.missing":"Ebuilds that have a missing or empty SLOT variable",
"DEPEND.badmaskedindev":"Masked ebuilds with bad DEPEND settings (matched against *all* ebuilds) in developing arch",
"RDEPEND.badmaskedindev":"Masked ebuilds with RDEPEND settings (matched against *all* ebuilds) in developing arch",
"PDEPEND.badmaskedindev":"Masked ebuilds with PDEPEND settings (matched against *all* ebuilds) in developing arch",
+ "PDEPEND.suspect":"PDEPEND contains a package that usually only belongs in DEPEND.",
"DEPEND.syntax":"Syntax error in DEPEND (usually an extra/missing space/parenthesis)",
"RDEPEND.syntax":"Syntax error in RDEPEND (usually an extra/missing space/parenthesis)",
"PDEPEND.syntax":"Syntax error in PDEPEND (usually an extra/missing space/parenthesis)",
+ "DEPEND.badtilde":"DEPEND uses the ~ dep operator with a non-zero revision part, which is useless (the revision is ignored)",
+ "RDEPEND.badtilde":"RDEPEND uses the ~ dep operator with a non-zero revision part, which is useless (the revision is ignored)",
+ "PDEPEND.badtilde":"PDEPEND uses the ~ dep operator with a non-zero revision part, which is useless (the revision is ignored)",
"LICENSE.syntax":"Syntax error in LICENSE (usually an extra/missing space/parenthesis)",
"PROVIDE.syntax":"Syntax error in PROVIDE (usually an extra/missing space/parenthesis)",
"PROPERTIES.syntax":"Syntax error in PROPERTIES (usually an extra/missing space/parenthesis)",
"variable.invalidchar":"A variable contains an invalid character that is not part of the ASCII character set",
"variable.readonly":"Assigning a readonly variable",
"LIVEVCS.stable":"This ebuild is a live checkout from a VCS but has stable keywords.",
- "IUSE.invalid":"This ebuild has a variable in IUSE that is not in the use.desc or use.local.desc file",
+ "LIVEVCS.unmasked":"This ebuild is a live checkout from a VCS but has keywords and is not masked in the global package.mask.",
+ "IUSE.invalid":"This ebuild has a variable in IUSE that is not in the use.desc or its metadata.xml file",
"IUSE.undefined":"This ebuild does not define IUSE (style guideline says to define IUSE even when empty)",
"LICENSE.invalid":"This ebuild is listing a license that doesnt exist in portages license/ dir.",
"KEYWORDS.invalid":"This ebuild contains KEYWORDS that are not listed in profiles/arch.list or for which no valid profile was found",
"RDEPEND.implicit":"RDEPEND is unset in the ebuild which triggers implicit RDEPEND=$DEPEND assignment",
"RDEPEND.suspect":"RDEPEND contains a package that usually only belongs in DEPEND.",
"RESTRICT.invalid":"This ebuild contains invalid RESTRICT values.",
- "digestentry.unused":"Some files listed in the Manifest aren't referenced in SRC_URI",
+ "digest.assumed":"Existing digest must be assumed correct (Package level only)",
+ "digest.missing":"Some files listed in SRC_URI aren't referenced in the Manifest",
+ "digest.unused":"Some files listed in the Manifest aren't referenced in SRC_URI",
"ebuild.nostable":"There are no ebuilds that are marked as stable for your ARCH",
"ebuild.allmasked":"All ebuilds are masked for this package (Package level only)",
"ebuild.majorsyn":"This ebuild has a major syntax error that may cause the ebuild to fail partially or fully",
"upstream.workaround":"The ebuild works around an upstream bug, an upstream bug should be filed and tracked in bugs.gentoo.org"
}
-qacats = qahelp.keys()
+qacats = list(qahelp)
qacats.sort()
qawarnings = set((
"changelog.missing",
"changelog.notadded",
-"digestentry.unused",
+"digest.assumed",
+"digest.unused",
"ebuild.notadded",
"ebuild.nostable",
"ebuild.allmasked",
"DEPEND.badmasked","RDEPEND.badmasked","PDEPEND.badmasked",
"DEPEND.badindev","RDEPEND.badindev","PDEPEND.badindev",
"DEPEND.badmaskedindev","RDEPEND.badmaskedindev","PDEPEND.badmaskedindev",
+"DEPEND.badtilde", "RDEPEND.badtilde", "PDEPEND.badtilde",
"DESCRIPTION.toolong",
"KEYWORDS.dropped",
"KEYWORDS.stupid",
"KEYWORDS.missing",
"IUSE.undefined",
+"PDEPEND.suspect",
"RDEPEND.implicit",
"RDEPEND.suspect",
"RESTRICT.invalid",
"virtual.unavailable",
"usage.obsolete",
"upstream.workaround",
-"LIVEVCS.stable"
+"LIVEVCS.stable",
+"LIVEVCS.unmasked",
))
non_ascii_re = re.compile(r'[^\x00-\x7f]')
missingvars=["KEYWORDS","LICENSE","DESCRIPTION","HOMEPAGE","SLOT"]
allvars = set(x for x in portage.auxdbkeys if not x.startswith("UNUSED_"))
-allvars.discard("CDEPEND")
allvars.update(Package.metadata_keys)
allvars = sorted(allvars)
commitmessage=None
"dev-lang/swig",
"dev-lang/yasm",
"dev-perl/extutils-pkgconfig",
- "dev-python/setuptools",
"dev-util/byacc",
"dev-util/cmake",
"dev-util/ftjam",
+ "dev-util/gperf",
"dev-util/gtk-doc",
"dev-util/gtk-doc-am",
"dev-util/intltool",
"sys-devel/bison",
"sys-devel/dev86",
"sys-devel/flex",
- "sys-devel/libtool",
"sys-devel/m4",
"sys-devel/pmake",
"x11-misc/bdftopcf",
options, arguments = ParseArgs(sys.argv, qahelp)
if options.version:
- print "Portage", portage.VERSION
+ print("Portage", portage.VERSION)
sys.exit(0)
# Set this to False when an extraordinary issue (generally
prefix = bad(" * ")
from textwrap import wrap
for line in wrap(msg, 70):
- print prefix + line
+ print(prefix + line)
sys.exit(1)
del repo_lines
logging.info('PORTDIR = "' + portdir + '"')
logging.info('PORTDIR_OVERLAY = "%s"' % env['PORTDIR_OVERLAY'])
+categories = []
+for path in set([portdir, portdir_overlay]):
+ categories.extend(portage.util.grabfile(
+ os.path.join(path, 'profiles', 'categories')))
+repoman_settings.categories = tuple(sorted(
+ portage.util.stack_lists([categories], incremental=1)))
+del categories
+
portdb.mysettings = repoman_settings
root_config = RootConfig(repoman_settings, trees[root], None)
# We really only need to cache the metadata that's necessary for visibility
# Reason for this is if they're trying to commit in just $FILESDIR/*, the Manifest needs updating.
# this check ensures that repoman knows where it is, and the manifest recommit is at least possible.
if options.mode == 'commit' and repolevel not in [1,2,3]:
- print red("***")+" Commit attempts *must* be from within a vcs co, category, or package directory."
- print red("***")+" Attempting to commit from a packages files directory will be blocked for instance."
- print red("***")+" This is intended behaviour, to ensure the manifest is recommited for a package."
- print red("***")
+ print(red("***")+" Commit attempts *must* be from within a vcs co, category, or package directory.")
+ print(red("***")+" Attempting to commit from a packages files directory will be blocked for instance.")
+ print(red("***")+" This is intended behaviour, to ensure the manifest is recommited for a package.")
+ print(red("***"))
err("Unable to identify level we're commiting from for %s" % '/'.join(reposplit))
startdir = normalize_path(mydir)
def caterror(mycat):
err(mycat+" is not an official category. Skipping QA checks in this directory.\nPlease ensure that you add "+catdir+" to "+repodir+"/profiles/categories\nif it is a new category.")
-# setup a uselist from portage
-uselist=[]
-try:
- uselist=portage.grabfile(portdir+"/profiles/use.desc")
- for l in range(0,len(uselist)):
- uselist[l]=uselist[l].split()[0]
- for var in repoman_settings["USE_EXPAND"].split():
- vardescs = portage.grabfile(portdir+"/profiles/desc/"+var.lower()+".desc")
- for l in range(0, len(vardescs)):
- uselist.append(var.lower() + "_" + vardescs[l].split()[0])
-except (IOError, OSError, ParseError), e:
- logging.exception("Couldn't read USE flags from use.desc")
- sys.exit(1)
+class ProfileDesc(object):
+ __slots__ = ('abs_path', 'arch', 'status', 'sub_path', 'tree_path',)
+ def __init__(self, arch, status, sub_path, tree_path):
+ self.arch = arch
+ self.status = status
+ self.sub_path = normalize_path(sub_path.lstrip(os.sep))
+ self.tree_path = tree_path
+ self.abs_path = os.path.join(tree_path, 'profiles', self.sub_path)
+
+profile_list = []
+valid_profile_types = frozenset(['dev', 'exp', 'stable'])
+
+# get lists of valid keywords, licenses, and use
+kwlist = set()
+liclist = set()
+uselist = set()
+global_pmasklines = []
+
+for path in portdb.porttrees:
+ try:
+ liclist.update(os.listdir(os.path.join(path, "licenses")))
+ except OSError:
+ pass
+ kwlist.update(portage.grabfile(os.path.join(path,
+ "profiles", "arch.list")))
+
+ use_desc = portage.grabfile(os.path.join(path, 'profiles', 'use.desc'))
+ for x in use_desc:
+ x = x.split()
+ if x:
+ uselist.add(x[0])
+
+ expand_desc_dir = os.path.join(path, 'profiles', 'desc')
+ try:
+ expand_list = os.listdir(expand_desc_dir)
+ except OSError:
+ pass
+ else:
+ for fn in expand_list:
+ if not fn[-5:] == '.desc':
+ continue
+ use_prefix = fn[:-5].lower() + '_'
+ for x in portage.grabfile(os.path.join(expand_desc_dir, fn)):
+ x = x.split()
+ if x:
+ uselist.add(use_prefix + x[0])
-# get lists of valid keywords and licenses
-kwlist = set(portage.grabfile(os.path.join(portdir, "profiles", "arch.list")))
-liclist = set(portage.listdir(os.path.join(portdir, "licenses")))
+ global_pmasklines.append(portage.util.grabfile_package(
+ os.path.join(path, 'profiles', 'package.mask'), recursive=1))
-if portdir_overlay != portdir:
- for porttree in portdb.porttrees[1:]:
- try:
- liclist.update(os.listdir(os.path.join(porttree, "licenses")))
- except OSError:
- pass
- kwlist.update(portage.grabfile(os.path.join(porttree,
- "profiles", "arch.list")))
+ desc_path = os.path.join(path, 'profiles', 'profiles.desc')
+ try:
+ desc_file = codecs.open(_unicode_encode(desc_path,
+ encoding=_encodings['fs'], errors='strict'),
+ mode='r', encoding=_encodings['repo.content'], errors='replace')
+ except EnvironmentError:
+ pass
+ else:
+ for i, x in enumerate(desc_file):
+ if x[0] == "#":
+ continue
+ arch = x.split()
+ if len(arch) == 0:
+ continue
+ if len(arch) != 3:
+ err("wrong format: \"" + bad(x.strip()) + "\" in " + \
+ desc_path + " line %d" % (i+1, ))
+ elif arch[0] not in kwlist:
+ err("invalid arch: \"" + bad(arch[0]) + "\" in " + \
+ desc_path + " line %d" % (i+1, ))
+ elif arch[2] not in valid_profile_types:
+ err("invalid profile type: \"" + bad(arch[2]) + "\" in " + \
+ desc_path + " line %d" % (i+1, ))
+ profile_desc = ProfileDesc(arch[0], arch[2], arch[1], portdir)
+ if not os.path.isdir(profile_desc.abs_path):
+ logging.error(
+ "Invalid %s profile (%s) for arch %s in %s line %d",
+ arch[2], arch[1], arch[0], desc_path, i+1)
+ continue
+ profile_list.append(profile_desc)
+ desc_file.close()
+
+repoman_settings['PORTAGE_ARCHLIST'] = ' '.join(sorted(kwlist))
+repoman_settings.backup_changes('PORTAGE_ARCHLIST')
+
+global_pmasklines = portage.util.stack_lists(global_pmasklines, incremental=1)
+global_pmaskdict = {}
+for x in global_pmasklines:
+ global_pmaskdict.setdefault(portage.dep_getkey(x), []).append(x)
+del global_pmasklines
+
+def has_global_mask(pkg):
+ mask_atoms = global_pmaskdict.get(pkg.cp)
+ if mask_atoms:
+ pkg_list = [pkg]
+ for x in mask_atoms:
+ if portage.dep.match_from_list(x, pkg_list):
+ return x
+ return None
+
+# Ensure that profile sub_path attributes are unique. Process in reverse order
+# so that profiles with duplicate sub_path from overlays will override
+# profiles with the same sub_path from parent repos.
+profiles = {}
+profile_list.reverse()
+profile_sub_paths = set()
+for prof in profile_list:
+ if prof.sub_path in profile_sub_paths:
+ continue
+ profile_sub_paths.add(prof.sub_path)
+ profiles.setdefault(prof.arch, []).append(prof)
+
+for x in repoman_settings.archlist():
+ if x[0] == "~":
+ continue
+ if x not in profiles:
+ print(red("\""+x+"\" doesn't have a valid profile listed in profiles.desc."))
+ print(red("You need to either \"cvs update\" your profiles dir or follow this"))
+ print(red("up with the "+x+" team."))
+ print()
if not liclist:
logging.fatal("Couldn't find licenses?")
logging.fatal("Couldn't read KEYWORDS from arch.list")
sys.exit(1)
+if not uselist:
+ logging.fatal("Couldn't find use.desc?")
+ sys.exit(1)
+
scanlist=[]
if repolevel==2:
#we are inside a category directory
logging.debug("Found the following packages to scan:\n%s" % '\n'.join(scanlist))
-profiles={}
-valid_profile_types = frozenset(["dev", "exp", "stable"])
-descfile=portdir+"/profiles/profiles.desc"
-if os.path.exists(descfile):
- for i, x in enumerate(open(descfile)):
- if x[0]=="#":
- continue
- arch=x.split()
- if len(arch) == 0:
- continue
- if len(arch)!=3:
- err("wrong format: \"" + bad(x.strip()) + "\" in " + \
- descfile + " line %d" % (i+1, ))
- elif arch[0] not in kwlist:
- err("invalid arch: \"" + bad(arch[0]) + "\" in " + \
- descfile + " line %d" % (i+1, ))
- elif arch[2] not in valid_profile_types:
- err("invalid profile type: \"" + bad(arch[2]) + "\" in " + \
- descfile + " line %d" % (i+1, ))
- if not os.path.isdir(portdir+"/profiles/"+arch[1]):
- print "Invalid "+arch[2]+" profile ("+arch[1]+") for arch "+arch[0]
- continue
- if arch[0] in profiles:
- profiles[arch[0]]+= [[arch[1], arch[2]]]
- else:
- profiles[arch[0]] = [[arch[1], arch[2]]]
-
- for x in repoman_settings.archlist():
- if x[0] == "~":
- continue
- if x not in profiles:
- print red("\""+x+"\" doesn't have a valid profile listed in profiles.desc.")
- print red("You need to either \"cvs update\" your profiles dir or follow this")
- print red("up with the "+x+" team.")
- print
-else:
- print red("profiles.desc does not exist: "+descfile)
- print red("You need to do \"cvs update\" in profiles dir.")
- print
- sys.exit(1)
-
def dev_keywords(profiles):
"""
Create a set of KEYWORDS values that exist in 'dev'
want to add the --include-dev option.
"""
type_arch_map = {}
- for arch, arch_profiles in profiles.iteritems():
- for profile_path, profile_type in arch_profiles:
- arch_set = type_arch_map.get(profile_type)
+ for arch, arch_profiles in profiles.items():
+ for prof in arch_profiles:
+ arch_set = type_arch_map.get(prof.status)
if arch_set is None:
arch_set = set()
- type_arch_map[profile_type] = arch_set
+ type_arch_map[prof.status] = arch_set
arch_set.add(arch)
dev_keywords = type_arch_map.get('dev', set())
if options.mode == "manifest":
pass
elif not find_binary('xmllint'):
- print red("!!! xmllint not found. Can't check metadata.xml.\n")
+ print(red("!!! xmllint not found. Can't check metadata.xml.\n"))
if options.xml_parse or repolevel==3:
- print red("!!!")+" sorry, xmllint is needed. failing\n"
+ print(red("!!!")+" sorry, xmllint is needed. failing\n")
sys.exit(1)
else:
#hardcoded paths/urls suck. :-/
else:
must_fetch=0
- except (OSError,IOError), e:
+ except (OSError,IOError) as e:
if e.errno != 2:
- print red("!!!")+" caught exception '%s' for %s/metadata.dtd, bailing" % (str(e), portage.CACHE_PATH)
+ print(red("!!!")+" caught exception '%s' for %s/metadata.dtd, bailing" % (str(e), portage.CACHE_PATH))
sys.exit(1)
if must_fetch:
- print
- print green("***")+" the local copy of metadata.dtd needs to be refetched, doing that now"
- print
+ print()
+ print(green("***")+" the local copy of metadata.dtd needs to be refetched, doing that now")
+ print()
val = 0
try:
try:
os.unlink(metadata_dtd)
- except OSError, e:
+ except OSError as e:
if e.errno != errno.ENOENT:
raise
del e
val=portage.fetch(['http://www.gentoo.org/dtd/metadata.dtd'],repoman_settings,fetchonly=0, \
try_mirrors=0)
- except SystemExit, e:
+ except SystemExit as e:
raise # Need to propogate this
- except Exception,e:
- print
- print red("!!!")+" attempting to fetch 'http://www.gentoo.org/dtd/metadata.dtd', caught"
- print red("!!!")+" exception '%s' though." % str(e)
+ except Exception as e:
+ print()
+ print(red("!!!")+" attempting to fetch 'http://www.gentoo.org/dtd/metadata.dtd', caught")
+ print(red("!!!")+" exception '%s' though." % str(e))
val=0
if not val:
- print red("!!!")+" fetching new metadata.dtd failed, aborting"
+ print(red("!!!")+" fetching new metadata.dtd failed, aborting")
sys.exit(1)
#this can be problematic if xmllint changes their output
xmllint_capable=True
if options.mode == "manifest":
pass
elif options.pretend:
- print green("\nRepoMan does a once-over of the neighborhood...")
+ print(green("\nRepoMan does a once-over of the neighborhood..."))
else:
- print green("\nRepoMan scours the neighborhood...")
+ print(green("\nRepoMan scours the neighborhood..."))
new_ebuilds = set()
modified_changelogs = set()
(vcs == "svn" and repolevel < 3 and options.mode != "commit")
# Build a regex from thirdpartymirrors for the SRC_URI.mirror check.
-thirdpartymirrors = portage.flatten(repoman_settings.thirdpartymirrors().values())
+thirdpartymirrors = portage.flatten(list(repoman_settings.thirdpartymirrors().values()))
for x in scanlist:
#ebuilds and digests added to cvs respectively.
fetchlist_dict=fetchlist_dict)
mf.create(requiredDistfiles=None,
assumeDistHashesAlways=True)
- for distfiles in fetchlist_dict.itervalues():
+ for distfiles in fetchlist_dict.values():
for distfile in distfiles:
if os.path.isfile(os.path.join(distdir, distfile)):
mf.fhashdict['DIST'].pop(distfile, None)
repoman_settings["O"] = checkdir
if not portage.digestgen([], repoman_settings, myportdb=portdb):
- print "Unable to generate manifest."
+ print("Unable to generate manifest.")
dofail = 1
if options.mode == "manifest":
if not dofail and options.force and auto_assumed and \
pkgs = {}
for y in checkdirlist:
if y in no_exec and \
- stat.S_IMODE(os.stat(os.path.join(checkdir, y)).st_mode) & 0111:
+ stat.S_IMODE(os.stat(os.path.join(checkdir, y)).st_mode) & 0o111:
stats["file.executable"] += 1
fails["file.executable"].append(os.path.join(checkdir, y))
if y.endswith(".ebuild"):
ebuildlist.append(pf)
cpv = "%s/%s" % (catdir, pf)
try:
- myaux = dict(izip(allvars, portdb.aux_get(cpv, allvars)))
+ myaux = dict(zip(allvars, portdb.aux_get(cpv, allvars)))
except KeyError:
stats["ebuild.syntax"] += 1
fails["ebuild.syntax"].append(os.path.join(x, y))
# Sort ebuilds in ascending order for the KEYWORDS.dropped check.
pkgsplits = {}
- for i in xrange(len(ebuildlist)):
+ for i in range(len(ebuildlist)):
ebuild_split = portage.pkgsplit(ebuildlist[i])
pkgsplits[ebuild_split] = ebuildlist[i]
ebuildlist[i] = ebuild_split
ebuildlist.sort(key=cmp_sort_key(portage.pkgcmp))
- for i in xrange(len(ebuildlist)):
+ for i in range(len(ebuildlist)):
ebuildlist[i] = pkgsplits[ebuildlist[i]]
del pkgsplits
continue
try:
line = 1
- for l in codecs.open(checkdir+"/"+y, "r", "utf8"):
+ for l in codecs.open(_unicode_encode(os.path.join(checkdir, y),
+ encoding=_encodings['fs'], errors='strict'),
+ mode='r', encoding=_encodings['repo.content']):
line +=1
- except UnicodeDecodeError, ue:
+ except UnicodeDecodeError as ue:
stats["file.UTF8"] += 1
s = ue.object[:ue.start]
l2 = s.count("\n")
for mykey in fetchlist_dict:
try:
myfiles_all.extend(fetchlist_dict[mykey])
- except portage.exception.InvalidDependString, e:
+ except portage.exception.InvalidDependString as e:
src_uri_error = True
try:
portdb.aux_get(mykey, ["SRC_URI"])
myfiles_all = set(myfiles_all)
for entry in mydigests:
if entry not in myfiles_all:
- stats["digestentry.unused"] += 1
- fails["digestentry.unused"].append(checkdir+"::"+entry)
+ stats["digest.unused"] += 1
+ fails["digest.unused"].append(checkdir+"::"+entry)
+ for entry in myfiles_all:
+ if entry not in mydigests:
+ stats["digest.missing"] += 1
+ fails["digest.missing"].append(checkdir+"::"+entry)
del myfiles_all
if os.path.exists(checkdir+"/files"):
full_path = os.path.join(repodir, relative_path)
try:
mystat = os.stat(full_path)
- except OSError, oe:
+ except OSError as oe:
if oe.errno == 2:
# don't worry about it. it likely was removed via fix above.
continue
if z == "CVS" or z == ".svn":
continue
filesdirlist.append(y+"/"+z)
- # current policy is no files over 20k, this is the check.
+ # Current policy is no files over 20 KiB, these are the checks. File size between
+ # 20 KiB and 60 KiB causes a warning, while file size over 60 KiB causes an error.
+ elif mystat.st_size > 61440:
+ stats["file.size.fatal"] += 1
+ fails["file.size.fatal"].append("("+ str(mystat.st_size//1024) + " KiB) "+x+"/files/"+y)
elif mystat.st_size > 20480:
stats["file.size"] += 1
- fails["file.size"].append("("+ str(mystat.st_size/1024) + "K) "+x+"/files/"+y)
+ fails["file.size"].append("("+ str(mystat.st_size//1024) + " KiB) "+x+"/files/"+y)
m = disallowed_filename_chars_re.search(
os.path.basename(y.rstrip(os.sep)))
(checkdir, y, m.group(0)))
if desktop_file_validate and desktop_pattern.match(y):
- status, cmd_output = commands.getstatusoutput(
+ status, cmd_output = subprocess_getstatusoutput(
"'%s' '%s'" % (desktop_file_validate, full_path))
if os.WIFEXITED(status) and os.WEXITSTATUS(status) != os.EX_OK:
# Note: in the future we may want to grab the
relative_path + ': %s' % error_match.group(1))
del mydigests
-
- if "ChangeLog" not in checkdirlist:
+ # Note: We don't use ChangeLogs in distributed SCMs.
+ # It will be generated on server side from scm log,
+ # before package moves to the rsync server.
+ # This is needed because we try to avoid merge collisions.
+ if vcs not in ( "git", ) and "ChangeLog" not in checkdirlist:
stats["changelog.missing"]+=1
fails["changelog.missing"].append(x+"/ChangeLog")
f = open(os.path.join(checkdir, "metadata.xml"))
utilities.parse_metadata_use(f, muselist)
f.close()
- except (EnvironmentError, ParseError), e:
+ except (EnvironmentError, ParseError) as e:
metadata_bad = True
stats["metadata.bad"] += 1
fails["metadata.bad"].append("%s/metadata.xml: %s" % (x, e))
if xmllint_capable and not metadata_bad:
# xmlint can produce garbage output even on success, so only dump
# the ouput when it fails.
- st, out = commands.getstatusoutput(
+ st, out = subprocess_getstatusoutput(
"xmllint --nonet --noout --dtdvalid '%s' '%s'" % \
(metadata_dtd, os.path.join(checkdir, "metadata.xml")))
if st != os.EX_OK:
- print red("!!!") + " metadata.xml is invalid:"
+ print(red("!!!") + " metadata.xml is invalid:")
for z in out.splitlines():
- print red("!!! ")+z
+ print(red("!!! ")+z)
stats["metadata.bad"]+=1
fails["metadata.bad"].append(x+"/metadata.xml")
stats['changelog.ebuildadded'] += 1
fails['changelog.ebuildadded'].append(relative_path)
- if stat.S_IMODE(os.stat(full_path).st_mode) & 0111:
+ if stat.S_IMODE(os.stat(full_path).st_mode) & 0o111:
stats["file.executable"] += 1
fails["file.executable"].append(x+"/"+y+".ebuild")
if vcs in ("cvs", "svn") and check_ebuild_notadded and y not in eadded:
fails["ebuild.invalidname"].append(x+"/"+y+".ebuild")
continue
elif myesplit[0]!=pkgdir:
- print pkgdir,myesplit[0]
+ print(pkgdir,myesplit[0])
stats["ebuild.namenomatch"]=stats["ebuild.namenomatch"]+1
fails["ebuild.namenomatch"].append(x+"/"+y+".ebuild")
continue
pkg = pkgs[y]
+
+ if pkg.invalid:
+ for k, msgs in pkg.invalid.items():
+ 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
live_ebuild = live_eclasses.intersection(inherited)
- for k, v in myaux.iteritems():
+ for k, v in myaux.items():
if not isinstance(v, basestring):
continue
m = non_ascii_re.search(v)
"%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:
- myaux["PROVIDE"] = 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
- myaux["PROVIDE"] = " ".join(portage.flatten(myaux["PROVIDE"]))
- for myprovide in myaux["PROVIDE"].split():
+ # The Package class automatically evaluates USE conditionals.
+ 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
bad_stable_keywords)
del bad_stable_keywords
+ if keywords and not has_global_mask(pkg):
+ stats["LIVEVCS.unmasked"] += 1
+ fails["LIVEVCS.unmasked"].append(relative_path)
+
if options.ignore_arches:
arches = [[repoman_settings["ARCH"], repoman_settings["ARCH"],
repoman_settings["ACCEPT_KEYWORDS"].split()]]
except ValueError:
badsyntax.append("parenthesis mismatch")
mydeplist = []
- except portage.exception.InvalidDependString, e:
+ except portage.exception.InvalidDependString as e:
badsyntax.append(str(e))
del e
mydeplist = []
try:
portage.dep.use_reduce(mydeplist, matchall=1)
- except portage.exception.InvalidDependString, e:
+ except portage.exception.InvalidDependString as e:
badsyntax.append(str(e))
for token in operator_tokens:
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 in ("RDEPEND", "PDEPEND"):
+ stats[mytype + '.suspect'] += 1
+ fails[mytype + '.suspect'].append(relative_path + \
+ ": 'test?' USE conditional in %s" % mytype)
continue
try:
atom = portage.dep.Atom(token)
portage.dep_getkey(atom) == "virtual/jdk":
stats['java.eclassesnotused'] += 1
fails['java.eclassesnotused'].append(relative_path)
- elif mytype == "RDEPEND":
+ elif mytype in ("PDEPEND", "RDEPEND"):
if not is_blocker and \
portage.dep_getkey(atom) in suspect_rdepend:
- stats['RDEPEND.suspect'] += 1
- fails['RDEPEND.suspect'].append(
+ stats[mytype + '.suspect'] += 1
+ fails[mytype + '.suspect'].append(
relative_path + ": '%s'" % atom)
if eapi == "0":
if portage.dep.dep_getslot(atom):
" not supported with EAPI='%s':" + \
" '%s'") % (mytype, eapi, atom))
+ if atom.operator == "~" and \
+ portage.versions.catpkgsplit(atom.cpv)[3] != "r0":
+ stats[mytype + '.badtilde'] += 1
+ fails[mytype + '.badtilde'].append(
+ (relative_path + ": %s uses the ~ operator"
+ " with a non-zero revision:" + \
+ " '%s'") % (mytype, atom))
+
type_list.extend([mytype] * (len(badsyntax) - len(type_list)))
for m,b in zip(type_list, badsyntax):
stats[m+".syntax"] += 1
fails[m+".syntax"].append(catpkg+".ebuild "+m+": "+b)
- badlicsyntax = len(filter(lambda x:x=="LICENSE", type_list))
- badprovsyntax = len(filter(lambda x:x=="PROVIDE", type_list))
+ badlicsyntax = len([z for z in type_list if z == "LICENSE"])
+ badprovsyntax = len([z for z in type_list if z == "PROVIDE"])
baddepsyntax = len(type_list) != badlicsyntax + badprovsyntax
badlicsyntax = badlicsyntax > 0
badprovsyntax = badprovsyntax > 0
try:
myrestrict = portage.dep.use_reduce(
portage.dep.paren_reduce(myaux["RESTRICT"]), matchall=1)
- except portage.exception.InvalidDependString, e:
+ except portage.exception.InvalidDependString as e:
stats["RESTRICT.syntax"] = stats["RESTRICT.syntax"] + 1
fails["RESTRICT.syntax"].append(
"%s: RESTRICT: %s" % (relative_path, e))
full_path = os.path.join(repodir, relative_path)
try:
# All ebuilds should have utf_8 encoding.
- f = codecs.open(full_path, mode='r', encoding='utf_8')
+ f = codecs.open(_unicode_encode(full_path,
+ encoding=_encodings['fs'], errors='strict'),
+ mode='r', encoding=_encodings['repo.content'])
try:
for check_name, e in run_checks(f, pkg):
stats[check_name] += 1
for prof in profiles[arch]:
- if prof[1] not in ("stable", "dev") or \
- prof[1] == "dev" and not options.include_dev:
+ if prof.status not in ("stable", "dev") or \
+ prof.status == "dev" and not options.include_dev:
continue
- profdir = portdir+"/profiles/"+prof[0]
-
- if prof[0] in arch_caches:
- dep_settings = arch_caches[prof[0]]
- else:
+ dep_settings = arch_caches.get(prof.sub_path)
+ if dep_settings is None:
dep_settings = portage.config(
- config_profile_path=profdir,
+ config_profile_path=prof.abs_path,
config_incrementals=portage.const.INCREMENTALS,
local_config=False,
env=env)
if options.without_mask:
dep_settings.pmaskdict.clear()
- arch_caches[prof[0]] = dep_settings
+ arch_caches[prof.sub_path] = dep_settings
while True:
try:
# Protect ACCEPT_KEYWORDS from config.regenerate()
except ValueError:
break
- xmatch_cache_key = (prof[0], tuple(groups))
+ xmatch_cache_key = (prof.sub_path, tuple(groups))
xcache = arch_xmatch_caches.get(xmatch_cache_key)
if xcache is None:
portdb.melt()
prov_cp = portage.dep_getkey(myprovide)
if prov_cp not in dep_settings.getvirtuals():
stats["virtual.unavailable"]+=1
- fails["virtual.unavailable"].append(x+"/"+y+".ebuild: "+keyword+"("+prof[0]+") "+prov_cp)
+ fails["virtual.unavailable"].append("%s: %s(%s) %s" % \
+ (relative_path, keyword, prof.sub_path, prov_cp))
if not baddepsyntax:
ismasked = os.path.join(catdir, y) not in \
have_dev_keywords = \
bool(dev_keywords.intersection(keywords))
- if prof[1] == "dev":
+ if prof.status == "dev":
suffix=suffix+"indev"
for mytype,mypos in [["DEPEND",len(missingvars)],["RDEPEND",len(missingvars)+1],["PDEPEND",len(missingvars)+2]]:
myvalue = myaux[mytype]
if not myvalue:
continue
- try:
- mydep = portage.dep_check(myvalue, portdb,
- dep_settings, use="all", mode=matchmode,
- trees=trees)
- except KeyError, e:
- stats[mykey]=stats[mykey]+1
- fails[mykey].append(x+"/"+y+".ebuild: "+keyword+"("+prof[0]+") "+repr(e[0]))
- continue
-
- if mydep[0]==1:
- if mydep[1]!=[]:
+
+ success, atoms = portage.dep_check(myvalue, portdb,
+ dep_settings, use="all", mode=matchmode,
+ trees=trees)
+
+ if success:
+ if atoms:
#we have some unsolvable deps
#remove ! deps, which always show up as unsatisfiable
- d=0
- while d<len(mydep[1]):
- if mydep[1][d][0]=="!":
- del mydep[1][d]
- else:
- d += 1
+ atoms = [str(atom) for atom in atoms if not atom.blocker]
#if we emptied out our list, continue:
- if not mydep[1]:
+ if not atoms:
continue
stats[mykey]=stats[mykey]+1
- fails[mykey].append(x+"/"+y+".ebuild: "+keyword+"("+prof[0]+") "+repr(mydep[1]))
+ fails[mykey].append("%s: %s(%s) %s" % \
+ (relative_path, keyword,
+ prof.sub_path, repr(atoms)))
else:
stats[mykey]=stats[mykey]+1
- fails[mykey].append(x+"/"+y+".ebuild: "+keyword+"("+prof[0]+") "+repr(mydep[1]))
+ fails[mykey].append("%s: %s(%s) %s" % \
+ (relative_path, keyword,
+ prof.sub_path, repr(atoms)))
# Check for 'all unstable' or 'all masked' -- ACCEPT_KEYWORDS is stripped
# XXX -- Needs to be implemented in dep code. Can't determine ~arch nicely.
suggest_include_dev = True
if suggest_ignore_masked or suggest_include_dev:
- print
+ print()
if suggest_ignore_masked:
- print bold("Note: use --without-mask to check " + \
- "KEYWORDS on dependencies of masked packages")
+ print(bold("Note: use --without-mask to check " + \
+ "KEYWORDS on dependencies of masked packages"))
if suggest_include_dev:
- print bold("Note: use --include-dev (-d) to check " + \
- "dependencies for 'dev' profiles")
- print
+ print(bold("Note: use --include-dev (-d) to check " + \
+ "dependencies for 'dev' profiles"))
+ print()
if options.mode != 'commit':
if dofull:
- print bold("Note: type \"repoman full\" for a complete listing.")
+ print(bold("Note: type \"repoman full\" for a complete listing."))
if dowarn and not dofail:
- print green("RepoMan sez:"),"\"You're only giving me a partial QA payment?\n I'll take it this time, but I'm not happy.\""
+ print(green("RepoMan sez:"),"\"You're only giving me a partial QA payment?\n I'll take it this time, but I'm not happy.\"")
elif not dofail:
- print green("RepoMan sez:"),"\"If everyone were like you, I'd be out of business!\""
+ print(green("RepoMan sez:"),"\"If everyone were like you, I'd be out of business!\"")
elif dofail:
- print turquoise("Please fix these important QA issues first.")
- print green("RepoMan sez:"),"\"Make your QA payment on time and you'll never see the likes of me.\"\n"
+ print(turquoise("Please fix these important QA issues first."))
+ print(green("RepoMan sez:"),"\"Make your QA payment on time and you'll never see the likes of me.\"\n")
sys.exit(1)
else:
if dofail and can_force and options.force and not options.pretend:
- print green("RepoMan sez:") + \
+ print(green("RepoMan sez:") + \
" \"You want to commit even with these QA issues?\n" + \
- " I'll take it this time, but I'm not happy.\"\n"
+ " I'll take it this time, but I'm not happy.\"\n")
elif dofail:
if options.force and not can_force:
- print bad("The --force option has been disabled due to extraordinary issues.")
- print turquoise("Please fix these important QA issues first.")
- print green("RepoMan sez:"),"\"Make your QA payment on time and you'll never see the likes of me.\"\n"
+ print(bad("The --force option has been disabled due to extraordinary issues."))
+ print(turquoise("Please fix these important QA issues first."))
+ print(green("RepoMan sez:"),"\"Make your QA payment on time and you'll never see the likes of me.\"\n")
sys.exit(1)
if options.pretend:
- print green("RepoMan sez:"), "\"So, you want to play it safe. Good call.\"\n"
+ print(green("RepoMan sez:"), "\"So, you want to play it safe. Good call.\"\n")
myunadded = []
if vcs == "cvs":
try:
myvcstree=portage.cvstree.getentries("./",recursive=1)
myunadded=portage.cvstree.findunadded(myvcstree,recursive=1,basedir="./")
- except SystemExit, e:
+ except SystemExit as e:
raise # TODO propogate this
except:
err("Error retrieving CVS tree; exiting.")
try:
svnstatus=os.popen("svn status --no-ignore").readlines()
myunadded = [ "./"+elem.rstrip().split()[1] for elem in svnstatus if elem.startswith("?") or elem.startswith("I") ]
- except SystemExit, e:
+ except SystemExit as e:
raise # TODO propogate this
except:
err("Error retrieving SVN info; exiting.")
for x in range(len(myunadded)-1,-1,-1):
xs=myunadded[x].split("/")
if xs[-1]=="files":
- print "!!! files dir is not added! Please correct this."
+ print("!!! files dir is not added! Please correct this.")
sys.exit(-1)
elif xs[-1]=="Manifest":
# It's a manifest... auto add
del myunadded[x]
if myautoadd:
- print ">>> Auto-Adding missing Manifest(s)..."
+ print(">>> Auto-Adding missing Manifest(s)...")
if options.pretend:
if vcs == "cvs":
- print "(cvs add "+" ".join(myautoadd)+")"
+ print("(cvs add "+" ".join(myautoadd)+")")
if vcs == "svn":
- print "(svn add "+" ".join(myautoadd)+")"
+ print("(svn add "+" ".join(myautoadd)+")")
elif vcs == "git":
- print "(git add "+" ".join(myautoadd)+")"
+ print("(git add "+" ".join(myautoadd)+")")
retval=0
else:
if vcs == "cvs":
sys.exit(retval)
if myunadded:
- print red("!!! The following files are in your local tree but are not added to the master")
- print red("!!! tree. Please remove them from the local tree or add them to the master tree.")
+ print(red("!!! The following files are in your local tree but are not added to the master"))
+ print(red("!!! tree. Please remove them from the local tree or add them to the master tree."))
for x in myunadded:
- print " ",x
- print
- print
+ print(" ",x)
+ print()
+ print()
sys.exit(1)
if vcs == "cvs":
if vcs:
if not (mychanged or mynew or myremoved):
- print green("RepoMan sez:"), "\"Doing nothing is not always good for QA.\""
- print
- print "(Didn't find any changed files...)"
- print
- sys.exit(0)
+ print(green("RepoMan sez:"), "\"Doing nothing is not always good for QA.\"")
+ print()
+ print("(Didn't find any changed files...)")
+ print()
+ sys.exit(1)
# Manifests need to be regenerated after all other commits, so don't commit
# them now even if they have changed.
if myfile not in expansion:
continue
- myout = commands.getstatusoutput("egrep -q "+headerstring+" "+myfile)
+ myout = subprocess_getstatusoutput("egrep -q "+headerstring+" "+myfile)
if myout[0] == 0:
myheaders.append(myfile)
- print "* %s files being committed..." % green(str(len(myupdates))),
+ print("* %s files being committed..." % green(str(len(myupdates))), end=' ')
if vcs == 'git':
# With git, there's never any keyword expansion, so there's
# no need to regenerate manifests and all files will be
# committed in one big commit at the end.
- print
+ print()
else:
- print "%s have headers that will change." % green(str(len(myheaders)))
- print "* Files with headers will cause the " + \
- "manifests to be made and recommited."
+ print("%s have headers that will change." % green(str(len(myheaders))))
+ print("* Files with headers will cause the " + \
+ "manifests to be made and recommited.")
logging.info("myupdates: %s", myupdates)
logging.info("myheaders: %s", myheaders)
commitmessage = f.read()
f.close()
del f
- except (IOError, OSError), e:
+ except (IOError, OSError) as e:
if e.errno == errno.ENOENT:
portage.writemsg("!!! File Not Found: --commitmsgfile='%s'\n" % options.commitmsgfile)
else:
except KeyboardInterrupt:
exithandler()
if not commitmessage or not commitmessage.strip():
- print "* no commit message? aborting commit."
+ print("* no commit message? aborting commit.")
sys.exit(1)
commitmessage = commitmessage.rstrip()
portage_version = getattr(portage, "VERSION", None)
mymsg.write(commitmessage)
mymsg.close()
- print
- print green("Using commit message:")
- print green("------------------------------------------------------------------------------")
- print commitmessage
- print green("------------------------------------------------------------------------------")
- print
+ print()
+ print(green("Using commit message:"))
+ print(green("------------------------------------------------------------------------------"))
+ print(commitmessage)
+ print(green("------------------------------------------------------------------------------"))
+ print()
# Having a leading ./ prefix on file paths can trigger a bug in
# the cvs server when committing files to multiple directories,
try:
if options.pretend:
- print "(%s)" % (" ".join(commit_cmd),)
+ print("(%s)" % (" ".join(commit_cmd),))
else:
retval = spawn(commit_cmd, env=os.environ)
if retval != os.EX_OK:
if "PORTAGE_GPG_DIR" in repoman_settings:
gpgcmd += " --homedir "+repoman_settings["PORTAGE_GPG_DIR"]
if options.pretend:
- print "("+gpgcmd+" "+filename+")"
+ print("("+gpgcmd+" "+filename+")")
else:
rValue = os.system(gpgcmd+" "+filename)
if rValue == os.EX_OK:
portage.digestgen([], repoman_settings, manifestonly=1,
myportdb=portdb)
elif repolevel==1: # repo-cvsroot
- print green("RepoMan sez:"), "\"You're rather crazy... doing the entire repository.\"\n"
+ print(green("RepoMan sez:"), "\"You're rather crazy... doing the entire repository.\"\n")
for x in myfiles:
xs=x.split("/")
if len(xs) < 4-repolevel:
portage.digestgen([], repoman_settings, manifestonly=1,
myportdb=portdb)
else:
- print red("I'm confused... I don't know where I am!")
+ print(red("I'm confused... I don't know where I am!"))
sys.exit(1)
# Force an unsigned commit when more than one Manifest needs to be signed.
try:
if options.pretend:
- print "(%s)" % (" ".join(commit_cmd),)
+ print("(%s)" % (" ".join(commit_cmd),))
else:
retval = spawn(commit_cmd, env=os.environ)
if retval:
continue
gpgsign(os.path.join(repoman_settings["O"], "Manifest"))
elif repolevel==1: # repo-cvsroot
- print green("RepoMan sez:"), "\"You're rather crazy... doing the entire repository.\"\n"
+ print(green("RepoMan sez:"), "\"You're rather crazy... doing the entire repository.\"\n")
mydone=[]
for x in myfiles:
xs=x.split("/")
if not os.path.isdir(repoman_settings["O"]):
continue
gpgsign(os.path.join(repoman_settings["O"], "Manifest"))
- except portage.exception.PortageException, e:
+ except portage.exception.PortageException as e:
portage.writemsg("!!! %s\n" % str(e))
portage.writemsg("!!! Disabled FEATURES='sign'\n")
signed = False
update_index_cmd = ["git", "update-index"]
update_index_cmd.extend(f.lstrip("./") for f in myfiles)
if options.pretend:
- print "(%s)" % (" ".join(update_index_cmd),)
+ print("(%s)" % (" ".join(update_index_cmd),))
else:
retval = spawn(update_index_cmd, env=os.environ)
if retval != os.EX_OK:
try:
if options.pretend:
- print "(%s)" % (" ".join(commit_cmd),)
+ print("(%s)" % (" ".join(commit_cmd),))
else:
retval = spawn(commit_cmd, env=os.environ)
if retval != os.EX_OK:
except OSError:
pass
- print
+ print()
if vcs:
- print "Commit complete."
+ print("Commit complete.")
else:
- print "repoman was too scared by not seeing any familiar version control file that he forgot to commit anything"
- print green("RepoMan sez:"), "\"If everyone were like you, I'd be out of business!\"\n"
+ print("repoman was too scared by not seeing any familiar version control file that he forgot to commit anything")
+ print(green("RepoMan sez:"), "\"If everyone were like you, I'd be out of business!\"\n")
sys.exit(0)