| Giorgi Lekveishvili | 285ab62 | 2023-11-22 13:50:45 +0400 | [diff] [blame] | 1 | #!/bin/ash |
| 2 | # Copyright (C) 2011, 2020 SAP SE |
| 3 | # |
| 4 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | # you may not use this file except in compliance with the License. |
| 6 | # You may obtain a copy of the License at |
| 7 | # |
| 8 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | # |
| 10 | # Unless required by applicable law or agreed to in writing, software |
| 11 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | # See the License for the specific language governing permissions and |
| 14 | # limitations under the License. |
| 15 | |
| 16 | usage() |
| 17 | { |
| 18 | echo "Usage: $0 [ -s ProjectName ] [ -p ProjectName ] [ -b ProjectName ]" |
| 19 | echo "-s ProjectName : skip this project" |
| 20 | echo "-p ProjectName : run git-gc for this project" |
| 21 | echo "-b ProjectName : do not write bitmaps for this project" |
| 22 | echo "" |
| 23 | echo "By default the script will run git-gc for all projects unless \"-p\" option is provided" |
| 24 | echo |
| 25 | echo "Examples:" |
| 26 | echo " Run git-gc for all projects but skip foo and bar/baz projects" |
| 27 | echo " $0 -s foo -s bar/baz" |
| 28 | echo " Run git-gc only for foo and bar/baz projects" |
| 29 | echo " $0 -p foo -p bar/baz" |
| 30 | echo " Run git-gc only for bar project without writing bitmaps" |
| 31 | echo " $0 -p bar -b bar" |
| 32 | echo |
| 33 | echo "To specify a one-time --aggressive git gc for a repository X, simply" |
| 34 | echo "create an empty file called \'gc-aggressive-once\' in the \$SITE/git/X.git" |
| 35 | echo "folder:" |
| 36 | echo |
| 37 | echo " \$ cd \$SITE/git/X.git" |
| 38 | echo " \$ touch gc-aggressive-once" |
| 39 | echo |
| 40 | echo "On the next run, gc.sh will use --aggressive option for gc-ing this" |
| 41 | echo "repository *and* will remove this file. Next time, gc.sh again runs" |
| 42 | echo "normal gc for this repository." |
| 43 | echo |
| 44 | echo "To specify a permanent --aggressive git gc for a repository, create" |
| 45 | echo "an empty file named "gc-aggresssive" in the same folder:" |
| 46 | echo |
| 47 | echo " \$ cd \$SITE/git/X.git" |
| 48 | echo " \$ touch gc-aggressive" |
| 49 | echo |
| 50 | echo "Every next git gc on this repository will use --aggressive option." |
| 51 | exit 2 |
| 52 | } |
| 53 | |
| 54 | gc_options() |
| 55 | { |
| 56 | if test -f "$1/gc-aggressive" ; then |
| 57 | echo "--aggressive" |
| 58 | elif test -f "$1/gc-aggressive-once" ; then |
| 59 | echo "--aggressive" |
| 60 | rm -f "$1/gc-aggressive-once" |
| 61 | else |
| 62 | echo "" |
| 63 | fi |
| 64 | } |
| 65 | |
| 66 | log_opts() |
| 67 | { |
| 68 | if test -z $1 ; then |
| 69 | echo "" |
| 70 | else |
| 71 | echo " [$1]" |
| 72 | fi |
| 73 | } |
| 74 | |
| 75 | log() |
| 76 | { |
| 77 | # Rotate the $LOG if current date is different from the last modification of $LOG |
| 78 | if test -f "$LOG" ; then |
| 79 | TODAY=$(date +%Y-%m-%d) |
| 80 | LOG_LAST_MODIFIED=$(date +%Y-%m-%d -r $LOG) |
| 81 | if test "$TODAY" != "$LOG_LAST_MODIFIED" ; then |
| 82 | mv "$LOG" "$LOG.$LOG_LAST_MODIFIED" |
| 83 | gzip "$LOG.$LOG_LAST_MODIFIED" |
| 84 | fi |
| 85 | fi |
| 86 | |
| 87 | # Do not log an empty line |
| 88 | if [[ ! "$1" =~ ^[[:space:]]*$ ]]; then |
| 89 | echo $1 |
| 90 | echo $1 >>$LOG |
| 91 | fi |
| 92 | } |
| 93 | |
| 94 | gc_all_projects() |
| 95 | { |
| 96 | find $TOP -type d -path "*.git" -prune -o -name "*.git" | while IFS= read d |
| 97 | do |
| 98 | gc_project "${d#$TOP/}" |
| 99 | done |
| 100 | } |
| 101 | |
| 102 | gc_specified_projects() |
| 103 | { |
| 104 | for PROJECT_NAME in ${GC_PROJECTS} |
| 105 | do |
| 106 | gc_project "$PROJECT_NAME" |
| 107 | done |
| 108 | } |
| 109 | |
| 110 | gc_project() |
| 111 | { |
| 112 | PROJECT_NAME="$@" |
| 113 | PROJECT_DIR="$TOP/$PROJECT_NAME" |
| 114 | |
| 115 | if [[ ! -d "$PROJECT_DIR" ]]; then |
| 116 | OUT=$(date +"%D %r Failed: Directory does not exist: $PROJECT_DIR") && log "$OUT" |
| 117 | return 1 |
| 118 | fi |
| 119 | |
| 120 | OPTS=$(gc_options "$PROJECT_DIR") |
| 121 | LOG_OPTS=$(log_opts $OPTS) |
| 122 | |
| 123 | # Check if git-gc for this project has to be skipped |
| 124 | if [ $SKIP_PROJECTS_OPT -eq 1 ]; then |
| 125 | for SKIP_PROJECT in "${SKIP_PROJECTS}"; do |
| 126 | if [ "$SKIP_PROJECT" == "$PROJECT_NAME" ] ; then |
| 127 | OUT=$(date +"%D %r Skipped: $PROJECT_NAME") && log "$OUT" |
| 128 | return 0 |
| 129 | fi |
| 130 | done |
| 131 | fi |
| 132 | |
| 133 | # Check if writing bitmaps for this project has to be disabled |
| 134 | WRITEBITMAPS='true'; |
| 135 | if [ $DONOT_WRITE_BITMAPS_OPT -eq 1 ]; then |
| 136 | for BITMAP_PROJECT in "${DONOT_WRITE_BITMAPS}"; do |
| 137 | if [ "$BITMAP_PROJECT" == "$PROJECT_NAME" ] ; then |
| 138 | WRITEBITMAPS='false'; |
| 139 | fi |
| 140 | done |
| 141 | fi |
| 142 | |
| 143 | OUT=$(date +"%D %r Started: $PROJECT_NAME$LOG_OPTS") && log "$OUT" |
| 144 | |
| 145 | git --git-dir="$PROJECT_DIR" config core.logallrefupdates true |
| 146 | |
| 147 | git --git-dir="$PROJECT_DIR" config repack.usedeltabaseoffset true |
| 148 | git --git-dir="$PROJECT_DIR" config repack.writebitmaps $WRITEBITMAPS |
| 149 | git --git-dir="$PROJECT_DIR" config pack.compression 9 |
| 150 | git --git-dir="$PROJECT_DIR" config pack.indexversion 2 |
| 151 | |
| 152 | git --git-dir="$PROJECT_DIR" config gc.autodetach false |
| 153 | git --git-dir="$PROJECT_DIR" config gc.auto 0 |
| 154 | git --git-dir="$PROJECT_DIR" config gc.autopacklimit 0 |
| 155 | git --git-dir="$PROJECT_DIR" config gc.packrefs true |
| 156 | git --git-dir="$PROJECT_DIR" config gc.reflogexpire never |
| 157 | git --git-dir="$PROJECT_DIR" config gc.reflogexpireunreachable never |
| 158 | git --git-dir="$PROJECT_DIR" config receive.autogc false |
| 159 | |
| 160 | git --git-dir="$PROJECT_DIR" config pack.window 250 |
| 161 | git --git-dir="$PROJECT_DIR" config pack.depth 50 |
| 162 | |
| 163 | OUT=$(git -c gc.auto=6700 -c gc.autoPackLimit=4 --git-dir="$PROJECT_DIR" gc --auto --prune $OPTS || date +"%D %r Failed: $PROJECT_NAME") \ |
| 164 | && log "$OUT" |
| 165 | |
| 166 | (find "$PROJECT_DIR/refs/changes" -type d | xargs rmdir; |
| 167 | find "$PROJECT_DIR/refs/changes" -type d | xargs rmdir |
| 168 | ) 2>/dev/null |
| 169 | |
| 170 | OUT=$(date +"%D %r Finished: $PROJECT_NAME$LOG_OPTS") && log "$OUT" |
| 171 | } |
| 172 | |
| 173 | ########################### |
| 174 | # Main script starts here # |
| 175 | ########################### |
| 176 | |
| 177 | SKIP_PROJECTS= |
| 178 | GC_PROJECTS= |
| 179 | DONOT_WRITE_BITMAPS= |
| 180 | SKIP_PROJECTS_OPT=0 |
| 181 | GC_PROJECTS_OPT=0 |
| 182 | DONOT_WRITE_BITMAPS_OPT=0 |
| 183 | |
| 184 | while getopts 's:p:b:?h' c |
| 185 | do |
| 186 | case $c in |
| 187 | s) |
| 188 | SKIP_PROJECTS="${SKIP_PROJECTS} ${OPTARG}.git" |
| 189 | SKIP_PROJECTS_OPT=1 |
| 190 | ;; |
| 191 | p) |
| 192 | GC_PROJECTS="${GC_PROJECTS} ${OPTARG}.git" |
| 193 | GC_PROJECTS_OPT=1 |
| 194 | ;; |
| 195 | b) |
| 196 | DONOT_WRITE_BITMAPS="${DONOT_WRITE_BITMAPS} ${OPTARG}.git" |
| 197 | DONOT_WRITE_BITMAPS_OPT=1 |
| 198 | ;; |
| 199 | h|?) |
| 200 | usage |
| 201 | ;; |
| 202 | esac |
| 203 | done |
| 204 | |
| 205 | test $# -eq 0 || usage |
| 206 | |
| 207 | TOP=/var/gerrit/git |
| 208 | LOG=/var/log/git/gc.log |
| 209 | |
| 210 | OUT=$(date +"%D %r Started") && log "$OUT" |
| 211 | |
| 212 | if [ $GC_PROJECTS_OPT -eq 1 ]; then |
| 213 | gc_specified_projects |
| 214 | else |
| 215 | gc_all_projects |
| 216 | fi |
| 217 | |
| 218 | OUT=$(date +"%D %r Finished") && log "$OUT" |
| 219 | |
| 220 | exit 0 |