def test_tags_are_updated_when_clean( tsrc_cli: CLI, git_server: GitServer, workspace_path: Path ) -> None: """Scenario: * Create a manifest with a foo repo, frozen at the v0.1 tag * Initialize a workspace from this manifest * Push a new file to the foo repo * Create a new v0.2 tag on the foo repo * Configure the manifest so that `foo` is frozen at the v0.2 tag * Run `tsrc sync` * Check that foo has been updated to the `v0.2` tag """ git_server.add_repo("foo") git_server.tag("foo", "v0.1") git_server.manifest.set_repo_tag("foo", "v0.1") tsrc_cli.run("init", git_server.manifest_url) git_server.push_file("foo", "new.txt") git_server.tag("foo", "v0.2") git_server.manifest.set_repo_tag("foo", "v0.2") tsrc_cli.run("sync") foo_path = workspace_path / "foo" assert ( foo_path / "new.txt" ).exists(), "foo should have been updated to the v0.2 tag"
def test_use_specific_groups( tsrc_cli: CLI, git_server: GitServer, workspace_path: Path ) -> None: """ Scenario: * the manifest contains two groups, 'foo' and 'spam' * the manifest contains one repo 'other' * the 'other' repo is configured with a file copy * the user runs `init --group foo, spam` * we don't want 'other' to be cloned * we don't want the file copy to be attempted """ git_server.add_group("foo", ["bar", "baz"]) git_server.add_group("spam", ["eggs", "beacon"]) git_server.add_repo("other") git_server.push_file("other", "THANKS") git_server.manifest.set_repo_file_copies("other", [("THANKS", "THANKS.copy")]) manifest_url = git_server.manifest_url tsrc_cli.run("init", manifest_url, "--groups", "foo", "spam") assert_cloned(workspace_path, "bar") assert_cloned(workspace_path, "eggs") assert_not_cloned(workspace_path, "other")
def test_update_symlink( tsrc_cli: CLI, git_server: GitServer, workspace_path: Path ) -> None: """Scenario: * Crate a manifest with a 'foo' repo * Push 'foo.txt' to the 'foo' repo * Configure the 'foo' repo with a symlink copy from 'foo.link' to 'foo/foo.txt' * Run `tsrc init` * Update the link in the manifest * Push 'bar.txt' to the 'foo' repo * Run `tsrc sync` * Update the 'foo' repo with a symlink from 'foo.link' to 'foo/bar.txt' * Check that the link in <workspace>/foo.link was updated to point to foo/bar.txt """ manifest_url = git_server.manifest_url git_server.add_repo("foo") git_server.push_file("foo", "foo.txt") git_server.manifest.set_symlink("foo", "foo.link", "foo/foo.txt") tsrc_cli.run("init", manifest_url) git_server.push_file("foo", "bar.txt") git_server.manifest.set_symlink("foo", "foo.link", "foo/bar.txt") tsrc_cli.run("sync") actual_link = workspace_path / "foo.link" assert actual_link.exists() assert os.readlink(str(actual_link)) == os.path.normpath("foo/bar.txt")
def test_sync_with_no_update_manifest_flag_leaves_changes( tsrc_cli: CLI, git_server: GitServer, workspace_path: Path ) -> None: """ Scenario: * Create a manifest with one repo, foo * Initialize a workspace from this manifest * Add repo bar and do not commit or push this change * Run tsrc sync --no-update-manifest * The manifest is not updated from the remote, and the change is left * Both foo and bar are present after the sync """ git_server.add_repo("foo") git_server.push_file("foo", "foo.txt", contents="foo") tsrc_cli.run("init", git_server.manifest_url) git_server.add_repo("bar", add_to_manifest=False) git_server.push_file("bar", "bar.txt", contents="bar") add_repo_unstaged("bar", git_server, workspace_path) tsrc_cli.run("sync", "--no-update-manifest") bar_path = workspace_path / "bar" assert bar_path.exists(), "bar should have been synced" assert ( bar_path / "bar.txt" ).read_text() == "bar", "bar should have the correct contents"
def test_copies_are_up_to_date( tsrc_cli: CLI, git_server: GitServer, workspace_path: Path ) -> None: """ Scenario: * Create a manifest with one repo, foo * Configure a copy from foo/foo.txt to top.txt * Initialize a workspace from this manifest * Push a new version of `foo.txt` to the foo repo * Run `tsrc sync` * Check that `top.txt` has been updated """ manifest_url = git_server.manifest_url git_server.add_repo("foo") git_server.push_file("foo", "foo.txt", contents="v1") git_server.manifest.set_file_copy("foo", "foo.txt", "top.txt") tsrc_cli.run("init", manifest_url) git_server.push_file("foo", "foo.txt", contents="v2") tsrc_cli.run("sync") assert ( workspace_path / "top.txt" ).read_text() == "v2", "copy should have been updated" assert (workspace_path / "top.txt").read_text() == "v2"
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_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_sha1s_are_skipped_when_not_clean( tsrc_cli: CLI, git_server: GitServer, workspace_path: Path ) -> None: """Scenario: * Create a manifest with a foo repo, frozen at an initial revision * Initialize a workspace from this manifest * Push a new file to the foo repo * Configure the manifest so that foo is frozen at the new revision * Create an untracked file in the foo repo * Run `tsrc sync` * Check that `tsrc sync` fails and that foo is not updated """ git_server.add_repo("foo") initial_sha1 = git_server.get_sha1("foo") git_server.manifest.set_repo_sha1("foo", initial_sha1) tsrc_cli.run("init", git_server.manifest_url) (workspace_path / "foo/untracked.txt").write_text("") git_server.push_file("foo", "new.txt") new_sha1 = git_server.get_sha1("foo") git_server.manifest.set_repo_sha1("foo", new_sha1) tsrc_cli.run_and_fail("sync") foo_path = workspace_path / "foo" assert not ( foo_path / "new.txt" ).exists(), "foo should not have been updated (untracked files)"
def test_status_not_on_any_branch( tsrc_cli: CLI, git_server: GitServer, workspace_path: Path, message_recorder: MessageRecorder, ) -> None: """Scenario: * Create a workspace with one repo * Make sure the repo is not an any branch * Run `tsrc status` * Check that the output contains a sha1 """ git_server.add_repo("foo") # we need more that one commit # to be in 'detached HEAD': git_server.push_file("foo", "new.txt") git_server.add_repo("bar") tsrc_cli.run("init", git_server.manifest_url) # detach HEAD on foo repo foo_path = workspace_path / "foo" run_git(foo_path, "checkout", "HEAD~1") tsrc_cli.run("status") assert message_recorder.find(r"\* foo [a-f0-9]{7}")
def test_happy(tsrc_cli: CLI, git_server: GitServer, message_recorder: MessageRecorder) -> None: """ Scenario: * Create a manifest with two repos, foo and bar * Initialize a workspace from this manifest * Create a tag named v0.1 on foo and bar * Run `tsrc log --from v0.1 """ git_server.add_repo("foo") git_server.add_repo("spam") git_server.push_file("foo", "bar.txt", message="boring bar") git_server.tag("foo", "v0.1") git_server.tag("spam", "v0.1") manifest_url = git_server.manifest_url tsrc_cli.run("init", manifest_url) git_server.push_file("foo", "foo.txt", message="new foo!") tsrc_cli.run("sync") message_recorder.reset() tsrc_cli.run("log", "--from", "v0.1") assert message_recorder.find("new foo!") message_recorder.reset() tsrc_cli.run("log", "--from", "v0.1", "--to", "v0.1") assert not message_recorder.find("new foo!")
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, including a file system copy * Run `tsrc apply-manifest /path/to/copied_manifest` * Check that the new repo is cloned * Check that the copy is performed """ 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) git_server.push_file("bar", "src") add_repo_to_manifest_with_copy(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" assert ( workspace_path / "dest").exists(), "file system operations should have been performed"
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_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_sha1s_are_updated_when_clean( tsrc_cli: CLI, git_server: GitServer, workspace_path: Path ) -> None: """Scenario: * Create a manifest with a foo repo, frozen at an initial revision * Initialize a workspace from this manifest * Push a new file to the foo repo * Configure the manifest so that `foo` is frozen at the new revision * Run `tsrc sync` * Check that foo has been updated to the new revision """ git_server.add_repo("foo") initial_sha1 = git_server.get_sha1("foo") git_server.manifest.set_repo_sha1("foo", initial_sha1) tsrc_cli.run("init", git_server.manifest_url) git_server.push_file("foo", "new.txt") new_sha1 = git_server.get_sha1("foo") git_server.manifest.set_repo_sha1("foo", new_sha1) tsrc_cli.run("sync") foo_path = workspace_path / "foo" assert ( foo_path / "new.txt" ).exists(), f"foo should have been updated to the {new_sha1} revision"
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_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_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_sync_happy(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) git_server.push_file("foo/bar", "bar.txt", contents="this is bar") tsrc_cli.run("sync") bar_txt_path = workspace_path / "foo/bar/bar.txt" assert bar_txt_path.text() == "this is bar"
def test_copies_are_readonly(tsrc_cli: CLI, git_server: GitServer, workspace_path: Path) -> None: manifest_url = git_server.manifest_url git_server.add_repo("foo") git_server.push_file("foo", "foo.txt", contents="v1") git_server.manifest.set_repo_file_copies("foo", [("foo.txt", "top.txt")]) tsrc_cli.run("init", manifest_url) foo_txt = workspace_path / "top.txt" assert not os.access(foo_txt, os.W_OK)
def test_status_dirty(tsrc_cli: CLI, git_server: GitServer, workspace_path: Path, message_recorder: MessageRecorder) -> None: git_server.add_repo("foo/bar") git_server.push_file("foo/bar", "CMakeLists.txt") manifest_url = git_server.manifest_url tsrc_cli.run("init", manifest_url) (workspace_path / "foo/bar/CMakeLists.txt").write_text("DIRTY FILE") tsrc_cli.run("status") assert message_recorder.find(r"\* foo/bar master \(dirty\)")
def test_copies_are_up_to_date(tsrc_cli: CLI, git_server: GitServer, workspace_path: Path) -> None: manifest_url = git_server.manifest_url git_server.add_repo("foo") git_server.push_file("foo", "foo.txt", contents="v1") git_server.manifest.set_repo_file_copies("foo", [("foo.txt", "top.txt")]) tsrc_cli.run("init", manifest_url) git_server.push_file("foo", "foo.txt", contents="v2") tsrc_cli.run("sync") assert (workspace_path / "top.txt").text() == "v2"
def test_changing_branch(tsrc_cli: CLI, git_server: GitServer, workspace_path: Path, message_recorder: MessageRecorder) -> None: git_server.add_repo("foo") manifest_url = git_server.manifest_url tsrc_cli.run("init", manifest_url) git_server.change_repo_branch("foo", "next") git_server.push_file("foo", "next.txt") git_server.manifest.set_repo_branch("foo", "next") tsrc_cli.run("sync", expect_fail=True) assert message_recorder.find("not on the correct branch")
def test_foreach_shell(tsrc_cli: CLI, git_server: GitServer, message_recorder: MessageRecorder) -> None: git_server.add_repo("foo") git_server.add_repo("spam") git_server.push_file("foo", "doc/index.html") git_server.push_file("spam", "doc/index.html") manifest_url = git_server.manifest_url tsrc_cli.run("init", manifest_url) cmd = get_cmd_for_foreach_test(shell=True) cmd.append("doc") tsrc_cli.run("foreach", "-c", " ".join(cmd)) assert message_recorder.find("`%s`" % " ".join(cmd))
def test_foreach_with_errors(tsrc_cli: CLI, git_server: GitServer, message_recorder: MessageRecorder) -> None: git_server.add_repo("foo") git_server.add_repo("spam") git_server.push_file("foo", "foo/bar.txt", contents="this is bar") manifest_url = git_server.manifest_url tsrc_cli.run("init", manifest_url) cmd = get_cmd_for_foreach_test(shell=False) cmd.append("foo") tsrc_cli.run("foreach", *cmd, expect_fail=True) assert message_recorder.find("Command failed") assert message_recorder.find(r"\* spam")
def test_copy_files_happy(tsrc_cli: CLI, git_server: GitServer, workspace_path: Path) -> None: manifest_url = git_server.manifest_url git_server.add_repo("master") top_cmake_contents = "# Top CMakeLists.txt" git_server.push_file("master", "top.cmake", contents=top_cmake_contents) git_server.manifest.set_repo_file_copies("master", [("top.cmake", "CMakeLists.txt")]) tsrc_cli.run("init", manifest_url) assert (workspace_path / "CMakeLists.txt").text() == top_cmake_contents
def test_uses_correct_branch_for_repo(tsrc_cli: CLI, git_server: GitServer, workspace_path: Path) -> None: git_server.add_repo("foo") git_server.change_repo_branch("foo", "next") git_server.push_file("foo", "next.txt") git_server.manifest.set_repo_branch("foo", "next") manifest_url = git_server.manifest_url tsrc_cli.run("init", manifest_url) foo_path = workspace_path / "foo" assert tsrc.git.get_current_branch(foo_path) == "next"
def test_sha1s_are_not_updated(tsrc_cli: CLI, git_server: GitServer, workspace_path: Path) -> None: git_server.add_repo("foo") initial_sha1 = git_server.get_sha1("foo") git_server.manifest.set_repo_sha1("foo", initial_sha1) tsrc_cli.run("init", git_server.manifest_url) git_server.push_file("foo", "new.txt") tsrc_cli.run("sync") foo_path = workspace_path / "foo" assert not (foo_path / "new.txt").exists()
def test_shallow_clones(tsrc_cli: CLI, git_server: GitServer, workspace_path: Path) -> None: git_server.add_repo("foo/bar") git_server.add_repo("spam/eggs") git_server.push_file("foo/bar", "bar.txt", contents="this is bar") manifest_url = git_server.manifest_url tsrc_cli.run("init", "--shallow", manifest_url) assert_shallow_clone(workspace_path, "foo/bar") assert_shallow_clone(workspace_path, "spam/eggs") git_server.add_repo("foo/baz") tsrc_cli.run("sync") assert_shallow_clone(workspace_path, "foo/baz")
def test_sync_with_errors(tsrc_cli: CLI, git_server: GitServer, workspace_path: Path, message_recorder: MessageRecorder) -> 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) git_server.push_file("foo/bar", "bar.txt", contents="Bar is true") bar_src = workspace_path / "foo/bar" (bar_src / "bar.txt").write_text("Bar is false") tsrc_cli.run("sync", expect_fail=True) assert message_recorder.find("Failed to synchronize workspace") assert message_recorder.find(r"\* foo/bar")
def test_resets_to_sha1(tsrc_cli: CLI, git_server: GitServer, workspace_path: Path) -> None: git_server.add_repo("foo") initial_sha1 = git_server.get_sha1("foo") git_server.manifest.set_repo_sha1("foo", initial_sha1) git_server.push_file("foo", "2.txt", message="Working on v2") manifest_url = git_server.manifest_url tsrc_cli.run("init", manifest_url) foo_path = workspace_path / "foo" _, actual_ref = tsrc.git.run_captured(foo_path, "rev-parse", "HEAD") assert initial_sha1 == actual_ref