kopia lustrzana https://github.com/jupyterhub/repo2docker
Mercurial optional
rodzic
96914545e1
commit
5bb586931b
|
@ -1,8 +1,39 @@
|
|||
import subprocess
|
||||
import os
|
||||
from distutils.util import strtobool
|
||||
|
||||
from .base import ContentProvider, ContentProviderException
|
||||
from ..utils import execute_cmd
|
||||
|
||||
HG_EVOLVE_REQUIRED = strtobool(
|
||||
os.environ.get("REPO2DOCKER_HG_EVOLVE_REQUIRED", "False")
|
||||
)
|
||||
|
||||
if HG_EVOLVE_REQUIRED:
|
||||
if "REPO2DOCKER_HG_REQUIRED" in os.environ:
|
||||
HG_REQUIRED = strtobool(os.environ["REPO2DOCKER_HG_REQUIRED"])
|
||||
if not HG_REQUIRED:
|
||||
raise ValueError(
|
||||
"Incompatible values for environment variables "
|
||||
"REPO2DOCKER_HG_EVOLVE_REQUIRED=1 and REPO2DOCKER_HG_REQUIRED=0"
|
||||
)
|
||||
else:
|
||||
HG_REQUIRED = True
|
||||
else:
|
||||
HG_REQUIRED = strtobool(os.environ.get("REPO2DOCKER_HG_REQUIRED", "False"))
|
||||
|
||||
|
||||
def is_mercurial_available():
|
||||
try:
|
||||
subprocess.check_output(["hg", "version"])
|
||||
except subprocess.CalledProcessError:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
if HG_REQUIRED and not is_mercurial_available():
|
||||
raise RuntimeError("REPO2DOCKER_HG_REQUIRED but the command `hg` is not available")
|
||||
|
||||
|
||||
class Mercurial(ContentProvider):
|
||||
"""Provide contents of a remote Mercurial repository."""
|
||||
|
@ -16,6 +47,8 @@ class Mercurial(ContentProvider):
|
|||
stderr=subprocess.DEVNULL,
|
||||
)
|
||||
except subprocess.CalledProcessError:
|
||||
# warning: if hg is not installed and `not HG_REQUIRED`,
|
||||
# we return None even for a hg repo
|
||||
return None
|
||||
|
||||
return {"repo": source, "ref": ref}
|
||||
|
@ -26,7 +59,14 @@ class Mercurial(ContentProvider):
|
|||
|
||||
# make a clone of the remote repository
|
||||
try:
|
||||
cmd = ["hg", "clone", repo, output_dir]
|
||||
cmd = [
|
||||
"hg",
|
||||
"clone",
|
||||
repo,
|
||||
output_dir,
|
||||
"--config",
|
||||
"phases.publish=False",
|
||||
]
|
||||
if ref is not None:
|
||||
# don't update so the clone will include an empty working
|
||||
# directory, the given ref will be updated out later
|
||||
|
@ -35,9 +75,9 @@ class Mercurial(ContentProvider):
|
|||
yield line
|
||||
|
||||
except subprocess.CalledProcessError as error:
|
||||
msg = "Failed to clone repository from {repo}".format(repo=repo)
|
||||
msg = f"Failed to clone repository from {repo}"
|
||||
if ref is not None:
|
||||
msg += " (ref {ref})".format(ref=ref)
|
||||
msg += f" (ref {ref})"
|
||||
msg += "."
|
||||
raise ContentProviderException(msg) from error
|
||||
|
||||
|
|
|
@ -5,6 +5,29 @@ from tempfile import TemporaryDirectory
|
|||
import pytest
|
||||
|
||||
from repo2docker.contentproviders import Mercurial
|
||||
from repo2docker.contentproviders.mercurial import (
|
||||
HG_REQUIRED,
|
||||
HG_EVOLVE_REQUIRED,
|
||||
is_mercurial_available,
|
||||
)
|
||||
|
||||
skip_if_no_hg = pytest.mark.skipif(
|
||||
not HG_REQUIRED and not is_mercurial_available(),
|
||||
reason="not HG_REQUIRED and Mercurial not available",
|
||||
)
|
||||
|
||||
|
||||
def is_evolve_available():
|
||||
if not is_mercurial_available():
|
||||
return False
|
||||
output = subprocess.getoutput("hg version -v")
|
||||
return " evolve " in output
|
||||
|
||||
|
||||
EVOLVE_AVAILABLE = is_evolve_available()
|
||||
|
||||
if HG_EVOLVE_REQUIRED and not EVOLVE_AVAILABLE:
|
||||
raise RuntimeError("HG_EVOLVE_REQUIRED and not EVOLVE_AVAILABLE")
|
||||
|
||||
|
||||
def _add_content_to_hg(repo_dir):
|
||||
|
@ -16,6 +39,14 @@ def _add_content_to_hg(repo_dir):
|
|||
subprocess.check_call(["hg", "add", "test"], cwd=repo_dir)
|
||||
subprocess.check_call(["hg", "commit", "-m", "Test commit"], cwd=repo_dir)
|
||||
|
||||
if EVOLVE_AVAILABLE:
|
||||
subprocess.check_call(["hg", "topic", "test-topic"], cwd=repo_dir)
|
||||
subprocess.check_call(
|
||||
["hg", "commit", "-m", "Test commit in topic test-topic"],
|
||||
cwd=repo_dir,
|
||||
)
|
||||
subprocess.check_call(["hg", "up", "default"], cwd=repo_dir)
|
||||
|
||||
|
||||
def _get_node_id(repo_dir):
|
||||
"""Get repository's current commit node ID (currently SHA1)."""
|
||||
|
@ -46,6 +77,7 @@ def hg_repo_with_content(hg_repo):
|
|||
yield hg_repo, node_id
|
||||
|
||||
|
||||
@skip_if_no_hg
|
||||
def test_detect_mercurial(hg_repo_with_content, repo_with_content):
|
||||
mercurial = Mercurial()
|
||||
assert mercurial.detect("this-is-not-a-directory") is None
|
||||
|
@ -58,6 +90,7 @@ def test_detect_mercurial(hg_repo_with_content, repo_with_content):
|
|||
assert mercurial.detect(hg_repo) == {"repo": hg_repo, "ref": None}
|
||||
|
||||
|
||||
@skip_if_no_hg
|
||||
def test_clone(hg_repo_with_content):
|
||||
"""Test simple hg clone to a target dir"""
|
||||
upstream, node_id = hg_repo_with_content
|
||||
|
@ -72,9 +105,10 @@ def test_clone(hg_repo_with_content):
|
|||
assert mercurial.content_id == node_id
|
||||
|
||||
|
||||
@skip_if_no_hg
|
||||
def test_bad_ref(hg_repo_with_content):
|
||||
"""
|
||||
Test trying to checkout a ref that doesn't exist
|
||||
Test trying to update to a ref that doesn't exist
|
||||
"""
|
||||
upstream, node_id = hg_repo_with_content
|
||||
with TemporaryDirectory() as clone_dir:
|
||||
|
@ -82,3 +116,30 @@ def test_bad_ref(hg_repo_with_content):
|
|||
with pytest.raises(ValueError):
|
||||
for _ in Mercurial().fetch(spec, clone_dir):
|
||||
pass
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
not HG_EVOLVE_REQUIRED and not EVOLVE_AVAILABLE,
|
||||
reason="not HG_EVOLVE_REQUIRED and hg-evolve not available",
|
||||
)
|
||||
@skip_if_no_hg
|
||||
def test_ref_topic(hg_repo_with_content):
|
||||
"""
|
||||
Test trying to update to a topic
|
||||
"""
|
||||
upstream, node_id = hg_repo_with_content
|
||||
node_id = subprocess.Popen(
|
||||
["hg", "identify", "-i", "-r", "topic(test-topic)"],
|
||||
stdout=subprocess.PIPE,
|
||||
cwd=upstream,
|
||||
)
|
||||
node_id = node_id.stdout.read().decode().strip()
|
||||
|
||||
with TemporaryDirectory() as clone_dir:
|
||||
spec = {"repo": upstream, "ref": "test-topic"}
|
||||
mercurial = Mercurial()
|
||||
for _ in mercurial.fetch(spec, clone_dir):
|
||||
pass
|
||||
assert (Path(clone_dir) / "test").exists()
|
||||
|
||||
assert mercurial.content_id == node_id
|
||||
|
|
Ładowanie…
Reference in New Issue