diff --git a/alibuild_helpers/build.py b/alibuild_helpers/build.py index 4fcb08c6..d5c59b16 100644 --- a/alibuild_helpers/build.py +++ b/alibuild_helpers/build.py @@ -14,6 +14,7 @@ from alibuild_helpers.utilities import yamlDump from alibuild_helpers.utilities import resolve_tag, resolve_version from alibuild_helpers.git import git, clone_speedup_options, Git +from alibuild_helpers.sl import sapling, Sapling from alibuild_helpers.sync import (NoRemoteSync, HttpRemoteSync, S3RemoteSync, Boto3RemoteSync, RsyncRemoteSync) import yaml @@ -62,6 +63,10 @@ def update_git_repos(args, specs, buildOrder, develPkgs): def update_repo(package, git_prompt): specs[package]["scm"] = Git() + if package in develPkgs: + localCheckout = os.path.join(os.getcwd(), specs[package]["package"]) + if exists("%s/.sl" % localCheckout): + specs[package]["scm"] = Sapling() updateReferenceRepoSpec(args.referenceSources, package, specs[package], fetch=args.fetchRepos, usePartialClone=not args.docker, @@ -368,8 +373,10 @@ def doBuild(args, parser): # otherwise we use Sapling if exists("%s/.git" % args.configDir): scm = Git() + elif exists("%s/.sl" % args.configDir): + scm = Sapling() else: - error("Cannot find .git directory in %s.", args.configDir) + error("Cannot find SCM directory in %s.", args.configDir) return 1 os.environ["ALIBUILD_ALIDIST_HASH"] = scm.checkedOutCommitName(directory=args.configDir) diff --git a/alibuild_helpers/sl.py b/alibuild_helpers/sl.py new file mode 100644 index 00000000..ed07986a --- /dev/null +++ b/alibuild_helpers/sl.py @@ -0,0 +1,47 @@ +from shlex import quote # Python 3.3+ +from alibuild_helpers.cmd import getstatusoutput +from alibuild_helpers.log import debug +from alibuild_helpers.scm import SCM + +SL_COMMAND_TIMEOUT_SEC = 120 +"""How many seconds to let any sl command execute before being terminated.""" + +class Sapling(SCM): + name = "Sapling" + def checkedOutCommitName(self, directory): + return sapling(("whereami", ), directory) + def branchOrRef(self, directory): + # Format is [+] + identity = sapling(("identify", ), directory) + return identity.split(" ")[-1] + def exec(self, *args, **kwargs): + return sapling(*args, **kwargs) + def parseRefs(self, output): + return { + sl_ref: sl_hash for sl_ref, sep, sl_hash + in (line.partition("\t") for line in output.splitlines()) if sep + } + def listRefsCmd(self): + return ["bookmark", "--list", "--remote", "-R"] + def diffCmd(self, directory): + return "cd %s && sl diff && sl status" % directory + def checkUntracked(self, line): + return line.startswith("? ") + +def sapling(args, directory=".", check=True, prompt=True): + debug("Executing sl %s (in directory %s)", " ".join(args), directory) + # We can't use git --git-dir=%s/.git or git -C %s here as the former requires + # that the directory we're inspecting to be the root of a git directory, not + # just contained in one (and that breaks CI tests), and the latter isn't + # supported by the git version we have on slc6. + # Silence cd as shell configuration can cause the new directory to be echoed. + err, output = getstatusoutput("""\ + set -e +x + sl -R {directory} {args} + """.format( + directory=quote(directory), + args=" ".join(map(quote, args)), + ), timeout=SL_COMMAND_TIMEOUT_SEC) + if check and err != 0: + raise RuntimeError("Error {} from sl {}: {}".format(err, " ".join(args), output)) + return output if check else (err, output)