Exemple #1
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))
Exemple #2
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))
Exemple #3
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))
Exemple #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
Exemple #5
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}
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}
Exemple #7
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
Exemple #8
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)
Exemple #9
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)
Exemple #10
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)
Exemple #11
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)
Exemple #12
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)
Exemple #13
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)
Exemple #14
0
def _switch_to_git_ref(git, ref_to_reset_to, is_tag):
    """ Switch To Git Ref """
    if is_tag:
        # checkout puts the git current repo in a detached HEAD status
        # As setting a tag in the manifest means oubvioulsy a read-only git copy,
        # The detached HEAD prevents an user to accidentally pull up to the original branch HEAD and commits things
        rc, out = git.checkout(ref_to_reset_to, "--", raises=False)
    else:
        # reset --hard keeps the attached HEAD, and that's probably what the user needs to be able to track changes
        # and commits some things. If the user wants its git copy in read-only, he can use a tag instead of a branch
        rc, out = git.reset("--hard", ref_to_reset_to, "--", raises=False)
    return rc, out
Exemple #15
0
def _switch_to_git_ref(git, ref_to_reset_to, is_tag):
    """ Switch To Git Ref """
    if is_tag:
        # checkout puts the git current repo in a detached HEAD status
        # As setting a tag in the manifest means oubvioulsy a read-only git copy,
        # The detached HEAD prevents an user to accidentally pull up to the original branch HEAD and commits things
        rc, out = git.checkout(ref_to_reset_to, "--", raises=False)
    else:
        # reset --hard keeps the attached HEAD, and that's probably what the user needs to be able to track changes
        # and commits some things. If the user wants its git copy in read-only, he can use a tag instead of a branch
        rc, out = git.reset("--hard", ref_to_reset_to, "--", raises=False)
    return rc, out
Exemple #16
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)
Exemple #17
0
    def _clone_missing(self, git_project, repo, worktree_clone=None):
        # You may be wondering why we use `git clone` when used with the --clone
        # option, and a combination of `git init`, `git fetch`, `git checkout` in
        # the general case.
        # The  reason is that in the general case, we can have the following scenario:
        #  - first foo/bar is created
        #  - then foo/ is added to the manifest
        # In that case, trying to call `git clone` in foo/ will fail
        #
        # But when we are using --clone we know we have sorted the repos to clone
        # by their relative paths in the worktree, (see qisrc.sync.compute_repo_diff)
        # so we know foo/ will always be created before foo/bar/
        branch = repo.default_branch
        fixed_ref = repo.fixed_ref
        clone_url = repo.clone_url
        git = qisrc.git.Git(git_project.path)
        remote_name = repo.default_remote.name
        remote_ref = "%s/%s" % (remote_name, branch)
        clone_project = None
        ok = True
        message = ""
        # Only use a local clone if:
        #   * worktree_clone is set
        #   * we find a matching project in the worktree_clone
        use_local = False
        if worktree_clone:
            clone_project = worktree_clone.find_repo(repo)
            if clone_project:
                use_local = True

        if use_local:
            # Only need to create the parent directory, `git clone` will take
            # care of the rest
            to_make = os.path.dirname(git_project.path)
            qisys.sh.mkdir(to_make)
            (ok, message) = git.local_clone(clone_project, clone_url,
                                            remote_name=remote_name,
                                            branch=branch)
        else:
            # Need to create the full path, since we will use
            # `git init ; git fetch ; git checkout`
            qisys.sh.mkdir(git_project.path, recursive=True)
            (ok, message) = git.safe_clone(clone_url,
                                           remote_name=remote_name,
                                           branch=branch)

        if not ok:
            ui.error("Cloning repo failed")
            ui.error(message)
            # If `git clone` fails, it's possible that the path does
            # not exist
            if os.path.exists(git_project.path) and git.is_empty():
                qisys.sh.rm(git_project.path)
            self.worktree.remove_project(repo.src)
            return False

        if fixed_ref:
            rc, out = git.reset("--hard", fixed_ref, raises=False)
            if rc != 0:
                ui.error("Failed to reset to fixed ref")
                ui.error(out)
                return False

        self.save_project_config(git_project)
        self.load_git_projects()
        return True
Exemple #18
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