Skip to content

Commit

Permalink
Fix compatibility with git 1.5.4.3 (Ubuntu Hardy).
Browse files Browse the repository at this point in the history
Thanks to Andy Chong for reporting the problem.

Basically it comes down to two things that are missing in that version but
exist in git 1.5.6:

  - git init --bare doesn't work, but git --bare init does.
  - git cat-file --batch doesn't exist in that version.

Unfortunately, the latter problem is pretty serious; bup join is really slow
without it.  I guess it might be time to implement an internal version of
cat-file.
  • Loading branch information
apenwarr committed Jan 6, 2010
1 parent 222fff0 commit 755be38
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 17 deletions.
87 changes: 72 additions & 15 deletions git.py
@@ -1,4 +1,4 @@
import os, errno, zlib, time, sha, subprocess, struct, mmap, stat
import os, errno, zlib, time, sha, subprocess, struct, mmap, stat, re
from helpers import *

verbose = 0
Expand Down Expand Up @@ -237,8 +237,9 @@ def close(self):
preexec_fn = _gitenv,
stdout = subprocess.PIPE)
out = p.stdout.read().strip()
if p.wait() or not out:
raise GitError('git index-pack returned an error')
_git_wait('git index-pack', p)
if not out:
raise GitError('git index-pack produced no output')
nameprefix = repo('objects/pack/%s' % out)
os.rename(self.filename + '.pack', nameprefix + '.pack')
os.rename(self.filename + '.idx', nameprefix + '.idx')
Expand Down Expand Up @@ -285,7 +286,7 @@ def read_ref(refname):
preexec_fn = _gitenv,
stdout = subprocess.PIPE)
out = p.stdout.read().strip()
rv = p.wait()
rv = p.wait() # not fatal
if rv:
assert(not out)
if out:
Expand All @@ -300,9 +301,7 @@ def update_ref(refname, newval, oldval):
p = subprocess.Popen(['git', 'update-ref', '--', refname,
newval.encode('hex'), oldval.encode('hex')],
preexec_fn = _gitenv)
rv = p.wait()
if rv:
raise GitError('update_ref returned error code %d' % rv)
_git_wait('git update-ref', p)


def guess_repo(path=None):
Expand All @@ -322,9 +321,10 @@ def init_repo(path=None):
raise GitError('"%d" exists but is not a directory\n' % d)
p = subprocess.Popen(['git', '--bare', 'init'], stdout=sys.stderr,
preexec_fn = _gitenv)
rv = p.wait()
if rv != 0:
raise GitError('git init returned %d\n' % rv)
_git_wait('git init', p)
p = subprocess.Popen(['git', 'config', 'pack.indexVersion', '2'],
stdout=sys.stderr, preexec_fn = _gitenv)
_git_wait('git config', p)


def check_repo_or_die(path=None):
Expand All @@ -348,17 +348,60 @@ def _treeparse(buf):
ofs += z+1+20
yield (spl[0], spl[1], sha)

_ver = None
def ver():
global _ver
if not _ver:
p = subprocess.Popen(['git', '--version'],
stdout=subprocess.PIPE)
gvs = p.stdout.read()
_git_wait('git --version', p)
m = re.match(r'git version (\S+.\S+)', gvs)
if not m:
raise GitError('git --version weird output: %r' % gvs)
_ver = tuple(m.group(1).split('.'))
needed = ('1','5','4')
if _ver < needed:
raise GitError('git version %s or higher is required; you have %s'
% ('.'.join(needed), '.'.join(_ver)))
return _ver


def _git_wait(cmd, p):
rv = p.wait()
if rv != 0:
raise GitError('%s returned %d' % (cmd, rv))


def _git_capture(argv):
p = subprocess.Popen(argv, stdout=subprocess.PIPE, preexec_fn = _gitenv)
r = p.stdout.read()
_git_wait(repr(argv), p)
return r


_ver_warned = 0
class CatPipe:
def __init__(self):
self.p = subprocess.Popen(['git', 'cat-file', '--batch'],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
preexec_fn = _gitenv)
global _ver_warned
wanted = ('1','5','6')
if ver() < wanted:
if not _ver_warned:
log('warning: git version < %s; bup will be slow.\n'
% '.'.join(wanted))
_ver_warned = 1
self.get = self._slow_get
else:
self.p = subprocess.Popen(['git', 'cat-file', '--batch'],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
preexec_fn = _gitenv)
self.get = self._fast_get

def get(self, id):
def _fast_get(self, id):
assert(id.find('\n') < 0)
assert(id.find('\r') < 0)
assert(id[0] != '-')
self.p.stdin.write('%s\n' % id)
hdr = self.p.stdout.readline()
spl = hdr.split(' ')
Expand All @@ -370,6 +413,20 @@ def get(self, id):
yield blob
assert(self.p.stdout.readline() == '\n')

def _slow_get(self, id):
assert(id.find('\n') < 0)
assert(id.find('\r') < 0)
assert(id[0] != '-')
type = _git_capture(['git', 'cat-file', '-t', id]).strip()
yield type

p = subprocess.Popen(['git', 'cat-file', type, id],
stdout=subprocess.PIPE,
preexec_fn = _gitenv)
for blob in chunkyreader(p.stdout):
yield blob
_git_wait('git cat-file', p)

def _join(self, it):
type = it.next()
if type == 'blob':
Expand Down
7 changes: 5 additions & 2 deletions test-sh
Expand Up @@ -7,7 +7,7 @@ export BUP_DIR="$TOP/buptest.tmp"

bup()
{
"$TOP/bup" "$@"
"$TOP/bup" "$@"
}

set -x
Expand Down Expand Up @@ -35,7 +35,10 @@ diff -u testfile2 out2c.tmp
git repack -Ad
git prune
(cd "$TOP/t/sampledata" && bup save -vvn master .) || exit 1
n=$(git fsck --full --strict 2>&1 | tee -a /dev/stderr | wc -l)
n=$(git fsck --full --strict 2>&1 |
grep -v 'dangling commit' |
tee -a /dev/stderr |
wc -l)
if [ "$n" != 0 ]; then
echo "git fsck error."
exit 5
Expand Down

0 comments on commit 755be38

Please sign in to comment.