Esempio n. 1
0
 def _clone_missing(self, git_project, repo):
     """ Clone Missing """
     branch = repo.default_branch
     fixed_ref = repo.fixed_ref
     clone_url = repo.clone_url
     qisys.sh.mkdir(git_project.path, recursive=True)
     git = qisrc.git.Git(git_project.path)
     remote_name = repo.default_remote.name
     try:
         git.init()
         git.remote("add", remote_name, clone_url)
         git.fetch(remote_name, "--quiet")
         if branch:
             git.checkout("-b", branch, "%s/%s" % (remote_name, branch))
         if fixed_ref:
             git.checkout("-q", fixed_ref)
     except Exception:
         ui.error("Cloning repo failed")
         if git.is_empty():
             qisys.sh.rm(git_project.path)
         self.worktree.remove_project(repo.src)
         return False
     self.save_project_config(git_project)
     self.load_git_projects()
     return True
Esempio n. 2
0
def clever_reset_ref(git_project, ref, raises=True):
    """ Resets only if needed, fetches only if needed """
    try:
        remote_name = git_project.default_remote.name
    except AttributeError:
        error_msg = "Project {} has no default remote, defaulting to origin"
        ui.error(error_msg.format(git_project.name))
        remote_name = "origin"
    git = qisrc.git.Git(git_project.path)
    # Deals with "refs/" prefixed ref first
    if ref.startswith("refs/"):
        return _reset_hard_to_refs_prefixed_ref(git,
                                                remote_name,
                                                ref,
                                                raises=raises)
    # Else, ref format is a local name (branch or tag)
    # Check if this ref exists and if we are already in the expected state
    rc, ref_sha1 = git.call("rev-parse", ref, "--", raises=False)
    if rc != 0:
        # Maybe this is a newly pushed tag, try to fetch:
        git.fetch(remote_name, "--prune")
        rc, ref_sha1 = git.call("rev-parse", ref, "--", raises=False)
        if rc != 0:
            return False, "Could not parse %s as a valid ref" % ref
    _, actual_sha1 = git.call("rev-parse", "HEAD", raises=False)
    if actual_sha1 == ref_sha1:  # Nothing to do
        return None if raises else True, ""
    # Reset to the ref local name
    return _reset_hard_to_local_refs_name(git, remote_name, ref, raises=raises)
Esempio n. 3
0
def print_diff(git_project, manifest_branch, destination_branch):
    """
        Show what to merge in prepare_merge_request style
    """
    git = qisrc.git.Git(git_project.path)
    default_remote = git_project.default_remote
    if not default_remote:
        return True
    remote_name = default_remote.name
    if remote_name not in ["origin"]:
        return True
    default_branch = git_project.default_branch
    if not default_branch:
        return True
    if git_project.src == "manifest/default":
        return True
    git.fetch(remote_name, "--prune")
    devel_ref = "%s/%s" % (remote_name, manifest_branch)
    base_ref = "%s/%s" % (remote_name, destination_branch)
    status, message = qisrc.git.get_status(git,
                                           devel_ref,
                                           base_ref,
                                           with_message=True)
    pretty_name = git_project.name.split(".git")[0]
    ui.info(pretty_name, status, message)
    return status in ["no-diff", "ahead"]
Esempio n. 4
0
def fetch_manifest(worktree, manifest_git_url, branch="master",
    profile="default",
    src="manifest/default"):
    """ Fetch the manifest for a worktree

    :param manifest_git_url: A git repository containing a
        'manifest.xml' file, ala repo
    :param branch: The branch to use
    :param src: The path where to store the clone of the manifest

    Note: every changes made by the user directly in the manifest repo
    will be lost!

    """
    manifest = worktree.get_project(src)
    if not manifest:
        clone_project(worktree, manifest_git_url, src=src)
        manifest = worktree.get_project(src)
    # Make sure manifest project is on the correct, up to date branch:
    git = qisrc.git.Git(manifest.path)
    git.set_remote("origin", manifest_git_url)
    git.set_tracking_branch(branch, "origin")
    git.checkout("-f", branch, quiet=True)
    git.fetch(quiet=True)
    git.reset("--hard", "origin/%s" % branch, quiet=True)
    filename = profile + ".xml"
    manifest_file = os.path.join(manifest.path, filename)
    if not os.path.exists(manifest_file):
        mess  = "Could not find a file named '%s' " % filename
        mess += "in the repository: %s\n" % manifest_git_url
        raise Exception(mess)
    return manifest_file
Esempio n. 5
0
def clever_reset_ref(git_project, ref, raises=True):
    """ Resets only if needed, fetches only if needed """
    try:
        remote_name = git_project.default_remote.name
    except AttributeError:
        error_msg = "Project {} has no default remote, defaulting to origin"
        ui.error(error_msg.format(git_project.name))
        remote_name = "origin"
    git = qisrc.git.Git(git_project.path)
    # Deals with "refs/" prefixed ref first
    if ref.startswith("refs/"):
        return _reset_hard_to_refs_prefixed_ref(git, remote_name, ref, raises=raises)
    # Else, ref format is a local name (branch or tag)
    # Check if this ref exists and if we are already in the expected state
    rc, ref_sha1 = git.call("rev-parse", ref, "--", raises=False)
    if rc != 0:
        # Maybe this is a newly pushed tag, try to fetch:
        git.fetch(remote_name)
        rc, ref_sha1 = git.call("rev-parse", ref, "--", raises=False)
        if rc != 0:
            return False, "Could not parse %s as a valid ref" % ref
    _, actual_sha1 = git.call("rev-parse", "HEAD", raises=False)
    if actual_sha1 == ref_sha1:  # Nothing to do
        return None if raises else True, ""
    # Reset to the ref local name
    return _reset_hard_to_local_refs_name(git, remote_name, ref, raises=raises)
Esempio n. 6
0
def test_wrong_setup():
    git = FakeGit("repo")
    git.add_result("checkout", 0, "")
    git.checkout("-f", "master")
    # pylint: disable-msg=E1101
    with pytest.raises(Exception) as e:
        git.fetch()
    assert "Unexpected call to fetch" in e.value.message
Esempio n. 7
0
def test_fake_git_wrong_setup():
    git = FakeGit("repo")
    git.add_result("checkout", 0, "")
    git.checkout("-f", "master")
    # pylint: disable-msg=E1101
    with pytest.raises(Exception) as e:
        git.fetch()
    assert "Unexpected call to fetch" in e.value.args[0]
Esempio n. 8
0
def push(project,
         local_ref,
         remote_branch,
         bypass_review=False,
         dry_run=False,
         reviewers=None,
         topic=None,
         draft=False):
    """ Push the changes for review.

    Unless review is False, in this case, simply update
    the remote gerrit branch

    :param reviewers: A list of reviewers to invite to review

    """
    git = qisrc.git.Git(project.path)
    review_remote = project.review_remote
    args = list()
    if dry_run:
        args.append("--dry-run")
    args.append(review_remote.url)
    if bypass_review:
        args.append("%s:%s" % (local_ref, remote_branch))
    else:
        ui.info("Pushing code to", review_remote.name, "for review.")
        if draft:
            remote_ref = "refs/drafts/%s" % remote_branch
        else:
            remote_ref = "refs/for/%s" % remote_branch
        if topic:
            remote_ref = "%s/%s" % (remote_ref, topic)
        args.append("%s:%s" % (local_ref, remote_ref))
    if reviewers and not dry_run:
        # Get the SHA1s that will be pushed so that we can add reviewers
        remote = project.review_remote
        remote.parse_url()
        server = remote.server
        username = remote.username
        ssh_port = remote.port
        ui.info("Fetching", remote.name)
        git.fetch(remote.name, "--quiet")
        commits_pushed = git.get_log("%s/%s" % (remote.name, remote_branch),
                                     "HEAD")
        sha1s = [commit["sha1"] for commit in commits_pushed]
    ui.info("Publishing changes")
    git.push(*args)
    if reviewers and not dry_run:
        ui.info("Adding reviewers...", ("(" + ", ".join(reviewers) + ")"))
        try:
            set_reviewers(sha1s, reviewers, username, server, ssh_port)
        except qisys.command.CommandFailedException as e:
            ui.warning("Couldn't set reviewers")
            ui.warning(e)
        else:
            ui.info("Done!")
Esempio n. 9
0
def test_commands_are_logged():
    git = FakeGit("repo")
    git.add_result("fetch", 0, "")
    git.add_result("reset", 0, "")
    git.fetch()
    git.reset("--hard", quiet=True)
    calls = git.calls
    assert len(calls) == 2
    assert calls[0][0] == ("fetch",)
    assert calls[1][0] == ("reset", "--hard")
    assert calls[1][1] == {"quiet" : True}
Esempio n. 10
0
def _reset_hard_to_local_refs_name(git, remote_name, ref, raises=True):
    """ deals with the git reset --hard command for short name ref (NOT on the format 'refs/xxx') """
    need_to_fetch, _ = git.call("show", "--oneline", ref, "--", raises=False)
    if need_to_fetch:
        git.fetch(remote_name, "--tags", "--prune")
    # else: SHA-1 already exists locally, no need to fetch
    _, tag_list = git.tag("-l", ref, raises=False)
    is_tag = ref == tag_list
    # Perform effective switch
    rc, out = _switch_to_git_ref(git, ref, is_tag)
    return None if raises else (rc == 0), out
Esempio n. 11
0
def test_fake_git_commands_are_logged():
    git = FakeGit("repo")
    git.add_result("fetch", 0, "")
    git.add_result("reset", 0, "")
    git.fetch()
    git.reset("--hard", quiet=True)
    calls = git.calls
    assert len(calls) == 2
    assert calls[0][0] == ("fetch", )
    assert calls[1][0] == ("reset", "--hard")
    assert calls[1][1] == {"quiet": True}
Esempio n. 12
0
def _reset_hard_to_local_refs_name(git, remote_name, ref, raises=True):
    """ deals with the git reset --hard command for short name ref (NOT on the format 'refs/xxx') """
    need_to_fetch, _ = git.call("show", "--oneline", ref, "--", raises=False)
    if need_to_fetch:
        git.fetch(remote_name, "--tags")
    # else: SHA-1 already exists locally, no need to fetch
    _, tag_list = git.tag("-l", ref, raises=False)
    is_tag = ref == tag_list
    # Perform effective switch
    rc, out = _switch_to_git_ref(git, ref, is_tag)
    return None if raises else (rc == 0), out
Esempio n. 13
0
 def _sync_manifest(self, local_manifest):
     """ Update the local manifest clone with the remote """
     manifest_repo = os.path.join(self.manifests_root, local_manifest.name)
     git = qisrc.git.Git(manifest_repo)
     with git.transaction() as transaction:
         git.fetch("origin")
         git.checkout("-B", local_manifest.branch)
         git.reset("--hard", "origin/%s" % local_manifest.branch)
     if not transaction.ok:
         ui.warning("Update failed")
         ui.info(transaction.output)
         return
Esempio n. 14
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)
Esempio n. 15
0
def clever_reset_ref(git_project, ref, raises=True):
    """ Resets only if needed, fetches only if needed """
    try:
        remote_name = git_project.default_remote.name
    except AttributeError:
        error_msg = "Project {} has no default remote, defaulting to origin"
        ui.error(error_msg.format(git_project.name))
        remote_name = "origin"

    git = qisrc.git.Git(git_project.path)
    if ref.startswith("refs/"):
        if raises:
            git.fetch(remote_name, ref)
            git.reset("--hard", "FETCH_HEAD")
            return
        else:
            with git.tansaction() as transaction:
                git.fetch(remote_name, ref)
                git.reset("--hard", "FETCH_HEAD")
                return transaction.ok, transaction.output

    rc, ref_sha1 = git.call("rev-parse", ref, raises=False)
    if rc != 0:
        # Maybe this is a newly pushed tag, try to fetch:
        git.fetch(remote_name)
        rc, ref_sha1 = git.call("rev-parse", ref, raises=False)
        if rc != 0:
            return False, "Could not parse %s as a valid ref" % ref
    _, actual_sha1 = git.call("rev-parse", "HEAD", raises=False)
    if actual_sha1 == ref_sha1:  # Nothing to do
        if raises:
            return
        else:
            return True, ""
    ret, _ = git.call("show", "--oneline", ref, raises=False)
    if ret == 0:  # SHA-1 exists locally
        if raises:
            git.reset("--hard", ref)
        else:
            rc, out = git.reset("--hard", ref, raises=False)
            return (rc == 0), out
    else:  # Full fetch in this case
        if raises:
            git.fetch(remote_name)
            git.reset("--hard", ref)
        else:
            with git.transaction() as transaction:
                git.fetch(remote_name)
                git.reset("--hard", ref)
            return transaction.ok, transaction.output
Esempio n. 16
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)
Esempio n. 17
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)
Esempio n. 18
0
def push(project,  branch, bypass_review=False, dry_run=False,
         reviewers=None, topic=None):
    """ Push the changes for review.

    Unless review is False, in this case, simply update
    the remote gerrit branch

    :param reviewers: A list of reviewers to invite to review

    """
    git = qisrc.git.Git(project.path)
    review_remote = project.review_remote
    args = list()
    if dry_run:
        args.append("--dry-run")
    args.append(review_remote.url)
    if bypass_review:
        args.append("%s:%s" % (branch, branch))
    else:
        ui.info("Pushing code to", review_remote.name, "for review.")
        remote_ref = "refs/for/%s" % branch
        if topic:
            remote_ref = "%s/%s" % (remote_ref, topic)
        args.append("%s:%s" % (branch, remote_ref))
    if reviewers and not dry_run:
        # Get the SHA1s that will be pushed so that we can add reviewers
        remote = project.review_remote
        remote.parse_url()
        server = remote.server
        username = remote.username
        ssh_port = remote.port
        git.fetch(remote.name)
        commits_pushed = git.get_log("%s/%s" % (remote.name, branch), "HEAD")
        sha1s = [commit["sha1"] for commit in commits_pushed]
    git.push(*args)
    if reviewers and not dry_run:
        ui.info("Adding reviewers...")
        try:
            for sha1 in sha1s:
                set_reviewers(sha1, reviewers, username, server, ssh_port)
        except qisys.command.CommandFailedException as e:
            ui.warning("Couldn't set reviewers")
            ui.warning(e)
        else:
            ui.info("Done!")
Esempio n. 19
0
def _reset_hard_to_refs_prefixed_ref(git, remote_name, ref, raises=True):
    """ deals with the git reset --hard command for long name ref (on the format 'refs/xxx') """
    assert ref.startswith("refs/")
    # Check the ref format to retrieve the effective ref name to switch on
    if ref.startswith("refs/remotes") and "/{}/".format(remote_name) in ref:
        # When the ref format begin with refs/remotes/<remote_name>/, that's the format seen by the local (git show-ref)
        git.fetch(remote_name)
        ref_to_reset_to = ref
        is_tag = False
    else:
        # The ref is in the format seen by a remote (git ls-remote):
        # refs/heads/xxx, refs/tags/xxx, refs/remotes/<other_remote>/xxx, refs/merge-requests/xxx
        git.fetch(remote_name, ref)  # This command will write the pointed commit number into the pseudo ref FETCH_HEAD
        ref_to_reset_to = "FETCH_HEAD"
        is_tag = ref.startswith("refs/tags")
    # Perform effective switch
    rc, out = _switch_to_git_ref(git, ref_to_reset_to, is_tag)
    return None if raises else (rc == 0), out
Esempio n. 20
0
def test_fake_git_fake_call():
    git = FakeGit("repo")
    git.add_result("fetch", 0, "")
    (retcode, _) = git.fetch(raises=False)
    assert retcode == 0
    git2 = FakeGit("repo2")
    git2.add_result("fetch", 2, "Remote end hung up unexpectedly")
    (retcode, out) = git2.fetch(raises=False)
    assert retcode == 2
    assert "Remote end hung up" in out
Esempio n. 21
0
def _reset_hard_to_refs_prefixed_ref(git, remote_name, ref, raises=True):
    """ deals with the git reset --hard command for long name ref (on the format 'refs/xxx') """
    assert ref.startswith("refs/")
    # Check the ref format to retrieve the effective ref name to switch on
    if ref.startswith("refs/remotes") and "/{}/".format(remote_name) in ref:
        # When the ref format begin with refs/remotes/<remote_name>/, that's the format seen by the local (git show-ref)
        git.fetch(remote_name, "--prune")
        ref_to_reset_to = ref
        is_tag = False
    else:
        # The ref is in the format seen by a remote (git ls-remote):
        # refs/heads/xxx, refs/tags/xxx, refs/remotes/<other_remote>/xxx, refs/merge-requests/xxx
        # This command will write the pointed commit number into the pseudo ref FETCH_HEAD
        git.fetch(remote_name, ref, "--prune")
        ref_to_reset_to = "FETCH_HEAD"
        is_tag = ref.startswith("refs/tags")
    # Perform effective switch
    rc, out = _switch_to_git_ref(git, ref_to_reset_to, is_tag)
    return None if raises else (rc == 0), out
Esempio n. 22
0
def test_fake_call():
    git = FakeGit("repo")
    git.add_result("fetch", 0, "")
    (retcode, _) = git.fetch(raises=False)
    assert retcode == 0
    git2 = FakeGit("repo2")
    git2.add_result("fetch", 2, "Remote end hung up unexpectedly")
    (retcode, out) = git2.fetch(raises=False)
    assert retcode == 2
    assert "Remote end hung up" in out
Esempio n. 23
0
 def _clone_missing(self, git_project, repo):
     branch = repo.default_branch
     clone_url = repo.clone_url
     qisys.sh.mkdir(git_project.path, recursive=True)
     git = qisrc.git.Git(git_project.path)
     remote_name = repo.default_remote.name
     try:
         git.init()
         git.remote("add", remote_name, clone_url)
         git.fetch(remote_name, "--quiet")
         git.checkout("-b", branch, "%s/%s" % (remote_name, branch))
     except:
         ui.error("Cloning repo failed")
         if git.is_empty():
             qisys.sh.rm(git_project.path)
         self.worktree.remove_project(repo.src)
         return False
     self.save_project_config(git_project)
     self.load_git_projects()
     return True
Esempio n. 24
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)
Esempio n. 25
0
 def _clone_missing(self, git_project, repo):
     branch = repo.default_branch
     clone_url = repo.clone_url
     qisys.sh.mkdir(git_project.path, recursive=True)
     git = qisrc.git.Git(git_project.path)
     remote_name = repo.default_remote.name
     try:
         git.init()
         git.remote("add", remote_name, clone_url)
         git.fetch(remote_name, "--quiet")
         remote_branch = "%s/%s" % (remote_name, branch)
         rc, _ = git.call("rev-parse", "--verify", "--quiet", remote_branch, raises=False)
         # When `remote_branch` is invalid, try to checkout `branch` instead
         git.checkout("-b", branch, branch if rc else remote_branch)
     except:
         ui.error("Cloning repo failed")
         if git.is_empty():
             qisys.sh.rm(git_project.path)
         self.worktree.remove_project(repo.src)
         return False
     self.save_project_config(git_project)
     self.load_git_projects()
     return True
Esempio n. 26
0
def clever_reset_ref(git_project, ref):
    """ Resets only if needed, fetches only if needed """
    try:
        remote_name = git_project.default_remote.name
    except AttributeError:
        error_msg = "Project {} has no default remote, defaulting to origin"
        ui.error(error_msg.format(git_project.name))
        remote_name = "origin"

    git = qisrc.git.Git(git_project.path)
    if ref.startswith("refs/"):
        git.fetch(remote_name, ref)
        git.reset("--hard", "FETCH_HEAD")
        return
    _, actual_sha1 = git.call("rev-parse", "HEAD", raises=False)
    if actual_sha1 == ref:  # Nothing to do
        return
    ret, _ = git.call("show", "--oneline", ref, raises=False)
    if ret == 0:  # SHA-1 exists locally
        git.reset("--hard", ref)
    else:  # Full fetch in this case
        git.fetch(remote_name)
        git.reset("--hard", ref)
Esempio n. 27
0
 def _clone_missing(self, git_project, repo):
     branch = repo.default_branch
     clone_url = repo.clone_url
     qisys.sh.mkdir(git_project.path, recursive=True)
     git = qisrc.git.Git(git_project.path)
     remote_name = repo.default_remote.name
     try:
         git.init()
         git.remote("add", remote_name, clone_url)
         git.fetch(remote_name, "--quiet")
         remote_branch = "%s/%s" % (remote_name, branch)
         rc, _ = git.call("rev-parse", "--verify", "--quiet", remote_branch, raises=False)
         # When `remote_branch` is invalid, try to checkout `branch` instead
         git.checkout("-b", branch, branch if rc else remote_branch)
     except:
         ui.error("Cloning repo failed")
         if git.is_empty():
             qisys.sh.rm(git_project.path)
         self.worktree.remove_project(repo.src)
         return False
     self.save_project_config(git_project)
     self.load_git_projects()
     return True