+ try:
+ return GRun('rev-parse', '--verify', git_id
+ ).discard_stderr().output_one_line()
+ except GitRunException:
+ raise GitException, 'Unknown revision: %s' % git_id
+
+def ref_exists(ref):
+ try:
+ rev_parse(ref)
+ return True
+ except GitException:
+ return False
+
+def branch_exists(branch):
+ return ref_exists('refs/heads/%s' % branch)
+
+def create_branch(new_branch, tree_id = None):
+ """Create a new branch in the git repository
+ """
+ if branch_exists(new_branch):
+ raise GitException, 'Branch "%s" already exists' % new_branch
+
+ current_head_file = get_head_file()
+ current_head = get_head()
+ set_head_file(new_branch)
+ __set_head(current_head)
+
+ # a checkout isn't needed if new branch points to the current head
+ if tree_id:
+ try:
+ switch(tree_id)
+ except GitException:
+ # Tree switching failed. Revert the head file
+ set_head_file(current_head_file)
+ delete_branch(new_branch)
+ raise
+
+ if os.path.isfile(os.path.join(basedir.get(), 'MERGE_HEAD')):
+ os.remove(os.path.join(basedir.get(), 'MERGE_HEAD'))
+
+def switch_branch(new_branch):
+ """Switch to a git branch
+ """
+ global __head
+
+ if not branch_exists(new_branch):
+ raise GitException, 'Branch "%s" does not exist' % new_branch
+
+ tree_id = rev_parse('refs/heads/%s^{commit}' % new_branch)
+ if tree_id != get_head():
+ refresh_index()
+ try:
+ GRun('read-tree', '-u', '-m', get_head(), tree_id).run()
+ except GitRunException:
+ raise GitException, 'read-tree failed (local changes maybe?)'
+ __head = tree_id
+ set_head_file(new_branch)
+
+ if os.path.isfile(os.path.join(basedir.get(), 'MERGE_HEAD')):
+ os.remove(os.path.join(basedir.get(), 'MERGE_HEAD'))
+
+def delete_ref(ref):
+ if not ref_exists(ref):
+ raise GitException, '%s does not exist' % ref
+ sha1 = GRun('show-ref', '-s', ref).output_one_line()
+ try:
+ GRun('update-ref', '-d', ref, sha1).run()
+ except GitRunException:
+ raise GitException, 'Failed to delete ref %s' % ref
+
+def delete_branch(name):
+ delete_ref('refs/heads/%s' % name)
+
+def rename_ref(from_ref, to_ref):
+ if not ref_exists(from_ref):
+ raise GitException, '"%s" does not exist' % from_ref
+ if ref_exists(to_ref):
+ raise GitException, '"%s" already exists' % to_ref
+
+ sha1 = GRun('show-ref', '-s', from_ref).output_one_line()
+ try:
+ GRun('update-ref', to_ref, sha1, '0'*40).run()
+ except GitRunException:
+ raise GitException, 'Failed to create new ref %s' % to_ref
+ try:
+ GRun('update-ref', '-d', from_ref, sha1).run()
+ except GitRunException:
+ raise GitException, 'Failed to delete ref %s' % from_ref
+
+def rename_branch(from_name, to_name):
+ """Rename a git branch."""
+ rename_ref('refs/heads/%s' % from_name, 'refs/heads/%s' % to_name)
+ try:
+ if get_head_file() == from_name:
+ set_head_file(to_name)
+ except DetachedHeadException:
+ pass # detached HEAD, so the renamee can't be the current branch
+ reflog_dir = os.path.join(basedir.get(), 'logs', 'refs', 'heads')
+ if os.path.exists(reflog_dir) \
+ and os.path.exists(os.path.join(reflog_dir, from_name)):
+ rename(reflog_dir, from_name, to_name)