Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Speed up "git fat checkout" and "git fat pull" #68

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 39 additions & 16 deletions git-fat
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ def gitconfig_set(name, value, file=None):
class GitFat(object):
DecodeError = RuntimeError
def __init__(self):
self.verbose = verbose_stderr if os.environ.get('GIT_FAT_VERBOSE') else verbose_ignore
self.is_verbose = os.environ.get('GIT_FAT_VERBOSE')
self.verbose = verbose_stderr if self.is_verbose else verbose_ignore
try:
self.gitroot = subprocess.check_output('git rev-parse --show-toplevel'.split()).strip()
except subprocess.CalledProcessError:
Expand Down Expand Up @@ -403,21 +404,43 @@ class GitFat(object):
def checkout(self, show_orphans=False):
'Update any stale files in the present working tree'
self.assert_init_done()
for digest, fname in self.orphan_files():
objpath = os.path.join(self.objdir, digest)
if os.access(objpath, os.R_OK):
print('Restoring %s -> %s' % (digest, fname))
# The output of our smudge filter depends on the existence of
# the file in .git/fat/objects, but git caches the file stat
# from the previous time the file was smudged, therefore it
# won't try to re-smudge. I don't know a git command that
# specifically invalidates that cache, but touching the file
# also does the trick.
os.utime(fname, None)
# This re-smudge is essentially a copy that restores permissions.
subprocess.check_call(['git', 'checkout-index', '--index', '--force', fname])
elif show_orphans:
print('Data unavailable: %s %s' % (digest,fname))
orphan_files_is_accessible = [(digest, fname, os.access(os.path.join(self.objdir, digest), os.R_OK)) for digest, fname in self.orphan_files()]
filenames_to_restore = [fname for digest, fname, accessible in orphan_files_is_accessible if accessible]

for fname in filenames_to_restore:
# The output of our smudge filter depends on the existence of
# the file in .git/fat/objects, but git caches the file stat
# from the previous time the file was smudged, therefore it
# won't try to re-smudge. I don't know a git command that
# specifically invalidates that cache, but touching the file
# also does the trick.
os.utime(fname, None)

if show_orphans:
for digest, fname, accessible in orphan_files_is_accessible:
if not accessible:
print('Data unavailable: %s %s' % (digest,fname))

filenames_nullterm = "\x00".join(filenames_to_restore)

if not self.is_verbose:
print('Restoring %d Files' % (len(filenames_to_restore),))
else:
print('Restoring %d Files:' % (len(filenames_to_restore),))
for digest, fname, accessible in orphan_files_is_accessible:
if accessible:
print('%s: %s' % (digest, fname))

if filenames_to_restore:
# This re-smudge is essentially a copy that restores permissions.
cmd = ['git', 'checkout-index', '--stdin', '-z', '--index', '--force']
p = subprocess.Popen(cmd, stdin = subprocess.PIPE)
p.communicate(filenames_nullterm)
retcode = p.wait()
if retcode != 0:
error = subprocess.CalledProcessError(retcode, " ".join(cmd))
raise error

def cmd_pull(self, args):
'Pull anything that I have referenced, but not stored'
self.setup()
Expand Down