testing: migrate fetchMercurial.sh
Change-Id: Iab81ea161e3be69bf7753b3ed9cd8f59cd8fe0ed
This commit is contained in:
@@ -1,122 +0,0 @@
|
||||
source common.sh
|
||||
|
||||
[[ $(type -p hg) ]] || skipTest "Mercurial not installed"
|
||||
|
||||
clearStore
|
||||
|
||||
# Intentionally not in a canonical form
|
||||
# See https://github.com/NixOS/nix/issues/6195
|
||||
repo=$TEST_ROOT/./hg
|
||||
|
||||
rm -rf $repo ${repo}-tmp $TEST_HOME/.cache/nix
|
||||
|
||||
hg init $repo
|
||||
echo '[ui]' >> $repo/.hg/hgrc
|
||||
echo 'username = Foobar <foobar@example.org>' >> $repo/.hg/hgrc
|
||||
|
||||
# Set ui.tweakdefaults to ensure HGPLAIN is being set.
|
||||
echo 'tweakdefaults = True' >> $repo/.hg/hgrc
|
||||
|
||||
echo utrecht > $repo/hello
|
||||
touch $repo/.hgignore
|
||||
hg add --cwd $repo hello .hgignore
|
||||
hg commit --cwd $repo -m 'Bla1'
|
||||
rev1=$(hg log --cwd $repo -r tip --template '{node}')
|
||||
|
||||
echo world > $repo/hello
|
||||
hg commit --cwd $repo -m 'Bla2'
|
||||
rev2=$(hg log --cwd $repo -r tip --template '{node}')
|
||||
hg --cwd $repo bookmark aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
|
||||
# Fetch an unclean branch.
|
||||
echo unclean > $repo/hello
|
||||
path=$(nix eval --impure --raw --expr "(builtins.fetchMercurial \"file://$repo\").outPath")
|
||||
[[ $(cat $path/hello) = unclean ]]
|
||||
hg revert --cwd $repo --all
|
||||
|
||||
# Fetch the currently checked out revision.
|
||||
path=$(nix eval --impure --raw --expr "(builtins.fetchMercurial \"file://$repo\").outPath")
|
||||
[[ $(cat $path/hello) = world ]]
|
||||
|
||||
# In pure eval mode, fetchMercurial without a revision should fail.
|
||||
[[ $(nix eval --impure --raw --expr "(builtins.readFile (fetchMercurial \"file://$repo\" + \"/hello\"))") = world ]]
|
||||
(! nix eval --raw --expr "builtins.readFile (fetchMercurial \"file://$repo\" + \"/hello\")")
|
||||
|
||||
# Fetch using an explicit revision hash.
|
||||
path2=$(nix eval --impure --raw --expr "(builtins.fetchMercurial { url = \"file://$repo\"; rev = \"$rev2\"; }).outPath")
|
||||
[[ $path = $path2 ]]
|
||||
|
||||
out=$(nix eval --impure --raw --expr "builtins.fetchMercurial { url = \"file://$repo\"; rev = \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"; }" 2>&1) || status=$?
|
||||
[[ $status == 1 ]]
|
||||
[[ $out =~ 'hg failed with exit code' ]]
|
||||
|
||||
# In pure eval mode, fetchMercurial with a revision should succeed.
|
||||
[[ $(nix eval --raw --expr "builtins.readFile (fetchMercurial { url = \"file://$repo\"; rev = \"$rev2\"; } + \"/hello\")") = world ]]
|
||||
|
||||
# Fetch again. This should be cached.
|
||||
mv $repo ${repo}-tmp
|
||||
path2=$(nix eval --impure --raw --expr "(builtins.fetchMercurial \"file://$repo\").outPath")
|
||||
[[ $path = $path2 ]]
|
||||
|
||||
[[ $(nix eval --impure --raw --expr "(builtins.fetchMercurial \"file://$repo\").branch") = default ]]
|
||||
[[ $(nix eval --impure --expr "(builtins.fetchMercurial \"file://$repo\").revCount") = 2 ]]
|
||||
[[ $(nix eval --impure --raw --expr "(builtins.fetchMercurial \"file://$repo\").rev") = $rev2 ]]
|
||||
|
||||
# But with TTL 0, it should fail.
|
||||
(! nix eval --impure --refresh --expr "builtins.fetchMercurial \"file://$repo\"")
|
||||
|
||||
# Fetching with a explicit hash should succeed.
|
||||
path2=$(nix eval --refresh --raw --expr "(builtins.fetchMercurial { url = \"file://$repo\"; rev = \"$rev2\"; }).outPath")
|
||||
[[ $path = $path2 ]]
|
||||
|
||||
path2=$(nix eval --refresh --raw --expr "(builtins.fetchMercurial { url = \"file://$repo\"; rev = \"$rev1\"; }).outPath")
|
||||
[[ $(cat $path2/hello) = utrecht ]]
|
||||
|
||||
mv ${repo}-tmp $repo
|
||||
|
||||
# Using a clean working tree should produce the same result.
|
||||
path2=$(nix eval --impure --raw --expr "(builtins.fetchMercurial \"$repo\").outPath")
|
||||
[[ $path = $path2 ]]
|
||||
|
||||
# Using an unclean tree should yield the tracked but uncommitted changes.
|
||||
mkdir $repo/dir1 $repo/dir2
|
||||
echo foo > $repo/dir1/foo
|
||||
echo bar > $repo/bar
|
||||
echo bar > $repo/dir2/bar
|
||||
hg add --cwd $repo dir1/foo
|
||||
hg rm --cwd $repo hello
|
||||
|
||||
path2=$(nix eval --impure --raw --expr "(builtins.fetchMercurial \"$repo\").outPath")
|
||||
[ ! -e $path2/hello ]
|
||||
[ ! -e $path2/bar ]
|
||||
[ ! -e $path2/dir2/bar ]
|
||||
[ ! -e $path2/.hg ]
|
||||
[[ $(cat $path2/dir1/foo) = foo ]]
|
||||
|
||||
[[ $(nix eval --impure --raw --expr "(builtins.fetchMercurial \"$repo\").rev") = 0000000000000000000000000000000000000000 ]]
|
||||
|
||||
# ... unless we're using an explicit ref.
|
||||
path3=$(nix eval --impure --raw --expr "(builtins.fetchMercurial { url = \"$repo\"; rev = \"default\"; }).outPath")
|
||||
[[ $path = $path3 ]]
|
||||
|
||||
# Committing should not affect the store path.
|
||||
hg commit --cwd $repo -m 'Bla3'
|
||||
|
||||
path4=$(nix eval --impure --refresh --raw --expr "(builtins.fetchMercurial \"file://$repo\").outPath")
|
||||
[[ $path2 = $path4 ]]
|
||||
|
||||
echo paris > $repo/hello
|
||||
# Passing a `name` argument should be reflected in the output path
|
||||
path5=$(nix eval -vvvvv --impure --refresh --raw --expr "(builtins.fetchMercurial { url = \"file://$repo\"; name = \"foo\"; } ).outPath")
|
||||
[[ $path5 =~ -foo$ ]]
|
||||
|
||||
# Fetch the currently checked out revision on a non-default branch.
|
||||
hg branch --cwd $repo meow
|
||||
hg commit --cwd $repo -m 'Bla4'
|
||||
[[ $(nix eval --impure --raw --expr "(builtins.fetchMercurial \"file://$repo\").branch") = meow ]]
|
||||
[[ $(nix eval --impure --expr "(builtins.fetchMercurial \"file://$repo\").revCount") = 4 ]]
|
||||
|
||||
# Fetch an older revision currently checked out.
|
||||
hg update --cwd $repo 2
|
||||
[[ $(nix eval --impure --raw --expr "(builtins.fetchMercurial \"file://$repo\").branch") = default ]]
|
||||
[[ $(nix eval --impure --expr "(builtins.fetchMercurial \"file://$repo\").revCount") = 3 ]]
|
||||
@@ -38,7 +38,6 @@ functional_tests_scripts = [
|
||||
'remote-store.sh',
|
||||
'legacy-ssh-store.sh',
|
||||
'experimental-features.sh',
|
||||
'fetchMercurial.sh',
|
||||
'gc-auto.sh',
|
||||
'user-envs.sh',
|
||||
'binary-cache.sh',
|
||||
|
||||
@@ -0,0 +1,251 @@
|
||||
import dataclasses
|
||||
import shutil
|
||||
import subprocess
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from textwrap import dedent
|
||||
from collections.abc import Callable
|
||||
|
||||
import pytest
|
||||
from testlib.fixtures.env import ManagedEnv
|
||||
from testlib.fixtures.nix import Nix
|
||||
from testlib.fixtures.command import Command
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def common_init(nix: Nix):
|
||||
nix.settings.add_xp_feature("nix-command")
|
||||
nix.env.path.add_program("hg")
|
||||
|
||||
|
||||
@dataclass
|
||||
class HgRepo:
|
||||
path: Path
|
||||
rev1: str
|
||||
rev2: str
|
||||
|
||||
@property
|
||||
def uri(self) -> str:
|
||||
# Intentionally not in a canonical form
|
||||
# See https://github.com/NixOS/nix/issues/6195
|
||||
return f'"file://{self.path.parent}/./{self.path.name}"'
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def static_hg_repo(tmp_path_factory: pytest.TempPathFactory) -> HgRepo:
|
||||
"""
|
||||
create a static mercurial repo with our default settings because hg is *so slow*
|
||||
"""
|
||||
repo = tmp_path_factory.mktemp("hg")
|
||||
|
||||
subprocess.check_call(["hg", "init", repo])
|
||||
(repo / ".hg/hgrc").write_text(
|
||||
dedent("""
|
||||
[ui]
|
||||
username = Foobar <foobar@example.org>
|
||||
|
||||
# Set ui.tweakdefaults to ensure HGPLAIN is being set.
|
||||
tweakdefaults = True
|
||||
""")
|
||||
)
|
||||
|
||||
(repo / "hello").write_text("utrecht")
|
||||
(repo / ".hgignore").touch()
|
||||
subprocess.check_call(["hg", "add", "--cwd", repo, "hello", ".hgignore"])
|
||||
subprocess.check_call(["hg", "commit", "--cwd", repo, "-m", "Bla1"])
|
||||
rev1 = (
|
||||
subprocess.run(
|
||||
["hg", "log", "--cwd", repo, "-r", "tip", "--template", "{node}"],
|
||||
stdout=subprocess.PIPE,
|
||||
check=True,
|
||||
)
|
||||
.stdout.strip()
|
||||
.decode("utf8", errors="replace")
|
||||
)
|
||||
|
||||
(repo / "hello").write_text("world")
|
||||
subprocess.check_call(["hg", "commit", "--cwd", repo, "-m", "Bla2"])
|
||||
rev2 = (
|
||||
subprocess.run(
|
||||
["hg", "log", "--cwd", repo, "-r", "tip", "--template", "{node}"],
|
||||
stdout=subprocess.PIPE,
|
||||
check=True,
|
||||
)
|
||||
.stdout.strip()
|
||||
.decode("utf8", errors="replace")
|
||||
)
|
||||
|
||||
subprocess.check_call(
|
||||
["hg", "--cwd", repo, "bookmark", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]
|
||||
)
|
||||
|
||||
return HgRepo(repo, rev1, rev2)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def hg(static_hg_repo: HgRepo, env: ManagedEnv) -> HgRepo:
|
||||
repo = env.dirs.home / "hg"
|
||||
shutil.copytree(static_hg_repo.path, repo)
|
||||
return dataclasses.replace(static_hg_repo, path=repo)
|
||||
|
||||
|
||||
def test_fetch_unclean(hg: HgRepo, nix: Nix):
|
||||
(hg.path / "hello").write_text("unclean")
|
||||
result = (
|
||||
nix.nix(
|
||||
["eval", "--impure", "--raw", "--expr", f"(builtins.fetchMercurial {hg.uri}).outPath"]
|
||||
)
|
||||
.run()
|
||||
.ok()
|
||||
)
|
||||
assert "is unclean" in result.stderr_plain
|
||||
assert (Path(result.stdout_plain) / "hello").read_text() == "unclean"
|
||||
|
||||
|
||||
def test_fetch_current_rev(hg: HgRepo, nix: Nix):
|
||||
expr = f"(builtins.fetchMercurial {hg.uri}).outPath"
|
||||
result = nix.nix(["eval", "--impure", "--raw", "--expr", expr]).run().ok()
|
||||
assert (Path(result.stdout_plain) / "hello").read_text() == "world"
|
||||
|
||||
|
||||
def test_pure_fetch_without_rev(hg: HgRepo, nix: Nix):
|
||||
expr = f'builtins.readFile (builtins.fetchMercurial {hg.uri} + "/hello")'
|
||||
result = nix.nix(["eval", "--raw", "--expr", expr]).run().expect(1)
|
||||
assert (
|
||||
"error: in pure evaluation mode, 'fetchMercurial' requires a Mercurial revision"
|
||||
in result.stderr_s
|
||||
)
|
||||
|
||||
|
||||
def test_pure_fetch_with_good_rev(hg: HgRepo, nix: Nix):
|
||||
expr = f'(builtins.fetchMercurial {{ url = {hg.uri}; rev = "{hg.rev2}"; }}).outPath'
|
||||
result = nix.nix(["eval", "--raw", "--expr", expr]).run().ok()
|
||||
assert (Path(result.stdout_plain) / "hello").read_text() == "world"
|
||||
|
||||
|
||||
def test_pure_fetch_with_bad_rev(hg: HgRepo, nix: Nix):
|
||||
expr = f'(builtins.fetchMercurial {{ url = {hg.uri}; rev = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; }}).outPath'
|
||||
result = nix.nix(["eval", "--raw", "--expr", expr]).run().expect(1)
|
||||
assert "hg failed with exit code" in result.stderr_s
|
||||
|
||||
|
||||
def test_fetch_attrs(hg: HgRepo, nix: Nix):
|
||||
expr = f'builtins.removeAttrs (builtins.fetchMercurial {{ url = {hg.uri}; rev = "{hg.rev2}"; }}) [ "outPath" ]'
|
||||
result = nix.nix(["eval", "--impure", "--json", "--expr", expr]).run().json()
|
||||
assert result["branch"] == "default"
|
||||
assert result["revCount"] == 2
|
||||
assert result["rev"] == hg.rev2
|
||||
|
||||
|
||||
def test_caching(hg: HgRepo, nix: Nix):
|
||||
expr = f"(builtins.fetchMercurial {hg.uri}).outPath"
|
||||
path1 = nix.nix(["eval", "--impure", "--raw", "--expr", expr]).run().ok().stdout_plain
|
||||
shutil.rmtree(hg.path)
|
||||
path2 = nix.nix(["eval", "--impure", "--raw", "--expr", expr]).run().ok().stdout_plain
|
||||
assert path1 == path2
|
||||
assert (Path(path2) / "hello").read_text() == "world"
|
||||
|
||||
# with TTL 0 refetch should fail
|
||||
result = nix.nix(["eval", "--impure", "--refresh", "--expr", expr]).run().expect(1)
|
||||
assert "error: 'hg pull' failed" in result.stderr_s
|
||||
|
||||
|
||||
class TestExplicitHashes:
|
||||
def test_rev2(self, hg: HgRepo, nix: Nix):
|
||||
expr = f'(builtins.fetchMercurial {{ url = {hg.uri}; rev = "{hg.rev2}"; }}).outPath'
|
||||
path1 = nix.nix(["eval", "--raw", "--expr", expr]).run().ok().stdout_plain
|
||||
shutil.rmtree(hg.path)
|
||||
path2 = nix.nix(["eval", "--refresh", "--raw", "--expr", expr]).run().ok().stdout_plain
|
||||
assert path1 == path2
|
||||
|
||||
def test_rev1(self, hg: HgRepo, nix: Nix):
|
||||
expr = f'(builtins.fetchMercurial {{ url = {hg.uri}; rev = "{hg.rev1}"; }}).outPath'
|
||||
path2 = nix.nix(["eval", "--refresh", "--raw", "--expr", expr]).run().ok().stdout_plain
|
||||
assert (Path(path2) / "hello").read_text() == "utrecht"
|
||||
|
||||
|
||||
class TestFetchDirt:
|
||||
@pytest.fixture(scope="class")
|
||||
def static_changed_repo(
|
||||
self, static_hg_repo: HgRepo, tmp_path_factory: pytest.TempPathFactory
|
||||
) -> HgRepo:
|
||||
repo = tmp_path_factory.mktemp("hg-changed")
|
||||
shutil.copytree(static_hg_repo.path, repo, dirs_exist_ok=True)
|
||||
|
||||
for name in ["dir1", "dir2"]:
|
||||
(repo / name).mkdir()
|
||||
(repo / "dir1/foo").write_text("foo")
|
||||
(repo / "bar").write_text("bar")
|
||||
(repo / "dir2/bar").write_text("bar")
|
||||
subprocess.check_call(["hg", "add", "--cwd", repo, "dir1/foo"])
|
||||
subprocess.check_call(["hg", "rm", "--cwd", repo, "hello"])
|
||||
|
||||
return dataclasses.replace(static_hg_repo, path=repo)
|
||||
|
||||
# this intentionally overrides the module-level fixture name
|
||||
@pytest.fixture
|
||||
def hg(self, static_changed_repo: HgRepo, env: ManagedEnv) -> HgRepo:
|
||||
repo = env.dirs.home / "hg"
|
||||
shutil.copytree(static_changed_repo.path, repo)
|
||||
return dataclasses.replace(static_changed_repo, path=repo)
|
||||
|
||||
def test_fetch_simple(self, hg: HgRepo, nix: Nix, command: Callable[..., Command]):
|
||||
expr = f"""
|
||||
let f = builtins.fetchMercurial {hg.uri};
|
||||
in {{ path = f.outPath; rev = f.rev; }}
|
||||
"""
|
||||
result = nix.nix(["eval", "--impure", "--json", "--expr", expr]).run().json()
|
||||
path = Path(result["path"])
|
||||
assert not (path / "hello").exists()
|
||||
assert not (path / "bar").exists()
|
||||
assert not (path / "dir2/bar").exists()
|
||||
assert (path / "dir1/foo").read_text() == "foo"
|
||||
assert result["rev"] == "0000000000000000000000000000000000000000"
|
||||
|
||||
command(["hg", "commit", "--cwd", hg.path, "-m", "Bla3"]).run().ok()
|
||||
result2 = nix.nix(["eval", "--impure", "--json", "--expr", expr]).run().json()
|
||||
assert result["path"] == result2["path"]
|
||||
|
||||
def test_fetch_rev(self, hg: HgRepo, nix: Nix):
|
||||
expr = f"""
|
||||
let f = builtins.fetchMercurial {{ url = {hg.uri}; rev = "default"; }};
|
||||
in {{ path = f.outPath; rev = f.rev; }}
|
||||
"""
|
||||
result = nix.nix(["eval", "--impure", "--json", "--expr", expr]).run().json()
|
||||
path = Path(result["path"])
|
||||
assert (path / "hello").exists()
|
||||
assert not (path / "bar").exists()
|
||||
assert not (path / "dir2/bar").exists()
|
||||
assert not (path / "dir1/foo").exists()
|
||||
assert result["rev"] == hg.rev2
|
||||
|
||||
|
||||
def test_fetch_with_name(hg: HgRepo, nix: Nix):
|
||||
"""Passing a `name` argument should be reflected in the output path"""
|
||||
(hg.path / "hello").write_text("paris")
|
||||
expr = f'(builtins.fetchMercurial {{ url = {hg.uri}; name = "foo"; }}).outPath'
|
||||
path = (
|
||||
nix.nix(["eval", "--impure", "--refresh", "--raw", "--expr", expr]).run().ok().stdout_plain
|
||||
)
|
||||
assert path.endswith("-foo")
|
||||
|
||||
|
||||
class TestNondefaultBranch:
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup(self, hg: HgRepo, command: Callable[..., Command]):
|
||||
(hg.path / "hello").write_text("paris")
|
||||
command(["hg", "branch", "--cwd", hg.path, "meow"]).run().ok()
|
||||
command(["hg", "commit", "--cwd", hg.path, "-m", "Bla3"]).run().ok()
|
||||
|
||||
def test_simple(self, hg: HgRepo, nix: Nix):
|
||||
expr = f'builtins.removeAttrs (builtins.fetchMercurial {hg.uri}) [ "outPath" ]'
|
||||
result = nix.nix(["eval", "--impure", "--json", "--expr", expr]).run().json()
|
||||
assert result["branch"] == "meow"
|
||||
assert result["revCount"] == 3
|
||||
|
||||
def test_older_rev(self, hg: HgRepo, nix: Nix, command: Callable[..., Command]):
|
||||
command(["hg", "update", "--cwd", hg.path, "1"]).run().ok()
|
||||
expr = f'builtins.removeAttrs (builtins.fetchMercurial {hg.uri}) [ "outPath" ]'
|
||||
result = nix.nix(["eval", "--impure", "--json", "--expr", expr]).run().json()
|
||||
assert result["branch"] == "default"
|
||||
assert result["revCount"] == 2
|
||||
Reference in New Issue
Block a user