Beispiel #1
0
    def __init__(self, repo, message, ref=None, commit_cls=sync_commit.Commit,
                 initial_empty=False):
        """Object to be used as a context manager for commiting changes to the repo.

        This class provides low-level access to the git repository in order to
        make commits without requiring a checkout. It also enforces locking so that
        only one process may make a commit at a time.

        In order to use the object, one initalises it and then invokes it as a context
        manager e.g.

        with CommitBuilder(repo, "Some commit message" ref=ref) as commit_builder:
            # Now we have acquired the lock so that the commit ref points to is fixed
            commit_builder.add_tree({"some/path": "Some file data"})
            commit_bulder.delete(["another/path"])
        # On exiting the context, the commit is created, the ref updated to point at the
        # new commit and the lock released

        # To get the created commit we call get
        commit = commit_builder.get()

        The class may be used reentrantly. This is to support a pattern where a method
        may be called either with an existing commit_builder instance or create a new
        instance, and in either case use a with block.

        In order to improve the performance of the low-level access here, we use libgit2
        to access the repository.
        """
        # Class state
        self.repo = repo
        self.pygit2_repo = pygit2_get(repo)
        self.message = message if message is not None else ""
        self.commit_cls = commit_cls
        self.initial_empty = initial_empty
        if not ref:
            self.ref = None
        elif hasattr(ref, "path"):
            self.ref = ref.path
        else:
            self.ref = ref

        self._count = 0

        # State set for the life of the context manager
        self.lock = RepoLock(repo)
        self.parents = None
        self.commit = None
        self.index = None
        self.has_changes = False
Beispiel #2
0
def do_configure_repos(git_gecko, git_wpt, *args, **kwargs):
    import repos
    name = kwargs.get("repo")
    r = repos.wrappers[name](env.config)
    with RepoLock(r.repo()):
        r.configure(
            os.path.abspath(os.path.normpath(kwargs.get("config_file"))))
Beispiel #3
0
def _update_gecko(git_gecko):
    with RepoLock(git_gecko):
        logger.info("Fetching mozilla-unified")
        # Not using the built in fetch() function since that tries to parse the output
        # and sometimes fails
        git_gecko.git.fetch("mozilla")
        if "autoland" in [item.name for item in git_gecko.remotes]:
            logger.info("Fetching autoland")
            git_gecko.git.fetch("autoland")
Beispiel #4
0
def do_fetch(git_gecko, git_wpt, *args, **kwargs):
    import repos
    c = env.config
    name = kwargs.get("repo")
    r = repos.wrappers[name](c)
    logger.info("Fetching %s in %s..." % (name, r.root))
    pyrepo = r.repo()
    with RepoLock(pyrepo):
        try:
            pyrepo.git.fetch(*r.fetch_args)
        except git.GitCommandError as e:
            # GitPython fails when git warns about adding known host key for new IP
            if re.search(".*Warning: Permanently added.*host key.*",
                         e.stderr) is not None:
                logger.debug(e.stderr)
            else:
                raise e
Beispiel #5
0
def _update_wpt(git_wpt):
    with RepoLock(git_wpt):
        logger.info("Fetching web-platform-tests")
        git_wpt.git.fetch("origin")
Beispiel #6
0
class CommitBuilder(object):
    def __init__(self, repo, message, ref=None, commit_cls=sync_commit.Commit,
                 initial_empty=False):
        """Object to be used as a context manager for commiting changes to the repo.

        This class provides low-level access to the git repository in order to
        make commits without requiring a checkout. It also enforces locking so that
        only one process may make a commit at a time.

        In order to use the object, one initalises it and then invokes it as a context
        manager e.g.

        with CommitBuilder(repo, "Some commit message" ref=ref) as commit_builder:
            # Now we have acquired the lock so that the commit ref points to is fixed
            commit_builder.add_tree({"some/path": "Some file data"})
            commit_bulder.delete(["another/path"])
        # On exiting the context, the commit is created, the ref updated to point at the
        # new commit and the lock released

        # To get the created commit we call get
        commit = commit_builder.get()

        The class may be used reentrantly. This is to support a pattern where a method
        may be called either with an existing commit_builder instance or create a new
        instance, and in either case use a with block.

        In order to improve the performance of the low-level access here, we use libgit2
        to access the repository.
        """
        # Class state
        self.repo = repo
        self.pygit2_repo = pygit2_get(repo)
        self.message = message if message is not None else ""
        self.commit_cls = commit_cls
        self.initial_empty = initial_empty
        if not ref:
            self.ref = None
        elif hasattr(ref, "path"):
            self.ref = ref.path
        else:
            self.ref = ref

        self._count = 0

        # State set for the life of the context manager
        self.lock = RepoLock(repo)
        self.parents = None
        self.commit = None
        self.index = None
        self.has_changes = False

    def __enter__(self):
        self._count += 1
        if self._count != 1:
            return self

        self.lock.__enter__()

        # First we create an empty index
        self.index = pygit2.Index()

        if self.ref is not None:
            try:
                ref = self.pygit2_repo.lookup_reference(self.ref)
            except KeyError:
                self.parents = []
            else:
                self.parents = [ref.peel().id]
                if not self.initial_empty:
                    self.index.read_tree(ref.peel().tree)
        else:
            self.parents = []
        return self

    def __exit__(self, *args, **kwargs):
        self._count -= 1
        if self._count != 0:
            return

        if not self.has_changes:
            if self.parents:
                sha1 = self.parents[0]
            else:
                return None
        else:
            tree_id = self.index.write_tree(self.pygit2_repo)

            sha1 = self.pygit2_repo.create_commit(self.ref,
                                                  self.pygit2_repo.default_signature,
                                                  self.pygit2_repo.default_signature,
                                                  self.message,
                                                  tree_id,
                                                  self.parents)
        self.lock.__exit__(*args, **kwargs)
        self.commit = self.commit_cls(self.repo, sha1)

    def add_tree(self, tree):
        self.has_changes = True
        for path, data in tree.iteritems():
            blob = self.pygit2_repo.create_blob(data)
            index_entry = pygit2.IndexEntry(path, blob, pygit2.GIT_FILEMODE_BLOB)
            self.index.add(index_entry)

    def delete(self, delete):
        self.has_changes = True
        if delete:
            for path in delete:
                self.index.remove(path)

    def get(self):
        return self.commit