def test_sync_not_on_master( tsrc_cli: CLI, git_server: GitServer, workspace_path: Path, message_recorder: MessageRecorder, ) -> None: """ " Scenario: * Create a manifest with two repos, foo and bar * Initialize a workspace from this manifest * Checkout a different branch on foo, tracking an existing remote * Run `tsrc sync` * Check that: * foo is updated * but the command fails because foo was not an the expected branch """ git_server.add_repo("foo") git_server.add_repo("bar") git_server.push_file("foo", "devel.txt", branch="devel") manifest_url = git_server.manifest_url tsrc_cli.run("init", manifest_url) foo_path = workspace_path / "foo" tsrc.git.run(foo_path, "checkout", "-B", "devel") tsrc.git.run(foo_path, "branch", "--set-upstream-to", "origin/devel") tsrc_cli.run_and_fail("sync") assert (foo_path / "devel.txt").exists(), "foo should have been updated" assert message_recorder.find("not on the correct branch")
def test_apply_manifest_adds_new_repo(tsrc_cli: CLI, git_server: GitServer, workspace_path: Path) -> None: """Scenario: * Create a manifest with one repo * Create a workspace using `tsrc init` * Copy the manifest file somewhere in the workspace * Create a new repo on the server * Edit the copied manifest to contain the new repo * Run `tsrc apply-manifest /path/to/copied_manifest` * Check that the new repo gets cloned """ git_server.add_repo("foo") tsrc_cli.run("init", git_server.manifest_url) cloned_manifest_path = workspace_path / ".tsrc/manifest/manifest.yml" copied_manifest_path = workspace_path / "manifest.yml" shutil.copy(cloned_manifest_path, copied_manifest_path) bar_url = git_server.add_repo("bar", add_to_manifest=False) add_repo_to_manifest(copied_manifest_path, "bar", bar_url) tsrc_cli.run("apply-manifest", str(copied_manifest_path)) assert (workspace_path / "bar").exists(), "bar repo should have been cloned"
def test_sync_with_errors( tsrc_cli: CLI, git_server: GitServer, workspace_path: Path, message_recorder: MessageRecorder, ) -> None: """ " Scenario: * Create a manifest with two repos (foo and bar) * Initialize a workspace from this manifest * Push a new file to the foo repo * Create a merge conflict in the foo repo * Run `tsrc sync` * Check that it fails and contains the proper error message """ git_server.add_repo("foo") git_server.add_repo("bar") manifest_url = git_server.manifest_url tsrc_cli.run("init", manifest_url) git_server.push_file("foo", "conflict.txt", contents="this is red") foo_src = workspace_path / "foo" (foo_src / "conflict.txt").write_text("this is green") tsrc_cli.run_and_fail("sync") assert message_recorder.find("Failed to synchronize workspace") assert message_recorder.find(r"\* foo")
def test_switching_manifest_branch( tsrc_cli: CLI, git_server: GitServer, workspace_path: Path ) -> None: """Scenario: * Initialize a new workspace with a manifest on the master branch * Create a new repo bar, on the 'devel' branch of the manifest * Run `tsrc sync`: bar should not get cloned * Configure the workspace to use the `devel` branch of the manifest * Run `tsrc sync` again * Check that bar is cloned """ git_server.add_repo("foo") tsrc_cli.run("init", git_server.manifest_url) git_server.manifest.change_branch("devel") git_server.add_repo("bar") bar_path = workspace_path / "bar" tsrc_cli.run("sync") assert not bar_path.exists(), "bar should not have been cloned" change_workspace_manifest_branch(workspace_path, "devel") tsrc_cli.run("sync") assert bar_path.exists(), "bar should have been cloned"
def test_sync_uses_group_from_config_by_default( tsrc_cli: CLI, git_server: GitServer, workspace_path: Path ) -> None: """Scenario: * Create a manifest containing: * a group named 'foo' containing the repos 'bar' and 'baz' * a repo named 'other' not in any group * Initialize a workspace from this manifest using the `foo` group * Check that bar and baz are cloned * Check that `other` is not cloned """ git_server.add_group("foo", ["bar", "baz"]) git_server.add_repo("other") tsrc_cli.run("init", git_server.manifest_url, "--group", "foo") tsrc_cli.run("sync") assert ( workspace_path / "bar" ).exists(), "bar should have been cloned (in foo group)" assert ( workspace_path / "baz" ).exists(), "baz should have been cloned (in foo group)" assert not ( workspace_path / "other" ).exists(), "other should not have been cloned (not in foo group)"
def test_foreach_with_all_cloned_repos_requested( tsrc_cli: CLI, git_server: GitServer, workspace_path: Path, message_recorder: MessageRecorder, ) -> None: """ * Create a manifest containing: * a group named `foo` with repos `bar` and `baz`, * a group named `spam` with repos `eggs` and `beacon` * a repo named `quux`, not part of any group * Initialize a workspace from this manifest, using the `foo` group * Force the clone of the `other` repo * Check that `tsrc foreach --all-cloned` visits all repos """ git_server.add_group("foo", ["bar", "baz"]) git_server.add_group("spam", ["eggs", "bacon"]) quux_url = git_server.add_repo("quux") manifest_url = git_server.manifest_url tsrc_cli.run("init", manifest_url, "--groups", "foo", "spam") tsrc.git.run(workspace_path, "clone", quux_url) message_recorder.reset() tsrc_cli.run("foreach", "--all-cloned", "ls") assert message_recorder.find("bar\n") assert message_recorder.find("baz\n") assert message_recorder.find("eggs\n") assert message_recorder.find("bacon\n") assert message_recorder.find("quux\n")
def test_empty_repo(tsrc_cli: CLI, git_server: GitServer, workspace_path: Path) -> None: git_server.add_repo("foo", empty=True) git_server.add_repo("bar") manifest_url = git_server.manifest_url tsrc_cli.run("init", manifest_url, expect_fail=True)
def test_can_use_new_group( tsrc_cli: CLI, git_server: GitServer, workspace_path: Path ) -> None: """Scenario: * Create a manifest containing: * a group named 'default' containing the repos 'foo' and 'bar' * Initialize a workspace from this manifest using the default group * Create a new group 'group1' containing just 'foo' * Push a new file to 'foo' and 'bar' * Run `tsrc sync --group 'group1' * Check only `foo` is updated """ git_server.add_group("default", ["foo", "bar"]) tsrc_cli.run("init", git_server.manifest_url) git_server.manifest.configure_group("group1", ["foo"]) git_server.push_file("foo", "foo.txt") git_server.push_file("bar", "bar.txt") tsrc_cli.run("sync", "--group", "group1") assert ( workspace_path / "foo/foo.txt" ).exists(), "foo should have been updated - included in the 'group1 group" assert not ( workspace_path / "bar/bar.txt" ).exists(), ( "bar should not have been updated - not included in the 'group1 group" )
def test_use_given_group( tsrc_cli: CLI, git_server: GitServer, workspace_path: Path, message_recorder: MessageRecorder, ) -> None: """Scenario: * Create a manifest with two disjoint groups, group1 and group2 * Initialize a workspace from this manifest using the two groups * Run `tsrc status --group group1` * Check that the output contains repos from group1, but not from group2 """ git_server.add_group("group1", ["foo"]) git_server.add_group("group2", ["bar"]) manifest_url = git_server.manifest_url tsrc_cli.run("init", manifest_url, "--groups", "group1", "group2") message_recorder.reset() tsrc_cli.run("status", "--group", "group1") assert message_recorder.find(r"\* foo"), "foo status have been read" assert not message_recorder.find(r"\* bar"), "bar should have been skipped"
def test_status_incorrect_branch( tsrc_cli: CLI, git_server: GitServer, workspace_path: Path, message_recorder: MessageRecorder, ) -> None: """Scenario: * Create a workspace with one repo * Create and checkout an 'other' branch * Run `tsrc status` * Check that the repo is shown as not being on the correct branch """ git_server.add_repo("foo") manifest_url = git_server.manifest_url tsrc_cli.run("init", manifest_url) foo_path = workspace_path / "foo" run_git(foo_path, "checkout", "-b", "other") run_git(foo_path, "push", "--set-upstream", "origin", "other:other") tsrc_cli.run("status") assert message_recorder.find(r"\* foo\s+other\s+\(expected: master\)")
def test_status_with_missing_repos( tsrc_cli: CLI, git_server: GitServer, workspace_path: Path, message_recorder: MessageRecorder, ) -> None: """Scenario: * Create a manifest with two repos, foo and bar * Initialize a workspace from this manifest * Remove the `foo` clone * Run `tsrc status` * Check that it does not crash """ git_server.add_repo("foo") git_server.add_repo("bar") manifest_url = git_server.manifest_url tsrc_cli.run("init", manifest_url) # shutil.rmtree has trouble removing read-only # files in the .git repo, but this won't affect # the outcome of the test anyway shutil.rmtree(workspace_path / "foo", ignore_errors=True) tsrc_cli.run("status")
def test_init_with_args( tsrc_cli: CLI, git_server: GitServer, monkeypatch: Any, tmp_path: Path ) -> None: git_server.add_repo("foo") work2_path = (tmp_path / "work2").mkdir() tsrc_cli.run("init", "--workspace", work2_path, git_server.manifest_url) assert_cloned(work2_path, "foo")
def test_can_add_copies(workspace_path: Path, git_server: GitServer) -> None: git_server.add_repo("foo") git_server.manifest.set_file_copy("foo", "foo.txt", "top.txt") manifest = read_remote_manifest(workspace_path, git_server) assert manifest.file_system_operations == [ tsrc.Copy("foo", "foo.txt", "top.txt") ]
def test_set_project_dest_and_branch( tsrc_cli: CLI, git_server: GitServer, workspace_path: Path ) -> None: git_server.add_repo("foo") git_server.add_repo("bar", default_branch="devel") tsrc_cli.run("init", git_server.manifest_url) bar_path = workspace_path / "bar" run_git(bar_path, "checkout", "-b", "other") workspace = Workspace(workspace_path) manifest = workspace.get_manifest() env_setter = EnvSetter(workspace) workspace_vars = get_workspace_vars(workspace) assert workspace_vars["TSRC_MANIFEST_URL"] == git_server.manifest_url assert workspace_vars["TSRC_MANIFEST_BRANCH"] == "master" assert workspace_vars["TSRC_WORKSPACE_PATH"] == str(workspace_path) foo_repo = manifest.get_repo("foo") foo_env = env_setter.get_env_for_repo(foo_repo) # check that shared env is part of the result for foo assert foo_env["TSRC_MANIFEST_URL"] == git_server.manifest_url assert foo_env["TSRC_PROJECT_CLONE_URL"] == foo_repo.clone_url # check that bar and foo envs are different bar_repo = manifest.get_repo("bar") bar_env = env_setter.get_env_for_repo(bar_repo) assert bar_env["TSRC_PROJECT_DEST"] == "bar" assert bar_env["TSRC_PROJECT_MANIFEST_BRANCH"] == "devel" # check that git status is set assert bar_env["TSRC_PROJECT_STATUS_BRANCH"] == "other"
def test_sync_with_force( tsrc_cli: CLI, git_server: GitServer, workspace_path: Path ) -> None: """ Scenario: * Create a manifest with one repo, foo * Create a tag `latest` on foo * Initialize a workspace from this manifest * Delete and re-create the `latest` tag * Run tsrc sync --force * Check that the clone was reset to the correct revision (aka, `git fetch --force` was called). """ git_server.add_repo("foo") git_server.push_file("foo", "latest.txt", contents="1") git_server.tag("foo", "latest") tsrc_cli.run("init", git_server.manifest_url) git_server.push_file("foo", "latest.txt", contents="2") git_server.tag("foo", "latest", force=True) tsrc_cli.run("sync", "--force") foo_path = workspace_path / "foo" assert ( foo_path / "latest.txt" ).read_text() == "2", "foo should have been reset to the latest tag"
def test_can_set_remote_head(tmp_path: Path, git_server: GitServer) -> None: git_server.add_repo("foo") git_server.manifest.change_branch("main") git_server.manifest.set_head("main") run_git(tmp_path, "clone", git_server.manifest_url, "manifest") assert get_current_branch(tmp_path / "manifest") == "main"
def test_repo_default_branch_not_master(tsrc_cli: CLI, git_server: GitServer, workspace_path: Path) -> None: git_server.add_repo("foo", default_branch="devel") tsrc_cli.run("init", git_server.manifest_url) foo_path = workspace_path / "foo" assert tsrc.git.get_current_branch(foo_path) == "devel"
def test_git_server_change_repo_branch(workspace_path: Path, git_server: GitServer) -> None: foo_url = git_server.add_repo("foo") git_server.change_repo_branch("foo", "devel") git_server.push_file("foo", "devel.txt", contents="this is devel\n") tsrc.git.run(workspace_path, "clone", foo_url, "--branch", "devel") foo_path = workspace_path / "foo" assert (foo_path / "devel.txt").text() == "this is devel\n"
def test_init_simple(tsrc_cli: CLI, git_server: GitServer, workspace_path: Path) -> None: git_server.add_repo("foo/bar") git_server.add_repo("spam/eggs") manifest_url = git_server.manifest_url tsrc_cli.run("init", manifest_url) assert_cloned(workspace_path, "foo/bar") assert_cloned(workspace_path, "spam/eggs")
def test_clone_destination_is_a_file(tsrc_cli: CLI, git_server: GitServer, workspace_path: Path) -> None: manifest_url = git_server.manifest_url git_server.add_repo("foo") with (workspace_path / "foo").open("w") as f: f.write("this is a file") tsrc_cli.run_and_fail_with(ClonerError, "init", manifest_url)
def test_no_remote_named_origin(tsrc_cli: CLI, git_server: GitServer, workspace_path: Path) -> None: git_server.add_repo("foo") tsrc_cli.run("init", git_server.manifest_url) foo_path = workspace_path / "foo" tsrc.git.run(foo_path, "remote", "rename", "origin", "upstream") tsrc_cli.run("sync")
def repo_path(monkeypatch: Any, git_server: GitServer, tsrc_cli: CLI, workspace_path: Path) -> Path: """ Path to a freshly cloned repository """ git_server.add_repo("owner/project") manifest_url = git_server.manifest_url tsrc_cli.run("init", manifest_url) repo_path = workspace_path / "owner/project" monkeypatch.chdir(repo_path) return repo_path
def test_sync_with_force(tsrc_cli: CLI, git_server: GitServer, workspace_path: Path) -> None: git_server.add_repo("foo") git_server.push_file("foo", "latest.txt", contents="1") git_server.tag("foo", "latest") tsrc_cli.run("init", git_server.manifest_url) git_server.push_file("foo", "latest.txt", contents="2") git_server.tag("foo", "latest", force=True) tsrc_cli.run("sync", "--force")
def test_new_repo_added_to_manifest(tsrc_cli: CLI, git_server: GitServer, workspace_path: Path) -> None: git_server.add_repo("foo/bar") manifest_url = git_server.manifest_url tsrc_cli.run("init", manifest_url) git_server.add_repo("spam/eggs") tsrc_cli.run("sync") assert (workspace_path / "spam/eggs").exists()
def test_init_maint_manifest_branch(tsrc_cli: CLI, git_server: GitServer, workspace_path: Path) -> None: git_server.add_repo("bar") # foo repo will only exist on the 'devel' branch of the manifest: git_server.manifest.change_branch("devel") git_server.add_repo("foo") tsrc_cli.run("init", "--branch", "devel", git_server.manifest_url) assert_cloned(workspace_path, "foo")
def test_use_default_group(tsrc_cli: CLI, git_server: GitServer, workspace_path: Path) -> None: git_server.add_group("default", ["a", "b"]) git_server.add_repo("c") manifest_url = git_server.manifest_url tsrc_cli.run("init", manifest_url) assert_cloned(workspace_path, "a") assert_not_cloned(workspace_path, "c")
def test_copy_files_source_does_not_exist( tsrc_cli: CLI, git_server: GitServer, workspace_path: Path, message_recorder: MessageRecorder) -> None: manifest_url = git_server.manifest_url git_server.add_repo("master") git_server.manifest.set_repo_file_copies("master", [("top.cmake", "CMakeLists.txt")]) tsrc_cli.run("init", manifest_url, expect_fail=True) assert message_recorder.find("Failed to perform the following copies")
def test_sync_finds_root(tsrc_cli: CLI, git_server: GitServer, workspace_path: Path, monkeypatch: Any) -> None: """Check that you can run `tsrc sync` from inside a cloned repository """ git_server.add_repo("foo/bar") tsrc_cli.run("init", git_server.manifest_url) monkeypatch.chdir(workspace_path / "foo/bar") tsrc_cli.run("sync")
def test_shallow_with_fix_ref(tsrc_cli: CLI, git_server: GitServer, workspace_path: Path, message_recorder: MessageRecorder) -> None: git_server.add_repo("foo") initial_sha1 = git_server.get_sha1("foo") git_server.push_file("foo", "one.c") git_server.manifest.set_repo_sha1("foo", initial_sha1) manifest_url = git_server.manifest_url tsrc_cli.run("init", "--shallow", manifest_url, expect_fail=True) assert message_recorder.find("Cannot use --shallow with a fixed sha1")
def test_create_submodule(workspace_path: Path, git_server: GitServer) -> None: top_url = git_server.add_repo("top") sub_url = git_server.add_repo("sub", add_to_manifest=False) git_server.add_submodule("top", url=sub_url, path=Path("sub")) tsrc.git.run(workspace_path, "clone", top_url, "--recurse-submodules") top_path = workspace_path / "top" sub_readme = top_path / "sub" / "README" assert sub_readme.exists()