Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / bin / git-archive-all.sh
1 #!/bin/bash -
2 #
3 # File:        git-archive-all.sh
4 #
5 # Description: A utility script that builds an archive file(s) of all
6 #              git repositories and submodules in the current path.
7 #              Useful for creating a single tarfile of a git super-
8 #              project that contains other submodules.
9 #
10 # Examples:    Use git-archive-all.sh to create archive distributions
11 #              from git repositories. To use, simply do:
12 #
13 #                  cd $GIT_DIR; git-archive-all.sh
14 #
15 #              where $GIT_DIR is the root of your git superproject.
16 #
17 # License:     GPL3
18 #
19 ###############################################################################
20 #
21 # This program is free software; you can redistribute it and/or modify
22 # it under the terms of the GNU General Public License as published by
23 # the Free Software Foundation; either version 2 of the License, or
24 # (at your option) any later version.
25 #
26 # This program is distributed in the hope that it will be useful,
27 # but WITHOUT ANY WARRANTY; without even the implied warranty of
28 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
29 # GNU General Public License for more details.
30 #
31 # You should have received a copy of the GNU General Public License
32 # along with this program; if not, write to the Free Software
33 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
34 #
35 ###############################################################################
36
37 # DEBUGGING
38 set -e
39 set -C # noclobber
40
41 # TRAP SIGNALS
42 trap 'cleanup' QUIT EXIT
43
44 # For security reasons, explicitly set the internal field separator
45 # to newline, space, tab
46 OLD_IFS=$IFS
47 IFS='
48         '
49
50 function cleanup () {
51     rm -rf $TMPDIR
52     IFS="$OLD_IFS"
53 }
54
55 function usage () {
56     echo "Usage is as follows:"
57     echo
58     echo "$PROGRAM <--version>"
59     echo "    Prints the program version number on a line by itself and exits."
60     echo
61     echo "$PROGRAM <--usage|--help|-?>"
62     echo "    Prints this usage output and exits."
63     echo
64     echo "$PROGRAM [--format <fmt>] [--prefix <path>] [--verbose|-v] [--separate|-s]"
65     echo "         [--tree-ish|-t <tree-ish>] [--ignore pattern] [output_file]"
66     echo "    Creates an archive for the entire git superproject, and its submodules"
67     echo "    using the passed parameters, described below."
68     echo
69     echo "    If '--format' is specified, the archive is created with the named"
70     echo "    git archiver backend. Obviously, this must be a backend that git archive"
71     echo "    understands. The format defaults to 'tar' if not specified."
72     echo
73     echo "    If '--prefix' is specified, the archive's superproject and all submodules"
74     echo "    are created with the <path> prefix named. The default is to not use one."
75     echo
76     echo "    If '--separate' or '-s' is specified, individual archives will be created"
77     echo "    for each of the superproject itself and its submodules. The default is to"
78     echo "    concatenate individual archives into one larger archive."
79     echo
80     echo "    If '--tree-ish' is specified, the archive will be created based on whatever"
81     echo "    you define the tree-ish to be. Branch names, commit hash, etc. are acceptable."
82     echo "    Defaults to HEAD if not specified. See git archive's documentation for more"
83     echo "    information on what a tree-ish is."
84     echo
85     echo "    If '--ignore' is specified, we will filter out any submodules that"
86     echo "    match the specified pattern."
87     echo
88     echo "    If 'output_file' is specified, the resulting archive is created as the"
89     echo "    file named. This parameter is essentially a path that must be writeable."
90     echo "    When combined with '--separate' ('-s') this path must refer to a directory."
91     echo "    Without this parameter or when combined with '--separate' the resulting"
92     echo "    archive(s) are named with a dot-separated path of the archived directory and"
93     echo "    a file extension equal to their format (e.g., 'superdir.submodule1dir.tar')."
94     echo
95     echo "    If '--verbose' or '-v' is specified, progress will be printed."
96 }
97
98 function version () {
99     echo "$PROGRAM version $VERSION"
100 }
101
102 # Internal variables and initializations.
103 readonly PROGRAM=`basename "$0"`
104 readonly VERSION=0.2
105
106 OLD_PWD="`pwd`"
107 TMPDIR=`mktemp -d "${TMPDIR:-/tmp}/$PROGRAM.XXXXXX"`
108 TMPFILE=`mktemp "$TMPDIR/$PROGRAM.XXXXXX"` # Create a place to store our work's progress
109 TOARCHIVE=`mktemp "$TMPDIR/$PROGRAM.toarchive.XXXXXX"`
110 OUT_FILE=$OLD_PWD # assume "this directory" without a name change by default
111 SEPARATE=0
112 VERBOSE=0
113
114 TARCMD=tar
115 [[ $(uname) == "Darwin" ]] && TARCMD=gnutar
116 FORMAT=tar
117 PREFIX=
118 TREEISH=HEAD
119 IGNORE=
120
121 # RETURN VALUES/EXIT STATUS CODES
122 readonly E_BAD_OPTION=254
123 readonly E_UNKNOWN=255
124
125 # Process command-line arguments.
126 while test $# -gt 0; do
127     case $1 in
128         --format )
129             shift
130             FORMAT="$1"
131             shift
132             ;;
133
134         --prefix )
135             shift
136             PREFIX="$1"
137             shift
138             ;;
139
140         --separate | -s )
141             shift
142             SEPARATE=1
143             ;;
144
145         --tree-ish | -t )
146             shift
147             TREEISH="$1"
148             shift
149             ;;
150
151         --ignore )
152             shift
153             IGNORE="$1"
154             shift
155             ;;
156
157         --version )
158             version
159             exit
160             ;;
161
162         --verbose | -v )
163             shift
164             VERBOSE=1
165             ;;
166
167         -? | --usage | --help )
168             usage
169             exit
170             ;;
171
172         -* )
173             echo "Unrecognized option: $1" >&2
174             usage
175             exit $E_BAD_OPTION
176             ;;
177
178         * )
179             break
180             ;;
181     esac
182 done
183
184 if [ ! -z "$1" ]; then
185     OUT_FILE="$1"
186     shift
187 fi
188
189 # Validate parameters; error early, error often.
190 if [ $SEPARATE -eq 1 -a ! -d $OUT_FILE ]; then
191     echo "When creating multiple archives, your destination must be a directory."
192     echo "If it's not, you risk being surprised when your files are overwritten."
193     exit
194 elif [ `git config -l | grep -q '^core\.bare=false'; echo $?` -ne 0 ]; then
195     echo "$PROGRAM must be run from a git working copy (i.e., not a bare repository)."
196     exit
197 fi
198
199 # Create the superproject's git-archive
200 if [ $VERBOSE -eq 1 ]; then
201     echo -n "creating superproject archive..."
202 fi
203 git archive --format=$FORMAT --prefix="$PREFIX" $TREEISH > $TMPDIR/$(basename "$(pwd)").$FORMAT
204 if [ $VERBOSE -eq 1 ]; then
205     echo "done"
206 fi
207 echo $TMPDIR/$(basename "$(pwd)").$FORMAT >| $TMPFILE # clobber on purpose
208 superfile=`head -n 1 $TMPFILE`
209
210 if [ $VERBOSE -eq 1 ]; then
211     echo -n "looking for subprojects..."
212 fi
213 # find all '.git' dirs, these show us the remaining to-be-archived dirs
214 # we only want directories that are below the current directory
215 find . -mindepth 2 -name '.git' -type d -print | sed -e 's/^\.\///' -e 's/\.git$//' >> $TOARCHIVE
216 # as of version 1.7.8, git places the submodule .git directories under the superprojects .git dir
217 # the submodules get a .git file that points to their .git dir. we need to find all of these too
218 find . -mindepth 2 -name '.git' -type f -print | xargs grep -l "gitdir" | sed -e 's/^\.\///' -e 's/\.git$//' >> $TOARCHIVE
219
220 if [ -n "$IGNORE" ]; then
221     cat $TOARCHIVE | grep -v $IGNORE > $TOARCHIVE.new
222     mv $TOARCHIVE.new $TOARCHIVE
223 fi
224
225 if [ $VERBOSE -eq 1 ]; then
226     echo "done"
227     echo "  found:"
228     cat $TOARCHIVE | while read arch
229     do
230       echo "    $arch"
231     done
232 fi
233
234 if [ $VERBOSE -eq 1 ]; then
235     echo -n "archiving submodules..."
236 fi
237 while read path; do
238     TREEISH=$(git submodule | grep "^ .*${path%/} " | cut -d ' ' -f 2) # git submodule does not list trailing slashes in $path
239     cd "$path"
240     git archive --format=$FORMAT --prefix="${PREFIX}$path" ${TREEISH:-HEAD} > "$TMPDIR"/"$(echo "$path" | sed -e 's/\//./g')"$FORMAT
241     if [ $FORMAT == 'zip' ]; then
242         # delete the empty directory entry; zipped submodules won't unzip if we don't do this
243         zip -d "$(tail -n 1 $TMPFILE)" "${PREFIX}${path%/}" >/dev/null # remove trailing '/'
244     fi
245     echo "$TMPDIR"/"$(echo "$path" | sed -e 's/\//./g')"$FORMAT >> $TMPFILE
246     cd "$OLD_PWD"
247 done < $TOARCHIVE
248 if [ $VERBOSE -eq 1 ]; then
249     echo "done"
250 fi
251
252 if [ $VERBOSE -eq 1 ]; then
253     echo -n "concatenating archives into single archive..."
254 fi
255 # Concatenate archives into a super-archive.
256 if [ $SEPARATE -eq 0 ]; then
257     if [ $FORMAT == 'tar' ]; then
258         sed -e '1d' $TMPFILE | while read file; do
259             $TARCMD --concatenate -f "$superfile" "$file" && rm -f "$file"
260         done
261     elif [ $FORMAT == 'zip' ]; then
262         sed -e '1d' $TMPFILE | while read file; do
263             # zip incorrectly stores the full path, so cd and then grow
264             cd `dirname "$file"`
265             zip -g "$superfile" `basename "$file"` && rm -f "$file"
266         done
267         cd "$OLD_PWD"
268     fi
269
270     echo "$superfile" >| $TMPFILE # clobber on purpose
271 fi
272 if [ $VERBOSE -eq 1 ]; then
273     echo "done"
274 fi
275
276 if [ $VERBOSE -eq 1 ]; then
277     echo -n "moving archive to $OUT_FILE..."
278 fi
279 while read file; do
280     mv "$file" "$OUT_FILE"
281 done < $TMPFILE
282 if [ $VERBOSE -eq 1 ]; then
283     echo "done"
284 fi