Add utilities for fast-import, exporting repository.

Redo subprocess error handling.
This commit is contained in:
Tommi Virtanen 2007-09-01 17:47:42 -07:00
parent fd11351859
commit 0dbee1fadd
2 changed files with 145 additions and 8 deletions

View file

@ -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 RuntimeError(
("Command '%r' returned non-zero exit status %d"
% (args, returncode)),
)
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 GitCheckoutIndexError('exit status %d' % returncode)

View file

@ -1,6 +1,7 @@
from nose.tools import eq_ as eq
import os
import subprocess
from gitosis import repository
@ -55,3 +56,49 @@ def test_init_templates():
eq(got, '#!/bin/sh\n# i can override standard templates\n')
# standard templates are there, too
assert os.path.isfile(os.path.join(path, 'hooks', 'pre-rebase'))
def test_export_simple():
tmp = maketemp()
git_dir = os.path.join(tmp, 'repo.git')
repository.init(path=git_dir)
repository.fast_import(
git_dir=git_dir,
committer='John Doe <jdoe@example.com>',
commit_msg="""\
Reverse the polarity of the neutron flow.
Frobitz the quux and eschew obfuscation.
""",
files=[
('foo', 'content'),
('bar/quux', 'another'),
],
)
export = os.path.join(tmp, 'export')
repository.export(git_dir=git_dir, path=export)
eq(sorted(os.listdir(export)),
sorted(['foo', 'bar']))
eq(readFile(os.path.join(export, 'foo')), 'content')
eq(os.listdir(os.path.join(export, 'bar')), ['quux'])
eq(readFile(os.path.join(export, 'bar', 'quux')), 'another')
child = subprocess.Popen(
args=['git', 'cat-file', 'commit', 'HEAD'],
cwd=git_dir,
stdout=subprocess.PIPE,
close_fds=True,
env=dict(GIT_DIR=git_dir),
)
got = child.stdout.read().splitlines()
returncode = child.wait()
if returncode != 0:
raise RuntimeError('git exit status %d' % returncode)
eq(got[0].split(None, 1)[0], 'tree')
eq(got[1].rsplit(None, 2)[0],
'author John Doe <jdoe@example.com>')
eq(got[2].rsplit(None, 2)[0],
'committer John Doe <jdoe@example.com>')
eq(got[3], '')
eq(got[4], 'Reverse the polarity of the neutron flow.')
eq(got[5], '')
eq(got[6], 'Frobitz the quux and eschew obfuscation.')
eq(got[7:], [])