1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
|
#!/bin/sh
# copyright, licensing and documentation at the end
set -e
set -u
usage() {
perl -MPod::Usage=pod2usage -e"pod2usage(-input => '$0', -verbose=>99, -sections=>[qw(SYNOPSIS DESCRIPTION)])"
exit 1
}
STATS=
VERBOSE=
HAVE_BC=
PARALLEL=
while getopts vshp opt; do
case $opt in
h) usage;;
s) STATS=1
if command -v bc > /dev/null 2>&1; then
HAVE_BC=1
else
echo "W: 'bc' not available, stats will use byte units" >&2
fi
;;
p) PARALLEL=1;;
v) VERBOSE=1;;
?) usage;;
esac
done
shift `expr $OPTIND - 1`
[ -z "${1:-}" ] || usage
cd "${DPT_PACKAGES:?}"
if [ -n "$HAVE_BC" ]; then
calc() {
( echo "scale=1"; echo "$@" ) | LC_ALL=C bc
}
else
calc() {
echo $(( "$@" ))
}
fi
human() {
local K_DIV=1024
local M_DIV=$(( $K_DIV * $K_DIV ))
local G_DIV=$(( $M_DIV * $K_DIV ))
if [ -n "$HAVE_BC" ]; then
if [ `calc "$1 / $G_DIV >= 1.1"` = "1" ]; then
echo `calc "$1 / $G_DIV"`G
elif [ `calc "$1 / $M_DIV > 1.1"` = "1" ]; then
echo `calc "$1 / $M_DIV"`M
elif [ `calc "$1 / $K_DIV > 1.1"` = "1" ]; then
echo `calc "$1 / $K_DIV"`K
else
echo $1
fi
else
echo $1
fi
}
if [ -n "$STATS" ]; then
TOTAL_BEFORE=$(find . -maxdepth 2 -type d -name .git -print0 | du -sbP --total --files0-from=- | tail -1 | cut -f1)
fi
if [ -n "$PARALLEL" ]; then
find . -maxdepth 2 -type d -name .git -print0 | \
xargs -r0 -P $(nproc) -I '{}' sh -c "GIT_DIR='{}' git gc --quiet"
else
for d in `find . -maxdepth 1 -type d`; do
[ -d "$d/.git" ] || continue
if [ -n "$VERBOSE" ]; then
echo -n "`basename $d`"
fi
if [ -n "$STATS" ]; then
BEFORE=`du -sbP $d/.git | cut -f1`
fi
GIT_DIR="$d/.git" git gc --quiet
if [ -n "$STATS" ]; then
AFTER=`du -sbP $d/.git | cut -f1`
fi
if [ -n "$VERBOSE" ]; then
echo -n " done."
if [ -n "$STATS" ]; then
printf " %s -> %s (-%s, %0.1f%%)" \
`human $BEFORE` `human $AFTER` \
`human $(( $BEFORE - $AFTER ))` \
`calc "100*($BEFORE-$AFTER)/$BEFORE"`
fi
echo
fi
done
fi
if [ -n "$STATS" ]; then
TOTAL_AFTER=$(find . -maxdepth 2 -type d -name .git -print0 | du -sbP --total --files0-from=- | tail -1 | cut -f1)
GAIN=$(( $TOTAL_BEFORE - $TOTAL_AFTER ))
printf "Total disk usage: %s -> %s (-%s, %0.1f%%)\n" \
`human $TOTAL_BEFORE` `human $TOTAL_AFTER` \
`human $GAIN` \
`calc "100*($GAIN)/$TOTAL_BEFORE"`
fi
exit 0
POD=<<'EOF'
=head1 NAME
dpt-gc - swipe pkg-perl working directories
=head1 SYNOPSIS
B<dpt gc> [I<option>...]
=head1 DESCRIPTION
B<dpt gc> runs L<git(1)> garbage collection in cloned pkg-perl's repositories. It is suitable to be run from L<cron(1)>, e.g. weekly.
=head1 CONFIGURATION
B<dpt gc> uses the C<DPT_PACKAGES> environment variable. If
C<DPT_PACKAGES> is not defined, the command fails.
See L<dpt-config(5)> for details.
=head1 OPTIONS
=over
=item B<-h>
Display usage information.
=item B<-p>
Run in parallel, utilizing all CPUs.
=item B<-s>
Display statistics about disk usage before and after garbage collection.
=item B<-v>
Verbose operation. Let L<git-gc(1)> emit progress messages. Doesn't display
per-repository stats when B<-p> is used.
=back
=head1 COPYRIGHT & LICENSE
Copyright 2013, 2017 Damyan Ivanov L<dmn@debian.org>
Copyright 2017, 2018 gregor herrmann L<gregoa@debian.org>
This program is free software, licensed under the same terms as perl.
=cut
EOF
|