conftest.py (4434B)
1 # This Source Code Form is subject to the terms of the Mozilla Public 2 # License, v. 2.0. If a copy of the MPL was not distributed with this 3 # file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 5 import os 6 import platform 7 import shutil 8 import subprocess 9 import tempfile 10 from pathlib import Path 11 12 import pytest 13 14 # Execute the first element in each list of steps within a `repo` directory, 15 # then copy the whole directory to a `remoterepo`, and finally execute the 16 # second element on just `repo`. 17 SETUP = { 18 "hg": [ 19 """ 20 echo "foo" > foo 21 echo "bar" > bar 22 hg init 23 hg add * 24 hg commit -m "Initial commit" 25 hg phase --public . 26 """, 27 """ 28 echo [paths] > .hg/hgrc 29 echo "default = ../remoterepo" >> .hg/hgrc 30 """, 31 ], 32 "git": [ 33 """ 34 echo "foo" > foo 35 echo "bar" > bar 36 git init 37 git config user.name "Testing McTesterson" 38 git config user.email "<test@example.org>" 39 git add * 40 git commit -am "Initial commit" 41 """, 42 """ 43 git remote add upstream ../remoterepo 44 git fetch upstream 45 git branch -u upstream/master 46 """, 47 ], 48 "jj": [ 49 """ 50 echo "foo" > foo 51 echo "bar" > bar 52 git init 53 git config user.name "Testing McTesterson" 54 git config user.email "<test@example.org>" 55 git add * 56 git commit -am "Initial commit" 57 jj git init --colocate 58 jj config set --repo user.name "Testing McTesterson" 59 jj config set --repo user.email "test@example.org" 60 jj describe --reset-author --no-edit 61 jj abandon 62 """, 63 """ 64 jj git remote add upstream ../remoterepo 65 jj git fetch --remote upstream 66 jj bookmark track master@upstream 67 """, 68 ], 69 "src": [ 70 """ 71 echo "foo" > foo 72 echo "bar" > bar 73 mkdir config 74 echo 1.0 > config/milestone.txt 75 """, 76 "", 77 ], 78 } 79 80 81 class RepoTestFixture: 82 def __init__(self, repo_dir: Path, vcs: str, steps: list[str]): 83 self.dir = repo_dir 84 self.vcs = vcs 85 86 # This creates a step iterator. Each time execute_next_step() 87 # is called the next set of instructions will be executed. 88 self.steps = (shell(cmd, self.dir) for cmd in steps) 89 90 def execute_next_step(self): 91 next(self.steps) 92 93 94 def shell(cmd, working_dir): 95 for step in cmd.split(os.linesep): 96 subprocess.check_call(step, shell=True, cwd=working_dir) 97 98 99 @pytest.fixture(params=["git", "hg", "jj", "src"]) 100 def repo(request): 101 if request.param == "jj": 102 if os.getenv("MOZ_AUTOMATION") == "1": 103 fetches_dir = os.environ.get("MOZ_FETCHES_DIR", "") 104 jj_dir = Path(fetches_dir) / "jj" 105 if jj_dir.is_dir(): 106 os.environ["PATH"] = os.pathsep.join([str(jj_dir), os.environ["PATH"]]) 107 if platform.system() == "Darwin": 108 pytest.skip( 109 "jj tests disabled for MacOS CI due to incompatible git on workers" 110 ) 111 if os.getenv("MOZ_AVOID_JJ_VCS") not in (None, "0", ""): 112 pytest.skip("jj support disabled") 113 try: 114 subprocess.call(["jj", "--version"], stdout=subprocess.DEVNULL) 115 except OSError: 116 pytest.skip("jj unavailable") 117 118 # Isolate jj tests from user's local config 119 os.environ["JJ_CONFIG"] = "" 120 121 vcs = request.param 122 # Use tempfile since pytest's tempdir is too long for jj on Windows 123 td = tempfile.TemporaryDirectory(prefix=f"{vcs}-repo") 124 tmpdir = Path(td.name) 125 steps = SETUP[vcs] 126 127 if hasattr(request.module, "STEPS"): 128 if vcs == "src" and vcs not in request.module.STEPS: 129 # Special-case SourceRepository: most tests do not handle this case, 130 # so allow it to be skipped if STEPS is defined but not for src. 131 # (Tests without STEPS will need to skip manually.) 132 pytest.skip("not applicable for src repo") 133 steps.extend(request.module.STEPS[vcs]) 134 135 repo_dir = (tmpdir / "repo").resolve() 136 (tmpdir / "repo").mkdir() 137 138 repo_test_fixture = RepoTestFixture(repo_dir, vcs, steps) 139 140 repo_test_fixture.execute_next_step() 141 142 shutil.copytree(str(repo_dir), str(tmpdir / "remoterepo")) 143 144 repo_test_fixture.execute_next_step() 145 146 yield repo_test_fixture