Пример #1
0
def test_using_force_when_not_an_a_branch(qisrc_action, git_server):
    git_server.create_repo("foo.git")
    git_server.push_file("foo.git", "foo.txt", "this is foo")
    manifest_url = git_server.manifest_url
    qisrc_action("init", manifest_url)
    git_worktree = TestGitWorkTree()
    foo_proj = git_worktree.get_git_project("foo")
    git = qisrc.git.Git(foo_proj.path)
    git.checkout("HEAD~1")
    assert not git.get_current_branch()
    qisrc_action("checkout", "master", "--force")
    assert git.get_current_branch() == "master"
Пример #2
0
def test_using_force_when_not_an_a_branch(qisrc_action, git_server):
    git_server.create_repo("foo.git")
    git_server.push_file("foo.git", "foo.txt", "this is foo")
    manifest_url = git_server.manifest_url
    qisrc_action("init", manifest_url)
    git_worktree = TestGitWorkTree()
    foo_proj = git_worktree.get_git_project("foo")
    git = qisrc.git.Git(foo_proj.path)
    git.checkout("HEAD~1")
    assert not git.get_current_branch()
    qisrc_action("checkout", "master", "--force")
    assert git.get_current_branch() == "master"
Пример #3
0
def test_removing_forked_project(qisrc_action, git_server):
    git_server.create_repo("booz")
    git_server.switch_manifest_branch("devel")
    git_server.change_branch("booz", "devel")
    qisrc_action("init", git_server.manifest_url, "--branch", "devel")
    git_worktree = TestGitWorkTree()
    booz_proj = git_worktree.get_git_project("booz")
    git = qisrc.git.Git(booz_proj.path)
    assert git.get_current_branch() == "devel"
    git_server.change_branch("booz", "master")
    qisrc_action("sync", "-a", retcode=True)
    qisrc_action("checkout", "devel")
    assert git.get_current_branch() == "master"
Пример #4
0
 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)
Пример #5
0
def test_removing_forked_project(qisrc_action, git_server):
    git_server.create_repo("booz")
    git_server.switch_manifest_branch("devel")
    git_server.change_branch("booz", "devel")
    qisrc_action("init", git_server.manifest_url, "--branch", "devel")
    git_worktree = TestGitWorkTree()
    booz_proj = git_worktree.get_git_project("booz")
    git = qisrc.git.Git(booz_proj.path)
    assert git.get_current_branch() == "devel"
    git_server.change_branch("booz", "master")
    qisrc_action("sync", "-a", retcode=True)
    qisrc_action("checkout", "devel")
    assert git.get_current_branch() == "master"
Пример #6
0
def diff_worktree(git_worktree, git_projects, branch, cmd=None):
    """ Run  `git <cmd> local_branch..remote_branch` for every project

    """
    if not cmd:
        cmd = ["log"]
    remote_projects = git_worktree.get_projects_on_branch(branch)
    for git_project in git_projects:
        remote_project = remote_projects.get(git_project.src)
        if not remote_project:
            continue
        git = qisrc.git.Git(git_project.path)
        local_branch = git.get_current_branch()
        remote_branch = remote_project.default_branch.name
        remote_ref = "%s/%s" % (remote_project.default_remote.name, remote_branch)
        rc, out = git.call("merge-base", local_branch, remote_ref, raises=False)
        if rc != 0:
            continue
        merge_base = out.strip()
        full_cmd = cmd + ["%s..%s" % (merge_base, local_branch)]

        color = ui.config_color(sys.stdout)
        if color:
            full_cmd.append("--color=always")
        rc, out = git.call(*full_cmd, raises=False)
        if rc != 0:
            continue
        if not out:
            continue
        ui.info(ui.bold, git_project.src)
        ui.info(ui.bold, "-" * len(git_project.src))
        ui.info(out)
        ui.info()
Пример #7
0
def diff_worktree(git_worktree, git_projects, branch, cmd=None):
    """ Run  `git <cmd> local_branch..remote_branch` for every project

    """
    if not cmd:
        cmd = ["log"]
    remote_projects = git_worktree.get_projects_on_branch(branch)
    for git_project in git_projects:
        remote_project = remote_projects.get(git_project.src)
        if not remote_project:
            continue
        git = qisrc.git.Git(git_project.path)
        local_branch = git.get_current_branch()
        remote_branch = remote_project.default_branch.name
        remote_ref = "%s/%s" % (remote_project.default_remote.name, remote_branch)
        rc, out = git.call("merge-base", local_branch, remote_ref, raises=False)
        if rc != 0:
            continue
        merge_base = out.strip()
        full_cmd = cmd + ["%s..%s" % (merge_base, local_branch)]

        color = ui.config_color(sys.stdout)
        if color:
            full_cmd.append("--color=always")
        rc, out = git.call(*full_cmd, raises=False)
        if rc != 0:
            continue
        if not out:
            continue
        ui.info(ui.bold, git_project.src)
        ui.info(ui.bold, "-" * len(git_project.src))
        ui.info(out)
        ui.info()
Пример #8
0
    def push_submodule(self, project, submodule_url, destination_dir,
                       branch="master", fast_forward=True,
                       message=None):
        """
        Push a submodule to the given project.
        It is assumed that the project has been created.
        """
        src = project.replace(".git", "")
        repo_src = self.src.join(src)
        git = qisrc.git.Git(repo_src.strpath)
        if git.get_current_branch() != branch:
            git.checkout("--force", "-B", branch)
        if not fast_forward:
            git.reset("--hard", "HEAD~1")

        to_write = repo_src.join(destination_dir)
        if to_write.exists():
            raise RuntimeError("path %s already exists" % destination_dir)

        if not message:
            message = "Add submodule %s" % destination_dir

        git.call("submodule", "add", submodule_url, destination_dir)
        git.add(destination_dir)
        git.commit("--message", message)
        if fast_forward:
            git.push("origin", "%s:%s" % (branch, branch))
        else:
            git.push("origin", "--force", "%s:%s" % (branch, branch))
Пример #9
0
def check_state(project, untracked):
    """ Check and register the state of a project. """
    state_project = ProjectState(project)
    git = qisrc.git.Git(project.path)
    if not git.is_valid():
        state_project.valid = False
        return state_project
    state_project.clean = git.is_clean(untracked=untracked)
    if project.fixed_ref:
        state_project.ahead, state_project.behind = stat_fixed_ref(git, project.fixed_ref)
        state_project.fixed_ref = project.fixed_ref
        _set_status(git, state_project, untracked=untracked)
        return state_project
    state_project.current_branch = git.get_current_branch()
    state_project.tracking = git.get_tracking_branch()
    if project.default_remote and project.default_branch:
        state_project.manifest_branch = "%s/%s" % (project.default_remote.name, project.default_branch.name)
    if state_project.current_branch is None:
        state_project.not_on_a_branch = True
        return state_project
    if project.default_branch:
        if state_project.current_branch != project.default_branch.name:
            state_project.incorrect_proj = True
    (state_project.ahead, state_project.behind) = stat_tracking_remote(
        git,
        state_project.current_branch,
        state_project.tracking)
    if state_project.incorrect_proj:
        (state_project.ahead_manifest, state_project.behind_manifest) = stat_tracking_remote(
            git, state_project.current_branch, "%s/%s" % (
                project.default_remote.name, project.default_branch.name))
    _set_status(git, state_project, untracked=untracked)
    return state_project
Пример #10
0
def do(args):
    """ Main entry point """
    git_worktree = qisrc.parsers.get_git_worktree(args)
    git_projects = qisrc.parsers.get_git_projects(git_worktree, args)
    for git_project in git_projects:
        maintainers = qisrc.maintainers.get(git_project)
        if not maintainers:
            mess = """\
The project in {src} has no maintainer.
Please edit {qiproject_xml} to silence this warning
"""
            ui.warning(mess.format(src=git_project.src, qiproject_xml=git_project.qiproject_xml), end="")
        reviewers = [x["email"] for x in maintainers]
        reviewers.extend(args.reviewers or list())
        git = qisrc.git.Git(git_project.path)
        current_branch = git.get_current_branch()
        if not current_branch:
            ui.error("Not currently on any branch")
            sys.exit(2)
        if git_project.review:
            qisrc.review.push(
                git_project,
                current_branch,
                bypass_review=(not args.review),
                dry_run=args.dry_run,
                reviewers=reviewers,
                topic=args.topic,
            )
        else:
            if args.dry_run:
                git.push("-n")
            else:
                git.push()
Пример #11
0
    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")
Пример #12
0
def check_state(project, untracked):
    """Check and register the state of a project."""
    state_project = ProjectState(project)

    git = qisrc.git.Git(project.path)

    if not git.is_valid():
        state_project.valid = False
        return state_project

    state_project.clean = git.is_clean(untracked = untracked)
    state_project.current_branch = git.get_current_branch()
    state_project.tracking = git.get_tracking_branch()

    #clean worktree, but is the current branch sync with the remote one?
    if state_project.clean:
        if state_project.current_branch is None:
            state_project.not_on_a_branch = True
            return state_project

        if state_project.current_branch != project.branch:
            state_project.incorrect_proj = True

        (state_project.ahead, state_project.behind) = stat_tracking_remote(git,
                state_project.current_branch, state_project.tracking)

    if not state_project.sync_and_clean:
        out = git.get_status(untracked)
        if out is not None:
            state_project.status = [ x[:3]
                    for x in out.splitlines() if len(x.strip()) > 0 ]

    return state_project
Пример #13
0
def do(args):
    """ Main entry point """
    git_worktree = qisrc.parsers.get_git_worktree(args)
    git_projects = qisrc.parsers.get_git_projects(git_worktree, args)
    for git_project in git_projects:
        maintainers = qisrc.maintainers.get(git_project)
        if not maintainers:
            mess = """\
The project in {src} has no maintainer.
Please edit {qiproject_xml} to silence this warning
"""
            ui.warning(mess.format(src=git_project.src,
                                   qiproject_xml=git_project.qiproject_xml),
                                   end="")
        reviewers = [x['email'] for x in maintainers]
        reviewers.extend(args.reviewers or list())
        # Prefer gerrit logins or groups instead of e-mails
        reviewers = [x.split("@")[0] for x in reviewers]
        git = qisrc.git.Git(git_project.path)
        current_branch = git.get_current_branch()
        if not current_branch:
            ui.error("Not currently on any branch")
            sys.exit(2)
        if git_project.review:
            qisrc.review.push(git_project, current_branch,
                              bypass_review=(not args.review),
                              dry_run=args.dry_run, reviewers=reviewers,
                              topic=args.topic)
        else:
            if args.dry_run:
                git.push("-n")
            else:
                git.push()
Пример #14
0
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
Пример #15
0
def test_qisrc_checkout_with_branch_to_ref(qisrc_action, git_server):
    """ Test QiSrc Checkout With Branch to Ref """
    manifest_url = git_server.manifest_url
    git_server.create_repo("foo.git")
    git_server.create_repo("bar.git")
    git_server.push_file("foo.git", "a.txt", "a")
    git_server.push_tag("foo.git", "v0.1")
    git_server.push_file("foo.git", "b.txt", "b")
    git_server.push_tag("bar.git", "v0.2")
    git_server.push_file("bar.git", "c.txt", "b")
    qisrc_action("init", manifest_url)
    git_server.switch_manifest_branch("devel")
    git_server.set_fixed_ref("foo.git", "v0.1")
    git_server.set_fixed_ref("bar.git", "v0.2")
    git_worktree = TestGitWorkTree()
    foo_proj = git_worktree.get_git_project("foo")
    git = TestGit(foo_proj.path)
    assert git.get_current_branch() == "master"
    qisrc_action("checkout", "devel")
    _, sha1 = git.call("rev-parse", "HEAD", raises=False)
    expected = git.get_ref_sha1("refs/tags/v0.1")
    assert sha1 == expected
    bar_proj = git_worktree.get_git_project("bar")
    bar_git = qisrc.git.Git(bar_proj.path)
    _, sha1 = bar_git.call("rev-parse", "HEAD", raises=False)
    expected = bar_git.get_ref_sha1("refs/tags/v0.2")
    assert sha1 == expected
Пример #16
0
def do(args):
    """ Main entry point """
    git_worktree = qisrc.parsers.get_git_worktree(args)
    git_project = qisrc.parsers.get_one_git_project(git_worktree, args)
    git = qisrc.git.Git(git_project.path)
    current_branch = git.get_current_branch()
    if not current_branch:
        ui.error("Not currently on any branch")
        sys.exit(2)
    if git_project.review:
        maintainers = qisrc.maintainers.get(git_project, warn_if_none=True)
        reviewers = [x['email'] for x in maintainers]
        reviewers.extend(args.reviewers or list())
        # Prefer gerrit logins or groups instead of e-mails
        reviewers = [x.split("@")[0] for x in reviewers]
        qisrc.review.push(git_project, current_branch,
                          bypass_review=(not args.review),
                          dry_run=args.dry_run, reviewers=reviewers,
                          topic=args.topic)
    else:
        if args.dry_run:
            git.push("-n")
        else:
            if args.review and not args.yes:
                mess = """\
The project is not under code review.
Are you sure you want to run `git push` ?
This action cannot be undone\
"""
                answer = qisys.interact.ask_yes_no(mess, default=False)
                if answer:
                    git.push()
            else:
                git.push()
Пример #17
0
def test_switching_from_fixed_ref_to_branch_local_changes(qisrc_action, git_server, record_messages):
    """ Test Swithcing From Fixed Ref To Branch Local Changes """
    git_server.create_repo("foo.git")
    git_server.push_file("foo.git", "a.txt", "a")
    git_server.push_tag("foo.git", "v0.1")
    git_server.push_file("foo.git", "b.txt", "b")
    git_server.push_tag("foo.git", "v0.2")
    git_server.push_file("foo.git", "c.txt", "c")
    git_server.set_fixed_ref("foo.git", "v0.1")
    qisrc_action("init", git_server.manifest_url)
    git_worktree = TestGitWorkTree()
    foo_proj = git_worktree.get_git_project("foo")
    git = TestGit(foo_proj.path)
    git.write_file("a.txt", "unstaged changes")
    git_server.set_branch("foo.git", "master")
    record_messages.reset()
    rc = qisrc_action("sync", retcode=True)
    # ERROR message must be displayed to warn user
    assert rc != 0
    assert record_messages.find("unstaged changes")
    _, sha1 = git.call("rev-parse", "HEAD", raises=False)
    expected = git.get_ref_sha1("refs/tags/v0.1")
    # git repo unchanged
    assert sha1 == expected
    git.call("reset", "--hard")
    qisrc_action("sync", retcode=True)
    # if modification is revert sync must be successful
    assert git.get_current_branch() == "master"
def test_switching_from_fixed_ref_to_branch_local_changes(
        qisrc_action, git_server, record_messages):
    """ Test Swithcing From Fixed Ref To Branch Local Changes """
    git_server.create_repo("foo.git")
    git_server.push_file("foo.git", "a.txt", "a")
    git_server.push_tag("foo.git", "v0.1")
    git_server.push_file("foo.git", "b.txt", "b")
    git_server.push_tag("foo.git", "v0.2")
    git_server.push_file("foo.git", "c.txt", "c")
    git_server.set_fixed_ref("foo.git", "v0.1")
    qisrc_action("init", git_server.manifest_url)
    git_worktree = TestGitWorkTree()
    foo_proj = git_worktree.get_git_project("foo")
    git = TestGit(foo_proj.path)
    git.write_file("a.txt", "unstaged changes")
    git_server.set_branch("foo.git", "master")
    record_messages.reset()
    rc = qisrc_action("sync", retcode=True)
    # ERROR message must be displayed to warn user
    assert rc != 0
    assert record_messages.find("unstaged changes")
    _, sha1 = git.call("rev-parse", "HEAD", raises=False)
    expected = git.get_ref_sha1("refs/tags/v0.1")
    # git repo unchanged
    assert sha1 == expected
    git.call("reset", "--hard")
    qisrc_action("sync", retcode=True)
    # if modification is revert sync must be successful
    assert git.get_current_branch() == "master"
Пример #19
0
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"
Пример #20
0
def test_qisrc_checkout_with_branch_to_ref(qisrc_action, git_server):
    """ Test QiSrc Checkout With Branch to Ref """
    manifest_url = git_server.manifest_url
    git_server.create_repo("foo.git")
    git_server.create_repo("bar.git")
    git_server.push_file("foo.git", "a.txt", "a")
    git_server.push_tag("foo.git", "v0.1")
    git_server.push_file("foo.git", "b.txt", "b")
    git_server.push_tag("bar.git", "v0.2")
    git_server.push_file("bar.git", "c.txt", "b")
    qisrc_action("init", manifest_url)
    git_server.switch_manifest_branch("devel")
    git_server.set_fixed_ref("foo.git", "v0.1")
    git_server.set_fixed_ref("bar.git", "v0.2")
    git_worktree = TestGitWorkTree()
    foo_proj = git_worktree.get_git_project("foo")
    git = TestGit(foo_proj.path)
    assert git.get_current_branch() == "master"
    qisrc_action("checkout", "devel")
    _, sha1 = git.call("rev-parse", "HEAD", raises=False)
    expected = git.get_ref_sha1("refs/tags/v0.1")
    assert sha1 == expected
    bar_proj = git_worktree.get_git_project("bar")
    bar_git = qisrc.git.Git(bar_proj.path)
    _, sha1 = bar_git.call("rev-parse", "HEAD", raises=False)
    expected = bar_git.get_ref_sha1("refs/tags/v0.2")
    assert sha1 == expected
Пример #21
0
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"
Пример #22
0
    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")
Пример #23
0
    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))
Пример #24
0
def do(args):
    """ Main entry point """
    git_worktree = qisrc.parsers.get_git_worktree(args)
    git_project = qisrc.parsers.get_one_git_project(git_worktree, args)
    git = qisrc.git.Git(git_project.path)
    current_branch = git.get_current_branch()
    if not current_branch:
        ui.error("Not currently on any branch")
        sys.exit(2)
    if git_project.review:
        maintainers = qisrc.maintainers.get(git_project, warn_if_none=True)
        reviewers = [x['email'] for x in maintainers]
        reviewers.extend(args.reviewers or list())
        # Prefer gerrit logins or groups instead of e-mails
        reviewers = [x.split("@")[0] for x in reviewers]
        qisrc.review.push(git_project, current_branch,
                          bypass_review=(not args.review),
                          dry_run=args.dry_run, reviewers=reviewers,
                          topic=args.topic)
    else:
        if args.dry_run:
            git.push("-n")
        else:
            if args.review and not args.yes:
                mess = """\
The project is not under code review.
Are you sure you want to run `git push` ?
This action cannot be undone\
"""
                answer = qisys.interact.ask_yes_no(mess, default=False)
                if answer:
                    git.push()
            else:
                git.push()
Пример #25
0
    def push_file(self, project, filename, contents,
                  branch="master", fast_forward=True,
                  message=None):
        """ Push a new file with the given contents to the given project
        It is assumed that the project has beed created

        """
        src = project.replace(".git", "")
        repo_src = self.src.join(src)
        git = qisrc.git.Git(repo_src.strpath)
        if git.get_current_branch() != branch:
            git.checkout("--force", "-B", branch)
        if not fast_forward:
            git.reset("--hard", "HEAD~1")
        to_write = repo_src.join(filename)
        if not message:
            if to_write.check(file=True):
                message = "Update %s" % filename
            else:
                message = "Add %s" % filename
        repo_src.ensure(filename, file=True)
        repo_src.join(filename).write(contents)
        git.add(filename)
        git.commit("--message", message)
        if fast_forward:
            git.push("origin", "%s:%s" % (branch, branch))
        else:
            git.push("origin", "--force", "%s:%s" % (branch, branch))
Пример #26
0
    def push_file(self, project, filename, contents,
                  branch="master", fast_forward=True,
                  message=None):
        """ Push a new file with the given contents to the given project
        It is assumed that the project has been created

        """
        src = project.replace(".git", "")
        repo_src = self.src.join(src)
        git = qisrc.git.Git(repo_src.strpath)
        if git.get_current_branch() != branch:
            git.checkout("--force", "-B", branch)
        if not fast_forward:
            git.reset("--hard", "HEAD~1")
        to_write = repo_src.join(filename)
        if not message:
            if to_write.check(file=True):
                message = "Update %s" % filename
            else:
                message = "Add %s" % filename
        repo_src.ensure(filename, file=True)
        repo_src.join(filename).write(contents)
        git.add(filename)
        git.commit("--message", message)
        if fast_forward:
            git.push("origin", "%s:%s" % (branch, branch))
        else:
            git.push("origin", "--force", "%s:%s" % (branch, branch))
Пример #27
0
def test_use_correct_manifest_branch(git_worktree, git_server):
    git_server.switch_manifest_branch("devel")
    manifest_url = git_server.manifest_url
    worktree_syncer = qisrc.sync.WorkTreeSyncer(git_worktree)
    worktree_syncer.configure_manifest("default", manifest_url, branch="devel")
    local_manifest = git_worktree.tmpdir.join(".qi", "manifests", "default")
    git = qisrc.git.Git(local_manifest.strpath)
    assert git.get_current_branch() == "devel"
Пример #28
0
 def push_manifest(self, message, allow_empty=False):
     """ Push new manifest.xml version """
     manifest_repo = self.root.join("src", "manifest")
     git = qisrc.git.Git(manifest_repo.strpath)
     commit_args = ["--all", "--message", message]
     if allow_empty:
         commit_args.append("--allow-empty")
     git.commit(*commit_args)
     if git.get_current_branch() != self.manifest_branch:
         git.checkout("--force", "-B", self.manifest_branch)
     git.push("origin", "%s:%s" % (self.manifest_branch, self.manifest_branch))
Пример #29
0
 def push_manifest(self, message, allow_empty=False):
     """ Push new manifest.xml version """
     manifest_repo = self.root.join("src", "manifest")
     git = qisrc.git.Git(manifest_repo.strpath)
     commit_args = ["--all", "--message", message]
     if allow_empty:
         commit_args.append("--allow-empty")
     git.commit(*commit_args)
     if git.get_current_branch() != self.manifest_branch:
         git.checkout("--force", "-B", self.manifest_branch)
     git.push("origin", "%s:%s" % (self.manifest_branch, self.manifest_branch))
Пример #30
0
def init_worktree(worktree, manifest_location, setup_review=True):
    """ (re)-intianlize a worktree given a manifest location.
    Clonie any missing repository, set the correct
    remote and tracking branch on every repository

    :param setup_review: Also set up the projects for review
    """
    errors = list()
    manifest = qisrc.manifest.load(manifest_location)
    if not manifest.projects:
        return
    project_count = len(manifest.projects)
    ui.info(ui.green, "Initializing worktree ...")
    setup_ok = True
    for i, project in enumerate(manifest.projects):
        ui.info(
            ui.green, "*", ui.reset, "(%2i/%2i)" % (i+1, project_count),
            ui.blue, project.name)
        # Use the same branch for the project as the branch
        # for the manifest, unless explicitely set:
        p_revision = project.revision
        p_url = project.fetch_url
        p_remote = project.remote
        p_src = project.path
        wt_project = worktree.get_project(p_src)
        if not wt_project:
            # Maybe we just need to add the project to the worktree:
            wt_project = add_if_missing(worktree, p_src, p_remote, p_url)
            if not wt_project:
                wt_project = clone_project(worktree, p_url, src=p_src,
                                           branch=p_revision,
                                           remote=p_remote)
        p_path = wt_project.path
        if project.review and setup_review and setup_ok:
            worktree.set_project_review(p_src, True)
            # If setup failed once, no point in trying for every project
            setup_ok = qisrc.review.setup_project(p_path, project.name,
                                                  project.review_url, p_revision)
        git = qisrc.git.Git(p_path)
        git.set_remote(p_remote, p_url)
        git.set_tracking_branch(p_revision, p_remote)
        cur_branch = git.get_current_branch()
        if cur_branch != p_revision:
            if not cur_branch:
                ui.warning("Project", project.name, "is on a detached HEAD",
                    "but should be on", p_revision)
            else:
                ui.warning("Project", project.name, "is on", cur_branch,
                    "but should be on", p_revision)
        worktree.set_git_project_config(p_src, p_remote, p_revision)
    if not setup_ok:
        qisrc.review.warn_gerrit()
Пример #31
0
    def checkout(self, branch, force=False):  # pylint: disable=too-many-locals,unused-argument
        """ Called by ``qisrc checkout``

        For each project, checkout the branch if it is different than
        the default branch of the manifest.

        """
        ui.info(ui.green, ":: Checkout projects ...")
        errors = list()
        manifest_xml = os.path.join(self.syncer.manifest_repo, "manifest.xml")
        manifest = qisrc.manifest.Manifest(manifest_xml)  # pylint: disable=unused-variable
        to_checkout = list()
        for project in self.git_projects:
            if project.default_branch is None:
                continue
            if project.fixed_ref:
                continue
            branch_name = project.default_branch.name
            git = qisrc.git.Git(project.path)
            if git.get_current_branch() != branch_name:
                to_checkout.append(project)

        n = len(to_checkout)
        if n == 0:
            ui.info(ui.green, "Nothing to checkout")
            return True

        max_src = max([len(x.src) for x in to_checkout])
        for i, project in enumerate(to_checkout):
            ui.info_count(i,
                          n,
                          ui.bold,
                          "Checkout",
                          ui.reset,
                          ui.blue,
                          project.src.ljust(max_src),
                          end="\r")
            if project.default_branch is None:
                continue
            branch_name = project.default_branch.name
            remote_name = project.default_remote.name
            git = qisrc.git.Git(project.path)
            ok, err = git.safe_checkout(branch_name, remote_name, force=force)
            if not ok:
                errors.append((project.src, err))
        if not errors:
            return True
        ui.error("Failed to checkout some projects")
        for (project, error) in errors:
            ui.info(project, ":", error)
        return False
Пример #32
0
 def _sync_git(repo, url, branch, ref):
     git = qisrc.git.Git(repo)
     git.set_remote("origin", url)
     if git.get_current_branch() != branch:
         git.checkout("-B", branch)
     with git.transaction() as transaction:
         git.fetch("origin")
         if ref:
             to_reset = ref
             git.reset("--hard", to_reset)
         else:
             git.reset("--hard", "origin/%s" % branch)
     if not transaction.ok:
         raise Exception("Update failed\n" + transaction.output)
Пример #33
0
 def push_tag(self, project, tag, branch="master", fast_forward=True):
     """ push tag on project """
     src = project.replace(".git", "")
     repo_src = self.src.join(src)
     git = qisrc.git.Git(repo_src.strpath)
     if git.get_current_branch() != branch:
         git.checkout("--force", "-B", branch)
     if not fast_forward:
         git.reset("--hard", "HEAD~1")
     # tag the branch
     git.call("tag", tag)
     if fast_forward:
         git.push("origin", tag)
     else:
         git.push("origin", "--force", tag)
Пример #34
0
 def push_tag(self, project, tag, branch="master", fast_forward=True):
     """ push tag on project """
     src = project.replace(".git", "")
     repo_src = self.src.join(src)
     git = qisrc.git.Git(repo_src.strpath)
     if git.get_current_branch() != branch:
         git.checkout("--force", "-B", branch)
     if not fast_forward:
         git.reset("--hard", "HEAD~1")
     # tag the branch
     git.call("tag", tag)
     if fast_forward:
         git.push("origin", tag)
     else:
         git.push("origin", "--force", tag)
Пример #35
0
 def _sync_manifest(self):
     """ Update the local manifest clone with the remote """
     git = qisrc.git.Git(self.manifest_repo)
     git.set_remote("origin", self.manifest.url)
     if git.get_current_branch() != self.manifest.branch:
         git.checkout("-B", self.manifest.branch)
     with git.transaction() as transaction:
         git.fetch("origin")
         if self.manifest.ref:
             to_reset = self.manifest.ref
             git.reset("--hard", to_reset)
         else:
             git.reset("--hard", "origin/%s" % self.manifest.branch)
     if not transaction.ok:
         raise Exception("Update failed\n" + transaction.output)
Пример #36
0
 def _sync_manifest(self):
     """ Update the local manifest clone with the remote """
     git = qisrc.git.Git(self.manifest_repo)
     git.set_remote("origin", self.manifest.url)
     if git.get_current_branch() != self.manifest.branch:
         git.checkout("-B", self.manifest.branch)
     with git.transaction() as transaction:
         git.fetch("origin")
         if self.manifest.ref:
             to_reset = self.manifest.ref
             git.reset("--hard", to_reset)
         else:
             git.reset("--hard", "origin/%s" % self.manifest.branch)
     if not transaction.ok:
         raise Exception("Update failed\n" + transaction.output)
Пример #37
0
 def checkout(self, branch, force=False):
     """
     Called by ``qisrc checkout``
     For each project, checkout the branch if it is different than
     the default branch of the manifest.
     """
     # FIXME: Why is there a branch parameter if not used
     ui.info(ui.green, ":: Checkout projects ...")
     errors = list()
     to_checkout = list()
     self.branch = branch
     for project in self.git_projects:
         if project.default_branch is None:
             continue
         if project.fixed_ref:
             continue
         branch_name = project.default_branch.name
         git = qisrc.git.Git(project.path)
         if git.get_current_branch() != branch_name:
             to_checkout.append(project)
     n = len(to_checkout)
     if n == 0:
         ui.info(ui.green, "Nothing to checkout")
         return True
     max_src = max([len(x.src) for x in to_checkout])
     for i, project in enumerate(to_checkout):
         ui.info_count(i,
                       n,
                       ui.bold,
                       "Checkout",
                       ui.reset,
                       ui.blue,
                       project.src.ljust(max_src),
                       end="\r")
         if project.default_branch is None:
             continue
         branch_name = project.default_branch.name
         remote_name = project.default_remote.name
         git = qisrc.git.Git(project.path)
         ok, err = git.safe_checkout(branch_name, remote_name, force=force)
         if not ok:
             errors.append((project.src, err))
     if not errors:
         return True
     ui.error("Failed to checkout some projects")
     for (project, error) in errors:
         ui.info(project, ":", error)
     return False
Пример #38
0
 def _safe_checkout(self, project, branch, force=False):
     """ Helper for self.checkout """
     git = qisrc.git.Git(project.path)
     current_branch = git.get_current_branch()
     if not current_branch:
         return False, "not on any branch, skipping"
     clean, error = git.require_clean_worktree()
     if not clean and not force:
         return False, error
     checkout_args = [branch]
     if force:
         checkout_args.append("--force")
     rc, out = git.checkout(*checkout_args, raises=False)
     if rc != 0:
         return False, "Checkout failed " + out
     return True, None
Пример #39
0
def test_switching_from_fixed_ref_to_branch(qisrc_action, git_server):
    git_server.create_repo("foo.git")
    git_server.push_file("foo.git", "a.txt", "a")
    git_server.push_tag("foo.git", "v0.1")
    git_server.push_file("foo.git", "b.txt", "b")
    qisrc_action("init", git_server.manifest_url)
    git_server.set_fixed_ref("foo.git", "v0.1")
    qisrc_action("sync")
    git_worktree = TestGitWorkTree()
    foo_proj = git_worktree.get_git_project("foo")
    git = qisrc.git.Git(foo_proj.path)
    _, sha1 = git.call("rev-parse", "HEAD", raises=False)
    expected = git.get_ref_sha1("refs/tags/v0.1")
    assert sha1 == expected
    git_server.set_branch("foo.git", "master")
    qisrc_action("sync")
    assert git.get_current_branch() == "master"
Пример #40
0
def test_switching_from_fixed_ref_to_branch(qisrc_action, git_server):
    """ Test Switching From Fixed Ref To Branch """
    git_server.create_repo("foo.git")
    git_server.push_file("foo.git", "a.txt", "a")
    git_server.push_tag("foo.git", "v0.1")
    git_server.push_file("foo.git", "b.txt", "b")
    qisrc_action("init", git_server.manifest_url)
    git_server.set_fixed_ref("foo.git", "v0.1")
    qisrc_action("sync")
    git_worktree = TestGitWorkTree()
    foo_proj = git_worktree.get_git_project("foo")
    git = qisrc.git.Git(foo_proj.path)
    _, sha1 = git.call("rev-parse", "HEAD", raises=False)
    expected = git.get_ref_sha1("refs/tags/v0.1")
    assert sha1 == expected
    git_server.set_branch("foo.git", "master")
    qisrc_action("sync")
    assert git.get_current_branch() == "master"
Пример #41
0
def diff_worktree(git_worktree, git_projects, branch, cmd=None):  # pylint: disable=too-many-locals
    """ Run  `git <cmd> local_branch..remote_branch` for every project

    """
    if not cmd:
        cmd = ["log"]
    remote_projects = git_worktree.get_projects_on_branch(branch)
    for git_project in git_projects:
        remote_project = remote_projects.get(git_project.src)
        if not remote_project:
            continue
        git = qisrc.git.Git(git_project.path)
        local_branch = git.get_current_branch()
        if not local_branch:
            message = (ui.brown, "Not on a branch")
        else:
            remote_branch = remote_project.default_branch.name
            remote_ref = "%s/%s" % (remote_project.default_remote.name,
                                    remote_branch)
            rc, out = git.call("merge-base",
                               local_branch,
                               remote_ref,
                               raises=False)
            if rc != 0:
                message = (ui.red, "Calling git merge-base failed")
            else:
                merge_base = out.strip()
                full_cmd = cmd + ["%s..%s" % (merge_base, local_branch)]

                color = ui.config_color(sys.stdout)
                if color:
                    full_cmd.append("--color=always")
                rc, out = git.call(*full_cmd, raises=False)
                if rc != 0:
                    message = (ui.red, "Calling git log failed")
                else:
                    if out:
                        message = (out, )
                    else:
                        continue
        ui.info(ui.bold, git_project.src)
        ui.info(ui.bold, "-" * len(git_project.src))
        ui.info(*message)
        ui.info()
Пример #42
0
def check_state(project, untracked):
    """Check and register the state of a project."""
    state_project = ProjectState(project)

    git = qisrc.git.Git(project.path)

    if not git.is_valid():
        state_project.valid = False
        return state_project

    state_project.clean = git.is_clean(untracked=untracked)
    if project.fixed_ref:
        state_project.ahead, state_project.behind = stat_fixed_ref(
            git, project.fixed_ref)
        state_project.fixed_ref = project.fixed_ref
        _set_status(git, state_project, untracked=untracked)
        return state_project

    state_project.current_branch = git.get_current_branch()
    state_project.tracking = git.get_tracking_branch()
    if project.default_remote and project.default_branch:
        state_project.manifest_branch = "%s/%s" % (project.default_remote.name,
                                                   project.default_branch.name)

    if state_project.current_branch is None:
        state_project.not_on_a_branch = True
        return state_project

    if project.default_branch:
        if state_project.current_branch != project.default_branch.name:
            state_project.incorrect_proj = True

    (state_project.ahead,
     state_project.behind) = stat_tracking_remote(git,
                                                  state_project.current_branch,
                                                  state_project.tracking)
    if state_project.incorrect_proj:
        (state_project.ahead_manifest,
         state_project.behind_manifest) = stat_tracking_remote(
             git, state_project.current_branch, "%s/%s" %
             (project.default_remote.name, project.default_branch.name))

        _set_status(git, state_project, untracked=untracked)
    return state_project
Пример #43
0
def check_state(project, untracked):
    """Check and register the state of a project."""
    state_project = ProjectState(project)

    git = qisrc.git.Git(project.path)

    if not git.is_valid():
        state_project.valid = False
        return state_project

    state_project.clean = git.is_clean(untracked=untracked)
    state_project.current_branch = git.get_current_branch()
    state_project.tracking = git.get_tracking_branch()
    if project.default_remote and project.default_branch:
        state_project.manifest_branch = "%s/%s" % (project.default_remote.name,
                                                   project.default_branch.name)

    if state_project.current_branch is None:
        state_project.not_on_a_branch = True
        return state_project

    if project.default_branch:
        if state_project.current_branch != project.default_branch.name:
            state_project.incorrect_proj = True

    (state_project.ahead,
     state_project.behind) = stat_tracking_remote(git,
                                                  state_project.current_branch,
                                                  state_project.tracking)
    if state_project.incorrect_proj:
        (state_project.ahead_manifest,
         state_project.behind_manifest) = stat_tracking_remote(
             git, state_project.current_branch, "%s/%s" %
             (project.default_remote.name, project.default_branch.name))

    if not state_project.sync_and_clean:
        out = git.get_status(untracked)
        if out is not None:
            state_project.status = [
                x for x in out.splitlines() if len(x.strip()) > 0
            ]

    return state_project
Пример #44
0
    def checkout(self, branch, force=False):
        """ Called by ``qisrc checkout``

        For each project, checkout the branch if it is different than
        the default branch of the manifest.

        """
        ui.info(ui.green, ":: Checkout projects ...")
        errors = list()
        manifest_xml = os.path.join(self._syncer.manifest_repo, "manifest.xml")
        manifest = qisrc.manifest.Manifest(manifest_xml)
        to_checkout = list()
        for project in self.git_projects:
            if project.default_branch is None:
                continue
            branch_name = project.default_branch.name
            git = qisrc.git.Git(project.path)
            if git.get_current_branch() != branch_name:
                to_checkout.append(project)

        n = len(to_checkout)
        if n == 0:
            ui.info(ui.green, "Nothing to checkout")
            return True

        max_src = max([len(x.src) for x in to_checkout])
        for i, project in enumerate(to_checkout):
            ui.info_count(i, n, ui.bold, "Checkout",
                         ui.reset, ui.blue, project.src.ljust(max_src), end="\r")
            if project.default_branch is None:
                continue
            branch_name = project.default_branch.name
            remote_name = project.default_remote.name
            git = qisrc.git.Git(project.path)
            ok, err = git.safe_checkout(branch_name, remote_name, force=force)
            if not ok:
                errors.append((project.src, err))
        if not errors:
            return True
        ui.error("Failed to checkout some projects")
        for (project, error) in errors:
            ui.info(project, ":", error)
        return False
Пример #45
0
    def _sync_manifest(self):
        """ Update the local manifest clone with the remote """
        if not self.manifest.url:
            mess = """ \
No manifest set for worktree in {root}
Please run `qisrc init MANIFEST_URL`
"""
            raise Exception(mess.format(root=self.git_worktree.root))
        git = qisrc.git.Git(self.manifest_repo)
        git.set_remote("origin", self.manifest.url)
        if git.get_current_branch() != self.manifest.branch:
            git.checkout("-B", self.manifest.branch)
        with git.transaction() as transaction:
            git.fetch("origin")
            if self.manifest.ref:
                to_reset = self.manifest.ref
                git.reset("--hard", to_reset)
            else:
                git.reset("--hard", "origin/%s" % self.manifest.branch)
        if not transaction.ok:
            raise Exception("Update failed\n" + transaction.output)
Пример #46
0
def diff_worktree(git_worktree, git_projects, branch, cmd=None):
    """ Run  `git <cmd> local_branch..remote_branch` for every project

    """
    if not cmd:
        cmd = ["log"]
    remote_projects = git_worktree.get_projects_on_branch(branch)
    for git_project in git_projects:
        remote_project = remote_projects.get(git_project.src)
        if not remote_project:
            continue
        git = qisrc.git.Git(git_project.path)
        local_branch = git.get_current_branch()
        if not local_branch:
            message = (ui.brown, "Not on a branch")
        else:
            remote_branch = remote_project.default_branch.name
            remote_ref = "%s/%s" % (remote_project.default_remote.name,
                                    remote_branch)
            if cmd[0] == "diff":
                full_cmd = cmd + [remote_ref, local_branch]
            else:
                full_cmd = cmd + ["%s...%s" % (remote_ref, local_branch)]

            color = ui.config_color(sys.stdout)
            if color:
                full_cmd.append("--color=always")
            rc, out = git.call(*full_cmd, raises=False)
            if rc != 0:
                message = (ui.red, "git", " ".join(full_cmd), "\n", out)
            else:
                if out:
                    message = (out, )
                else:
                    continue
        ui.info(ui.bold, git_project.src)
        ui.info(ui.bold, "-" * len(git_project.src))
        ui.info(*message)
        ui.info()
Пример #47
0
    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")
Пример #48
0
    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))