2020-09-04 13:14:04 +00:00
|
|
|
import subprocess
|
|
|
|
|
2022-10-31 22:32:14 +00:00
|
|
|
from ..utils import R2dState, execute_cmd
|
2020-09-04 13:14:04 +00:00
|
|
|
from .base import ContentProvider, ContentProviderException
|
|
|
|
|
2020-09-10 19:48:46 +00:00
|
|
|
args_enabling_topic = ["--config", "extensions.topic="]
|
2020-09-10 05:58:21 +00:00
|
|
|
|
2020-09-04 13:14:04 +00:00
|
|
|
|
|
|
|
class Mercurial(ContentProvider):
|
|
|
|
"""Provide contents of a remote Mercurial repository."""
|
|
|
|
|
|
|
|
def detect(self, source, ref=None, extra_args=None):
|
|
|
|
if "github.com/" in source or source.endswith(".git"):
|
|
|
|
return None
|
|
|
|
try:
|
|
|
|
subprocess.check_output(
|
2020-09-10 19:48:46 +00:00
|
|
|
["hg", "identify", source, "--config", "extensions.hggit=!"]
|
|
|
|
+ args_enabling_topic,
|
2020-09-09 16:10:19 +00:00
|
|
|
stderr=subprocess.DEVNULL,
|
2020-09-04 13:14:04 +00:00
|
|
|
)
|
|
|
|
except subprocess.CalledProcessError:
|
|
|
|
return None
|
|
|
|
|
|
|
|
return {"repo": source, "ref": ref}
|
|
|
|
|
|
|
|
def fetch(self, spec, output_dir, yield_output=False):
|
|
|
|
repo = spec["repo"]
|
|
|
|
ref = spec.get("ref", None)
|
|
|
|
|
|
|
|
# make a clone of the remote repository
|
|
|
|
try:
|
2020-09-10 05:58:21 +00:00
|
|
|
cmd = [
|
|
|
|
"hg",
|
|
|
|
"clone",
|
|
|
|
repo,
|
|
|
|
output_dir,
|
|
|
|
"--config",
|
|
|
|
"phases.publish=False",
|
2020-09-10 19:48:46 +00:00
|
|
|
] + args_enabling_topic
|
2020-09-04 13:14:04 +00:00
|
|
|
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
|
|
|
|
cmd.extend(["--noupdate"])
|
2022-10-23 16:09:11 +00:00
|
|
|
yield from execute_cmd(cmd, capture=yield_output)
|
2020-09-04 13:14:04 +00:00
|
|
|
|
|
|
|
except subprocess.CalledProcessError as error:
|
2020-09-10 05:58:21 +00:00
|
|
|
msg = f"Failed to clone repository from {repo}"
|
2020-09-04 13:14:04 +00:00
|
|
|
if ref is not None:
|
2020-09-10 05:58:21 +00:00
|
|
|
msg += f" (ref {ref})"
|
2020-09-04 13:14:04 +00:00
|
|
|
msg += "."
|
|
|
|
raise ContentProviderException(msg) from error
|
|
|
|
|
|
|
|
# check out the specific ref given by the user
|
|
|
|
if ref is not None:
|
|
|
|
try:
|
2022-10-23 16:09:11 +00:00
|
|
|
yield from execute_cmd(
|
2020-09-10 19:48:46 +00:00
|
|
|
["hg", "update", "--clean", ref] + args_enabling_topic,
|
2020-09-04 13:14:04 +00:00
|
|
|
cwd=output_dir,
|
|
|
|
capture=yield_output,
|
2022-10-23 16:09:11 +00:00
|
|
|
)
|
2020-09-04 13:14:04 +00:00
|
|
|
except subprocess.CalledProcessError:
|
|
|
|
self.log.error(
|
2022-10-23 17:18:37 +00:00
|
|
|
f"Failed to update to ref {ref}", extra=dict(phase=R2dState.FAILED)
|
2020-09-04 13:14:04 +00:00
|
|
|
)
|
2022-10-23 16:09:11 +00:00
|
|
|
raise ValueError(f"Failed to update to ref {ref}")
|
2020-09-04 13:14:04 +00:00
|
|
|
|
2020-09-10 19:48:46 +00:00
|
|
|
cmd = ["hg", "identify", "-i"] + args_enabling_topic
|
2020-09-04 13:14:04 +00:00
|
|
|
sha1 = subprocess.Popen(cmd, stdout=subprocess.PIPE, cwd=output_dir)
|
2020-09-07 07:43:22 +00:00
|
|
|
self._node_id = sha1.stdout.read().decode().strip()
|
2020-09-04 13:14:04 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def content_id(self):
|
2020-09-07 07:43:22 +00:00
|
|
|
"""A unique ID to represent the version of the content."""
|
|
|
|
return self._node_id
|