Example #1
0
    def write(files):
        repo = Repo(repo_path)

        blobs = {}
        dirs = {}

        def add_to_dirs(path):
            dirname = os.path.dirname(path)

            if path == '':
                return

            add_to_dirs(dirname)
            names = dirs.get(dirname, [])
            if path not in names:
                names.append(path)
            dirs[dirname] = names

        def savedir(dirname):
            tree = Tree()
            names = dirs[dirname]

            for name in names:
                basename = os.path.basename(name)
                sha = blobs.get(name, None)

                if sha is not None:
                    tree.add(basename.encode('utf-8'), 0100644, sha)
                    continue

                subtree = savedir(name)
                tree.add(basename.encode('utf-8'), 040000, subtree.id)

            repo.object_store.add_object(tree)
            return tree

        for metadata in files:
            blob = Blob.from_string(metadata.content)
            repo.object_store.add_object(blob)
            blobs[metadata.path[1:]] = blob.id
            add_to_dirs(metadata.path[1:])

        tree = savedir('')

        commit = Commit()
        commit.tree = tree.id

        commit.author = author.encode('utf-8')
        commit.author_time = author_time
        commit.author_timezone = author_timezone

        commit.committer = committer.encode('utf-8')
        commit.commit_time = commit_time
        commit.commit_timezone = commit_timezone

        commit.encoding = encoding.encode('utf-8')
        commit.message = message.encode('utf-8')

        repo.object_store.add_object(commit)
        repo[ref] = commit.id
Example #2
0
def create_commit(metadata, parents, tree_id):
    """Create a new Git commit object, and add it to the object store.

	Args:
	  metadata: Dictionary containing metadata to construct the commit,
	      including commit message and author data.
	  parents: The parents of this commit.
	  tree: The tree of files to use for this commit.
	Returns:
	  New commit object.
	"""
    commit = Commit()
    commit.tree = tree_id
    commit.author = "%s <%s>" % (metadata["GIT_AUTHOR_NAME"],
                                 metadata["GIT_AUTHOR_EMAIL"])
    commit.author_time = \
        utc_time_from_string(metadata["GIT_AUTHOR_DATE"])
    commit.author_timezone = 0

    commit.committer = "%s <%s>" % (metadata["GIT_COMMITTER_NAME"],
                                    metadata["GIT_COMMITTER_EMAIL"])
    commit.commit_time = \
        utc_time_from_string(metadata["GIT_COMMITTER_DATE"])
    commit.commit_timezone = 0

    commit.encoding = "UTF-8"
    commit.message = metadata["MESSAGE"]
    commit.parents = parents
    gitrepo.object_store.add_object(commit)

    return commit
Example #3
0
def create_commit(metadata, parents, tree_id):
	"""Create a new Git commit object, and add it to the object store.

	Args:
	  metadata: Dictionary containing metadata to construct the commit,
	      including commit message and author data.
	  parents: The parents of this commit.
	  tree: The tree of files to use for this commit.
	Returns:
	  New commit object.
	"""
	commit = Commit()
	commit.tree = tree_id
	commit.author = "%s <%s>" % (metadata["GIT_AUTHOR_NAME"],
	                             metadata["GIT_AUTHOR_EMAIL"])
	commit.author_time = \
	    utc_time_from_string(metadata["GIT_AUTHOR_DATE"])
	commit.author_timezone = 0

	commit.committer = "%s <%s>" % (metadata["GIT_COMMITTER_NAME"],
	                                metadata["GIT_COMMITTER_EMAIL"])
	commit.commit_time = \
	    utc_time_from_string(metadata["GIT_COMMITTER_DATE"])
	commit.commit_timezone = 0

	commit.encoding = "UTF-8"
	commit.message = metadata["MESSAGE"]
	commit.parents = parents
	gitrepo.object_store.add_object(commit)

	return commit
Example #4
0
File: start.py Project: Swizec/OS2
def init_the_git(config):
    path = config.get('Local', 'path')

    repo = Repo.init(path)
    blob = Blob.from_string(
        open(os.path.join(path, '.git-dropbox.cnf')).read())

    tree = Tree()
    tree.add(".git-dropbox.cnf", 0100644, blob.id)

    commit = Commit()
    commit.tree = tree.id
    commit.author = config.get('Local', 'user')
    commit.committer = 'Git-dropbox'
    commit.commit_time = int(time())
    commit.author_time = os.path.getctime(
        os.path.join(path, '.git-dropbox.cnf'))
    commit.commit_timezone = commit.author_timezone = parse_timezone(
        '-0200')[0]
    commit.encoding = 'UTF-8'
    commit.message = 'Initial commit'

    object_store = repo.object_store
    object_store.add_object(blob)
    object_store.add_object(tree)
    object_store.add_object(commit)

    repo.refs['refs/heads/master'] = commit.id
Example #5
0
 def commit_handler(self, cmd):
     """Process a CommitCommand."""
     commit = Commit()
     if cmd.author is not None:
         author = cmd.author
     else:
         author = cmd.committer
     (author_name, author_email, author_timestamp, author_timezone) = author
     (committer_name, committer_email, commit_timestamp,
      commit_timezone) = cmd.committer
     commit.author = author_name + b" <" + author_email + b">"
     commit.author_timezone = author_timezone
     commit.author_time = int(author_timestamp)
     commit.committer = committer_name + b" <" + committer_email + b">"
     commit.commit_timezone = commit_timezone
     commit.commit_time = int(commit_timestamp)
     commit.message = cmd.message
     commit.parents = []
     if cmd.from_:
         self._reset_base(cmd.from_)
     for filecmd in cmd.iter_files():
         if filecmd.name == b"filemodify":
             if filecmd.data is not None:
                 blob = Blob.from_string(filecmd.data)
                 self.repo.object_store.add(blob)
                 blob_id = blob.id
             else:
                 assert filecmd.dataref.startswith(b":"), \
                        ("non-marker refs not supported yet (%r)" %
                         filecmd.dataref)
                 blob_id = self.markers[filecmd.dataref[1:]]
             self._contents[filecmd.path] = (filecmd.mode, blob_id)
         elif filecmd.name == b"filedelete":
             del self._contents[filecmd.path]
         elif filecmd.name == b"filecopy":
             self._contents[filecmd.dest_path] = self._contents[
                 filecmd.src_path]
         elif filecmd.name == b"filerename":
             self._contents[filecmd.new_path] = self._contents[
                 filecmd.old_path]
             del self._contents[filecmd.old_path]
         elif filecmd.name == b"filedeleteall":
             self._contents = {}
         else:
             raise Exception("Command %s not supported" % filecmd.name)
     commit.tree = commit_tree(
         self.repo.object_store,
         ((path, hexsha, mode)
          for (path, (mode, hexsha)) in self._contents.items()))
     if self.last_commit != ZERO_SHA:
         commit.parents.append(self.last_commit)
     for merge in cmd.merges:
         if merge.startswith(b':'):
             merge = self.markers[merge[1:]]
         commit.parents.append(merge)
     self.repo.object_store.add_object(commit)
     self.repo[cmd.ref] = commit.id
     self.last_commit = commit.id
     if cmd.mark:
         self.markers[cmd.mark] = commit.id
Example #6
0
 def commit_handler(self, cmd):
     """Process a CommitCommand."""
     commit = Commit()
     if cmd.author is not None:
         author = cmd.author
     else:
         author = cmd.committer
     (author_name, author_email, author_timestamp, author_timezone) = author
     (committer_name, committer_email, commit_timestamp, commit_timezone) = cmd.committer
     commit.author = "%s <%s>" % (author_name, author_email)
     commit.author_timezone = author_timezone
     commit.author_time = int(author_timestamp)
     commit.committer = "%s <%s>" % (committer_name, committer_email)
     commit.commit_timezone = commit_timezone
     commit.commit_time = int(commit_timestamp)
     commit.message = cmd.message
     commit.parents = []
     contents = {}
     commit.tree = commit_tree(
         self.repo.object_store, ((path, hexsha, mode) for (path, (mode, hexsha)) in contents.iteritems())
     )
     if self.last_commit is not None:
         commit.parents.append(self.last_commit)
     commit.parents += cmd.merges
     self.repo.object_store.add_object(commit)
     self.repo[cmd.ref] = commit.id
     self.last_commit = commit.id
     if cmd.mark:
         self.markers[cmd.mark] = commit.id
Example #7
0
File: start.py Project: Swizec/OS2
def init_the_git(config):
    path = config.get('Local', 'path')

    repo = Repo.init(path)
    blob = Blob.from_string(open(os.path.join(path, '.git-dropbox.cnf')).read())

    tree = Tree()
    tree.add(".git-dropbox.cnf", 0100644, blob.id)

    commit = Commit()
    commit.tree = tree.id
    commit.author = config.get('Local', 'user')
    commit.committer = 'Git-dropbox'
    commit.commit_time = int(time())
    commit.author_time = os.path.getctime(os.path.join(path, '.git-dropbox.cnf'))
    commit.commit_timezone = commit.author_timezone = parse_timezone('-0200')[0]
    commit.encoding = 'UTF-8'
    commit.message = 'Initial commit'

    object_store = repo.object_store
    object_store.add_object(blob)
    object_store.add_object(tree)
    object_store.add_object(commit)

    repo.refs['refs/heads/master'] = commit.id
Example #8
0
File: patch.py Project: tmc/dulwich
def git_am_patch_split(f):
    """Parse a git-am-style patch and split it up into bits.

    :param f: File-like object to parse
    :return: Tuple with commit object, diff contents and git version
    """
    msg = rfc822.Message(f)
    c = Commit()
    c.author = msg["from"]
    c.committer = msg["from"]
    if msg["subject"].startswith("[PATCH"):
        subject = msg["subject"].split("]", 1)[1][1:]
    else:
        subject = msg["subject"]
    c.message = subject
    for l in f:
        if l == "---\n":
            break
        c.message += l
    diff = ""
    for l in f:
        if l == "-- \n":
            break
        diff += l
    version = f.next().rstrip("\n")
    return c, diff, version
Example #9
0
    def do_commit(self, message, committer=None,
                  author=None, commit_timestamp=None,
                  commit_timezone=None, author_timestamp=None,
                  author_timezone=None, tree=None):
        """Create a new commit.

        :param message: Commit message
        :param committer: Committer fullname
        :param author: Author fullname (defaults to committer)
        :param commit_timestamp: Commit timestamp (defaults to now)
        :param commit_timezone: Commit timestamp timezone (defaults to GMT)
        :param author_timestamp: Author timestamp (defaults to commit timestamp)
        :param author_timezone: Author timestamp timezone
            (defaults to commit timestamp timezone)
        :param tree: SHA1 of the tree root to use (if not specified the current index will be committed).
        :return: New commit SHA1
        """
        import time
        c = Commit()
        if tree is None:
            index = self.open_index()
            c.tree = index.commit(self.object_store)
        else:
            c.tree = tree
        # TODO: Allow username to be missing, and get it from .git/config
        if committer is None:
            raise ValueError("committer not set")
        c.committer = committer
        if commit_timestamp is None:
            commit_timestamp = time.time()
        c.commit_time = int(commit_timestamp)
        if commit_timezone is None:
            # FIXME: Use current user timezone rather than UTC
            commit_timezone = 0
        c.commit_timezone = commit_timezone
        if author is None:
            author = committer
        c.author = author
        if author_timestamp is None:
            author_timestamp = commit_timestamp
        c.author_time = int(author_timestamp)
        if author_timezone is None:
            author_timezone = commit_timezone
        c.author_timezone = author_timezone
        c.message = message
        try:
            old_head = self.refs["HEAD"]
            c.parents = [old_head]
            self.object_store.add_object(c)
            ok = self.refs.set_if_equals("HEAD", old_head, c.id)
        except KeyError:
            c.parents = []
            self.object_store.add_object(c)
            ok = self.refs.add_if_new("HEAD", c.id)
        if not ok:
            # Fail if the atomic compare-and-swap failed, leaving the commit and
            # all its objects as garbage.
            raise CommitError("HEAD changed during commit")

        return c.id
Example #10
0
def parse_patch_message(msg, encoding=None):
    """Extract a Commit object and patch from an e-mail message.

    Args:
      msg: An email message (email.message.Message)
      encoding: Encoding to use to encode Git commits
    Returns: Tuple with commit object, diff contents and git version
    """
    c = Commit()
    c.author = msg["from"].encode(encoding)
    c.committer = msg["from"].encode(encoding)
    try:
        patch_tag_start = msg["subject"].index("[PATCH")
    except ValueError:
        subject = msg["subject"]
    else:
        close = msg["subject"].index("] ", patch_tag_start)
        subject = msg["subject"][close + 2:]
    c.message = (subject.replace("\n", "") + "\n").encode(encoding)
    first = True

    body = msg.get_payload(decode=True)
    lines = body.splitlines(True)
    line_iter = iter(lines)

    for line in line_iter:
        if line == b"---\n":
            break
        if first:
            if line.startswith(b"From: "):
                c.author = line[len(b"From: "):].rstrip()
            else:
                c.message += b"\n" + line
            first = False
        else:
            c.message += line
    diff = b""
    for line in line_iter:
        if line == b"-- \n":
            break
        diff += line
    try:
        version = next(line_iter).rstrip(b"\n")
    except StopIteration:
        version = None
    return c, diff, version
Example #11
0
def parse_patch_message(msg, encoding=None):
    """Extract a Commit object and patch from an e-mail message.

    :param msg: An email message (email.message.Message)
    :param encoding: Encoding to use to encode Git commits
    :return: Tuple with commit object, diff contents and git version
    """
    c = Commit()
    c.author = msg["from"].encode(encoding)
    c.committer = msg["from"].encode(encoding)
    try:
        patch_tag_start = msg["subject"].index("[PATCH")
    except ValueError:
        subject = msg["subject"]
    else:
        close = msg["subject"].index("] ", patch_tag_start)
        subject = msg["subject"][close+2:]
    c.message = (subject.replace("\n", "") + "\n").encode(encoding)
    first = True

    body = msg.get_payload(decode=True)
    lines = body.splitlines(True)
    line_iter = iter(lines)

    for l in line_iter:
        if l == b"---\n":
            break
        if first:
            if l.startswith(b"From: "):
                c.author = l[len(b"From: "):].rstrip()
            else:
                c.message += b"\n" + l
            first = False
        else:
            c.message += l
    diff = b""
    for l in line_iter:
        if l == b"-- \n":
            break
        diff += l
    try:
        version = next(line_iter).rstrip(b"\n")
    except StopIteration:
        version = None
    return c, diff, version
Example #12
0
def git_am_patch_split(f):
    """Parse a git-am-style patch and split it up into bits.

    :param f: File-like object to parse
    :return: Tuple with commit object, diff contents and git version
    """
    parser = email.parser.Parser()
    msg = parser.parse(f)
    c = Commit()
    c.author = msg["from"]
    c.committer = msg["from"]
    try:
        patch_tag_start = msg["subject"].index("[PATCH")
    except ValueError:
        subject = msg["subject"]
    else:
        close = msg["subject"].index("] ", patch_tag_start)
        subject = msg["subject"][close+2:]
    c.message = subject.replace("\n", "") + "\n"
    first = True

    body = BytesIO(msg.get_payload())

    for l in body:
        if l == "---\n":
            break
        if first:
            if l.startswith("From: "):
                c.author = l[len("From: "):].rstrip()
            else:
                c.message += "\n" + l
            first = False
        else:
            c.message += l
    diff = ""
    for l in body:
        if l == "-- \n":
            break
        diff += l
    try:
        version = next(body).rstrip("\n")
    except StopIteration:
        version = None
    return c, diff, version
Example #13
0
def git_am_patch_split(f):
    """Parse a git-am-style patch and split it up into bits.

    :param f: File-like object to parse
    :return: Tuple with commit object, diff contents and git version
    """
    parser = email.parser.Parser()
    msg = parser.parse(f)
    c = Commit()
    c.author = msg["from"]
    c.committer = msg["from"]
    try:
        patch_tag_start = msg["subject"].index("[PATCH")
    except ValueError:
        subject = msg["subject"]
    else:
        close = msg["subject"].index("] ", patch_tag_start)
        subject = msg["subject"][close+2:]
    c.message = subject.replace("\n", "") + "\n"
    first = True

    body = BytesIO(msg.get_payload())

    for l in body:
        if l == "---\n":
            break
        if first:
            if l.startswith("From: "):
                c.author = l[len("From: "):].rstrip()
            else:
                c.message += "\n" + l
            first = False
        else:
            c.message += l
    diff = ""
    for l in body:
        if l == "-- \n":
            break
        diff += l
    try:
        version = next(body).rstrip("\n")
    except StopIteration:
        version = None
    return c, diff, version
Example #14
0
 def commit_handler(self, cmd):
     """Process a CommitCommand."""
     commit = Commit()
     if cmd.author is not None:
         author = cmd.author
     else:
         author = cmd.committer
     (author_name, author_email, author_timestamp, author_timezone) = author
     (committer_name, committer_email, commit_timestamp,
         commit_timezone) = cmd.committer
     commit.author = author_name + b" <" + author_email + b">"
     commit.author_timezone = author_timezone
     commit.author_time = int(author_timestamp)
     commit.committer = committer_name + b" <" + committer_email + b">"
     commit.commit_timezone = commit_timezone
     commit.commit_time = int(commit_timestamp)
     commit.message = cmd.message
     commit.parents = []
     if cmd.from_:
         cmd.from_ = self.lookup_object(cmd.from_)
         self._reset_base(cmd.from_)
     for filecmd in cmd.iter_files():
         if filecmd.name == b"filemodify":
             if filecmd.data is not None:
                 blob = Blob.from_string(filecmd.data)
                 self.repo.object_store.add(blob)
                 blob_id = blob.id
             else:
                 blob_id = self.lookup_object(filecmd.dataref)
             self._contents[filecmd.path] = (filecmd.mode, blob_id)
         elif filecmd.name == b"filedelete":
             del self._contents[filecmd.path]
         elif filecmd.name == b"filecopy":
             self._contents[filecmd.dest_path] = self._contents[
                 filecmd.src_path]
         elif filecmd.name == b"filerename":
             self._contents[filecmd.new_path] = self._contents[
                 filecmd.old_path]
             del self._contents[filecmd.old_path]
         elif filecmd.name == b"filedeleteall":
             self._contents = {}
         else:
             raise Exception("Command %s not supported" % filecmd.name)
     commit.tree = commit_tree(
         self.repo.object_store,
         ((path, hexsha, mode) for (path, (mode, hexsha)) in
             self._contents.items()))
     if self.last_commit != ZERO_SHA:
         commit.parents.append(self.last_commit)
     for merge in cmd.merges:
         commit.parents.append(self.lookup_object(merge))
     self.repo.object_store.add_object(commit)
     self.repo[cmd.ref] = commit.id
     self.last_commit = commit.id
     if cmd.mark:
         self.markers[cmd.mark] = commit.id
Example #15
0
    def export_hg_commit(self, rev):
        self.ui.note(_("converting revision %s\n") % hex(rev))

        oldenc = self.swap_out_encoding()

        ctx = self.repo.changectx(rev)
        extra = ctx.extra()

        commit = Commit()

        (time, timezone) = ctx.date()
        commit.author = self.get_git_author(ctx)
        commit.author_time = int(time)
        commit.author_timezone = -timezone

        if 'committer' in extra:
            # fixup timezone
            (name, timestamp, timezone) = extra['committer'].rsplit(' ', 2)
            commit.committer = name
            commit.commit_time = timestamp

            # work around a timezone format change
            if int(timezone) % 60 != 0: #pragma: no cover
                timezone = parse_timezone(timezone)
                # Newer versions of Dulwich return a tuple here
                if isinstance(timezone, tuple):
                    timezone, neg_utc = timezone
                    commit._commit_timezone_neg_utc = neg_utc
            else:
                timezone = -int(timezone)
            commit.commit_timezone = timezone
        else:
            commit.committer = commit.author
            commit.commit_time = commit.author_time
            commit.commit_timezone = commit.author_timezone

        commit.parents = []
        for parent in self.get_git_parents(ctx):
            hgsha = hex(parent.node())
            git_sha = self.map_git_get(hgsha)
            if git_sha:
                commit.parents.append(git_sha)

        commit.message = self.get_git_message(ctx)

        if 'encoding' in extra:
            commit.encoding = extra['encoding']

        tree_sha = commit_tree(self.git.object_store, self.iterblobs(ctx))
        commit.tree = tree_sha

        self.git.object_store.add_object(commit)
        self.map_set(commit.id, ctx.hex())

        self.swap_out_encoding(oldenc)
        return commit.id
Example #16
0
    def export_hg_commit(self, rev):
        self.ui.note(_("converting revision %s\n") % hex(rev))

        oldenc = self.swap_out_encoding()

        ctx = self.repo.changectx(rev)
        extra = ctx.extra()

        commit = Commit()

        (time, timezone) = ctx.date()
        commit.author = self.get_git_author(ctx)
        commit.author_time = int(time)
        commit.author_timezone = -timezone

        if 'committer' in extra:
            # fixup timezone
            (name, timestamp, timezone) = extra['committer'].rsplit(' ', 2)
            commit.committer = name
            commit.commit_time = timestamp

            # work around a timezone format change
            if int(timezone) % 60 != 0: #pragma: no cover
                timezone = parse_timezone(timezone)
                # Newer versions of Dulwich return a tuple here
                if isinstance(timezone, tuple):
                    timezone, neg_utc = timezone
                    commit._commit_timezone_neg_utc = neg_utc
            else:
                timezone = -int(timezone)
            commit.commit_timezone = timezone
        else:
            commit.committer = commit.author
            commit.commit_time = commit.author_time
            commit.commit_timezone = commit.author_timezone

        commit.parents = []
        for parent in self.get_git_parents(ctx):
            hgsha = hex(parent.node())
            git_sha = self.map_git_get(hgsha)
            if git_sha:
                commit.parents.append(git_sha)

        commit.message = self.get_git_message(ctx)

        if 'encoding' in extra:
            commit.encoding = extra['encoding']

        tree_sha = commit_tree(self.git.object_store, self.iterblobs(ctx))
        commit.tree = tree_sha

        self.git.object_store.add_object(commit)
        self.map_set(commit.id, ctx.hex())

        self.swap_out_encoding(oldenc)
        return commit.id
Example #17
0
 def test_commit(self):
     c = Commit()
     c.tree = b"cc9462f7f8263ef5adfbeff2fb936bb36b504cba"
     c.message = b"Some message"
     c.committer = b"Committer <Committer>"
     c.commit_time = 4
     c.commit_timezone = -60 * 3
     c.author_time = 5
     c.author_timezone = 60 * 2
     c.author = b"Author <author>"
     self.assertRoundtripCommit(c)
Example #18
0
 def _get_test_commit(self):
     c = Commit()
     c.committer = b"Jelmer <*****@*****.**>"
     c.commit_time = 0
     c.commit_timezone = 0
     c.author = b"Jelmer <*****@*****.**>"
     c.author_time = 0
     c.author_timezone = 0
     c.message = b"Teh foo bar"
     c.tree = b"cc9462f7f8263ef5adfbeff2fb936bb36b504cba"
     return c
Example #19
0
 def test_commit_double_negative_timezone(self):
     c = Commit()
     c.tree = b"cc9462f7f8263ef5adfbeff2fb936bb36b504cba"
     c.message = b"Some message"
     c.committer = b"Committer <Committer>"
     c.commit_time = 4
     (c.commit_timezone, c._commit_timezone_neg_utc) = parse_timezone(b"--700")
     c.author_time = 5
     c.author_timezone = 60 * 2
     c.author = b"Author <author>"
     self.assertRoundtripCommit(c)
Example #20
0
 def test_commit_extra(self):
     c = Commit()
     c.tree = b"cc9462f7f8263ef5adfbeff2fb936bb36b504cba"
     c.message = b"Some message"
     c.committer = b"Committer <Committer>"
     c.commit_time = 4
     c.commit_timezone = -60 * 3
     c.author_time = 5
     c.author_timezone = 60 * 2
     c.author = b"Author <author>"
     c._extra = [(b"HG:rename-source", b"hg")]
     self.assertRoundtripCommit(c)
Example #21
0
 def make_base(self):
     c = Commit()
     c.tree = 'd80c186a03f423a81b39df39dc87fd269736ca86'
     c.parents = ['ab64bbdcc51b170d21588e5c5d391ee5c0c96dfd', '4cffe90e0a41ad3f5190079d7c8f036bde29cbe6']
     c.author = 'James Westby <*****@*****.**>'
     c.committer = 'James Westby <*****@*****.**>'
     c.commit_time = 1174773719
     c.author_time = 1174773719
     c.commit_timezone = 0
     c.author_timezone = 0
     c.message =  'Merge ../b\n'
     return c
Example #22
0
 def make_base(self):
     c = Commit()
     c.tree = 'd80c186a03f423a81b39df39dc87fd269736ca86'
     c.parents = ['ab64bbdcc51b170d21588e5c5d391ee5c0c96dfd', '4cffe90e0a41ad3f5190079d7c8f036bde29cbe6']
     c.author = 'James Westby <*****@*****.**>'
     c.committer = 'James Westby <*****@*****.**>'
     c.commit_time = 1174773719
     c.author_time = 1174773719
     c.commit_timezone = 0
     c.author_timezone = 0
     c.message =  'Merge ../b\n'
     return c
Example #23
0
    def commit(self):
        # XXX: evidence for the rest of
        # this functions is supposed not to exist
        # yes, its that
        # XXX: generate all objects at once and
        #     add them as pack instead of legacy objects
        r = self.repo.repo
        store = r.object_store
        new_objects = []
        names = sorted(self.contents)
        nametree = defaultdict(list)
        for name in names:
            base = name.strip('/')
            while base:
                nbase = os.path.dirname(base)
                nametree[nbase].append(base)
                base = nbase

        if self.base_commit:
            tree = r.tree(self.base_commit.commit.tree)
            tree._ensure_parsed()
            print tree._entries
        else:
            tree = Tree()

        for src, dest in self.renames:
            src = src.strip('/')
            dest = dest.strip('/')
            tree[dest] = tree[src]
            del tree[src]

        for name in names:
            blob = Blob()
            blob.data = self.contents[name]
            new_objects.append((blob, name))
            tree.add(0555, os.path.basename(name), blob.id)

        new_objects.append((tree, ''))
        commit = Commit()
        if self.base_commit:
            commit.parents = [self.base_commit.commit.id]
        commit.tree = tree.id
        commit.message = self.extra['message']
        commit.committer = self.author
        commit.commit_time = int(self.time_unix)
        commit.commit_timezone = self.time_offset
        commit.author = self.author
        commit.author_time = int(self.time_unix)
        commit.author_timezone = self.time_offset
        new_objects.append((commit, ''))
        store.add_objects(new_objects)
        self.repo.repo.refs['HEAD'] = commit.id
Example #24
0
 def test_invalid_utf8(self):
     c = Commit()
     c.tree = b"cc9462f7f8263ef5adfbeff2fb936bb36b504cba"
     c.message = b"Some message \xc1"
     c.committer = b"Committer"
     c.commit_time = 4
     c.author_time = 5
     c.commit_timezone = 60 * 5
     c.author_timezone = 60 * 3
     c.author = b"Author"
     mapping = BzrGitMappingv1()
     self.assertEqual(mapping.revision_id_foreign_to_bzr(c.id),
                      mapping.get_revision_id(c))
Example #25
0
 def commit(self, message):
     self._validate_unicode_text(message, 'commit message')
     c = Commit()
     c.parents = [
         self.repository.lookup_bzr_revision_id(revid)[0]
         for revid in self.parents
     ]
     c.tree = commit_tree(self.store, self._iterblobs())
     encoding = self._revprops.pop(u'git-explicit-encoding', 'utf-8')
     c.encoding = encoding.encode('ascii')
     c.committer = fix_person_identifier(self._committer.encode(encoding))
     try:
         author = self._revprops.pop('author')
     except KeyError:
         try:
             authors = self._revprops.pop('authors').splitlines()
         except KeyError:
             author = self._committer
         else:
             if len(authors) > 1:
                 raise Exception("Unable to convert multiple authors")
             elif len(authors) == 0:
                 author = self._committer
             else:
                 author = authors[0]
     c.author = fix_person_identifier(author.encode(encoding))
     bugstext = self._revprops.pop('bugs', None)
     if bugstext is not None:
         message += "\n"
         for url, status in bugtracker.decode_bug_urls(bugstext):
             if status == bugtracker.FIXED:
                 message += "Fixes: %s\n" % url
             elif status == bugtracker.RELATED:
                 message += "Bug: %s\n" % url
             else:
                 raise bugtracker.InvalidBugStatus(status)
     if self._revprops:
         raise NotImplementedError(self._revprops)
     c.commit_time = int(self._timestamp)
     c.author_time = int(self._timestamp)
     c.commit_timezone = self._timezone
     c.author_timezone = self._timezone
     c.message = message.encode(encoding)
     if (self._config_stack.get('create_signatures') ==
             _mod_config.SIGN_ALWAYS):
         strategy = gpg.GPGStrategy(self._config_stack)
         c.gpgsig = strategy.sign(c.as_raw_string(), gpg.MODE_DETACH)
     self.store.add_object(c)
     self.repository.commit_write_group()
     self._new_revision_id = self._mapping.revision_id_foreign_to_bzr(c.id)
     return self._new_revision_id
Example #26
0
 def test_unknown_extra(self):
     c = Commit()
     c.tree = b"cc9462f7f8263ef5adfbeff2fb936bb36b504cba"
     c.message = b"Some message"
     c.committer = b"Committer"
     c.commit_time = 4
     c.author_time = 5
     c.commit_timezone = 60 * 5
     c.author_timezone = 60 * 3
     c.author = b"Author"
     c._extra.append((b"iamextra", b"foo"))
     mapping = BzrGitMappingv1()
     self.assertRaises(UnknownCommitExtra, mapping.import_commit, c,
                       mapping.revision_id_foreign_to_bzr)
Example #27
0
    def do_commit(self, message, committer=None, 
                  author=None, commit_timestamp=None,
                  commit_timezone=None, author_timestamp=None, 
                  author_timezone=None, tree=None):
        """Create a new commit.

        :param message: Commit message
        :param committer: Committer fullname
        :param author: Author fullname (defaults to committer)
        :param commit_timestamp: Commit timestamp (defaults to now)
        :param commit_timezone: Commit timestamp timezone (defaults to GMT)
        :param author_timestamp: Author timestamp (defaults to commit timestamp)
        :param author_timezone: Author timestamp timezone 
            (defaults to commit timestamp timezone)
        :param tree: SHA1 of the tree root to use (if not specified the current index will be committed).
        :return: New commit SHA1
        """
        import time
        index = self.open_index()
        c = Commit()
        if tree is None:
            c.tree = index.commit(self.object_store)
        else:
            c.tree = tree
        # TODO: Allow username to be missing, and get it from .git/config
        if committer is None:
            raise ValueError("committer not set")
        c.committer = committer
        if commit_timestamp is None:
            commit_timestamp = time.time()
        c.commit_time = int(commit_timestamp)
        if commit_timezone is None:
            # FIXME: Use current user timezone rather than UTC
            commit_timezone = 0
        c.commit_timezone = commit_timezone
        if author is None:
            author = committer
        c.author = author
        if author_timestamp is None:
            author_timestamp = commit_timestamp
        c.author_time = int(author_timestamp)
        if author_timezone is None:
            author_timezone = commit_timezone
        c.author_timezone = author_timezone
        c.message = message
        self.object_store.add_object(c)
        self.refs["HEAD"] = c.id
        return c.id
Example #28
0
 def test_unknown_hg_fields(self):
     c = Commit()
     c.tree = b"cc9462f7f8263ef5adfbeff2fb936bb36b504cba"
     c.message = b"Some message"
     c.committer = b"Committer"
     c.commit_time = 4
     c.author_time = 5
     c.commit_timezone = 60 * 5
     c.author_timezone = 60 * 3
     c.author = b"Author"
     c._extra = [(b"HG:extra", b"bla:Foo")]
     mapping = BzrGitMappingv1()
     self.assertRaises(UnknownMercurialCommitExtra, mapping.import_commit,
                       c, mapping.revision_id_foreign_to_bzr)
     self.assertEqual(mapping.revision_id_foreign_to_bzr(c.id),
                      mapping.get_revision_id(c))
Example #29
0
    def do_commit(self, committer, message,
                  author=None, commit_timestamp=None,
                  commit_timezone=None, author_timestamp=None, 
                  author_timezone=None, tree=None):
        """Create a new commit.

        :param committer: Committer fullname
        :param message: Commit message
        :param author: Author fullname (defaults to committer)
        :param commit_timestamp: Commit timestamp (defaults to now)
        :param commit_timezone: Commit timestamp timezone (defaults to GMT)
        :param author_timestamp: Author timestamp (defaults to commit timestamp)
        :param author_timezone: Author timestamp timezone 
            (defaults to commit timestamp timezone)
        :param tree: SHA1 of the tree root to use (if not specified the current index will be committed).
        :return: New commit SHA1
        """
        from dulwich.index import commit_index
        import time
        index = self.open_index()
        c = Commit()
        if tree is None:
            c.tree = commit_index(self.object_store, index)
        else:
            c.tree = tree
        c.committer = committer
        if commit_timestamp is None:
            commit_timestamp = time.time()
        c.commit_time = int(commit_timestamp)
        if commit_timezone is None:
            commit_timezone = 0
        c.commit_timezone = commit_timezone
        if author is None:
            author = committer
        c.author = author
        if author_timestamp is None:
            author_timestamp = commit_timestamp
        c.author_time = int(author_timestamp)
        if author_timezone is None:
            author_timezone = commit_timezone
        c.author_timezone = author_timezone
        c.message = message
        self.object_store.add_object(c)
        self.refs["HEAD"] = c.id
        return c.id
Example #30
0
 def test_commit_mergetag(self):
     c = Commit()
     c.tree = b"cc9462f7f8263ef5adfbeff2fb936bb36b504cba"
     c.message = b"Some message"
     c.committer = b"Committer <Committer>"
     c.commit_time = 4
     c.commit_timezone = -60 * 3
     c.author_time = 5
     c.author_timezone = 60 * 2
     c.author = b"Author <author>"
     tag = make_object(Tag,
                       tagger=b'Jelmer Vernooij <*****@*****.**>',
                       name=b'0.1', message=None,
                       object=(
                           Blob, b'd80c186a03f423a81b39df39dc87fd269736ca86'),
                       tag_time=423423423, tag_timezone=0)
     c.mergetag = [tag]
     self.assertRoundtripCommit(c)
Example #31
0
 def test_implicit_encoding_utf8(self):
     c = Commit()
     c.tree = b"cc9462f7f8263ef5adfbeff2fb936bb36b504cba"
     c.message = b"Some message"
     c.committer = b"Committer"
     c.commit_time = 4
     c.author_time = 5
     c.commit_timezone = 60 * 5
     c.author_timezone = 60 * 3
     c.author = u"Authér".encode("utf-8")
     mapping = BzrGitMappingv1()
     rev, roundtrip_revid, verifiers = mapping.import_commit(
         c, mapping.revision_id_foreign_to_bzr)
     self.assertEqual(None, roundtrip_revid)
     self.assertEqual({}, verifiers)
     self.assertEqual(u"Authér", rev.properties[u'author'])
     self.assertTrue(u"git-explicit-encoding" not in rev.properties)
     self.assertTrue(u"git-implicit-encoding" not in rev.properties)
Example #32
0
File: git.py Project: mbr/unleash
    def to_commit(self):
        new_commit = Commit()
        new_commit.parents = self.parent_ids

        new_commit.tree = self.tree.id
        new_commit.author = self.author
        new_commit.committer = self.committer

        new_commit.author_time = self.author_time
        new_commit.commit_time = self.commit_time

        new_commit.commit_timezone = self.commit_timezone
        new_commit.author_timezone = self.author_timezone

        new_commit.encoding = self.encoding
        new_commit.message = self.message.encode(self.encoding)

        return new_commit
Example #33
0
 def test_mergetag(self):
     c = Commit()
     c.tree = b"cc9462f7f8263ef5adfbeff2fb936bb36b504cba"
     c.message = b"Some message"
     c.committer = b"Committer"
     c.commit_time = 4
     c.author_time = 5
     c.commit_timezone = 60 * 5
     c.author_timezone = 60 * 3
     c.author = b"Author"
     tag = make_object(Tag,
                       tagger=b'Jelmer Vernooij <*****@*****.**>',
                       name=b'0.1', message=None,
                       object=(
                           Blob, b'd80c186a03f423a81b39df39dc87fd269736ca86'),
                       tag_time=423423423, tag_timezone=0)
     c.mergetag = [tag]
     mapping = BzrGitMappingv1()
     rev, roundtrip_revid, verifiers = mapping.import_commit(
         c, mapping.revision_id_foreign_to_bzr)
     self.assertEqual(
         rev.properties[u'git-mergetag-0'], tag.as_raw_string())
Example #34
0
 def test_commit(self):
     c = Commit()
     c.tree = b"cc9462f7f8263ef5adfbeff2fb936bb36b504cba"
     c.message = b"Some message"
     c.committer = b"Committer"
     c.commit_time = 4
     c.author_time = 5
     c.commit_timezone = 60 * 5
     c.author_timezone = 60 * 3
     c.author = b"Author"
     mapping = BzrGitMappingv1()
     rev, roundtrip_revid, verifiers = mapping.import_commit(
         c, mapping.revision_id_foreign_to_bzr)
     self.assertEqual(None, roundtrip_revid)
     self.assertEqual({}, verifiers)
     self.assertEqual(u"Some message", rev.message)
     self.assertEqual(u"Committer", rev.committer)
     self.assertEqual(u"Author", rev.properties[u'author'])
     self.assertEqual(300, rev.timezone)
     self.assertEqual([], rev.parent_ids)
     self.assertEqual("5", rev.properties[u'author-timestamp'])
     self.assertEqual("180", rev.properties[u'author-timezone'])
     self.assertEqual(b"git-v1:" + c.id, rev.revision_id)
    def __setitem__(self, path, raw):
        # XXX: I don't have much idea, what I'm doing here and I might
        # just corrupt your repository...

        # Mark directory as special (None, None) marker value
        if raw is None:
            super(Head, self).__setitem__(path, (None, None))
            return

        # Get old mode or use the default
        try:
            mode = super(Head, self).__getitem__(path)[1]
        except KeyError:
            mode = 0100644

        # Get existing entries for the content tree
        entries = [(key, sha_mode[0], cleanup_mode(sha_mode[1]))
                   for key, sha_mode in super(Head, self).iteritems()
                   if sha_mode[0] is not None and key is not path]

        # Get author
        # TODO: refactor to use plone.api or maybe use product_config
        from Products.CMFCore.utils import getToolByName
        portal_members = getToolByName(getSite(), 'portal_membership')
        member = portal_members.getAuthenticatedMember()
        author = '{0:s} <{1:s}>'.format(
            member.getProperty('fullname', '') or member.getId(),
            member.getProperty('email', '') or '*****@*****.**'
        )

        # Get timezone
        tz_diff = dateutil.tz.tzlocal().utcoffset(datetime.datetime.now())

        # Create commit
        commit = Commit()
        commit.author = author
        commit.committer = commit.author
        commit.commit_time = int(time.time())
        commit.author_time = commit.commit_time
        commit.commit_timezone = tz_diff.seconds
        commit.author_timezone = tz_diff.seconds
        if tz_diff < datetime.timedelta(0):
            commit._author_timezone_neg_utc = True
            commit._commit_timezone_neg_utc = True
        commit.encoding = 'UTF-8'
        commit.message = 'Update {0:s}'.format(path)
        commit.parents = [self._head]

        # Create blob and commit tree
        blob = Blob.from_string(raw)
        entries.append((path, blob.id, cleanup_mode(mode)))
        commit.tree = commit_tree(self._repo.object_store, entries)

        # Save blob and commit
        self._repo.object_store.add_object(blob)
        self._repo.object_store.add_object(commit)

        def determine_wants(haves):
            # Set new head for the branch
            return {self.__name__: commit.id}

        # Push to remote
        refs = self.__parent__._client.send_pack(
            self.__parent__._host_path,
            determine_wants,
            self._repo.object_store.generate_pack_contents,
            progress=logger.info
        )
        # Update heads
        for ref, sha in refs.items():
            if sha in self._repo.object_store:
                self._repo.refs[ref] = sha

        # Update "index"
        super(Head, self).__setitem__(path, (blob.id, mode))
Example #36
0
def prepare_commit(repo, parent_commit_id, new_version, author, message,
                   pkg_name=None):
    objects_to_add = set()

    log.debug('Preparing new commit for version %s based on %s' % (
        new_version, parent_commit_id,
    ))
    tree = repo[repo[parent_commit_id].tree]

    # get setup.py
    setuppy_mode, setuppy_id = tree['setup.py']
    setuppy = repo[setuppy_id]

    # get __init__.py's
    if pkg_name == None:
        pkg_name = find_assign(setuppy.data, 'name')

    log.debug('Package name is %s' % pkg_name)
    pkg_init_fn = '%s/__init__.py' % pkg_name

    try:
        (pkg_init_mode, pkg_init_id) =\
            tree.lookup_path(repo.object_store.__getitem__, pkg_init_fn)
    except KeyError:
        log.error('Did not find package "%s"' % pkg_init_fn)
        raise
    else:
        log.debug('Found %s' % pkg_init_fn)
        pkg_init = repo[pkg_init_id]
        release_pkg_init = Blob.from_string(
            replace_assign(pkg_init.data, '__version__', str(new_version))
        )
        objects_to_add.add(release_pkg_init)

    release_setup = Blob.from_string(replace_assign(setuppy.data, 'version',
                                     str(new_version)))

    # get documentation's conf.py
    try:
        # FIXME: 'docs/' should not be hardcoded here, also duplicates
        # stuff from build_docs
        docconf_fn = 'docs/conf.py'

        docconf_mode, docconf_id = tree.lookup_path(
            repo.object_store.__getitem__, docconf_fn)
        log.debug('Found %s' % docconf_fn)
    except KeyError:
        log.warning('No documentation found (missing %s)' % docconf_fn)
    else:
        # got docs, update version numbers in those as well
        docconf = repo[docconf_id]
        release_docconf_data = docconf.data
        new_shortver = new_version.copy()
        new_shortver.drop_extras()

        release_docconf_data = replace_assign(
            release_docconf_data, 'version', str(new_shortver)
        )
        release_docconf_data = replace_assign(
            release_docconf_data, 'release', str(new_version)
        )

        release_docconf = Blob.from_string(release_docconf_data)

        objects_to_add.add(release_docconf)

        # after this point, lookup_path cannot be used anymore
        objects_to_add.update(
            add_path_to_tree(
                repo, tree, docconf_fn, docconf_mode, release_docconf.id
            ))

    # tree modifications need to be delayed, if done above will affect searches
    objects_to_add.update(
        add_path_to_tree(
            repo, tree, pkg_init_fn, pkg_init_mode, release_pkg_init.id
        ))
    tree.add('setup.py', setuppy_mode, release_setup.id)
    objects_to_add.add(release_setup)
    objects_to_add.add(tree)

    now = int(time.time())
    new_commit = Commit()
    new_commit.parents = [parent_commit_id]

    new_commit.tree = tree.id

    new_commit.author = author
    new_commit.committer = author

    new_commit.commit_time = now
    new_commit.author_time = now

    now = int(time.time())
    offset = tzlocal().utcoffset(datetime.utcfromtimestamp(now))
    timezone = offset.days * 24 * 60 * 60 + offset.seconds
    new_commit.commit_timezone = timezone
    new_commit.author_timezone = timezone

    new_commit.encoding = 'utf8'
    new_commit.message = message
    objects_to_add.add(new_commit)

    # check objects
    for obj in objects_to_add:
        obj.check()

    return new_commit, tree, objects_to_add
Example #37
0
    def do_commit(self, message=None, committer=None,
                  author=None, commit_timestamp=None,
                  commit_timezone=None, author_timestamp=None,
                  author_timezone=None, tree=None, encoding=None,
                  ref=b'HEAD', merge_heads=None):
        """Create a new commit.

        :param message: Commit message
        :param committer: Committer fullname
        :param author: Author fullname (defaults to committer)
        :param commit_timestamp: Commit timestamp (defaults to now)
        :param commit_timezone: Commit timestamp timezone (defaults to GMT)
        :param author_timestamp: Author timestamp (defaults to commit
            timestamp)
        :param author_timezone: Author timestamp timezone
            (defaults to commit timestamp timezone)
        :param tree: SHA1 of the tree root to use (if not specified the
            current index will be committed).
        :param encoding: Encoding
        :param ref: Optional ref to commit to (defaults to current branch)
        :param merge_heads: Merge heads (defaults to .git/MERGE_HEADS)
        :return: New commit SHA1
        """
        import time
        c = Commit()
        if tree is None:
            index = self.open_index()
            c.tree = index.commit(self.object_store)
        else:
            if len(tree) != 40:
                raise ValueError("tree must be a 40-byte hex sha string")
            c.tree = tree

        try:
            self.hooks['pre-commit'].execute()
        except HookError as e:
            raise CommitError(e)
        except KeyError:  # no hook defined, silent fallthrough
            pass

        if merge_heads is None:
            # FIXME: Read merge heads from .git/MERGE_HEADS
            merge_heads = []
        if committer is None:
            # FIXME: Support GIT_COMMITTER_NAME/GIT_COMMITTER_EMAIL environment
            # variables
            committer = self._get_user_identity()
        c.committer = committer
        if commit_timestamp is None:
            # FIXME: Support GIT_COMMITTER_DATE environment variable
            commit_timestamp = time.time()
        c.commit_time = int(commit_timestamp)
        if commit_timezone is None:
            # FIXME: Use current user timezone rather than UTC
            commit_timezone = 0
        c.commit_timezone = commit_timezone
        if author is None:
            # FIXME: Support GIT_AUTHOR_NAME/GIT_AUTHOR_EMAIL environment
            # variables
            author = committer
        c.author = author
        if author_timestamp is None:
            # FIXME: Support GIT_AUTHOR_DATE environment variable
            author_timestamp = commit_timestamp
        c.author_time = int(author_timestamp)
        if author_timezone is None:
            author_timezone = commit_timezone
        c.author_timezone = author_timezone
        if encoding is not None:
            c.encoding = encoding
        if message is None:
            # FIXME: Try to read commit message from .git/MERGE_MSG
            raise ValueError("No commit message specified")

        try:
            c.message = self.hooks['commit-msg'].execute(message)
            if c.message is None:
                c.message = message
        except HookError as e:
            raise CommitError(e)
        except KeyError:  # no hook defined, message not modified
            c.message = message

        if ref is None:
            # Create a dangling commit
            c.parents = merge_heads
            self.object_store.add_object(c)
        else:
            try:
                old_head = self.refs[ref]
                c.parents = [old_head] + merge_heads
                self.object_store.add_object(c)
                ok = self.refs.set_if_equals(ref, old_head, c.id)
            except KeyError:
                c.parents = merge_heads
                self.object_store.add_object(c)
                ok = self.refs.add_if_new(ref, c.id)
            if not ok:
                # Fail if the atomic compare-and-swap failed, leaving the
                # commit and all its objects as garbage.
                raise CommitError("%s changed during commit" % (ref,))

        try:
            self.hooks['post-commit'].execute()
        except HookError as e:  # silent failure
            warnings.warn("post-commit hook failed: %s" % e, UserWarning)
        except KeyError:  # no hook defined, silent fallthrough
            pass

        return c.id
Example #38
0
def main():
    args = parser.parse_args()

    # open repo
    repo = Repo(args.repo)
    config = repo.get_config_stack()
    ref_name = b'refs/heads/' + args.branch.encode('ascii')

    old_head = repo.refs[ref_name] if ref_name in repo.refs else None

    root = OrderedDict()
    for orig, s_args, s_kwargs in args.sources:
        scheme = s_args.pop(0)

        # prepare include/exclude expressions
        include_exprs = [fnmatch.translate(pattern)
                         for pattern in s_kwargs.pop('include', [])]
        include_exprs.extend(s_kwargs.pop('rinclude', []))
        exclude_exprs = [fnmatch.translate(pattern)
                         for pattern in s_kwargs.pop('exclude', [])]
        exclude_exprs.extend(s_kwargs.pop('rexclude', []))

        includes = list(map(re.compile, include_exprs))
        excludes = list(map(re.compile, exclude_exprs))

        srcs = list(SOURCES[scheme].create(*s_args, **s_kwargs))
        sys.stderr.write(orig)
        sys.stderr.write('\n')

        for src in srcs:
            for path in src:
                # if includes are specified and none matches, skip
                if includes and not filter(lambda exp: exp.match(path),
                                           includes):
                    continue

                # vice-versa for excludes
                if excludes and filter(lambda exp: exp.match(path), excludes):
                    continue

                # add the blob
                mode, blob = src.get_blob(path)
                repo.object_store.add_object(blob)

                # tree entry
                node = root
                components = path.split('/')
                for c in components[:-1]:
                    node = node.setdefault(c, OrderedDict())

                node[components[-1]] = (mode, blob.id)

                sys.stderr.write(path)
                sys.stderr.write('\n')

        sys.stderr.write('\n')

    # collect trees
    def store_tree(node):
        tree = Tree()

        for name in node:
            if isinstance(node[name], dict):
                tree.add(name.encode(args.encoding),
                         MODE_TREE, store_tree(node[name]).id)
            else:
                tree.add(name.encode(args.encoding), *node[name])

        repo.object_store.add_object(tree)
        return tree

    tree = store_tree(root)

    def get_user():
        name = config.get(b'user', b'name').decode('utf8')
        email = config.get(b'user', b'email').decode('utf8')

        return '{} <{}>'.format(name, email)

    commit = Commit()

    if old_head:
        commit.parents = [old_head]

    commit.tree = tree.id
    commit.author = (args.author or get_user()).encode(args.encoding)
    commit.committer = (args.committer or get_user()).encode(args.encoding)

    commit.commit_time = args.commit_time
    commit.author_time = args.author_time

    commit.commit_timezone = args.commit_timezone[0]
    commit.author_timezone = args.author_timezone[0]

    commit.encoding = args.encoding.encode('ascii')
    commit.message = args.message.encode(args.encoding)

    repo.object_store.add_object(commit)

    # set ref
    if old_head:
        repo.refs.set_if_equals(ref_name, old_head, commit.id)
    else:
        repo.refs.add_if_new(ref_name, commit.id)

    print(commit.id)
Example #39
0
    def setup(self):

        self.teardown()

        index = RamStorage().create_index(DateRevisionHybrid())

        repo = MemoryRepo()
        store = repo.object_store

        sample_page_rst_blob, sample_page_with_attachments_rst_blob = (
            Blob.from_string(_SAMPLE_PAGE_RST),
            Blob.from_string(_SAMPLE_PAGE_WITH_ATTACHMENTS_RST),
        )

        store.add_object(sample_page_rst_blob)
        store.add_object(sample_page_with_attachments_rst_blob)

        sample_page_tree = Tree()
        sample_page_tree.add('page.rst', 0100644, sample_page_rst_blob.id)
        store.add_object(sample_page_tree)

        sample_page_with_attachments_tree = Tree()
        sample_page_with_attachments_tree.add(
            'page.rst', 0100644, sample_page_with_attachments_rst_blob.id
        )
        store.add_object(sample_page_with_attachments_tree)

        pages_tree = Tree()
        pages_tree.add('sample-page', 0100755, sample_page_tree.id)
        pages_tree.add(
            'sample-page-with-attachments',
            0100755,
            sample_page_with_attachments_tree.id,
        )
        store.add_object(pages_tree)

        root_tree = Tree()
        root_tree.add('page', 0100755, pages_tree.id)
        store.add_object(root_tree)

        c = Commit()
        c.tree = root_tree.id
        c.message = 'initial commit'
        c.committer = 'test committer <test@committer>'
        c.author = 'test author <test@author>'
        c.commit_time = 1174773719
        c.author_time = 1174773719
        c.commit_timezone = 0
        c.author_timezone = 0

        store.add_object(c)

        repo.refs['refs/heads/master'] = c.id
        repo.refs['HEAD'] = c.id

        build_hybrid_index(
            index=index,
            repo=repo,
            ref='HEAD',
        )

        searcher = index.searcher()

        self.index = index
        self.searcher = searcher
        self.api = GitPages(repo, searcher)

        self.repo = repo
        self.root_tree = root_tree
        self.pages_tree = pages_tree
        self.sample_page_tree = sample_page_tree
        self.sample_page_rst_blob = sample_page_rst_blob
Example #40
0
    def do_commit(self,
                  message='',
                  author=None,
                  committer=None,
                  branch='master',
                  parent=None):
        if isinstance(message, unicode):
            message = message.encode('utf-8')
        repo = self.repo
        try:
            parent = self._get_commit(parent, branch)
            root = repo[parent.tree]
        except BranchDoesNotExist:
            if branch == 'master':  # initial commit
                root = Tree()
            else:
                raise

        cache = {}
        paths = set()
        objects = set()

        for path, (action, data) in self.changes.iteritems():
            path = clean_path(path)
            paths.add(path)
            dirname, filename = os.path.split(path)
            trees = self._collect(root, dirname, cache)

            if action == WRITE:
                blob = Blob.from_string(data)
                trees[-1][2][filename] = (self.file_mode, blob.id)
                cache[blob.id] = blob

            elif action == DELETE:
                del trees[-1][2][filename]

            elif action == RENAME:
                old = self._collect(root, data, cache)
                mode, name, obj = old[-1]
                del old[-2][2][name]
                trees[-1][2][filename] = (mode, obj.id)
                cache.update(self._link(old[:-1]))
                paths.add(data)

            cache.update(self._link(trees))
        else:
            objects.add(root)

        # collect all objects that have to be committed
        for path in paths:
            objects.update(
                [obj for mode, name, obj in self._collect(root, path, cache)])

        # create the commit
        c = Commit()
        if parent:
            c.parents = [parent.id]
        c.tree = root.id
        c.committer = committer or self.committer
        c.author = author or c.committer

        t = time.localtime()
        c.commit_time = c.author_time = int(time.mktime(t))
        c.commit_timezone = c.author_timezone = t.tm_isdst * 3600 - time.timezone
        c.encoding = "UTF-8"
        c.message = message
        objects.add(c)

        # write everything to disk
        for obj in objects:
            repo.object_store.add_object(obj)

        repo.refs['refs/heads/%s' % branch] = c.id

        return DulwichCommit(self, c)
Example #41
0
    def export_hg_commit(self, rev, exporter):
        self.ui.note(_("converting revision %s\n") % hex(rev))

        oldenc = self.swap_out_encoding()

        ctx = self.repo.changectx(rev)
        extra = ctx.extra()

        commit = Commit()

        (time, timezone) = ctx.date()
        # work around to bad timezone offets - dulwich does not handle
        # sub minute based timezones. In the one known case, it was a
        # manual edit that led to the unusual value. Based on that,
        # there is no reason to round one way or the other, so do the
        # simplest and round down.
        timezone -= (timezone % 60)
        commit.author = self.get_git_author(ctx)
        commit.author_time = int(time)
        commit.author_timezone = -timezone

        if 'committer' in extra:
            if RE_HGGIT_COMMITTER_LINE.search(extra['committer']):
                # fixup timezone
                (name, timestamp, timezone) = extra['committer'].rsplit(' ', 2)
                commit.committer = name
                commit.commit_time = timestamp

                # work around a timezone format change
                if int(timezone) % 60 != 0:  # pragma: no cover
                    timezone = parse_timezone(timezone)
                    # Newer versions of Dulwich return a tuple here
                    if isinstance(timezone, tuple):
                        timezone, neg_utc = timezone
                        commit._commit_timezone_neg_utc = neg_utc
                else:
                    timezone = -int(timezone)
                commit.commit_timezone = timezone
            else:
                commit.committer = extra['committer']
                commit.commit_time = commit.author_time
                commit.commit_timezone = commit.author_timezone
        else:
            commit.committer = commit.author
            commit.commit_time = commit.author_time
            commit.commit_timezone = commit.author_timezone

        commit.parents = []
        for parent in self.get_git_parents(ctx):
            hgsha = hex(parent.node())
            git_sha = self.map_git_get(hgsha)
            if git_sha:
                if git_sha not in self.git.object_store:
                    raise hgutil.Abort(_('Parent SHA-1 not present in Git'
                                         'repo: %s' % git_sha))

                commit.parents.append(git_sha)

        commit.message = self.get_git_message(ctx)

        if 'encoding' in extra:
            commit.encoding = extra['encoding']

        for obj, nodeid in exporter.update_changeset(ctx):
            self.git.object_store.add_object(obj)

        tree_sha = exporter.root_tree_sha

        if tree_sha not in self.git.object_store:
            raise hgutil.Abort(_('Tree SHA-1 not present in Git repo: %s' %
                tree_sha))

        commit.tree = tree_sha

        self.git.object_store.add_object(commit)
        self.map_set(commit.id, ctx.hex())

        self.swap_out_encoding(oldenc)
        return commit.id
    def __setitem__(self, path, raw):
        # XXX: I don't have much idea, what I'm doing here and I might
        # just corrupt your repository...

        # Mark directory as special (None, None) marker value
        if raw is None:
            super(Head, self).__setitem__(path, (None, None))
            return

        # Get old mode or use the default
        try:
            mode = super(Head, self).__getitem__(path)[1]
        except KeyError:
            mode = 0100644

        # Get existing entries for the content tree
        entries = [(key, sha_mode[0], cleanup_mode(sha_mode[1]))
                   for key, sha_mode in super(Head, self).iteritems()
                   if sha_mode[0] is not None and key is not path]

        # Get author
        # TODO: refactor to use plone.api or maybe use product_config
        from Products.CMFCore.utils import getToolByName
        portal_members = getToolByName(getSite(), 'portal_membership')
        member = portal_members.getAuthenticatedMember()
        author = '{0:s} <{1:s}>'.format(
            member.getProperty('fullname', '') or member.getId(),
            member.getProperty('email', '') or '*****@*****.**')

        # Get timezone
        tz_diff = dateutil.tz.tzlocal().utcoffset(datetime.datetime.now())

        # Create commit
        commit = Commit()
        commit.author = author
        commit.committer = commit.author
        commit.commit_time = int(time.time())
        commit.author_time = commit.commit_time
        commit.commit_timezone = tz_diff.seconds
        commit.author_timezone = tz_diff.seconds
        if tz_diff < datetime.timedelta(0):
            commit._author_timezone_neg_utc = True
            commit._commit_timezone_neg_utc = True
        commit.encoding = 'UTF-8'
        commit.message = 'Update {0:s}'.format(path)
        commit.parents = [self._head]

        # Create blob and commit tree
        blob = Blob.from_string(raw)
        entries.append((path, blob.id, cleanup_mode(mode)))
        commit.tree = commit_tree(self._repo.object_store, entries)

        # Save blob and commit
        self._repo.object_store.add_object(blob)
        self._repo.object_store.add_object(commit)

        def determine_wants(haves):
            # Set new head for the branch
            return {self.__name__: commit.id}

        # Push to remote
        refs = self.__parent__._client.send_pack(
            self.__parent__._host_path,
            determine_wants,
            self._repo.object_store.generate_pack_contents,
            progress=logger.info)
        # Update heads
        for ref, sha in refs.items():
            if sha in self._repo.object_store:
                self._repo.refs[ref] = sha

        # Update "index"
        super(Head, self).__setitem__(path, (blob.id, mode))
Example #43
0
    def export_commit(self, rev, tree_sha, parent_lookup, lossy,
                      verifiers):
        """Turn a Bazaar revision in to a Git commit

        :param tree_sha: Tree sha for the commit
        :param parent_lookup: Function for looking up the GIT sha equiv of a
            bzr revision
        :param lossy: Whether to store roundtripping information.
        :param verifiers: Verifiers info
        :return dulwich.objects.Commit represent the revision:
        """
        from dulwich.objects import Commit, Tag
        commit = Commit()
        commit.tree = tree_sha
        if not lossy:
            metadata = CommitSupplement()
            metadata.verifiers = verifiers
        else:
            metadata = None
        parents = []
        for p in rev.parent_ids:
            try:
                git_p = parent_lookup(p)
            except KeyError:
                git_p = None
                if metadata is not None:
                    metadata.explicit_parent_ids = rev.parent_ids
            if git_p is not None:
                if len(git_p) != 40:
                    raise AssertionError("unexpected length for %r" % git_p)
                parents.append(git_p)
        commit.parents = parents
        try:
            encoding = rev.properties[u'git-explicit-encoding']
        except KeyError:
            encoding = rev.properties.get(u'git-implicit-encoding', 'utf-8')
        try:
            commit.encoding = rev.properties[u'git-explicit-encoding'].encode(
                'ascii')
        except KeyError:
            pass
        commit.committer = fix_person_identifier(rev.committer.encode(
            encoding))
        commit.author = fix_person_identifier(
            rev.get_apparent_authors()[0].encode(encoding))
        # TODO(jelmer): Don't use this hack.
        long = getattr(__builtins__, 'long', int)
        commit.commit_time = long(rev.timestamp)
        if u'author-timestamp' in rev.properties:
            commit.author_time = long(rev.properties[u'author-timestamp'])
        else:
            commit.author_time = commit.commit_time
        commit._commit_timezone_neg_utc = (
            u"commit-timezone-neg-utc" in rev.properties)
        commit.commit_timezone = rev.timezone
        commit._author_timezone_neg_utc = (
            u"author-timezone-neg-utc" in rev.properties)
        if u'author-timezone' in rev.properties:
            commit.author_timezone = int(rev.properties[u'author-timezone'])
        else:
            commit.author_timezone = commit.commit_timezone
        if u'git-gpg-signature' in rev.properties:
            commit.gpgsig = rev.properties[u'git-gpg-signature'].encode(
                'utf-8', 'surrogateescape')
        commit.message = self._encode_commit_message(rev, rev.message,
                                                     encoding)
        if not isinstance(commit.message, bytes):
            raise TypeError(commit.message)
        if metadata is not None:
            try:
                mapping_registry.parse_revision_id(rev.revision_id)
            except errors.InvalidRevisionId:
                metadata.revision_id = rev.revision_id
            mapping_properties = set(
                [u'author', u'author-timezone', u'author-timezone-neg-utc',
                 u'commit-timezone-neg-utc', u'git-implicit-encoding',
                 u'git-gpg-signature', u'git-explicit-encoding',
                 u'author-timestamp', u'file-modes'])
            for k, v in rev.properties.items():
                if k not in mapping_properties:
                    metadata.properties[k] = v
        if not lossy and metadata:
            if self.roundtripping:
                commit.message = inject_bzr_metadata(commit.message, metadata,
                                                     encoding)
            else:
                raise NoPushSupport(
                    None, None, self, revision_id=rev.revision_id)
        if not isinstance(commit.message, bytes):
            raise TypeError(commit.message)
        i = 0
        propname = u'git-mergetag-0'
        while propname in rev.properties:
            commit.mergetag.append(Tag.from_string(rev.properties[propname]))
            i += 1
            propname = u'git-mergetag-%d' % i
        if u'git-extra' in rev.properties:
            commit.extra.extend(
                [l.split(b' ', 1)
                 for l in rev.properties[u'git-extra'].splitlines()])
        return commit
Example #44
0
    for entry in tree.items():
        item = repo[entry.sha]
        if isinstance(item, Tree):
            new_tree.add(entry.path, entry.mode, render_tree(item, path+(entry.path,)))
        elif isinstance(item, Blob):
            if entry.path.startswith(".") or ("." not in entry.path) or entry.path.endswith(".py") or entry.path.endswith(".html") or entry.path.startswith("mnist.") or entry.path.endswith(".model"):
                continue
            if not entry.path.endswith(".rst"):
                new_tree.add(entry.path, entry.mode, entry.sha)
            else:
                name = "index.html" if entry.path == 'README.rst' else (entry.path[:-4]+".html")
                new_tree.add(name, entry.mode, render_rst(item, os.path.join(*(path +(name,)))))

    store.add_object(new_tree)
    return new_tree.id


new_commit = Commit()
new_commit.author = commit.author
new_commit.committer = commit.committer
new_commit.author_time = commit.author_time
new_commit.commit_time = commit.commit_time
new_commit.author_timezone = commit.author_timezone
new_commit.commit_timezone = commit.commit_timezone
new_commit.encoding = commit.encoding
new_commit.message = commit.message
new_commit.tree = render_tree(repo[commit.tree], ('.',))
store.add_object(new_commit)
repo['refs/heads/gh-pages'] = new_commit.id
Example #45
0
    def export_hg_commit(self, rev, exporter):
        self.ui.note(_("converting revision %s\n") % hex_(rev))

        oldenc = self.swap_out_encoding()

        ctx = self.repo.changectx(rev)
        extra = ctx.extra()

        commit = Commit()

        (time, timezone) = ctx.date()
        # work around to bad timezone offets - dulwich does not handle
        # sub minute based timezones. In the one known case, it was a
        # manual edit that led to the unusual value. Based on that,
        # there is no reason to round one way or the other, so do the
        # simplest and round down.
        timezone -= (timezone % 60)
        commit.author = self.get_git_author(ctx)
        commit.author_time = int(time)
        commit.author_timezone = -timezone

        if 'committer' in extra:
            # fixup timezone
            (name, timestamp, timezone) = extra['committer'].rsplit(' ', 2)
            commit.committer = name
            commit.commit_time = timestamp

            # work around a timezone format change
            if int(timezone) % 60 != 0:  #pragma: no cover
                timezone = parse_timezone(timezone)
                # Newer versions of Dulwich return a tuple here
                if isinstance(timezone, tuple):
                    timezone, neg_utc = timezone
                    commit._commit_timezone_neg_utc = neg_utc
            else:
                timezone = -int(timezone)
            commit.commit_timezone = timezone
        else:
            commit.committer = commit.author
            commit.commit_time = commit.author_time
            commit.commit_timezone = commit.author_timezone

        commit.parents = []
        for parent in self.get_git_parents(ctx):
            hgsha = hex_(parent.node())
            git_sha = self.map_git_get(hgsha)
            if git_sha:
                if git_sha not in self.git.object_store:
                    raise hgutil.Abort(
                        _('Parent SHA-1 not present in Git'
                          'repo: %s' % git_sha))

                commit.parents.append(git_sha)

        commit.message = self.get_git_message(ctx)

        if 'encoding' in extra:
            commit.encoding = extra['encoding']

        for obj, nodeid in exporter.update_changeset(ctx):
            self.git.object_store.add_object(obj)

        tree_sha = exporter.root_tree_sha

        if tree_sha not in self.git.object_store:
            raise hgutil.Abort(
                _('Tree SHA-1 not present in Git repo: %s' % tree_sha))

        commit.tree = tree_sha

        self.git.object_store.add_object(commit)
        self.map_set(commit.id, ctx.hex())

        self.swap_out_encoding(oldenc)
        return commit.id
Example #46
0
    def do_commit(self, message=None, committer=None,
                  author=None, commit_timestamp=None,
                  commit_timezone=None, author_timestamp=None,
                  author_timezone=None, tree=None, encoding=None,
                  ref=b'HEAD', merge_heads=None):
        """Create a new commit.

        :param message: Commit message
        :param committer: Committer fullname
        :param author: Author fullname (defaults to committer)
        :param commit_timestamp: Commit timestamp (defaults to now)
        :param commit_timezone: Commit timestamp timezone (defaults to GMT)
        :param author_timestamp: Author timestamp (defaults to commit timestamp)
        :param author_timezone: Author timestamp timezone
            (defaults to commit timestamp timezone)
        :param tree: SHA1 of the tree root to use (if not specified the
            current index will be committed).
        :param encoding: Encoding
        :param ref: Optional ref to commit to (defaults to current branch)
        :param merge_heads: Merge heads (defaults to .git/MERGE_HEADS)
        :return: New commit SHA1
        """
        import time
        c = Commit()
        if tree is None:
            index = self.open_index()
            c.tree = index.commit(self.object_store)
        else:
            if len(tree) != 40:
                raise ValueError("tree must be a 40-byte hex sha string")
            c.tree = tree
        if merge_heads is None:
            # FIXME: Read merge heads from .git/MERGE_HEADS
            merge_heads = []
        # TODO: Allow username to be missing, and get it from .git/config
        if committer is None:
            raise ValueError("committer not set")
        c.committer = committer
        if commit_timestamp is None:
            commit_timestamp = time.time()
        c.commit_time = int(commit_timestamp)
        if commit_timezone is None:
            # FIXME: Use current user timezone rather than UTC
            commit_timezone = 0
        c.commit_timezone = commit_timezone
        if author is None:
            author = committer
        c.author = author
        if author_timestamp is None:
            author_timestamp = commit_timestamp
        c.author_time = int(author_timestamp)
        if author_timezone is None:
            author_timezone = commit_timezone
        c.author_timezone = author_timezone
        if encoding is not None:
            c.encoding = encoding
        if message is None:
            # FIXME: Try to read commit message from .git/MERGE_MSG
            raise ValueError("No commit message specified")
        c.message = message
        try:
            old_head = self.refs[ref]
            c.parents = [old_head] + merge_heads
            self.object_store.add_object(c)
            ok = self.refs.set_if_equals(ref, old_head, c.id)
        except KeyError:
            c.parents = merge_heads
            self.object_store.add_object(c)
            ok = self.refs.add_if_new(ref, c.id)
        if not ok:
            # Fail if the atomic compare-and-swap failed, leaving the commit and
            # all its objects as garbage.
            raise CommitError("%s changed during commit" % (ref,))

        return c.id
    def do_commit(self, message=None, committer=None,
                  author=None, commit_timestamp=None,
                  commit_timezone=None, author_timestamp=None,
                  author_timezone=None, tree=None, encoding=None,
                  ref=b'HEAD', merge_heads=None):
        """Create a new commit.

        :param message: Commit message
        :param committer: Committer fullname
        :param author: Author fullname (defaults to committer)
        :param commit_timestamp: Commit timestamp (defaults to now)
        :param commit_timezone: Commit timestamp timezone (defaults to GMT)
        :param author_timestamp: Author timestamp (defaults to commit timestamp)
        :param author_timezone: Author timestamp timezone
            (defaults to commit timestamp timezone)
        :param tree: SHA1 of the tree root to use (if not specified the
            current index will be committed).
        :param encoding: Encoding
        :param ref: Optional ref to commit to (defaults to current branch)
        :param merge_heads: Merge heads (defaults to .git/MERGE_HEADS)
        :return: New commit SHA1
        """
        import time
        c = Commit()
        if tree is None:
            index = self.open_index()
            c.tree = index.commit(self.object_store)
        else:
            if len(tree) != 40:
                raise ValueError("tree must be a 40-byte hex sha string")
            c.tree = tree

        try:
            self.hooks['pre-commit'].execute()
        except HookError as e:
            raise CommitError(e)
        except KeyError:  # no hook defined, silent fallthrough
            pass

        if merge_heads is None:
            # FIXME: Read merge heads from .git/MERGE_HEADS
            merge_heads = []
        if committer is None:
            # FIXME: Support GIT_COMMITTER_NAME/GIT_COMMITTER_EMAIL environment
            # variables
            committer = self._get_user_identity()
        c.committer = committer
        if commit_timestamp is None:
            # FIXME: Support GIT_COMMITTER_DATE environment variable
            commit_timestamp = time.time()
        c.commit_time = int(commit_timestamp)
        if commit_timezone is None:
            # FIXME: Use current user timezone rather than UTC
            commit_timezone = 0
        c.commit_timezone = commit_timezone
        if author is None:
            # FIXME: Support GIT_AUTHOR_NAME/GIT_AUTHOR_EMAIL environment
            # variables
            author = committer
        c.author = author
        if author_timestamp is None:
            # FIXME: Support GIT_AUTHOR_DATE environment variable
            author_timestamp = commit_timestamp
        c.author_time = int(author_timestamp)
        if author_timezone is None:
            author_timezone = commit_timezone
        c.author_timezone = author_timezone
        if encoding is not None:
            c.encoding = encoding
        if message is None:
            # FIXME: Try to read commit message from .git/MERGE_MSG
            raise ValueError("No commit message specified")

        try:
            c.message = self.hooks['commit-msg'].execute(message)
            if c.message is None:
                c.message = message
        except HookError as e:
            raise CommitError(e)
        except KeyError:  # no hook defined, message not modified
            c.message = message

        if ref is None:
            # Create a dangling commit
            c.parents = merge_heads
            self.object_store.add_object(c)
        else:
            try:
                old_head = self.refs[ref]
                c.parents = [old_head] + merge_heads
                self.object_store.add_object(c)
                ok = self.refs.set_if_equals(ref, old_head, c.id)
            except KeyError:
                c.parents = merge_heads
                self.object_store.add_object(c)
                ok = self.refs.add_if_new(ref, c.id)
            if not ok:
                # Fail if the atomic compare-and-swap failed, leaving the commit and
                # all its objects as garbage.
                raise CommitError("%s changed during commit" % (ref,))

        try:
            self.hooks['post-commit'].execute()
        except HookError as e:  # silent failure
            warnings.warn("post-commit hook failed: %s" % e, UserWarning)
        except KeyError:  # no hook defined, silent fallthrough
            pass

        return c.id
Example #48
0
    def do_commit(self, message='', author=None, committer=None, branch='master', parent=None):
        if isinstance(message, unicode):
            message = message.encode('utf-8')
        repo = self.repo
        try:
            parent = self._get_commit(parent, branch)
            root = repo[parent.tree]
        except BranchDoesNotExist:
            if branch == 'master': # initial commit
                root = Tree()
            else:
                raise
            
        cache = {}
        paths = set()
        objects = set()
        
        for path, (action, data) in self.changes.iteritems():
            path = clean_path(path)
            paths.add(path)
            dirname, filename = os.path.split(path)
            trees = self._collect(root, dirname, cache)

            if action == WRITE:
                blob = Blob.from_string(data)
                trees[-1][2][filename] = (self.file_mode, blob.id)
                cache[blob.id] = blob

            elif action == DELETE:
                del trees[-1][2][filename]

            elif action == RENAME:
                old = self._collect(root, data, cache)
                mode, name, obj = old[-1]
                del old[-2][2][name]
                trees[-1][2][filename] = (mode, obj.id)
                cache.update(self._link(old[:-1]))
                paths.add(data)

            cache.update(self._link(trees))
        else:
            objects.add(root)

        # collect all objects that have to be committed
        for path in paths:
            objects.update([obj for mode, name, obj in self._collect(root, path, cache)])
            
        # create the commit
        c = Commit()
        if parent:
            c.parents = [parent.id]
        c.tree = root.id
        c.committer = committer or self.committer
        c.author = author or c.committer

        t = time.localtime()
        c.commit_time = c.author_time = int(time.mktime(t))
        c.commit_timezone = c.author_timezone = t.tm_isdst * 3600 - time.timezone
        c.encoding = "UTF-8"
        c.message = message
        objects.add(c)

        # write everything to disk
        for obj in objects:
            repo.object_store.add_object(obj)

        repo.refs['refs/heads/%s' % branch] = c.id

        return DulwichCommit(self, c)
Example #49
0
    def do_commit(self, message=None, committer=None,
                  author=None, commit_timestamp=None,
                  commit_timezone=None, author_timestamp=None,
                  author_timezone=None, tree=None, encoding=None,
                  ref='HEAD', merge_heads=None):
        """Create a new commit.

        :param message: Commit message
        :param committer: Committer fullname
        :param author: Author fullname (defaults to committer)
        :param commit_timestamp: Commit timestamp (defaults to now)
        :param commit_timezone: Commit timestamp timezone (defaults to GMT)
        :param author_timestamp: Author timestamp (defaults to commit timestamp)
        :param author_timezone: Author timestamp timezone
            (defaults to commit timestamp timezone)
        :param tree: SHA1 of the tree root to use (if not specified the
            current index will be committed).
        :param encoding: Encoding
        :param ref: Optional ref to commit to (defaults to current branch)
        :param merge_heads: Merge heads (defaults to .git/MERGE_HEADS)
        :return: New commit SHA1
        """
        import time
        c = Commit()
        if tree is None:
            index = self.open_index()
            c.tree = index.commit(self.object_store)
        else:
            if len(tree) != 40:
                raise ValueError("tree must be a 40-byte hex sha string")
            c.tree = tree
        if merge_heads is None:
            # FIXME: Read merge heads from .git/MERGE_HEADS
            merge_heads = []
        # TODO: Allow username to be missing, and get it from .git/config
        if committer is None:
            raise ValueError("committer not set")
        c.committer = committer
        if commit_timestamp is None:
            commit_timestamp = time.time()
        c.commit_time = int(commit_timestamp)
        if commit_timezone is None:
            # FIXME: Use current user timezone rather than UTC
            commit_timezone = 0
        c.commit_timezone = commit_timezone
        if author is None:
            author = committer
        c.author = author
        if author_timestamp is None:
            author_timestamp = commit_timestamp
        c.author_time = int(author_timestamp)
        if author_timezone is None:
            author_timezone = commit_timezone
        c.author_timezone = author_timezone
        if encoding is not None:
            c.encoding = encoding
        if message is None:
            # FIXME: Try to read commit message from .git/MERGE_MSG
            raise ValueError("No commit message specified")
        c.message = message
        try:
            old_head = self.refs[ref]
            c.parents = [old_head] + merge_heads
            self.object_store.add_object(c)
            ok = self.refs.set_if_equals(ref, old_head, c.id)
        except KeyError:
            c.parents = merge_heads
            self.object_store.add_object(c)
            ok = self.refs.add_if_new(ref, c.id)
        if not ok:
            # Fail if the atomic compare-and-swap failed, leaving the commit and
            # all its objects as garbage.
            raise CommitError("%s changed during commit" % (ref,))

        return c.id