]>
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()
69 """Unlink |path| if it exists else do nothing"""
70 if os
.path
.isfile(path
):
74 def clean_hooks(path
):
75 """Strip out sample files from hooks/"""
76 hooks_path
= os
.path
.join(path
, 'hooks')
77 for hook
in glob
.glob(os
.path
.join(hooks_path
, '*.sample')):
78 print('Trimming hook: %s' % hook
)
82 def clean_packs(path
):
83 """Strip out temp files from objects/packs/"""
84 packs_path
= os
.path
.join(path
, 'objects', 'packs')
85 for pack
in glob
.glob(os
.path
.join(packs_path
, 'tmp_pack_*')):
86 print('Trimming pack: %s' % pack
)
91 """See if the git repo is already packed"""
92 if set(('info', 'pack')) != set(os
.listdir(path
)):
94 packs
= os
.listdir(os
.path
.join(path
, 'pack'))
101 """Clean up and trim cruft and repack |path|"""
102 path
= find_git_dir(path
)
103 print('Repacking %s' % path
)
105 tmpdir
= find_temp_dir()
107 tmpdir
= tempfile
.mkdtemp(prefix
='git-repack.', dir=tmpdir
)
108 print('Using tempdir: %s' % tmpdir
)
113 # Push/pop the graft & alternate paths so we don't read them.
114 # XXX: In some cases, this is bad, but I don't use them that way ...
115 graft_file
= os
.path
.join(path
, 'info', 'grafts')
116 grafts
= readfile(graft_file
)
119 alt_file
= os
.path
.join(path
, 'objects', 'info', 'alternates')
120 alts
= readfile(alt_file
)
125 origin_path
= os
.path
.join(path
, 'refs', 'remotes', 'origin')
126 packed_refs
= readfile(os
.path
.join(path
, 'packed-refs'))
127 if os
.path
.exists(origin_path
) or 'refs/remotes/origin/' in packed_refs
:
128 cmd
= ['git', '--git-dir', path
, 'remote', 'prune', 'origin']
129 subprocess
.check_call(cmd
, cwd
='/')
134 print('Git repo is already packed; nothing to do')
138 print('Syncing git repo to tempdir')
139 shutil
.copytree(path
, tmpdir
, symlinks
=True)
144 cmd
= ['git', '--git-dir', rundir
, 'reflog', 'expire', '--all', '--stale-fix']
145 print('Cleaning reflog: %s' % ' '.join(cmd
))
146 subprocess
.check_call(cmd
, cwd
='/')
148 # This also packs refs/tags for us.
149 cmd
= ['git', '--git-dir', rundir
, 'gc', '--aggressive', '--prune=all']
150 print('Repacking git repo: %s' % ' '.join(cmd
))
151 subprocess
.check_call(cmd
, cwd
='/')
154 cmd
= ['rsync', '-a', '--delete', tmpdir
+ '/', path
+ '/']
155 print('Syncing back git repo: %s' % ' '.join(cmd
))
156 subprocess
.check_call(cmd
, cwd
='/')
157 cmd
= ['find', path
+ '/', '-exec', 'chmod', 'u+rw', '{}', '+']
158 subprocess
.check_call(cmd
, cwd
='/')
162 open(graft_file
, 'w').write(grafts
)
164 open(alt_file
, 'w').write(alts
)
166 shutil
.rmtree(tmpdir
)
170 """Get the command line parser"""
171 parser
= argparse
.ArgumentParser(description
=__doc__
)
172 parser
.add_argument('dir', help='The git repo to process')
177 """The main script entry point"""
178 parser
= get_parser()
179 opts
= parser
.parse_args(argv
)
183 if __name__
== '__main__':
184 exit(main(sys
.argv
[1:]))