from portage.output import bold, create_color_func, darkgreen, \
green, nocolor, red, turquoise, yellow
from portage.output import ConsoleStyleFile, StyleWriter
+from portage.util import writemsg_level
util.initialize_logger()
# commit (like if Manifest generation fails).
can_force = True
+portdir, portdir_overlay, mydir = utilities.FindPortdir(repoman_settings)
+if portdir is None:
+ sys.exit(1)
vcs = None
if os.path.isdir("CVS"):
vcs = "cvs"
if os.path.isdir(".svn"):
vcs = "svn"
+elif os.path.isdir(os.path.join(portdir_overlay, ".git")):
+ vcs = "git"
if vcs == "cvs" and \
"commit" == options.mode and \
logging.info("Not in a version controlled repository; enabling pretend mode.")
options.pretend = True
-try:
- portdir, portdir_overlay, mydir = utilities.FindPortdir(repoman_settings)
-except ValueError:
- sys.exit(1)
-
os.environ["PORTDIR"] = portdir
if portdir_overlay != portdir:
os.environ["PORTDIR_OVERLAY"] = portdir_overlay
mychanged = []
mynew = []
myremoved = []
+path_lstrip_re = re.compile(r'.*/')
if vcs == "cvs":
mycvstree = cvstree.getentries("./", recursive=1)
mychanged = cvstree.findchanged(mycvstree, recursive=1, basedir="./")
mynew = cvstree.findnew(mycvstree, recursive=1, basedir="./")
-
if vcs == "svn":
svnstatus = os.popen("svn status").readlines()
mychanged = [ "./" + elem.split()[-1:][0] for elem in svnstatus if elem and elem[:1] in "MR" ]
mynew = [ "./" + elem.split()[-1:][0] for elem in svnstatus if elem.startswith("A") ]
-
+elif vcs == "git":
+ mychanged = os.popen("git ls-files -m").readlines()
+ mychanged = [ "./" + elem[:-1] for elem in mychanged ]
+ mynew = os.popen("git diff --cached --name-only --diff-filter=A").readlines()
+ strip_levels = repolevel - 1
+ if strip_levels:
+ mynew = [path_lstrip_re.sub("", elem, strip_levels) for elem in mynew]
+ mynew = ["./" + elem[:-1] for elem in mynew]
if vcs:
new_ebuilds.update(x for x in mynew if x.endswith(".ebuild"))
modified_changelogs.update(x for x in chain(mychanged, mynew) \
eadded=[]
catdir,pkgdir=x.split("/")
checkdir=repodir+"/"+x
+ checkdir_relative = ""
+ if repolevel < 3:
+ checkdir_relative = os.path.join(pkgdir, checkdir_relative)
+ if repolevel < 2:
+ checkdir_relative = os.path.join(catdir, checkdir_relative)
+ checkdir_relative = os.path.join(".", checkdir_relative)
if options.mode == "manifest" or \
options.mode in ('commit', 'fix') and not options.pretend:
s = s[s.rfind("\n") + 1:]
fails["file.UTF8"].append("%s/%s: line %i, just after: '%s'" % (checkdir, y, line, s))
- if vcs and check_ebuild_notadded:
+ if vcs == "git" and check_ebuild_notadded:
+ myf = os.popen("git ls-files --others %s" % \
+ (portage._shell_quote(checkdir_relative),))
+ for l in myf:
+ if l[:-1][-7:] == ".ebuild":
+ stats["ebuild.notadded"] += 1
+ fails["ebuild.notadded"].append(
+ os.path.join(x, os.path.basename(l[:-1])))
+ myf.close()
+
+ if vcs in ("cvs", "svn") and check_ebuild_notadded:
try:
if vcs == "cvs":
myf=open(checkdir+"/CVS/Entries","r")
del metadata_bad
- changelog_path = "ChangeLog"
- if repolevel < 3:
- changelog_path = os.path.join(pkgdir, changelog_path)
- if repolevel < 2:
- changelog_path = os.path.join(catdir, changelog_path)
- changelog_path = os.path.join(".", changelog_path)
+ changelog_path = os.path.join(checkdir_relative, "ChangeLog")
changelog_modified = changelog_path in modified_changelogs
allmasked = True
if stat.S_IMODE(os.stat(full_path).st_mode) & 0111:
stats["file.executable"] += 1
fails["file.executable"].append(x+"/"+y+".ebuild")
- if vcs and check_ebuild_notadded and y not in eadded:
+ if vcs in ("cvs", "svn") and check_ebuild_notadded and y not in eadded:
#ebuild not added to vcs
stats["ebuild.notadded"]=stats["ebuild.notadded"]+1
fails["ebuild.notadded"].append(x+"/"+y+".ebuild")
-
myesplit=portage.pkgsplit(y)
if myesplit is None or myesplit[0] != x.split("/")[-1]:
stats["ebuild.invalidname"]=stats["ebuild.invalidname"]+1
raise # TODO propogate this
except:
err("Error retrieving CVS tree; exiting.")
-
if vcs == "svn":
try:
svnstatus=os.popen("svn status --no-ignore").readlines()
raise # TODO propogate this
except:
err("Error retrieving SVN info; exiting.")
+ if vcs == "git":
+ # get list of files not under version control or missing
+ myf = os.popen("git ls-files --others")
+ myunadded = [ "./" + elem[:-1] for elem in myf ]
+ myf.close()
+
myautoadd=[]
if myunadded:
for x in range(len(myunadded)-1,-1,-1):
print "(cvs add "+" ".join(myautoadd)+")"
if vcs == "svn":
print "(svn add "+" ".join(myautoadd)+")"
+ elif vcs == "git":
+ print "(git add "+" ".join(myautoadd)+")"
retval=0
else:
if vcs == "cvs":
retval=os.system("cvs add "+" ".join(myautoadd))
if vcs == "svn":
retval=os.system("svn add "+" ".join(myautoadd))
+ elif vcs == "git":
+ retval=os.system("git add "+" ".join(myautoadd))
if retval:
- print "!!! Exiting on vcs (shell) error code:",retval
+ writemsg_level("!!! Exiting on %s (shell) error code: %s\n" % \
+ (vcs, retval), level=logging.ERROR, noiselevel=-1)
sys.exit(retval)
if myunadded:
expansion = set("./" + prop.split(" - ")[0] \
for prop in props if " - " in prop)
+ elif vcs == "git":
+ mychanged = os.popen("git ls-files -m").readlines()
+ mychanged = [ "./" + elem[:-1] for elem in mychanged ]
+ mynew = os.popen("git diff --cached --name-only --diff-filter=A").readlines()
+ strip_levels = repolevel - 1
+ if strip_levels:
+ mynew = [path_lstrip_re.sub("", elem, strip_levels) for elem in mynew]
+ mynew = ["./" + elem[:-1] for elem in mynew]
+ myremoved = os.popen("git diff --cached --name-only --diff-filter=D").readlines()
+ if strip_levels:
+ myremoved = [path_lstrip_re.sub("", elem, strip_levels) for elem in myremoved]
+ myremoved = ["./" + elem[:-1] for elem in myremoved]
+
if vcs:
if not (mychanged or mynew or myremoved):
print green("RepoMan sez:"), "\"Doing nothing is not always good for QA.\""
if vcs == "svn":
print "(svn commit -F %s %s)" % \
(commitmessagefile, " ".join(myfiles))
+ elif vcs == "git":
+ print "(git commit -F %s %s)" % \
+ (commitmessagefile, " ".join(myfiles))
else:
if vcs == "cvs":
retval = spawn(["cvs", "-q", "commit",
retval = spawn(["svn", "commit",
"-F", commitmessagefile] + myfiles,
env=os.environ)
+ elif vcs == "git":
+ retval = spawn(["git", "commit", "-F",
+ commitmessagefile] + myfiles,
+ env=os.environ)
try:
os.unlink(commitmessagefile)
except OSError:
pass
if retval:
- print "!!! Exiting on cvs (shell) error code:",retval
+ writemsg_level("!!! Exiting on %s (shell) error code: %s\n" % \
+ (vcs, retval), level=logging.ERROR, noiselevel=-1)
sys.exit(retval)
# Setup the GPG commands
print "(cvs -q commit -F commitmessagefile)"
if vcs == "svn":
print "(svn -q commit -F commitmessagefile)"
+ elif vcs == "git":
+ print "(git commit -F commitmessagefile)"
else:
fd, commitmessagefile = tempfile.mkstemp(".repoman.msg")
mymsg = os.fdopen(fd, "w")
retval=os.system("cvs -q commit -F "+commitmessagefile)
if vcs == "svn":
retval=os.system("svn -q commit -F "+commitmessagefile)
+ elif vcs == "git":
+ retval=os.system("git commit -F "+commitmessagefile)
try:
os.unlink(commitmessagefile)
except OSError:
pass
if retval:
- print "!!! Exiting on cvs (shell) error code:",retval
+ writemsg_level("!!! Exiting on %s (shell) error code: %s\n" % \
+ (vcs, retval), level=logging.ERROR, noiselevel=-1)
sys.exit(retval)
manifest_commit_required = False
print "(cvs -q commit -F commitmessagefile)"
if vcs == "svn":
print "(svn -q commit -F commitmessagefile)"
+ elif vcs == "git":
+ print "(git commit -a -F commitmessagefile)"
else:
fd, commitmessagefile = tempfile.mkstemp(".repoman.msg")
mymsg = os.fdopen(fd, "w")
retval=os.system("cvs -q commit -F "+commitmessagefile)
if vcs == "svn":
retval=os.system("svn -q commit -F "+commitmessagefile)
+ elif vcs == "git":
+ retval=os.system("git commit -a -F "+commitmessagefile)
try:
os.unlink(commitmessagefile)
except OSError:
pass
if retval:
- print "!!! Exiting on cvs (shell) error code:",retval
+ writemsg_level("!!! Exiting on %s (shell) error code: %s\n" % \
+ (vcs, retval), level=logging.ERROR, noiselevel=-1)
sys.exit(retval)
print
if not serialized_tasks or "--nodeps" in self.myopts:
self._serialized_tasks_cache = serialized_tasks
+ self._scheduler_graph = self.digraph
else:
self._select_package = self._select_pkg_from_graph
self.myparams.add("selective")
return interactive_tasks
def _set_digraph(self, digraph):
- if self._max_jobs is not True and \
- self._max_jobs < 2:
+ if "--nodeps" in self.myopts or \
+ (self._max_jobs is not True and self._max_jobs < 2):
# save some memory
self._digraph = None
return
root_config.settings.lock()
self.pkgsettings[root] = portage.config(
- clone=self.trees[root]["vartree"].settings)
+ clone=root_config.settings)
rval = self._check_manifests()
if rval != os.EX_OK:
return None
if self._digraph is None:
- if self._jobs or self._task_queues.merge:
+ if (self._jobs or self._task_queues.merge) and \
+ not ("--nodeps" in self.myopts and \
+ (self._max_jobs is True or self._max_jobs > 1)):
self._choose_pkg_return_early = True
return None
return self._pkg_queue.pop(0)
_flush_elog_mod_echo()
+ counter_hash = settings.get("PORTAGE_COUNTER_HASH")
+ if counter_hash is not None and \
+ counter_hash == vardbapi._counter_hash():
+ # If vdb state has not changed then there's nothing else to do.
+ sys.exit(retval)
+
vdb_path = os.path.join(target_root, portage.VDB_PATH)
portage.util.ensure_dirs(vdb_path)
vdb_lock = None
# dependency to become unsatisfied.
for parent_node in graph.parent_nodes(pkg):
if not isinstance(parent_node, Package) \
- or parent_node.operation != "merge":
+ or parent_node.operation not in ("merge", "nomerge"):
continue
unsatisfied = \
graph.child_nodes(parent_node,
# it's already installed, but it has unsatisfied PDEPEND.
raise
mergelist[:] = pruned_mergelist
- dropped_tasks.update(unsatisfied_parents)
+
+ # Exclude installed packages that have been removed from the graph due
+ # to failure to build/install runtime dependencies after the dependent
+ # package has already been installed.
+ dropped_tasks.update(pkg for pkg in \
+ unsatisfied_parents if pkg.operation != "nomerge")
+ mydepgraph.break_refs(unsatisfied_parents)
+
del e, graph, traversed_nodes, \
unsatisfied_parents, unsatisfied_stack
continue
mysettings = trees[myroot]["vartree"].settings
mysettings.unlock()
adjust_config(myopts, mysettings)
+ mysettings["PORTAGE_COUNTER_HASH"] = \
+ trees[myroot]["vartree"].dbapi._counter_hash()
+ mysettings.backup_changes("PORTAGE_COUNTER_HASH")
mysettings.lock()
del myroot, mysettings
sys.exit(retval)
-def have_profile_dir(path, maxdepth=3):
- """ Try to figure out if 'path' has a /profiles dir in it by checking for a package.mask file
+def have_profile_dir(path, maxdepth=3, filename="profiles.desc"):
+ """
+ Try to figure out if 'path' has a profiles/
+ dir in it by checking for the given filename.
"""
while path != "/" and maxdepth:
- if os.path.exists(path + "/profiles/package.mask"):
+ if os.path.exists(os.path.join(path, "profiles", filename)):
return normalize_path(path)
path = normalize_path(path + "/..")
maxdepth -= 1
if have_profile_dir(location, subdir.count("/")):
portdir = portdir_overlay
break
-
- del p, s, path_ids
-
+
+ # Couldn't match location with anything from PORTDIR_OVERLAY,
+ # so fall back to have_profile_dir() checks alone. Assume that
+ # an overlay will contain at least a "repo_name" file while a
+ # master repo (portdir) will contain at least a "profiles.desc"
+ # file.
+ if not portdir_overlay:
+ portdir_overlay = have_profile_dir(location, filename="repo_name")
+ if portdir_overlay:
+ subdir = location[len(portdir_overlay):]
+ if subdir and subdir[-1] != os.sep:
+ subdir += os.sep
+ if have_profile_dir(location, subdir.count(os.sep)):
+ portdir = portdir_overlay
+
if not portdir_overlay:
if (settings["PORTDIR"] + os.path.sep).startswith(location):
portdir_overlay = settings["PORTDIR"]
msg = 'Repoman is unable to determine PORTDIR or PORTDIR_OVERLAY' + \
' from the current working directory'
logging.critical(msg)
- raise ValueError(msg)
+ return (None, None, None)
if not portdir:
portdir = settings["PORTDIR"]