repack: a minor mod on git-repack to allow pruning of grafted-over history
[puppet-git.git] / ppg-repack
blob2a60700e46512523ee62e2bd7105dc7920c99780
1 #!/bin/sh
3 # Copyright (c) 2005 Linus Torvalds
6 ##
7 ## cribbed from git v1.8.3-rc1-26-g8a45db1
8 ##
10 OPTIONS_KEEPDASHDASH=
11 OPTIONS_SPEC="\
12 git repack [options]
14 a pack everything in a single pack
15 A same as -a, and turn unreachable objects loose
16 d remove redundant packs, and run git-prune-packed
17 f pass --no-reuse-delta to git-pack-objects
18 F pass --no-reuse-object to git-pack-objects
19 n do not run git-update-server-info
20 q,quiet be quiet
21 l pass --local to git-pack-objects
22 unpack-unreachable= with -A, do not loosen objects older than this
23 Packing constraints
24 window= size of the window used for delta compression
25 window-memory= same as the above, but limit memory size instead of entries count
26 depth= limits the maximum delta depth
27 max-pack-size= maximum size of each packfile
29 SUBDIRECTORY_OK='Yes'
30 GIT_EXEC_PATH=$(git --exec-path)
31 . $GIT_EXEC_PATH/git-sh-setup
33 no_update_info= all_into_one= remove_redundant= unpack_unreachable=
34 local= no_reuse= extra=
35 while test $# != 0
37 case "$1" in
38 -n) no_update_info=t ;;
39 -a) all_into_one=t ;;
40 -A) all_into_one=t
41 unpack_unreachable=--unpack-unreachable ;;
42 --unpack-unreachable)
43 unpack_unreachable="--unpack-unreachable=$2"; shift ;;
44 -d) remove_redundant=t ;;
45 -q) GIT_QUIET=t ;;
46 -f) no_reuse=--no-reuse-delta ;;
47 -F) no_reuse=--no-reuse-object ;;
48 -l) local=--local ;;
49 --max-pack-size|--window|--window-memory|--depth)
50 extra="$extra $1=$2"; shift ;;
51 --) shift; break;;
52 *) usage ;;
53 esac
54 shift
55 done
57 case "`git config --bool repack.usedeltabaseoffset || echo true`" in
58 true)
59 extra="$extra --delta-base-offset" ;;
60 esac
62 PACKDIR="$GIT_OBJECT_DIRECTORY/pack"
63 PACKTMP="$PACKDIR/.tmp-$$-pack"
64 rm -f "$PACKTMP"-*
65 trap 'rm -f "$PACKTMP"-*' 0 1 2 3 15
67 # There will be more repacking strategies to come...
68 case ",$all_into_one," in
69 ,,)
70 args='--unpacked --incremental'
72 ,t,)
73 args= existing=
74 if [ -d "$PACKDIR" ]; then
75 for e in `cd "$PACKDIR" && find . -type f -name '*.pack' \
76 | sed -e 's/^\.\///' -e 's/\.pack$//'`
78 if [ -e "$PACKDIR/$e.keep" ]; then
79 : keep
80 else
81 existing="$existing $e"
83 done
84 if test -n "$existing" -a -n "$unpack_unreachable" -a \
85 -n "$remove_redundant"
86 then
87 # This may have arbitrary user arguments, so we
88 # have to protect it against whitespace splitting
89 # when it gets run as "pack-objects $args" later.
90 # Fortunately, we know it's an approxidate, so we
91 # can just use dots instead.
92 args="$args $(echo "$unpack_unreachable" | tr ' ' .)"
96 esac
98 mkdir -p "$PACKDIR" || exit
100 args="$args $local ${GIT_QUIET:+-q} $no_reuse$extra"
101 # we skip --keep-true-parents so history masked by a graft
102 # is discarded ...
103 names=$(git pack-objects --honor-pack-keep --non-empty --all --reflog $args </dev/null "$PACKTMP") ||
104 exit 1
105 if [ -z "$names" ]; then
106 say Nothing new to pack.
109 # Ok we have prepared all new packfiles.
111 # First see if there are packs of the same name and if so
112 # if we can move them out of the way (this can happen if we
113 # repacked immediately after packing fully.
114 rollback=
115 failed=
116 for name in $names
118 for sfx in pack idx
120 file=pack-$name.$sfx
121 test -f "$PACKDIR/$file" || continue
122 rm -f "$PACKDIR/old-$file" &&
123 mv "$PACKDIR/$file" "$PACKDIR/old-$file" || {
124 failed=t
125 break
127 rollback="$rollback $file"
128 done
129 test -z "$failed" || break
130 done
132 # If renaming failed for any of them, roll the ones we have
133 # already renamed back to their original names.
134 if test -n "$failed"
135 then
136 rollback_failure=
137 for file in $rollback
139 mv "$PACKDIR/old-$file" "$PACKDIR/$file" ||
140 rollback_failure="$rollback_failure $file"
141 done
142 if test -n "$rollback_failure"
143 then
144 echo >&2 "WARNING: Some packs in use have been renamed by"
145 echo >&2 "WARNING: prefixing old- to their name, in order to"
146 echo >&2 "WARNING: replace them with the new version of the"
147 echo >&2 "WARNING: file. But the operation failed, and"
148 echo >&2 "WARNING: attempt to rename them back to their"
149 echo >&2 "WARNING: original names also failed."
150 echo >&2 "WARNING: Please rename them in $PACKDIR manually:"
151 for file in $rollback_failure
153 echo >&2 "WARNING: old-$file -> $file"
154 done
156 exit 1
159 # Now the ones with the same name are out of the way...
160 fullbases=
161 for name in $names
163 fullbases="$fullbases pack-$name"
164 chmod a-w "$PACKTMP-$name.pack"
165 chmod a-w "$PACKTMP-$name.idx"
166 mv -f "$PACKTMP-$name.pack" "$PACKDIR/pack-$name.pack" &&
167 mv -f "$PACKTMP-$name.idx" "$PACKDIR/pack-$name.idx" ||
168 exit
169 done
171 # Remove the "old-" files
172 for name in $names
174 rm -f "$PACKDIR/old-pack-$name.idx"
175 rm -f "$PACKDIR/old-pack-$name.pack"
176 done
178 # End of pack replacement.
180 if test "$remove_redundant" = t
181 then
182 # We know $existing are all redundant.
183 if [ -n "$existing" ]
184 then
185 ( cd "$PACKDIR" &&
186 for e in $existing
188 case " $fullbases " in
189 *" $e "*) ;;
190 *) rm -f "$e.pack" "$e.idx" "$e.keep" ;;
191 esac
192 done
195 git prune-packed ${GIT_QUIET:+-q}
198 case "$no_update_info" in
199 t) : ;;
200 *) git update-server-info ;;
201 esac