def test_wrong_branch(self): bar_url = create_git_repo(self.tmp, "bar") work = os.path.join(self.tmp, "work") qibuild.sh.mkdir(work) bar_src = os.path.join(work, "bar") git = qisrc.git.Git(bar_src) git.clone(bar_url) git.update_branch("master", "origin") readme = read_readme(bar_src) self.assertEqual(readme, "bar\n") # Checkout a 'next' branch git.checkout("-b", "next") with open(os.path.join(bar_src, "README"), "w") as fp: fp.write("bar on next\n") git.commit("-a", "-m", "README next") # Push a new commit push_readme_v2(self.tmp, "bar", "master") # Update, check that master is up to date err = git.update_branch("master", "origin") self.assertFalse(err) git.checkout("master") readme = read_readme(bar_src) self.assertEqual(readme, "bar v2 on master\n")
def test_switch_manifest_branch(tmpdir, git_server): git_server.switch_manifest_branch("devel") assert git_server.manifest_branch == "devel" foo_clone = tmpdir.mkdir("foo") git = qisrc.git.Git(foo_clone.strpath) git.clone(git_server.manifest_url, "--branch", git_server.manifest_branch) assert git.get_current_branch() == "devel"
def test_conflict(self): bar_url = create_git_repo(self.tmp, "bar") work = os.path.join(self.tmp, "work") qibuild.sh.mkdir(work) bar_src = os.path.join(work, "bar") git = qisrc.git.Git(bar_src) git.clone(bar_url) # Create conflicting changes write_readme(bar_src, "conflicting changes\n", append=True) git.commit("-a", "-m", "conflicting changes") push_readme_v2(self.tmp, "bar", "master") # Updating branch should fail err = git.update_branch("master", "origin") self.assertTrue(err) self.assertTrue("Merge conflict in README" in err, err) # But we should be back at our previous commit readme = read_readme(bar_src) self.assertEqual(readme, "bar\nconflicting changes\n") self.assertEqual(git.get_current_branch(), "master") rebase_apply = os.path.join(git.repo, ".git", "rebase_apply") self.assertFalse(os.path.exists(rebase_apply))
def test_untracked_would_be_overwritten(self): bar_url = create_git_repo(self.tmp, "bar") work = os.path.join(self.tmp, "work") qibuild.sh.mkdir(work) bar_src = os.path.join(work, "bar") git = qisrc.git.Git(bar_src) git.clone(bar_url) # Create untracked, conflicting changes a_file = os.path.join(bar_src, "a_file") with open(a_file, "w") as fp: fp.write("a_file\n") upstream_src = os.path.join(self.tmp, "src", "bar") upstream_file = os.path.join(upstream_src, "a_file") with open(upstream_file, "w") as fp: fp.write("upstream file\n") upstream_git = qisrc.git.Git(upstream_src) upstream_git.call("add", "a_file") upstream_git.call("commit", "-m", "Add a file") upstream_git.call("push", bar_url, "master:master") err = git.update_branch("master", "origin") self.assertTrue(err) self.assertTrue("untracked working tree files" in err) self.assertEqual(git.get_current_branch(), "master")
def test_wrong_branch_unstaged(self): bar_url = create_git_repo(self.tmp, "bar") work = os.path.join(self.tmp, "work") qibuild.sh.mkdir(work) bar_src = os.path.join(work, "bar") git = qisrc.git.Git(bar_src) git.clone(bar_url) # Checkout a 'next' branch with unstaged changes git.checkout("-b", "next") write_readme(bar_src, "bar on next\n") push_readme_v2(self.tmp, "bar", "master") err = git.update_branch("master", "origin") self.assertFalse(err) # Check we are still on next with our # unstaged changes back self.assertEqual(git.get_current_branch(), "next") readme = read_readme(bar_src) self.assertEqual(readme, "bar on next\n") # Check that master is up to date git.checkout("-f", "master") readme = read_readme(bar_src) self.assertEqual(readme, "bar v2 on master\n")
def test_safe_checkout(cd_to_tmpdir, git_server): git_server.create_repo("foo.git") git = TestGit() git.clone(git_server.srv.join("foo.git").strpath) ok, mess = git.safe_checkout("devel", "origin") assert git.get_current_branch() == "devel" assert ok
def clone_manifest(self, manifest): """ Clone a new manifest in .qi/manifests/<name> """ manifest_repo = os.path.join(self.manifests_root, manifest.name) if not os.path.exists(manifest_repo): git = qisrc.git.Git(manifest_repo) git.clone(manifest.url, "--branch", manifest.branch, quiet=True)
def test_git_server_creates_valid_urls(tmpdir, git_server): origin_url = git_server.manifest.get_remote("origin").url foo_repo = git_server.create_repo("foo.git") foo_url = foo_repo.clone_url assert foo_url.startswith("file://") foo_clone = tmpdir.mkdir("foo") git = qisrc.git.Git(foo_clone.strpath) git.clone(foo_url)
def test_submodules(tmpdir): foo_url = create_git_repo_with_submodules(tmpdir.strpath) work = tmpdir.mkdir("work") foo = work.mkdir("foo") git = qisrc.git.Git(foo.strpath) git.clone(foo_url) bar = foo.join("bar") assert qisrc.git.is_submodule(bar.strpath) assert not qisrc.git.is_submodule(foo.strpath)
def clone_project(worktree, url, src=None, branch=None, remote="origin", skip_if_exists=False): """ Add a project to a worktree given its url. If src is not given, it will be guessed from the url If skip_if_exists is False, an error message will be raised if the project already exists """ should_add = True if not src: src = url.split("/")[-1].replace(".git", "") if os.path.isabs(src): src = os.path.relpath(worktree.root, src) src = qibuild.sh.to_posix_path(src) project = worktree.get_project(src, raises=False) if project: if not skip_if_exists: mess = "Could not add project from %s in %s\n" % (url, src) mess += "This path is already registered for worktree in %s\n" % worktree.root raise Exception(mess) else: if os.path.exists(project.path): ui.debug("Found project in %s, skipping" % src) return # Some one erase the project manually without telling qiworktree should_add = False path = os.path.join(worktree.root, src) path = qibuild.sh.to_native_path(path) if os.path.exists(path): if skip_if_exists: if qisrc.git.is_submodule(path): ui.warning("erasing submodule: ", path) qibuild.sh.rm(path) else: ui.debug("Adding project in %s", src) worktree.add_project(src) return else: mess = "Could not add project from %s in %s\n" % (url, src) mess += "This path already exists\n" raise Exception(mess) ui.info(ui.green, "Git clone: %s -> %s" % (url, path)) dirname = os.path.dirname(path) qibuild.sh.mkdir(dirname, recursive=True) git = qisrc.git.Git(path) if branch: git.clone(url, "-b", branch, "-o", remote) else: git.clone(url, "-o", remote) if should_add: worktree.add_project(path)
def test_on_new_project(qisrc_action, git_server, tmpdir, interact): foo_repo = git_server.create_repo("foo.git") foo_path = tmpdir.join("work").join("foo") foo_path.ensure(dir=True) git = qisrc.git.Git(foo_path.strpath) git.clone(foo_repo.clone_url) interact.answers = [True] with qisys.sh.change_cwd(foo_path.strpath): qisrc_action("push", retcode=True) assert not foo_path.join("qiproject.xml").check(file=True)
def test_pushing_files(tmpdir, git_server): """ Test Pushing Fles """ _origin_url = git_server.manifest.get_remote("origin").url foo_repo = git_server.create_repo("foo.git") foo_url = foo_repo.clone_url foo_clone = tmpdir.mkdir("foo") git = qisrc.git.Git(foo_clone.strpath) git.clone(foo_url) git_server.push_file("foo.git", "README", "This is foo\n") git.pull() assert foo_clone.join("README").read() == "This is foo\n"
def open_git_feed(toolchain_name, feed_url, name=None, branch="master", first_pass=True): git_path = qisys.sh.get_share_path("qi", "toolchains", toolchain_name + ".git") git = qisrc.git.Git(git_path) if first_pass: if os.path.exists(git_path): git.call("remote", "set-url", "origin", feed_url) git.call("fetch", "origin", "--quiet") git.call("reset", "--hard", "--quiet", "origin/%s" % branch) else: git.clone(feed_url, "--quiet", "--branch", branch) feed_path = os.path.join(git_path, "feeds", name + ".xml") return feed_path
def test_get_current_branch(self): bar_url = create_git_repo(self.tmp, "bar") work = os.path.join(self.tmp, "work") qibuild.sh.mkdir(work) bar_src = os.path.join(work, "bar") git = qisrc.git.Git(bar_src) git.clone(bar_url) self.assertEqual(git.get_current_branch(), "master") push_readme_v2(self.tmp, "bar", "master") git.pull() self.assertEqual(git.get_current_branch(), "master") git.checkout("-f", "HEAD~1") self.assertEqual(git.get_current_branch(), None)
def test_simple(self): bar_url = create_git_repo(self.tmp, "bar") work = os.path.join(self.tmp, "work") qibuild.sh.mkdir(work) bar_src = os.path.join(work, "bar") git = qisrc.git.Git(bar_src) git.clone(bar_url) # Should be a noop git.update_branch("master", "origin") readme = read_readme(bar_src) self.assertEqual(readme, "bar\n") # Push a new commit push_readme_v2(self.tmp, "bar", "master") # Update, check that branch is up to date git.update_branch("master", "origin") readme = read_readme(bar_src) self.assertEqual(readme, "bar v2 on master\n")
def test_set_tracking_branch(tmpdir): tmpdir = tmpdir.strpath bar_url = create_git_repo(tmpdir, "bar") work = os.path.join(tmpdir, "work") bar_src = os.path.join(work, "bar") git = qisrc.git.Git(bar_src) git.clone(bar_url) push_file(tmpdir, "bar", "README", "README on release", branch="release") push_file(tmpdir, "bar", "README", "README on master", branch="master") git.update_branch("master", "origin") git.set_tracking_branch("release", "origin") err = git.update_branch("release", "origin") assert not err # This should work out of the box git.pull() git.checkout("release") git.pull()
def test_wrong_branch_with_conflicts(self): bar_url = create_git_repo(self.tmp, "bar") work = os.path.join(self.tmp, "work") qibuild.sh.mkdir(work) bar_src = os.path.join(work, "bar") git = qisrc.git.Git(bar_src) git.clone(bar_url) # Create conflicting changes write_readme(bar_src, "conflicting changes\n", append=True) git.commit("-a", "-m", "conflicting changes") push_readme_v2(self.tmp, "bar", "master") # Checkout an other branch git.checkout("-b", "next") # Try to update master while being on an other branch: err = git.update_branch("master", "origin") self.assertTrue(err) self.assertTrue("Merge is not fast-forward" in err)
def clone_project(worktree, url, src=None, branch=None, remote="origin"): """ Add a project to a worktree given its url. If src is not given, it will be guessed from the url """ should_add = True if not src: src = url.split("/")[-1].replace(".git", "") if os.path.isabs(src): src = os.path.relpath(src, worktree.root) src = qisys.sh.to_posix_path(src) else: src = qisys.sh.to_posix_path(src) conflict_project = worktree.get_project(src, raises=False) if conflict_project: mess = "Could not add project from %s in %s\n" % (url, src) mess += "This path is already registered for worktree in %s\n" % \ worktree.root raise Exception(mess) path = os.path.join(worktree.root, src) path = qisys.sh.to_native_path(path) if os.path.exists(path): mess = "Could not add project from %s in %s\n" % (url, src) mess += "This path already exists\n" raise Exception(mess) ui.info(ui.green, "Git clone: %s -> %s" % (url, path)) dirname = os.path.dirname(path) qisys.sh.mkdir(dirname, recursive=True) git = qisrc.git.Git(path) if branch: git.clone(url, "-b", branch, "-o", remote) else: git.clone(url, "-o", remote) git.update_submodules() if should_add: worktree.add_project(path) return worktree.get_project(src)
def do(args): """ Main entry point """ worktree = qisys.parsers.get_worktree(args) if os.path.exists(args.path_or_url): path = args.path_or_url path = qisys.sh.to_native_path(path) worktree.add_project(path) return url = args.path_or_url src = args.src if not src: gitname = qisrc.git.name_from_url(url) src = gitname.replace(".git", "") src = os.path.join(os.getcwd(), src) worktree.add_project(src) worktree_proj = worktree.get_project(src) proj_path = worktree_proj.path if os.path.exists(proj_path): raise Exception("%s already exists" % proj_path) git = qisrc.git.Git(proj_path) git.clone(url, "--branch", args.branch)
def test_unstaged_changes_conflict(self): bar_url = create_git_repo(self.tmp, "bar") work = os.path.join(self.tmp, "work") qibuild.sh.mkdir(work) bar_src = os.path.join(work, "bar") git = qisrc.git.Git(bar_src) git.clone(bar_url) # Create unstaged, conflicting changes readme = os.path.join(bar_src, "README") with open(readme, "a") as fp: fp.write("Unstaged changes\n") push_readme_v2(self.tmp, "bar", "master") err = git.update_branch("master", "origin") self.assertTrue(err) self.assertTrue("Merge conflict in README" in err) self.assertTrue("Stashing back changes failed" in err) self.assertTrue(git.get_current_branch(), "master") rebase_apply = os.path.join(git.repo, ".git", "rebase_apply") self.assertFalse(os.path.exists(rebase_apply)) readme = read_readme(bar_src) self.assertTrue(readme, "Unstaged changes\n")
def test_set_remote(self): bar_url = create_git_repo(self.tmp, "bar", with_release_branch=True) work = os.path.join(self.tmp, "work") qibuild.sh.mkdir(work) bar_src = os.path.join(work, "bar") git = qisrc.git.Git(bar_src) git.clone(bar_url, "-o", "foo") # Must work: git.pull() git.set_remote("origin", bar_url) # Must NOT work: out, err_ = git.pull("origin", raises=False) self.assertFalse(out == 0) # Must work git.set_tracking_branch("master", "origin") git.pull() readme = read_readme(bar_src) self.assertEqual(readme, "bar\n") git.set_tracking_branch("stable", "origin", remote_branch="release-1.12") git.checkout("stable") git.pull() readme = read_readme(bar_src) self.assertEqual(readme, "bar on release-1.12\n")
def test_unstaged_changes_no_conflict(self): bar_url = create_git_repo(self.tmp, "bar") work = os.path.join(self.tmp, "work") qibuild.sh.mkdir(work) bar_src = os.path.join(work, "bar") git = qisrc.git.Git(bar_src) git.clone(bar_url) # Create unstaged, non-conflicting changes readme = os.path.join(bar_src, "README") with open(readme, "w") as fp: fp.write("Unstaged changes\n") upstream_src = os.path.join(self.tmp, "src", "bar") upstream_file = os.path.join(upstream_src, "a_file") with open(upstream_file, "w") as fp: fp.write("upstream file\n") upstream_git = qisrc.git.Git(upstream_src) upstream_git.call("add", "a_file") upstream_git.call("commit", "-m", "Add a file") upstream_git.call("push", bar_url, "master:master") err = git.update_branch("master", "origin") self.assertFalse(err) # Check that upstream file is here a_file = os.path.join(bar_src, "a_file") self.assertTrue(os.path.exists(a_file)) # Check that unstaged changes are here: readme = read_readme(bar_src) self.assertEqual(readme, "Unstaged changes\n") self.assertTrue(git.get_current_branch(), "master") rebase_apply = os.path.join(git.repo, ".git", "rebase_apply") self.assertFalse(os.path.exists(rebase_apply))
def test_push(tmpdir): foo_url = create_git_repo(tmpdir.strpath, "foo") work = tmpdir.mkdir("work") foo_src = work.mkdir("foo") foo_src = foo_src.strpath git = qisrc.git.Git(foo_src) git.clone(foo_url) # this should work: qisrc.review.push(foo_src, "master") (retcode, out) = git.call("ls-remote", "origin", raises=False) assert retcode == 0 assert "refs/for/master" not in out assert "refs/heads/master" in out gerrit_url = create_git_repo(tmpdir.strpath, "foo-gerrit") git.call("remote", "add", "gerrit", gerrit_url) git.set_config("review.remote", "gerrit") git.checkout("-b", "next") qisrc.review.push(foo_src, "next") (retcode, out) = git.call("ls-remote", "gerrit", raises=False) assert retcode == 0 assert "refs/for/next" in out assert "refs/heads/next" not in out
def test_untracked_files(self): bar_url = create_git_repo(self.tmp, "bar") work = os.path.join(self.tmp, "work") qibuild.sh.mkdir(work) bar_src = os.path.join(work, "bar") git = qisrc.git.Git(bar_src) git.clone(bar_url) # Create untracked, non-conflicting changes a_file = os.path.join(bar_src, "a_file") with open(a_file, "w") as fp: fp.write("a_file\n") push_readme_v2(self.tmp, "bar", "master") # Update branch, untracked files should still be here err = git.update_branch("master", "origin") self.assertFalse(err) self.assertTrue(os.path.exists(a_file)) with open(a_file, "r") as fp: contents = fp.read() self.assertEqual(contents, "a_file\n") readme = read_readme(bar_src) self.assertEqual(readme, "bar v2 on master\n")