Pull running 'hg pull' instead of using hglib to benefit from Mercurial's default transaction rollback (#1715)

Currently we use hglib, so when we send SIGTERM to the process which is doing the pull, the process is terminated
without error handling and the repository is left in a bad state.
Instead, by using 'hg pull', we benefit from Mercurial's handling of SIGTERM: transaction rollback.

Might help with #1673
This commit is contained in:
Marco Castelluccio 2020-07-24 00:20:52 +02:00 коммит произвёл GitHub
Родитель 256003a052
Коммит f375d686f4
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 25 добавлений и 24 удалений

Просмотреть файл

@ -10,7 +10,6 @@ import itertools
import json
import logging
import math
import multiprocessing
import os
import pickle
import shelve
@ -1092,12 +1091,12 @@ def clean(hg, repo_dir):
raise
def _run_hg_cmd(repo_dir, cmd, *args, **kwargs):
def _build_hg_cmd(cmd, *args, **kwargs):
cmd = hglib.util.cmdbuilder(cmd, *args, **kwargs,)
cmd.insert(0, hglib.HGPATH)
subprocess.run(cmd, cwd=repo_dir, check=True)
return cmd
def clone(
@ -1126,8 +1125,7 @@ def clone(
if "abort: repository" not in str(e) and "not found" not in str(e):
raise
_run_hg_cmd(
None,
cmd = _build_hg_cmd(
"robustcheckout",
url,
repo_dir,
@ -1137,6 +1135,7 @@ def clone(
branch=b"tip",
noupdate=not update,
)
subprocess.run(cmd, check=True)
logger.info(f"{repo_dir} cloned")
@ -1144,27 +1143,27 @@ def clone(
def pull(repo_dir: str, branch: str, revision: str) -> None:
"""Pull a revision from a branch of a remote repository into a local repository"""
def do_pull() -> None:
with hglib.open(repo_dir) as hg:
hg.pull(
source=f"https://hg.mozilla.org/{branch}/".encode("ascii"),
rev=revision.encode("ascii"),
)
@tenacity.retry(
stop=tenacity.stop_after_attempt(3),
reraise=True,
after=tenacity.after_log(logger, logging.DEBUG),
)
def trigger_pull() -> None:
p = multiprocessing.Process(target=do_pull)
p.start()
p.join(60 * 3)
cmd = _build_hg_cmd(
"pull",
f"https://hg.mozilla.org/{branch}/".encode("ascii"),
r=revision.encode("ascii"),
debug=True,
)
if p.is_alive():
p = subprocess.Popen(cmd, cwd=repo_dir)
try:
p.wait(timeout=180)
except subprocess.TimeoutExpired:
p.terminate()
p.join()
raise Exception(f"Timed out while pulling from {branch} after 3 minutes")
p.wait()
raise
trigger_pull()

Просмотреть файл

@ -229,14 +229,16 @@ def mock_repo(tmpdir: py.path.local, monkeypatch: MonkeyPatch) -> Tuple[str, str
# Allow using the local code analysis server.
responses.add_passthru("http://127.0.0.1")
orig_hgclient_pull = hglib.client.hgclient.pull
orig_hgutil_cmdbuilder = hglib.util.cmdbuilder
def hglib_pull(hgclient, source=None, rev=None, update=False):
orig_hgclient_pull(
hgclient, source=str(remote_dir).encode("ascii"), rev=rev, update=update
)
def hglib_cmdbuilder(name, *args, **kwargs):
if name == "pull":
args = list(args)
args[0] = str(remote_dir).encode("ascii")
monkeypatch.setattr(hglib.client.hgclient, "pull", hglib_pull)
return orig_hgutil_cmdbuilder(name, *args, **kwargs)
monkeypatch.setattr(hglib.util, "cmdbuilder", hglib_cmdbuilder)
return local_dir, remote_dir