]>
git.wh0rd.org - home.git/blob - .bin/git-repack
3 """Repack git repos fully the way I like them."""
5 from __future__
import print_function
17 """Return dict mapping path to its type"""
19 with
open('/proc/mounts') as fp
:
26 def find_git_dir(path
):
27 """Try to find the .git dir to operate on"""
29 real_path
= path
= os
.path
.realpath(path
)
32 if os
.path
.isdir(os
.path
.join(path
, '.git')):
33 curr_path
= os
.path
.join(path
, '.git')
35 if (os
.path
.isdir(os
.path
.join(curr_path
, 'refs')) and
36 os
.path
.isdir(os
.path
.join(curr_path
, 'objects')) and
37 os
.path
.isfile(os
.path
.join(curr_path
, 'config'))):
40 path
= os
.path
.dirname(path
)
43 raise ValueError('could not locate .git dir: %s (%s)' %
44 (orig_path
, real_path
))
48 """Find a good temp dir (one backed by tmpfs)"""
53 tempfile
.gettempdir(),
55 mounts
= mount_settings()
56 for path
in SEARCH_PATHS
:
57 if mounts
.get(path
) == 'tmpfs':
63 """Read |path| and return its data"""
64 if os
.path
.isfile(path
):
65 return open(path
).read()
70 """Unlink |path| if it exists else do nothing"""
71 if os
.path
.isfile(path
):
75 def clean_hooks(path
):
76 """Strip out sample files from hooks/"""
77 hooks_path
= os
.path
.join(path
, 'hooks')
78 for hook
in glob
.glob(os
.path
.join(hooks_path
, '*.sample')):
79 print('Trimming hook: %s' % hook
)
83 def clean_packs(path
):
84 """Strip out temp files from objects/packs/"""
85 packs_path
= os
.path
.join(path
, 'objects', 'packs')
86 for pack
in glob
.glob(os
.path
.join(packs_path
, 'tmp_pack_*')):
87 print('Trimming pack: %s' % pack
)
92 """See if the git repo is already packed"""
93 if set(('info', 'pack')) != set(os
.listdir(path
)):
95 packs
= os
.listdir(os
.path
.join(path
, 'pack'))
102 """Clean up and trim cruft and repack |path|"""
103 path
= find_git_dir(path
)
104 print('Repacking %s' % path
)
106 tmpdir
= find_temp_dir()
108 tmpdir
= tempfile
.mkdtemp(prefix
='git-repack.', dir=tmpdir
)
109 print('Using tempdir: %s' % tmpdir
)
114 # Push/pop the graft & alternate paths so we don't read them.
115 # XXX: In some cases, this is bad, but I don't use them that way ...
116 graft_file
= os
.path
.join(path
, 'info', 'grafts')
117 grafts
= readfile(graft_file
)
120 alt_file
= os
.path
.join(path
, 'objects', 'info', 'alternates')
121 alts
= readfile(alt_file
)
126 origin_path
= os
.path
.join(path
, 'refs', 'remotes', 'origin')
127 packed_refs
= readfile(os
.path
.join(path
, 'packed-refs'))
128 if os
.path
.exists(origin_path
) or 'refs/remotes/origin/' in packed_refs
:
129 cmd
= ['git', '--git-dir', path
, 'remote', 'prune', 'origin']
130 subprocess
.check_call(cmd
, cwd
='/')
135 print('Git repo is already packed; nothing to do')
139 print('Syncing git repo to tempdir')
140 shutil
.copytree(path
, tmpdir
, symlinks
=True)
145 cmd
= ['git', '--git-dir', rundir
, 'reflog', 'expire', '--all', '--stale-fix']
146 print('Cleaning reflog: %s' % ' '.join(cmd
))
147 subprocess
.check_call(cmd
, cwd
='/')
149 # This also packs refs/tags for us.
150 cmd
= ['git', '--git-dir', rundir
, 'gc', '--aggressive', '--prune=all']
151 print('Repacking git repo: %s' % ' '.join(cmd
))
152 subprocess
.check_call(cmd
, cwd
='/')
155 cmd
= ['rsync', '-a', '--delete', tmpdir
+ '/', path
+ '/']
156 print('Syncing back git repo: %s' % ' '.join(cmd
))
157 subprocess
.check_call(cmd
, cwd
='/')
158 cmd
= ['find', path
+ '/', '-exec', 'chmod', 'u+rw', '{}', '+']
159 subprocess
.check_call(cmd
, cwd
='/')
163 open(graft_file
, 'w').write(grafts
)
165 open(alt_file
, 'w').write(alts
)
167 shutil
.rmtree(tmpdir
)
171 """Get the command line parser"""
172 parser
= argparse
.ArgumentParser(description
=__doc__
)
173 parser
.add_argument('dir', help='The git repo to process')
178 """The main script entry point"""
179 parser
= get_parser()
180 opts
= parser
.parse_args(argv
)
184 if __name__
== '__main__':
185 exit(main(sys
.argv
[1:]))