This gives functions greater control over the behaviour of the subprocess call via `**runargs`. This also removes the _process_run_args helper which was just adding complexity more than anything. Differential Revision: https://phabricator.services.mozilla.com/D309177
272 lines
7.6 KiB
Python
272 lines
7.6 KiB
Python
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
# License, v. 2.0. If a copy of the MPL was not distributed with this,
|
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
import subprocess
|
|
import unittest.mock
|
|
|
|
import mozunit
|
|
import pytest
|
|
|
|
from mozversioncontrol import get_repository_object
|
|
|
|
STEPS = {
|
|
"hg": [
|
|
"""
|
|
echo "second" > second
|
|
hg add second
|
|
hg commit -m "second commit"
|
|
""",
|
|
],
|
|
"git": [
|
|
"""
|
|
echo "second" > second
|
|
git add second
|
|
git commit -m "second commit"
|
|
""",
|
|
],
|
|
"jj": [
|
|
"""
|
|
echo "second" > second
|
|
jj commit -m "second commit"
|
|
jj bookmark create test-bookmark -r @-
|
|
jj bookmark track test-bookmark --remote upstream
|
|
""",
|
|
],
|
|
}
|
|
|
|
|
|
def verify_push_succeeded(repo):
|
|
if repo.vcs == "hg":
|
|
result = subprocess.run(
|
|
["hg", "log", "-r", "tip", "-T", "{desc}"],
|
|
cwd=str(repo.dir.parent / "remoterepo"),
|
|
capture_output=True,
|
|
text=True,
|
|
check=True,
|
|
)
|
|
assert "second commit" in result.stdout
|
|
elif repo.vcs == "git":
|
|
subprocess.run(
|
|
["git", "fetch"],
|
|
cwd=str(repo.dir.parent / "remoterepo"),
|
|
check=True,
|
|
)
|
|
result = subprocess.run(
|
|
["git", "log", "master", "-1", "--format=%s"],
|
|
cwd=str(repo.dir.parent / "remoterepo"),
|
|
capture_output=True,
|
|
text=True,
|
|
check=True,
|
|
)
|
|
assert "second commit" in result.stdout
|
|
elif repo.vcs == "jj":
|
|
subprocess.run(
|
|
["jj", "git", "fetch", "--remote", "upstream"],
|
|
cwd=str(repo.dir),
|
|
check=True,
|
|
)
|
|
result = subprocess.run(
|
|
[
|
|
"jj",
|
|
"bookmark",
|
|
"list",
|
|
"--remote",
|
|
"upstream",
|
|
"test-bookmark",
|
|
],
|
|
cwd=str(repo.dir),
|
|
capture_output=True,
|
|
text=True,
|
|
check=True,
|
|
)
|
|
assert "second commit" in result.stdout
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"remote,ref,kwargs",
|
|
[
|
|
pytest.param(None, None, {}, id="no_args"),
|
|
pytest.param("remote", None, {}, id="with_remote"),
|
|
pytest.param("remote", "ref", {}, id="with_remote_and_ref"),
|
|
pytest.param("remote", "ref", {"force": True}, id="with_force"),
|
|
],
|
|
)
|
|
def test_push(repo, remote, ref, kwargs):
|
|
vcs = get_repository_object(repo.dir)
|
|
|
|
repo.execute_next_step()
|
|
|
|
if remote == "remote":
|
|
if repo.vcs == "hg":
|
|
remote = "../remoterepo"
|
|
elif repo.vcs == "git":
|
|
remote = "upstream"
|
|
elif repo.vcs == "jj":
|
|
remote = "upstream"
|
|
|
|
if ref == "ref":
|
|
if repo.vcs == "hg":
|
|
ref = "."
|
|
elif repo.vcs == "git":
|
|
ref = "master"
|
|
elif repo.vcs == "jj":
|
|
ref = "test-bookmark"
|
|
|
|
if ref is None and repo.vcs == "jj":
|
|
pytest.skip("jj requires a bookmark ref to push")
|
|
|
|
vcs.push(remote=remote, ref=ref, **kwargs)
|
|
verify_push_succeeded(repo)
|
|
|
|
|
|
def test_push_ref_without_remote_raises(repo):
|
|
vcs = get_repository_object(repo.dir)
|
|
|
|
with pytest.raises(
|
|
ValueError, match="Cannot specify ref without specifying remote"
|
|
):
|
|
vcs.push(ref="some-ref")
|
|
|
|
|
|
def test_jj_push_url_to_name_translation(repo):
|
|
"""Test that jj translates git URLs to remote names"""
|
|
if repo.vcs != "jj":
|
|
pytest.skip("Only relevant for jj repos")
|
|
|
|
vcs = get_repository_object(repo.dir)
|
|
repo.execute_next_step()
|
|
|
|
# Get the actual remote URL
|
|
result = subprocess.run(
|
|
["jj", "git", "remote", "list"],
|
|
cwd=str(repo.dir),
|
|
capture_output=True,
|
|
text=True,
|
|
check=True,
|
|
)
|
|
|
|
# Extract the upstream URL from output
|
|
for line in result.stdout.strip().splitlines():
|
|
if line.startswith("upstream "):
|
|
upstream_url = line.split(" ", 1)[1]
|
|
break
|
|
|
|
# Push using URL should work (it gets translated to "upstream")
|
|
vcs.push(remote=upstream_url, ref="test-bookmark")
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"with_dest",
|
|
[False, True],
|
|
)
|
|
def test_push_dest_branch(repo, with_dest):
|
|
if repo.vcs == "hg":
|
|
pytest.skip("Mercurial ignores dest_branch")
|
|
|
|
vcs = get_repository_object(repo.dir)
|
|
|
|
if not with_dest:
|
|
with pytest.raises(
|
|
ValueError, match="Cannot specify dest_branch without specifying ref"
|
|
):
|
|
vcs.push(remote="upstream", dest_branch="try")
|
|
return
|
|
|
|
repo.execute_next_step()
|
|
|
|
if repo.vcs == "git":
|
|
vcs.push(remote="upstream", ref="HEAD", dest_branch="try")
|
|
subprocess.run(
|
|
["git", "fetch"],
|
|
cwd=str(repo.dir.parent / "remoterepo"),
|
|
check=True,
|
|
)
|
|
result = subprocess.run(
|
|
["git", "log", "try", "-1", "--format=%s"],
|
|
cwd=str(repo.dir.parent / "remoterepo"),
|
|
capture_output=True,
|
|
text=True,
|
|
check=True,
|
|
)
|
|
assert "second commit" in result.stdout
|
|
elif repo.vcs == "jj":
|
|
change_id = vcs._resolve_to_change("test-bookmark")
|
|
subprocess.run(
|
|
["jj", "bookmark", "create", "try", "-r", change_id],
|
|
cwd=str(repo.dir),
|
|
check=True,
|
|
)
|
|
subprocess.run(
|
|
["jj", "bookmark", "track", "try", "--remote", "upstream"],
|
|
cwd=str(repo.dir),
|
|
check=True,
|
|
)
|
|
vcs.push(remote="upstream", ref="test-bookmark", dest_branch="try")
|
|
subprocess.run(
|
|
["jj", "git", "fetch", "--remote", "upstream"],
|
|
cwd=str(repo.dir),
|
|
check=True,
|
|
)
|
|
result = subprocess.run(
|
|
["jj", "bookmark", "list", "--remote", "upstream", "try"],
|
|
cwd=str(repo.dir),
|
|
capture_output=True,
|
|
text=True,
|
|
check=True,
|
|
)
|
|
assert "second commit" in result.stdout
|
|
|
|
|
|
def test_jj_push_change_id_with_dest_branch(repo):
|
|
"""Simulate push_to_try: a change ID as ref is resolved to a commit SHA
|
|
when dest_branch is set, allowing git to push it to a named remote branch.
|
|
"""
|
|
if repo.vcs != "jj":
|
|
pytest.skip("Only relevant for jj repos")
|
|
|
|
vcs = get_repository_object(repo.dir)
|
|
repo.execute_next_step()
|
|
|
|
change_id = vcs._resolve_to_change(vcs.HEAD_REVSET)
|
|
vcs.push(remote="upstream", ref=change_id, dest_branch="test-bookmark")
|
|
|
|
subprocess.run(
|
|
["jj", "git", "fetch", "--remote", "upstream"],
|
|
cwd=str(repo.dir),
|
|
check=True,
|
|
)
|
|
result = subprocess.run(
|
|
["jj", "bookmark", "list", "--remote", "upstream", "test-bookmark"],
|
|
cwd=str(repo.dir),
|
|
capture_output=True,
|
|
text=True,
|
|
check=True,
|
|
)
|
|
assert "second commit" in result.stdout
|
|
|
|
|
|
def test_push_env_passthrough(repo):
|
|
if repo.vcs in ("hg", "src"):
|
|
pytest.skip("env passthrough not supported for this VCS")
|
|
|
|
vcs = get_repository_object(repo.dir)
|
|
repo.execute_next_step()
|
|
|
|
if repo.vcs == "git":
|
|
remote, ref = "upstream", "master"
|
|
elif repo.vcs == "jj":
|
|
remote, ref = "upstream", "test-bookmark"
|
|
|
|
with unittest.mock.patch("mozversioncontrol.repo.base.subprocess.run") as mock_run:
|
|
mock_run.return_value.stdout = ""
|
|
vcs.push(remote=remote, ref=ref, env={"MVC_TEST_VAR": "sentinel"})
|
|
|
|
mock_run.assert_called_once()
|
|
passed_env = mock_run.call_args[1]["env"]
|
|
assert passed_env.get("MVC_TEST_VAR") == "sentinel"
|
|
|
|
|
|
if __name__ == "__main__":
|
|
mozunit.main()
|