3 # Report on project disk use.
4 # Output can be sent as email to admin with -m
5 # Automatically runs with nice and ionice (if available)
7 # Usage: project-disk-use [-m] [top-n-only]
9 # With -m mail the report to $cfg_admin instead of sending it to stdout
11 # Shows total disk usage in K bytes for $cfg_reporoot
12 # The top-n-only (all if not given) repos are then listed by
13 # decreasing order of disk space.
15 # Note that any *.git directories that are found in $cfg_reporoot that are
16 # not listed in $cfg_chroot/etc/group ARE included and have a '!' suffix added.
20 datefmt
='%Y-%m-%d %H:%M:%S %z'
21 startdate
="$(date "+$datefmt")"
26 if [ "$1" = "-m" ]; then
32 ! command -v nice
>/dev
/null || hasnice
=1
34 ! command -v ionice
>/dev
/null || hasionice
=1
41 _y
="${1%%[1-9]*}"; _x="${1#$_y}"; _x="${_x:-0}"
42 # add commas after each group of 3
44 while [ $_x -gt 999 ]; do
45 _y
="$(printf '%03d' $(($_x - $_x / 1000 * 1000)))${_y:+,$_y}"
48 [ $_x -eq 0 ] || _y
="$_x${_y:+,$_y}"
53 if [ -z "$1" ] ||
[ "$1" = "0" ]; then return; fi
54 if [ -z "$2" ] ||
[ "$2" = "0" ]; then return; fi
55 _fmtpct
=$
(( ( $1 * 100 + $2 / 2 ) / $2 ))
56 if [ $_fmtpct -le 100 ]; then
58 [ -z "$4" ] || _of
=" of $(fmtcomma $2)"
59 echo "${3:- }($_fmtpct%$_of)"
66 _cmd
="du $var_du_follow -k -s"
67 if [ -n "$var_du_exclude" ]; then
69 _cmd
="$_cmd $var_du_exclude \"$1\""
72 elif [ $# -ne 0 ]; then
73 echo "get_use_k: error: no du exclude option available" >&2
76 _cmd
="$_cmd \"$_targ\" 2>/dev/null | cut -f 1"
77 [ -z "$hasionice" ] || _cmd
="ionice -c 3 $_cmd"
78 [ -z "$hasnice" ] || _cmd
="nice -n 19 $_cmd"
83 cd "$cfg_reporoot/$1.git" ||
return 1
84 check_interval lastchange
2592000 # 30 days
87 projlist
="$(cut -d : -f 1 <"$cfg_chroot/etc
/group
")"
90 echo "$projlist" |
grep -q -e "^$1$"
93 totaluse
="$(get_use_k "$cfg_reporoot")"
94 globaluse
="$(get_use_k "$cfg_reporoot/_global
")"
95 totaluse
="$(( $totaluse - $globaluse ))"
96 if [ -n "$var_du_exclude" ]; then
97 # Attribute all hard-linked stuff in _recyclebin to non-_recyclebin
98 inuse
="$(get_use_k "$cfg_reporoot" "_recyclebin
")"
99 inuse
="$(( $inuse - $globaluse ))"
100 binned
="$(( $totaluse - $inuse ))"
102 # No du exclude option, if binned contains hard links into other repos
103 # its size may appear larger than it actually is and the kpct will be off
104 binned
="$(get_use_k "$cfg_reporoot/_recyclebin
")"
105 inuse
="$(( $totaluse - $binned ))"
121 while IFS
='' read -r proj
; do
123 absproj
="$(cd "$proj" && pwd -P)" && [ -n "$absproj" ] && [ -d "$absproj" ] ||
continue
124 if [ -L "$proj" ]; then
125 # symlinks to elsewhere under $cfg_reporoot are ignored
126 # symlinks to outside there are reported on unless orphaned
127 case "$absproj" in "$absroot"/*)
131 case "$absproj" in "$absroot"/*);;*)
138 if ! is_listed_proj
"$proj"; then
139 [ -z "$external" ] ||
continue
141 orphans
="$(( $orphans + 1 ))"
143 case "$proj" in */*) forks
="$(( $forks + 1 ))"; esac
144 mirror
="$(get_mirror_type "$proj.git
" 2>/dev/null)" ||
:
145 [ -z "$mirror" ] || mirrors
="$(( $mirrors + 1 ))"
146 if is_active
"$proj"; then
148 if [ -n "$mirror" ]; then
149 mactive
="$(( $mactive + 1 ))"
151 pactive
="$(( $pactive + 1 ))"
155 usek
="$(get_use_k "$proj.git
")"
159 girocco_bang_firstfail
=
160 girocco_bang_messagesent
=
161 [ -L "$proj.git/objects" ] ||
! [ -d "$proj.git/objects" ] ||
162 eval "$(git --git-dir="$cfg_reporoot/$proj.git
" config --get-regexp \
163 '^girocco\.((bang\.(count|firstfail|messagesent))|reposizek)$' |
164 LC_ALL=C awk '{gsub(/[.]/,"_
",$1); $0 ~ / / || sub(/$/," "); sub(/ /,"=\042"); print $0 "\042"}')" ||
:
166 if [ -n "$girocco_bang_count" ] && [ "${girocco_bang_count#*[!0-9]}" = "$girocco_bang_count" ] && [ "$girocco_bang_count" -gt 0 ]; then
167 banged
=$
(( $banged + 1 ))
168 girocco_bang_count
=$
(( 0 + $girocco_bang_count ))
169 b
="~(${girocco_bang_firstfail:+$girocco_bang_firstfail/}$girocco_bang_count"
170 if [ "$girocco_bang_messagesent" = "true" ] ||
[ "$girocco_bang_messagesent" = "1" ]; then
172 bangsent
=$
(( $bangsent + 1 ))
176 repok
="$girocco_reposizek"
180 repok
="${repok%%[!0-9]*}"
181 repokpct
=$
(( ( $repok * 100 + $usek / 2 ) / $usek ))
182 if [ $repokpct -le 100 ]; then
183 repokpct
="$repokpct%"
191 if [ -z "$external" ]; then
192 ktotal
=$
(( $ktotal + $repok ))
193 total
="$(( $total + $usek ))"
195 howmany
="$(( $howmany + 1 ))"
196 line
="$usek $repokpct $mirror $proj$a$x$b$nl"
197 results
="$results$line"
199 $(find -L . -type d \( -path ./_recyclebin -o -path ./_global -o -name '*.git' -print \) -prune 2>/dev/null)
202 kpct
=$
(( ( $ktotal * 100 + $inuse / 2 ) / $inuse ))
203 enddate
="$(date "+$datefmt")"
205 [ -z "$mailresult" ] || domail
='mailref "diskuse@$cfg_gitweburl" -s "[$cfg_name] Project Disk Use Report" "$cfg_admin"'
208 Project Disk Use Report
209 =======================
211 Start Time: $startdate
214 Repository Root: $cfg_reporoot
215 Unbinned Disk Use: $(fmtcomma "$inuse") (1024-byte blocks)
216 reposizek Total: $(fmtcomma "$ktotal") ($kpct%)
218 Recycle Bin Root: $cfg_reporoot/_recyclebin
219 Binned Disk Use: $(fmtcomma "$binned") (1024-byte blocks)
221 Total Disk Use: $(fmtcomma "$totaluse") (1024-byte blocks)
223 Repository Count: $(fmtcomma "$howmany")
224 Forks: $(fmtcomma "$forks")$(fmtpct "$forks" "$howmany")
225 Mirrors: $(fmtcomma "$mirrors")$(fmtpct "$mirrors" "$howmany")
226 ~Banged: $(fmtcomma "$banged")$(fmtpct "$banged" "$howmany")/($(( $banged - $bangsent )) unsent)
227 Orphaned: $(fmtcomma "$orphans")
228 Repository Total: $(fmtcomma "$total") (1024-byte blocks)
230 *30-Day Active: $(fmtcomma "$(( $pactive + $mactive ))")$(fmtpct "$(( $pactive + $mactive ))" "$howmany")
231 Push: $(fmtcomma "$pactive")$(fmtpct "$pactive" "$howmany")$(fmtpct "$pactive" "$(( $pactive + $mactive ))" "/" 1)$(fmtpct "$pactive" "$(( $howmany - $mirrors ))" "/" 1)
232 Mirror: $(fmtcomma "$mactive")$(fmtpct "$mactive" "$howmany")$(fmtpct "$mactive" "$(( $pactive + $mactive ))" "/" 1)$(fmtpct "$mactive" "$mirrors" "/" 1)
234 $(df -h "$cfg_reporoot")
237 if [ $# -lt 1 ] ||
[ $1 != "0" ]; then
239 message
="Individual Repository Use"
240 case "${1%%[!0-9]*}" in ?
*)
241 message
="Individual Repository Use (Top $1)"
242 topn
="head -n ${1%%[!0-9]*}"
247 echo "$message" |
tr -c '\n' -
249 printf '%s' "$results" |
sort -k1,1nr
-k4,4 |
250 while read -r a b c d
; do
251 printf "%10s %4s %s %s\n" "$(fmtcomma "$a")" "$b" "$c" "$d"
253 sed -e 's/ [M-] / /g' |
$topn