self.returncode = portage._doebuild_exit_status_check_and_log(
self.settings, self.phase, self.returncode)
+ if self.phase == "test" and self.returncode != os.EX_OK and \
+ "test-fail-continue" in self.settings.features:
+ self.returncode = os.EX_OK
+
portage._post_phase_userpriv_perms(self.settings)
class EbuildPhase(CompositeTask):
pkg = self.pkg
pkg_count = self.pkg_count
- if not self.opts.fetchonly:
+ if not (self.opts.pretend or self.opts.fetchonly):
self._build_dir.lock()
try:
shutil.rmtree(self._build_dir.dir_path)
portage.prepare_build_dirs(self.settings["ROOT"], self.settings, 1)
fetcher = BinpkgFetcher(background=self.background,
logfile=self.settings.get("PORTAGE_LOG_FILE"), pkg=self.pkg,
- scheduler=self.scheduler)
+ pretend=self.opts.pretend, scheduler=self.scheduler)
pkg_path = fetcher.pkg_path
self._pkg_path = pkg_path
self.wait()
return
+ if self.opts.pretend:
+ self._current_task = None
+ self.returncode = os.EX_OK
+ self.wait()
+ return
+
verifier = None
if self._verify:
logfile = None
self.wait()
def _unlock_builddir(self):
- if self.opts.fetchonly:
+ if self.opts.pretend or self.opts.fetchonly:
return
portage.elog.elog_process(self.pkg.cpv, self.settings)
self._build_dir.unlock()
class BinpkgFetcher(SpawnProcess):
- __slots__ = ("pkg",
+ __slots__ = ("pkg", "pretend",
"locked", "pkg_path", "_lock_obj")
def __init__(self, **kwargs):
return
pkg = self.pkg
+ pretend = self.pretend
bintree = pkg.root_config.trees["bintree"]
settings = bintree.settings
use_locks = "distlocks" in settings.features
pkg_path = self.pkg_path
- resume = os.path.exists(pkg_path)
+
+ if not pretend:
+ portage.util.ensure_dirs(os.path.dirname(pkg_path))
+ if use_locks:
+ self.lock()
+ exists = os.path.exists(pkg_path)
+ resume = exists and os.path.basename(pkg_path) in bintree.invalids
+ if not (pretend or resume):
+ # Remove existing file or broken symlink.
+ try:
+ os.unlink(pkg_path)
+ except OSError:
+ pass
# urljoin doesn't work correctly with
# unrecognized protocols like sftp
uri = settings["PORTAGE_BINHOST"].rstrip("/") + \
"/" + pkg.pf + ".tbz2"
+ if pretend:
+ portage.writemsg_stdout("\n%s\n" % uri, noiselevel=-1)
+ self.returncode = os.EX_OK
+ self.wait()
+ return
+
protocol = urlparse.urlparse(uri)[0]
fcmd_prefix = "FETCHCOMMAND"
if resume:
fetch_args = [portage.util.varexpand(x, mydict=fcmd_vars) \
for x in shlex.split(fcmd)]
- portage.util.ensure_dirs(os.path.dirname(pkg_path))
- if use_locks:
- self.lock()
-
if self.fd_pipes is None:
self.fd_pipes = {}
fd_pipes = self.fd_pipes
def _set_returncode(self, wait_retval):
SpawnProcess._set_returncode(self, wait_retval)
+ if self.returncode == os.EX_OK:
+ # If possible, update the mtime to match the remote package if
+ # the fetcher didn't already do it automatically.
+ bintree = self.pkg.root_config.trees["bintree"]
+ if bintree._remote_has_index:
+ remote_mtime = bintree._remotepkgs[self.pkg.cpv].get("MTIME")
+ if remote_mtime is not None:
+ try:
+ remote_mtime = float(remote_mtime)
+ except ValueError:
+ pass
+ else:
+ try:
+ local_mtime = os.stat(self.pkg_path).st_mtime
+ except OSError:
+ pass
+ else:
+ if remote_mtime != local_mtime:
+ try:
+ os.utime(self.pkg_path,
+ (remote_mtime, remote_mtime))
+ except OSError:
+ pass
+
if self.locked:
self.unlock()
noiselevel=-1, level=logging.ERROR)
return 1
+ vcs_dirs = frozenset([".git", ".svn", "CVS", ".hg"])
+ vcs_dirs = vcs_dirs.intersection(os.listdir(myportdir))
+
os.umask(0022)
updatecache_flg = False
if myaction == "metadata":
print "skipping sync"
updatecache_flg = True
+ elif ".git" in vcs_dirs:
+ # Update existing git repository, and ignore the syncuri. We are
+ # going to trust the user and assume that the user is in the branch
+ # that he/she wants updated. We'll let the user manage branches with
+ # git directly.
+ msg = ">>> Starting git pull in %s..." % myportdir
+ emergelog(xterm_titles, msg )
+ writemsg_level(msg + "\n")
+ exitcode = portage.spawn("cd %s ; git pull" % \
+ (portage._shell_quote(myportdir),), settings, free=1)
+ if exitcode != os.EX_OK:
+ msg = "!!! git pull error in %s." % myportdir
+ emergelog(xterm_titles, msg)
+ writemsg_level(msg + "\n", level=logging.ERROR, noiselevel=-1)
+ return exitcode
+ msg = ">>> Git pull in %s successful" % myportdir
+ emergelog(xterm_titles, msg)
+ writemsg_level(msg + "\n")
+ return exitcode
elif syncuri[:8]=="rsync://":
+ for vcs_dir in vcs_dirs:
+ writemsg_level(("!!! %s appears to be under revision " + \
+ "control (contains %s).\n!!! Aborting rsync sync.\n") % \
+ (myportdir, vcs_dir), level=logging.ERROR, noiselevel=-1)
+ return 1
if not os.path.exists(EPREFIX+"/usr/bin/rsync"):
- print "!!! rsync does not exist, so rsync support is disabled."
+ print "!!! /usr/bin/rsync does not exist, so rsync support is disabled."
print "!!! Type \"emerge net-misc/rsync\" to enable rsync support."
sys.exit(1)
mytimeout=180
del mtimedb["resume"]
mtimedb.commit()
mtimedb["resume"]={}
- # Stored as a dict starting with portage-2.2_rc7, and supported
+ # Stored as a dict starting with portage-2.1.6_rc1, and supported
# by >=portage-2.1.3_rc8. Versions <portage-2.1.3_rc8 only support
# a list type for options.
mtimedb["resume"]["myopts"] = myopts.copy()
repos = portdb.getRepositories()
for r in repos:
missing_repo_names.discard(portdb.getRepositoryPath(r))
+ if portdb.porttree_root in missing_repo_names and \
+ not os.path.exists(os.path.join(
+ portdb.porttree_root, "profiles")):
+ # This is normal if $PORTDIR happens to be empty,
+ # so don't warn about it.
+ missing_repo_names.remove(portdb.porttree_root)
if missing_repo_names:
msg = []
if (not os.path.isdir(self.pkgdir) and not getbinpkgs):
return 0
- if not getbinpkgsonly:
+ if True:
pkg_paths = {}
self._pkg_paths = pkg_paths
dirs = listdir(self.pkgdir, dirsonly=True, EmptyOnError=True)
aux_cache[k] = d[k]
self.dbapi._aux_cache[mycpv] = aux_cache
+ for cpv in list(metadata):
+ if cpv not in pkg_paths:
+ del metadata[cpv]
+
# Do not bother to write the Packages index if $PKGDIR/All/ exists
# since it will provide no benefit due to the need to read CATEGORY
# from xpak.
if update_pkgindex and os.access(self.pkgdir, os.W_OK):
- stale = [cpv for cpv in metadata if cpv not in self._pkg_paths]
- for cpv in stale:
- del metadata[cpv]
del pkgindex.packages[:]
pkgindex.packages.extend(metadata.itervalues())
self._update_pkgindex_header(pkgindex.header)
for cpv in self._remotepkgs:
self.dbapi.cpv_inject(cpv)
self.populated = 1
+ if getbinpkgsonly:
+ # Remote package instances override local package
+ # if they are not identical.
+ hash_names = ["SIZE"] + self._pkgindex_hashes
+ for cpv, local_metadata in metadata.iteritems():
+ remote_metadata = self._remotepkgs.get(cpv)
+ if remote_metadata is None:
+ continue
+ # Use digests to compare identity.
+ identical = True
+ for hash_name in hash_names:
+ local_value = local_metadata.get(hash_name)
+ if local_value is None:
+ continue
+ remote_value = remote_metadata.get(hash_name)
+ if remote_value is None:
+ continue
+ if local_value != remote_value:
+ identical = False
+ break
+ if identical:
+ del self._remotepkgs[cpv]
+ else:
+ # Local package instances override remote instances.
+ for cpv in metadata:
+ self._remotepkgs.pop(cpv, None)
return
self._remotepkgs = {}
try:
continue
mycat = self.remotepkgs[mypkg]["CATEGORY"].strip()
fullpkg = mycat+"/"+mypkg[:-5]
+
+ if fullpkg in metadata:
+ # When using this old protocol, comparison with the remote
+ # package isn't supported, so the local package is always
+ # preferred even if getbinpkgsonly is enabled.
+ continue
+
if not self.dbapi._category_re.match(mycat):
writemsg(("!!! Remote binary package has an " + \
"unrecognized category: '%s'\n") % fullpkg,
# invalid tbz2's can hurt things.
#print "cpv_inject("+str(fullpkg)+")"
self.dbapi.cpv_inject(fullpkg)
- metadata = self.remotepkgs[mypkg]
- for k, v in metadata.items():
- metadata[k] = v.strip()
- self._remotepkgs[fullpkg] = metadata
+ remote_metadata = self.remotepkgs[mypkg]
+ for k, v in remote_metadata.items():
+ remote_metadata[k] = v.strip()
+ self._remotepkgs[fullpkg] = remote_metadata
#print " -- Injected"
except SystemExit, e:
raise
if pkgindex_lock:
unlockfile(pkgindex_lock)
+ if self._remotepkgs is not None:
+ # When a remote package is downloaded and injected,
+ # update state so self.isremote() returns False.
+ self._remotepkgs.pop(cpv, None)
+
def _pkgindex_entry(self, cpv):
"""
Performs checksums and evaluates USE flag conditionals.
downloaded (or it is only partially downloaded)."""
if self._remotepkgs is None or pkgname not in self._remotepkgs:
return False
- pkg_path = self.getname(pkgname)
- if os.path.exists(pkg_path) and \
- os.path.basename(pkg_path) not in self.invalids:
- return False
+ # Presence in self._remotepkgs implies that it's remote. When a
+ # package is downloaded, state is updated by self.inject().
return True
def get_use(self, pkgname):