Skip to content

Commit

Permalink
Add support for sapling
Browse files Browse the repository at this point in the history
Sapling is a somewhat novel SCM from Facebook / Meta.

It is fully compatible with Git and provides a more powerful
yet userfriendly frontend, modeled after mercurial.

This adds Sapling support in alibuild, including:

* Support for alidist sapling checkouts
* Support for development packages which were cloned via sapling
  • Loading branch information
ktf committed Oct 18, 2023
1 parent 27e22e5 commit 25fcd02
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 4 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/pr-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ jobs:

- name: Install test dependencies
run: |
brew install modules alisw/system-deps/o2-full-deps
brew install modules alisw/system-deps/o2-full-deps sapling
python3 -m pip install --upgrade tox tox-gh-actions coverage
- name: Run tests
Expand Down
21 changes: 18 additions & 3 deletions alibuild_helpers/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -364,10 +369,20 @@ def doBuild(args, parser):
if not exists(specDir):
makedirs(specDir)

# By default Git is our SCM, so we find the commit hash of alidist
# using it.
# If the alidist workdir contains a .git directory, we use Git as SCM
# otherwise we use Sapling

scm = Git()
os.environ["ALIBUILD_ALIDIST_HASH"] = scm.checkedOutCommitName(directory=args.configDir)
try:
checkedOutCommitName = scm.checkedOutCommitName(directory=args.configDir)
except:
scm = Sapling()
try:
checkedOutCommitName = scm.checkedOutCommitName(directory=args.configDir)
except:
error("Cannot find SCM directory in %s.", args.configDir)
return 1
os.environ["ALIBUILD_ALIDIST_HASH"] = checkedOutCommitName

debug("Building for architecture %s", args.architecture)
debug("Number of parallel builds: %d", args.jobs)
Expand Down
47 changes: 47 additions & 0 deletions alibuild_helpers/sl.py
Original file line number Diff line number Diff line change
@@ -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 <hash>[+] <branch>
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)
10 changes: 10 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ allowlist_externals =
git
test
touch
sl
rm
deps =
py27: mock
coverage
Expand Down Expand Up @@ -109,6 +111,14 @@ commands =
touch zlib/foo
coverage run --source={toxinidir} -a {toxinidir}/aliBuild -a {env:ARCHITECTURE} --no-system --disable GCC-Toolchain build zlib
coverage run --source={envsitepackagesdir} -a -m unittest discover {toxinidir}/tests
# On Darwin we also test sapling support
darwin: sl clone https://github.com/alisw/alidist alidist-sapling
darwin: coverage run --source={toxinidir} -a {toxinidir}/aliBuild -a {env:ARCHITECTURE} -c alidist-sapling --no-system --disable GCC-Toolchain build zlib
darwin: rm -fr zlib
darwin: sl clone https://github.com/alisw/zlib
darwin: coverage run --source={toxinidir} -a {toxinidir}/aliBuild -a {env:ARCHITECTURE} --no-system --disable GCC-Toolchain build zlib
touch zlib/foo
darwin: coverage run --source={toxinidir} -a {toxinidir}/aliBuild -a {env:ARCHITECTURE} --no-system --disable GCC-Toolchain build zlib

[coverage:run]
branch = True
Expand Down

0 comments on commit 25fcd02

Please sign in to comment.