aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTommi Virtanen <tv@eagain.net>2007-09-01 17:47:42 -0700
committerTommi Virtanen <tv@eagain.net>2007-09-01 18:06:45 -0700
commit0dbee1faddc65533c1d485f4b6d6693852db07c6 (patch)
tree6607cb1ea1bc9789a9b18a18500994b03e98a4f2 /gitosis/repository.py
parentUse separate temp directories for separate tests. (diff)
downloadgitosis-gentoo-0dbee1faddc65533c1d485f4b6d6693852db07c6.tar.gz
gitosis-gentoo-0dbee1faddc65533c1d485f4b6d6693852db07c6.tar.bz2
gitosis-gentoo-0dbee1faddc65533c1d485f4b6d6693852db07c6.zip
Add utilities for fast-import, exporting repository.
Redo subprocess error handling.
Diffstat (limited to 'gitosis/repository.py')
-rw-r--r--gitosis/repository.py106
1 files changed, 98 insertions, 8 deletions
diff --git a/gitosis/repository.py b/gitosis/repository.py
index 17a8818..764c980 100644
--- a/gitosis/repository.py
+++ b/gitosis/repository.py
@@ -3,6 +3,15 @@ import subprocess
from gitosis import util
+class GitError(Exception):
+ """git failed"""
+
+ def __str__(self):
+ return '%s: %s' % (self.__doc__, ': '.join(self.args))
+
+class GitInitError(Exception):
+ """git init failed"""
+
def init(
path,
template=None,
@@ -15,17 +24,98 @@ def init(
args = [_git, 'init']
if template is not None:
args.append('--template=%s' % template)
- env = {}
- env.update(os.environ)
- env['GIT_DIR'] = '.'
returncode = subprocess.call(
args=args,
cwd=path,
close_fds=True,
- env=env,
+ env=dict(GIT_DIR='.'),
+ )
+ if returncode != 0:
+ raise GitInitError('exit status %d' % returncode)
+
+
+class GitFastImportError(GitError):
+ """git fast-import failed"""
+ pass
+
+def fast_import(
+ git_dir,
+ commit_msg,
+ committer,
+ files,
+ ):
+ """
+ Create an initial commit.
+ """
+ init(path=git_dir)
+ child = subprocess.Popen(
+ args=['git', 'fast-import', '--quiet', '--date-format=now'],
+ cwd=git_dir,
+ stdin=subprocess.PIPE,
+ close_fds=True,
+ env=dict(GIT_DIR=git_dir),
+ )
+ files = list(files)
+ for index, (path, content) in enumerate(files):
+ child.stdin.write("""\
+blob
+mark :%(mark)d
+data %(len)d
+%(content)s
+""" % dict(
+ mark=index+1,
+ len=len(content),
+ content=content,
+ ))
+ child.stdin.write("""\
+commit refs/heads/master
+committer %(committer)s now
+data %(commit_msg_len)d
+%(commit_msg)s
+""" % dict(
+ committer=committer,
+ commit_msg_len=len(commit_msg),
+ commit_msg=commit_msg,
+ ))
+ for index, (path, content) in enumerate(files):
+ child.stdin.write('M 100644 :%d %s\n' % (index+1, path))
+ child.stdin.close()
+ returncode = child.wait()
+ if returncode != 0:
+ raise GitFastImportError(
+ 'git fast-import failed', 'exit status %d' % returncode)
+
+class GitExportError(GitError):
+ """Export failed"""
+ pass
+
+class GitReadTreeError(GitExportError):
+ """git read-tree failed"""
+
+class GitCheckoutIndexError(GitExportError):
+ """git checkout-index failed"""
+
+def export(git_dir, path):
+ # it's a literal prefix for git, a trailing slash is needed to
+ # extract to the subdirectory
+ path = os.path.join(path, '')
+ returncode = subprocess.call(
+ args=['git', 'read-tree', 'HEAD'],
+ close_fds=True,
+ env=dict(GIT_DIR=git_dir),
+ )
+ if returncode != 0:
+ raise GitReadTreeError('exit status %d' % returncode)
+ returncode = subprocess.call(
+ args=[
+ 'git',
+ 'checkout-index',
+ '-a',
+ '-f',
+ '--prefix=%s' % path,
+ ],
+ close_fds=True,
+ env=dict(GIT_DIR=git_dir),
)
if returncode != 0:
- raise RuntimeError(
- ("Command '%r' returned non-zero exit status %d"
- % (args, returncode)),
- )
+ raise GitCheckoutIndexError('exit status %d' % returncode)