deleted file mode 100644
--- a/build/release/info.py
+++ /dev/null
@@ -1,218 +0,0 @@
-from datetime import datetime
-import os
-from os import path
-import re
-import shutil
-import sys
-from urllib2 import urlopen
-
-from release.paths import makeCandidatesDir
-
-import logging
-log = logging.getLogger(__name__)
-
-# If version has two parts with no trailing specifiers like "rc", we
-# consider it a "final" release for which we only create a _RELEASE tag.
-FINAL_RELEASE_REGEX = "^\d+\.\d+$"
-
-
-class ConfigError(Exception):
- pass
-
-
-def getBuildID(platform, product, version, buildNumber, nightlyDir='nightly',
- server='stage.mozilla.org'):
- infoTxt = makeCandidatesDir(product, version, buildNumber, nightlyDir,
- protocol='http', server=server) + \
- '%s_info.txt' % platform
- try:
- buildInfo = urlopen(infoTxt).read()
- except:
- log.error("Failed to retrieve %s" % infoTxt)
- raise
-
- for line in buildInfo.splitlines():
- key, value = line.rstrip().split('=', 1)
- if key == 'buildID':
- return value
-
-
-def findOldBuildIDs(product, version, buildNumber, platforms,
- nightlyDir='nightly', server='stage.mozilla.org'):
- ids = {}
- if buildNumber <= 1:
- return ids
- for n in range(1, buildNumber):
- for platform in platforms:
- if platform not in ids:
- ids[platform] = []
- try:
- id = getBuildID(platform, product, version, n, nightlyDir,
- server)
- ids[platform].append(id)
- except Exception, e:
- log.error("Hit exception: %s" % e)
- return ids
-
-
-def getReleaseConfigName(product, branch, version=None, staging=False):
- # XXX: Horrible hack for bug 842741. Because Thunderbird release
- # and esr both build out of esr17 repositories we'll bump the wrong
- # config for release without this.
- if product == 'thunderbird' and 'esr17' in branch and version and 'esr' not in version:
- cfg = 'release-thunderbird-comm-release.py'
- else:
- cfg = 'release-%s-%s.py' % (product, branch)
- if staging:
- cfg = 'staging_%s' % cfg
- return cfg
-
-
-def readReleaseConfig(configfile, required=[]):
- return readConfig(configfile, keys=['releaseConfig'], required=required)
-
-
-def readBranchConfig(dir, localconfig, branch, required=[]):
- shutil.copy(localconfig, path.join(dir, "localconfig.py"))
- oldcwd = os.getcwd()
- os.chdir(dir)
- sys.path.append(".")
- try:
- return readConfig("config.py", keys=['BRANCHES', branch],
- required=required)
- finally:
- os.chdir(oldcwd)
- sys.path.remove(".")
-
-
-def readConfig(configfile, keys=[], required=[]):
- c = {}
- execfile(configfile, c)
- for k in keys:
- c = c[k]
- items = c.keys()
- err = False
- for key in required:
- if key not in items:
- err = True
- log.error("Required item `%s' missing from %s" % (key, c))
- if err:
- raise ConfigError("Missing at least one item in config, see above")
- return c
-
-
-def isFinalRelease(version):
- return bool(re.match(FINAL_RELEASE_REGEX, version))
-
-
-def getBaseTag(product, version):
- product = product.upper()
- version = version.replace('.', '_')
- return '%s_%s' % (product, version)
-
-
-def getTags(baseTag, buildNumber, buildTag=True):
- t = ['%s_RELEASE' % baseTag]
- if buildTag:
- t.append('%s_BUILD%d' % (baseTag, int(buildNumber)))
- return t
-
-
-def getRuntimeTag(tag):
- return "%s_RUNTIME" % tag
-
-
-def getReleaseTag(tag):
- return "%s_RELEASE" % tag
-
-
-def generateRelbranchName(version, prefix='GECKO'):
- return '%s%s_%s_RELBRANCH' % (
- prefix, version.replace('.', ''),
- datetime.now().strftime('%Y%m%d%H'))
-
-
-def getReleaseName(product, version, buildNumber):
- return '%s-%s-build%s' % (product.title(), version, str(buildNumber))
-
-
-def getRepoMatchingBranch(branch, sourceRepositories):
- for sr in sourceRepositories.values():
- if branch in sr['path']:
- return sr
- return None
-
-
-def fileInfo(filepath, product):
- """Extract information about a release file. Returns a dictionary with the
- following keys set:
- 'product', 'version', 'locale', 'platform', 'contents', 'format',
- 'pathstyle'
-
- 'contents' is one of 'complete', 'installer'
- 'format' is one of 'mar' or 'exe'
- 'pathstyle' is either 'short' or 'long', and refers to if files are all in
- one directory, with the locale as part of the filename ('short' paths,
- firefox 3.0 style filenames), or if the locale names are part of the
- directory structure, but not the file name itself ('long' paths,
- firefox 3.5+ style filenames)
- """
- try:
- # Mozilla 1.9.0 style (aka 'short') paths
- # e.g. firefox-3.0.12.en-US.win32.complete.mar
- filename = os.path.basename(filepath)
- m = re.match("^(%s)-([0-9.]+)\.([-a-zA-Z]+)\.(win32)\.(complete|installer)\.(mar|exe)$" % product, filename)
- if not m:
- raise ValueError("Could not parse: %s" % filename)
- return {'product': m.group(1),
- 'version': m.group(2),
- 'locale': m.group(3),
- 'platform': m.group(4),
- 'contents': m.group(5),
- 'format': m.group(6),
- 'pathstyle': 'short',
- 'leading_path': '',
- }
- except:
- # Mozilla 1.9.1 and on style (aka 'long') paths
- # e.g. update/win32/en-US/firefox-3.5.1.complete.mar
- # win32/en-US/Firefox Setup 3.5.1.exe
- ret = {'pathstyle': 'long'}
- if filepath.endswith('.mar'):
- ret['format'] = 'mar'
- m = re.search("update/(win32|linux-i686|linux-x86_64|mac|mac64)/([-a-zA-Z]+)/(%s)-(\d+\.\d+(?:\.\d+)?(?:\w+(?:\d+)?)?)\.(complete)\.mar" % product, filepath)
- if not m:
- raise ValueError("Could not parse: %s" % filepath)
- ret['platform'] = m.group(1)
- ret['locale'] = m.group(2)
- ret['product'] = m.group(3)
- ret['version'] = m.group(4)
- ret['contents'] = m.group(5)
- ret['leading_path'] = ''
- elif filepath.endswith('.exe'):
- ret['format'] = 'exe'
- ret['contents'] = 'installer'
- # EUballot builds use a different enough style of path than others
- # that we can't catch them in the same regexp
- if filepath.find('win32-EUballot') != -1:
- ret['platform'] = 'win32'
- m = re.search("(win32-EUballot/)([-a-zA-Z]+)/((?i)%s) Setup (\d+\.\d+(?:\.\d+)?(?:\w+\d+)?(?:\ \w+\ \d+)?)\.exe" % product, filepath)
- if not m:
- raise ValueError("Could not parse: %s" % filepath)
- ret['leading_path'] = m.group(1)
- ret['locale'] = m.group(2)
- ret['product'] = m.group(3).lower()
- ret['version'] = m.group(4)
- else:
- m = re.search("(partner-repacks/[-a-zA-Z0-9_]+/|)(win32|mac|linux-i686)/([-a-zA-Z]+)/((?i)%s) Setup (\d+\.\d+(?:\.\d+)?(?:\w+(?:\d+)?)?(?:\ \w+\ \d+)?)\.exe" % product, filepath)
- if not m:
- raise ValueError("Could not parse: %s" % filepath)
- ret['leading_path'] = m.group(1)
- ret['platform'] = m.group(2)
- ret['locale'] = m.group(3)
- ret['product'] = m.group(4).lower()
- ret['version'] = m.group(5)
- else:
- raise ValueError("Unknown filetype for %s" % filepath)
-
- return ret
deleted file mode 100644
--- a/build/util/hg.py
+++ /dev/null
@@ -1,611 +0,0 @@
-"""Functions for interacting with hg"""
-import os
-import re
-import subprocess
-from urlparse import urlsplit
-from ConfigParser import RawConfigParser
-
-from util.commands import run_cmd, get_output, remove_path
-from util.retry import retry
-
-import logging
-log = logging.getLogger(__name__)
-
-
-class DefaultShareBase:
- pass
-DefaultShareBase = DefaultShareBase()
-
-
-class HgUtilError(Exception):
- pass
-
-
-def _make_absolute(repo):
- if repo.startswith("file://"):
- path = repo[len("file://"):]
- repo = "file://%s" % os.path.abspath(path)
- elif "://" not in repo:
- repo = os.path.abspath(repo)
- return repo
-
-
-def make_hg_url(hgHost, repoPath, protocol='https', revision=None,
- filename=None):
- """construct a valid hg url from a base hg url (hg.mozilla.org),
- repoPath, revision and possible filename"""
- base = '%s://%s' % (protocol, hgHost)
- repo = '/'.join(p.strip('/') for p in [base, repoPath])
- if not filename:
- if not revision:
- return repo
- else:
- return '/'.join([p.strip('/') for p in [repo, 'rev', revision]])
- else:
- assert revision
- return '/'.join([p.strip('/') for p in [repo, 'raw-file', revision, filename]])
-
-
-def get_repo_name(repo):
- return repo.rstrip('/').split('/')[-1]
-
-
-def get_repo_path(repo):
- repo = _make_absolute(repo)
- if repo.startswith("/"):
- return repo.lstrip("/")
- else:
- return urlsplit(repo).path.lstrip("/")
-
-
-def get_revision(path):
- """Returns which revision directory `path` currently has checked out."""
- return get_output(['hg', 'parent', '--template', '{node|short}'], cwd=path)
-
-
-def get_branch(path):
- return get_output(['hg', 'branch'], cwd=path).strip()
-
-
-def get_branches(path):
- branches = []
- for line in get_output(['hg', 'branches', '-c'], cwd=path).splitlines():
- branches.append(line.split()[0])
- return branches
-
-
-def is_hg_cset(rev):
- """Retruns True if passed revision represents a valid HG revision
- (long or short(er) 40 bit hex)"""
- try:
- int(rev, 16)
- return True
- except (TypeError, ValueError):
- return False
-
-
-def hg_ver():
- """Returns the current version of hg, as a tuple of
- (major, minor, build)"""
- ver_string = get_output(['hg', '-q', 'version'])
- match = re.search("\(version ([0-9.]+)\)", ver_string)
- if match:
- bits = match.group(1).split(".")
- if len(bits) < 3:
- bits += (0,)
- ver = tuple(int(b) for b in bits)
- else:
- ver = (0, 0, 0)
- log.debug("Running hg version %s", ver)
- return ver
-
-
-def purge(dest):
- """Purge the repository of all untracked and ignored files."""
- try:
- run_cmd(['hg', '--config', 'extensions.purge=', 'purge',
- '-a', '--all', dest], cwd=dest)
- except subprocess.CalledProcessError, e:
- log.debug('purge failed: %s' % e)
- raise
-
-
-def update(dest, branch=None, revision=None):
- """Updates working copy `dest` to `branch` or `revision`. If neither is
- set then the working copy will be updated to the latest revision on the
- current branch. Local changes will be discarded."""
- # If we have a revision, switch to that
- if revision is not None:
- cmd = ['hg', 'update', '-C', '-r', revision]
- run_cmd(cmd, cwd=dest)
- else:
- # Check & switch branch
- local_branch = get_output(['hg', 'branch'], cwd=dest).strip()
-
- cmd = ['hg', 'update', '-C']
-
- # If this is different, checkout the other branch
- if branch and branch != local_branch:
- cmd.append(branch)
-
- run_cmd(cmd, cwd=dest)
- return get_revision(dest)
-
-
-def clone(repo, dest, branch=None, revision=None, update_dest=True,
- clone_by_rev=False, mirrors=None, bundles=None):
- """Clones hg repo and places it at `dest`, replacing whatever else is
- there. The working copy will be empty.
-
- If `revision` is set, only the specified revision and its ancestors will
- be cloned.
-
- If `update_dest` is set, then `dest` will be updated to `revision` if
- set, otherwise to `branch`, otherwise to the head of default.
-
- If `mirrors` is set, will try and clone from the mirrors before
- cloning from `repo`.
-
- If `bundles` is set, will try and download the bundle first and
- unbundle it. If successful, will pull in new revisions from mirrors or
- the master repo. If unbundling fails, will fall back to doing a regular
- clone from mirrors or the master repo.
-
- Regardless of how the repository ends up being cloned, the 'default' path
- will point to `repo`.
- """
- if os.path.exists(dest):
- remove_path(dest)
-
- if bundles:
- log.info("Attempting to initialize clone with bundles")
- for bundle in bundles:
- if os.path.exists(dest):
- remove_path(dest)
- init(dest)
- log.info("Trying to use bundle %s", bundle)
- try:
- if not unbundle(bundle, dest):
- remove_path(dest)
- continue
- adjust_paths(dest, default=repo)
- # Now pull / update
- return pull(repo, dest, update_dest=update_dest,
- mirrors=mirrors, revision=revision, branch=branch)
- except Exception:
- remove_path(dest)
- log.exception("Problem unbundling/pulling from %s", bundle)
- continue
- else:
- log.info("Using bundles failed; falling back to clone")
-
- if mirrors:
- log.info("Attempting to clone from mirrors")
- for mirror in mirrors:
- log.info("Cloning from %s", mirror)
- try:
- retval = clone(mirror, dest, branch, revision,
- update_dest=update_dest, clone_by_rev=clone_by_rev)
- adjust_paths(dest, default=repo)
- return retval
- except:
- log.exception("Problem cloning from mirror %s", mirror)
- continue
- else:
- log.info("Pulling from mirrors failed; falling back to %s", repo)
- # We may have a partial repo here; mercurial() copes with that
- # We need to make sure our paths are correct though
- if os.path.exists(os.path.join(dest, '.hg')):
- adjust_paths(dest, default=repo)
- return mercurial(repo, dest, branch, revision, autoPurge=True,
- update_dest=update_dest, clone_by_rev=clone_by_rev)
-
- cmd = ['hg', 'clone']
- if not update_dest:
- cmd.append('-U')
-
- if clone_by_rev:
- if revision:
- cmd.extend(['-r', revision])
- elif branch:
- # hg >= 1.6 supports -b branch for cloning
- ver = hg_ver()
- if ver >= (1, 6, 0):
- cmd.extend(['-b', branch])
-
- cmd.extend([repo, dest])
- run_cmd(cmd)
-
- if update_dest:
- return update(dest, branch, revision)
-
-
-def common_args(revision=None, branch=None, ssh_username=None, ssh_key=None):
- """Fill in common hg arguments, encapsulating logic checks that depend on
- mercurial versions and provided arguments"""
- args = []
- if ssh_username or ssh_key:
- opt = ['-e', 'ssh']
- if ssh_username:
- opt[1] += ' -l %s' % ssh_username
- if ssh_key:
- opt[1] += ' -i %s' % ssh_key
- args.extend(opt)
- if revision:
- args.extend(['-r', revision])
- elif branch:
- if hg_ver() >= (1, 6, 0):
- args.extend(['-b', branch])
- return args
-
-
-def pull(repo, dest, update_dest=True, mirrors=None, **kwargs):
- """Pulls changes from hg repo and places it in `dest`.
-
- If `update_dest` is set, then `dest` will be updated to `revision` if
- set, otherwise to `branch`, otherwise to the head of default.
-
- If `mirrors` is set, will try and pull from the mirrors first before
- `repo`."""
-
- if mirrors:
- for mirror in mirrors:
- try:
- return pull(mirror, dest, update_dest=update_dest, **kwargs)
- except:
- log.exception("Problem pulling from mirror %s", mirror)
- continue
- else:
- log.info("Pulling from mirrors failed; falling back to %s", repo)
-
- # Convert repo to an absolute path if it's a local repository
- repo = _make_absolute(repo)
- cmd = ['hg', 'pull']
- # Don't pass -r to "hg pull", except when it's a valid HG revision.
- # Pulling using tag names is dangerous: it uses the local .hgtags, so if
- # the tag has moved on the remote side you won't pull the new revision the
- # remote tag refers to.
- pull_kwargs = kwargs.copy()
- if 'revision' in pull_kwargs and \
- not is_hg_cset(pull_kwargs['revision']):
- del pull_kwargs['revision']
-
- cmd.extend(common_args(**pull_kwargs))
-
- cmd.append(repo)
- run_cmd(cmd, cwd=dest)
-
- if update_dest:
- branch = None
- if 'branch' in kwargs and kwargs['branch']:
- branch = kwargs['branch']
- revision = None
- if 'revision' in kwargs and kwargs['revision']:
- revision = kwargs['revision']
- return update(dest, branch=branch, revision=revision)
-
-# Defines the places of attributes in the tuples returned by `out'
-REVISION, BRANCH = 0, 1
-
-
-def out(src, remote, **kwargs):
- """Check for outgoing changesets present in a repo"""
- cmd = ['hg', '-q', 'out', '--template', '{node} {branches}\n']
- cmd.extend(common_args(**kwargs))
- cmd.append(remote)
- if os.path.exists(src):
- try:
- revs = []
- for line in get_output(cmd, cwd=src).rstrip().split("\n"):
- try:
- rev, branch = line.split()
- # Mercurial displays no branch at all if the revision is on
- # "default"
- except ValueError:
- rev = line.rstrip()
- branch = "default"
- revs.append((rev, branch))
- return revs
- except subprocess.CalledProcessError, inst:
- # In some situations, some versions of Mercurial return "1"
- # if no changes are found, so we need to ignore this return code
- if inst.returncode == 1:
- return []
- raise
-
-
-def push(src, remote, push_new_branches=True, force=False, **kwargs):
- cmd = ['hg', 'push']
- cmd.extend(common_args(**kwargs))
- if force:
- cmd.append('-f')
- if push_new_branches:
- cmd.append('--new-branch')
- cmd.append(remote)
- run_cmd(cmd, cwd=src)
-
-
-def mercurial(repo, dest, branch=None, revision=None, update_dest=True,
- shareBase=DefaultShareBase, allowUnsharedLocalClones=False,
- clone_by_rev=False, mirrors=None, bundles=None, autoPurge=False):
- """Makes sure that `dest` is has `revision` or `branch` checked out from
- `repo`.
-
- Do what it takes to make that happen, including possibly clobbering
- dest.
-
- If allowUnsharedLocalClones is True and we're trying to use the share
- extension but fail, then we will be able to clone from the shared repo to
- our destination. If this is False, the default, then if we don't have the
- share extension we will just clone from the remote repository.
-
- If `clone_by_rev` is True, use 'hg clone -r <rev>' instead of 'hg clone'.
- This is slower, but useful when cloning repos with lots of heads.
-
- If `mirrors` is set, will try and use the mirrors before `repo`.
-
- If `bundles` is set, will try and download the bundle first and
- unbundle it instead of doing a full clone. If successful, will pull in
- new revisions from mirrors or the master repo. If unbundling fails, will
- fall back to doing a regular clone from mirrors or the master repo.
- """
- dest = os.path.abspath(dest)
- if shareBase is DefaultShareBase:
- shareBase = os.environ.get("HG_SHARE_BASE_DIR", None)
-
- log.info("Reporting hg version in use")
- cmd = ['hg', '-q', 'version']
- run_cmd(cmd, cwd='.')
-
- if shareBase:
- # Check that 'hg share' works
- try:
- log.info("Checking if share extension works")
- output = get_output(['hg', 'help', 'share'], dont_log=True)
- if 'no commands defined' in output:
- # Share extension is enabled, but not functional
- log.info("Disabling sharing since share extension doesn't seem to work (1)")
- shareBase = None
- elif 'unknown command' in output:
- # Share extension is disabled
- log.info("Disabling sharing since share extension doesn't seem to work (2)")
- shareBase = None
- except subprocess.CalledProcessError:
- # The command failed, so disable sharing
- log.info("Disabling sharing since share extension doesn't seem to work (3)")
- shareBase = None
-
- # Check that our default path is correct
- if os.path.exists(os.path.join(dest, '.hg')):
- hgpath = path(dest, "default")
-
- # Make sure that our default path is correct
- if hgpath != _make_absolute(repo):
- log.info("hg path isn't correct (%s should be %s); clobbering",
- hgpath, _make_absolute(repo))
- remove_path(dest)
-
- # If the working directory already exists and isn't using share we update
- # the working directory directly from the repo, ignoring the sharing
- # settings
- if os.path.exists(dest):
- if not os.path.exists(os.path.join(dest, ".hg")):
- log.warning("%s doesn't appear to be a valid hg directory; clobbering", dest)
- remove_path(dest)
- elif not os.path.exists(os.path.join(dest, ".hg", "sharedpath")):
- try:
- if autoPurge:
- purge(dest)
- return pull(repo, dest, update_dest=update_dest, branch=branch,
- revision=revision,
- mirrors=mirrors)
- except subprocess.CalledProcessError:
- log.warning("Error pulling changes into %s from %s; clobbering", dest, repo)
- log.debug("Exception:", exc_info=True)
- remove_path(dest)
-
- # If that fails for any reason, and sharing is requested, we'll try to
- # update the shared repository, and then update the working directory from
- # that.
- if shareBase:
- sharedRepo = os.path.join(shareBase, get_repo_path(repo))
- dest_sharedPath = os.path.join(dest, '.hg', 'sharedpath')
-
- if os.path.exists(sharedRepo):
- hgpath = path(sharedRepo, "default")
-
- # Make sure that our default path is correct
- if hgpath != _make_absolute(repo):
- log.info("hg path isn't correct (%s should be %s); clobbering",
- hgpath, _make_absolute(repo))
- # we need to clobber both the shared checkout and the dest,
- # since hgrc needs to be in both places
- remove_path(sharedRepo)
- remove_path(dest)
-
- if os.path.exists(dest_sharedPath):
- # Make sure that the sharedpath points to sharedRepo
- dest_sharedPath_data = os.path.normpath(
- open(dest_sharedPath).read())
- norm_sharedRepo = os.path.normpath(os.path.join(sharedRepo, '.hg'))
- if dest_sharedPath_data != norm_sharedRepo:
- # Clobber!
- log.info("We're currently shared from %s, but are being requested to pull from %s (%s); clobbering",
- dest_sharedPath_data, repo, norm_sharedRepo)
- remove_path(dest)
-
- try:
- log.info("Updating shared repo")
- mercurial(repo, sharedRepo, branch=branch, revision=revision,
- update_dest=False, shareBase=None, clone_by_rev=clone_by_rev,
- mirrors=mirrors, bundles=bundles, autoPurge=False)
- if os.path.exists(dest):
- if autoPurge:
- purge(dest)
- return update(dest, branch=branch, revision=revision)
-
- try:
- log.info("Trying to share %s to %s", sharedRepo, dest)
- return share(sharedRepo, dest, branch=branch, revision=revision)
- except subprocess.CalledProcessError:
- if not allowUnsharedLocalClones:
- # Re-raise the exception so it gets caught below.
- # We'll then clobber dest, and clone from original repo
- raise
-
- log.warning("Error calling hg share from %s to %s;"
- "falling back to normal clone from shared repo",
- sharedRepo, dest)
- # Do a full local clone first, and then update to the
- # revision we want
- # This lets us use hardlinks for the local clone if the OS
- # supports it
- clone(sharedRepo, dest, update_dest=False,
- mirrors=mirrors, bundles=bundles)
- return update(dest, branch=branch, revision=revision)
- except subprocess.CalledProcessError:
- log.warning(
- "Error updating %s from sharedRepo (%s): ", dest, sharedRepo)
- log.debug("Exception:", exc_info=True)
- remove_path(dest)
- # end if shareBase
-
- if not os.path.exists(os.path.dirname(dest)):
- os.makedirs(os.path.dirname(dest))
-
- # Share isn't available or has failed, clone directly from the source
- return clone(repo, dest, branch, revision,
- update_dest=update_dest, mirrors=mirrors,
- bundles=bundles, clone_by_rev=clone_by_rev)
-
-
-def apply_and_push(localrepo, remote, changer, max_attempts=10,
- ssh_username=None, ssh_key=None, force=False):
- """This function calls `changer' to make changes to the repo, and tries
- its hardest to get them to the origin repo. `changer' must be a
- callable object that receives two arguments: the directory of the local
- repository, and the attempt number. This function will push ALL
- changesets missing from remote."""
- assert callable(changer)
- branch = get_branch(localrepo)
- changer(localrepo, 1)
- for n in range(1, max_attempts + 1):
- new_revs = []
- try:
- new_revs = out(src=localrepo, remote=remote,
- ssh_username=ssh_username,
- ssh_key=ssh_key)
- if len(new_revs) < 1:
- raise HgUtilError("No revs to push")
- push(src=localrepo, remote=remote, ssh_username=ssh_username,
- ssh_key=ssh_key, force=force)
- return
- except subprocess.CalledProcessError, e:
- log.debug("Hit error when trying to push: %s" % str(e))
- if n == max_attempts:
- log.debug("Tried %d times, giving up" % max_attempts)
- for r in reversed(new_revs):
- run_cmd(['hg', '--config', 'extensions.mq=', 'strip', '-n',
- r[REVISION]], cwd=localrepo)
- raise HgUtilError("Failed to push")
- pull(remote, localrepo, update_dest=False,
- ssh_username=ssh_username, ssh_key=ssh_key)
- # After we successfully rebase or strip away heads the push is
- # is attempted again at the start of the loop
- try:
- run_cmd(['hg', '--config', 'ui.merge=internal:merge',
- 'rebase'], cwd=localrepo)
- except subprocess.CalledProcessError, e:
- log.debug("Failed to rebase: %s" % str(e))
- update(localrepo, branch=branch)
- for r in reversed(new_revs):
- run_cmd(['hg', '--config', 'extensions.mq=', 'strip', '-n',
- r[REVISION]], cwd=localrepo)
- changer(localrepo, n + 1)
-
-
-def share(source, dest, branch=None, revision=None):
- """Creates a new working directory in "dest" that shares history with
- "source" using Mercurial's share extension"""
- run_cmd(['hg', 'share', '-U', source, dest])
- return update(dest, branch=branch, revision=revision)
-
-
-def cleanOutgoingRevs(reponame, remote, username, sshKey):
- outgoingRevs = retry(out, kwargs=dict(src=reponame, remote=remote,
- ssh_username=username,
- ssh_key=sshKey))
- for r in reversed(outgoingRevs):
- run_cmd(['hg', '--config', 'extensions.mq=', 'strip', '-n',
- r[REVISION]], cwd=reponame)
-
-
-def path(src, name='default'):
- """Returns the remote path associated with "name" """
- try:
- return get_output(['hg', 'path', name], cwd=src).strip()
- except subprocess.CalledProcessError:
- return None
-
-
-def init(dest):
- """Initializes an empty repo in `dest`"""
- run_cmd(['hg', 'init', dest])
-
-
-def unbundle(bundle, dest):
- """Unbundles the bundle located at `bundle` into `dest`.
-
- `bundle` can be a local file or remote url."""
- try:
- get_output(['hg', 'unbundle', bundle], cwd=dest, include_stderr=True)
- return True
- except subprocess.CalledProcessError:
- return False
-
-
-def adjust_paths(dest, **paths):
- """Adjusts paths in `dest`/.hg/hgrc so that names in `paths` are set to
- paths[name].
-
- Note that any comments in the hgrc will be lost if changes are made to the
- file."""
- hgrc = os.path.join(dest, '.hg', 'hgrc')
- config = RawConfigParser()
- config.read(hgrc)
-
- if not config.has_section('paths'):
- config.add_section('paths')
-
- changed = False
- for path_name, path_value in paths.items():
- if (not config.has_option('paths', path_name) or
- config.get('paths', path_name) != path_value):
- changed = True
- config.set('paths', path_name, path_value)
-
- if changed:
- config.write(open(hgrc, 'w'))
-
-
-def commit(dest, msg, user=None):
- cmd = ['hg', 'commit', '-m', msg]
- if user:
- cmd.extend(['-u', user])
- run_cmd(cmd, cwd=dest)
- return get_revision(dest)
-
-
-def tag(dest, tags, user=None, msg=None, rev=None, force=None):
- cmd = ['hg', 'tag']
- if user:
- cmd.extend(['-u', user])
- if msg:
- cmd.extend(['-m', msg])
- if rev:
- cmd.extend(['-r', rev])
- if force:
- cmd.append('-f')
- cmd.extend(tags)
- run_cmd(cmd, cwd=dest)
- return get_revision(dest)