2 # Author: Hari Krishna Dara ( hari_vim at yahoo dot com )
\r
3 # Last Change: 17-Mar-2004 @ 18:47
\r
5 # - bash or ksh (tested on cygwin and MKS respectively).
\r
6 # - Info Zip for the -z option to work (comes with linux/cygwin). Download for
\r
8 # http://www.info-zip.org/
\r
9 # - GNU tar for the -a option to work (comes with linux/cygwin).
\r
11 # Licence: This program is free software; you can redistribute it and/or
\r
12 # modify it under the terms of the GNU General Public License.
\r
13 # See http://www.gnu.org/copyleft/gpl.txt
\r
15 # Shell script to take backup of all the open files in perforce SCM.
\r
18 # - Zip comment option -zz is no longer working?
\r
19 # - To create cpio archives, I can use "cpio -o -H | gzip" command.
\r
20 # - Option to generate a diff at the end.
\r
21 # - Option to restrict by type (useful to avoid huge binary files).
\r
22 # - Support to run zip from a different directory (to avoid certain path
\r
23 # component from getting into zipfile).
\r
28 $0 [<backup dir>] [<source dir>] ...
\r
29 $0 -h -n -q -v -z -zz [-c <change number>] [-t <backup dir>] [-r <backup root>] [[-s <source dir>] ...]
\r
30 -t specify full path name to the target directory. If -z is specified this
\r
31 becomes the path to the zip file name.
\r
32 -r set the root for creating the default backup dir/zip file. Not used if
\r
33 "backup dir" is specified. You can also set BAKUP_ROOT environmental
\r
34 variable. Defaults to p: (p drive), because that is what it is on my
\r
36 -i incremental backup, which makes the program use the previous backup
\r
37 directory/archive for that day (if it exists) instead of creating a new
\r
38 one. For tar (with "-a" option), you will have to provide one of the
\r
39 relevant options to force reuse an existing archive ("-ar" e.g.) or the
\r
40 existing archive will simply get overwritten. However this will not work
\r
41 with compressed tar archives. You can also specify any existing backup
\r
42 directory/archive path explicitly by using the "-t" option.
\r
43 -a create a tar file instead of copying the files. You can specify the
\r
44 tar file name using -t option.
\r
46 Pass -taropt to tar command.
\r
48 - Pass "-aC <dir>" or "-adirectory=<dir>" to cd to a directory before
\r
49 creating the tar file (thus dropping file component).
\r
50 - Pass "-az" to gzip the created tar file.
\r
51 -z create a zip file instead of copying the files. You can specify the
\r
52 zip file name using -t option.
\r
54 Pass -zipopt to zip command.
\r
55 Ex: Pass -zz for a prompt from zip to enter a comment.
\r
56 -s limit to open files matching the given wildcard (local or depot). This
\r
57 can be repeated multiple times to specify multiple source directories.
\r
58 You can pass in anything that the 'p4 opened' command itself accepts.
\r
59 -c limit the files to those specified in the change number, in addition to
\r
60 the -s option. This can't be repeated multiple times though.
\r
61 -n don't execute any commands, just show what is going to be done. Does not
\r
62 currently work with -z option.
\r
63 -q quite mode, no messages
\r
64 -v verbose mode, print messages (the default).
\r
65 -h print help message (this message) and exit
\r
66 The first unspecified directory is treated as target directory, and the
\r
67 remaining directories are treated as source directories. The '-n' option can
\r
68 be used to generate a batch script that can be run later. The source
\r
69 directory can be in depot or local format (NO BACKSLASHES PLEASE). Do not
\r
70 combine multiple options into one argument.
\r
73 - Backup all the open files into a default generated backup dir. in p:
\r
74 drive (p: driver is the default backup directory).
\r
75 bakup.sh mybak c:/dev/branch/src
\r
76 - Backup open files only under 'c:/dev/branch/src' into 'mybak'
\r
78 bakup.sh -s //depot/branch/src -s //depot/branch/cfg
\r
79 - Backup open files only under 'src' and 'cfg' into the default bakup
\r
82 You could add -z option to all the above usages to create a zip file
\r
83 instead of creating a directory. You need to have Info-Zip installed in the
\r
84 path for this to work.
\r
86 bakup.sh -n > mybackup.bat
\r
87 - Generates a 'mybackup.bat' batch file that can be run at a later
\r
88 time to take a backup. The files to be backed up are based on the
\r
89 time the script was generated, so it should be regenerated if the
\r
90 list has changed since then.
\r
95 generateTargetDirName()
\r
97 today=`date +"%d-%b-%Y"`
\r
99 #echo "---first time"
\r
100 tDir="$targetRoot/bakup-$today"
\r
102 while [ -d $tDir -o -f $tDir.* ]; do
\r
105 tDir="$targetRoot/bakup-${today}_$inc"
\r
106 #echo "---subsequent time inc=$inc tDir=$tDir"
\r
108 if [ $incrementalMode -ne 0 ]; then
\r
109 tDir=$prevDir # Backup one level to use an existing db.
\r
116 archiveOpt=${1/[-+]$2/}
\r
117 case $archiveOpt in
\r
120 -??*) # Mistyped long option
\r
121 archiveOpt="-$archiveOpt"
\r
125 ??*) # Long option.
\r
126 archiveOpt="--$archiveOpt"
\r
129 archiveOpt="-$archiveOpt"
\r
135 #getExtOpt '-a--directory' 'a'
\r
136 #getExtOpt '-a-directory' 'a'
\r
137 #getExtOpt '-adirectory' 'a'
\r
138 #getExtOpt '-aC' 'a'
\r
139 #getExtOpt '-a-C' 'a'
\r
144 if [ $# -eq 0 ]; then
\r
151 chDirectory='' # If set, the listing is generated relative to this dir.
\r
160 until [ $# -eq 0 ]; do
\r
175 archiveMode=2 # Tar.
\r
176 verboseMode=0 # Turn on quite mode, as zip will anyway show the files.
\r
177 testMode=1 # Turn on test mode, so we won't copy files.
\r
180 # Need to take care of options with optional args.
\r
181 extOpt=`getExtOpt $1 a`
\r
182 if [ $extOpt = -z -o $extOpt = -Z -o $extOpt = -j ]; then
\r
184 tarExt=`echo $extOpt | awk 'BEGIN{ext["-j"]="bz2";ext["-z"]="gz";ext["-Z"]="Z";}{print ext[$0];}'`
\r
186 archiveOpts="${archiveOpts} $extOpt"
\r
189 chDirectory=${extOpt/*=}
\r
194 #echo "---setting chDirectory=$chDirectory"
\r
195 archiveOpts="${archiveOpts} $chDirectory"
\r
200 archiveMode=1 # Zip.
\r
201 verboseMode=0 # Turn on quite mode, as zip will anyway show the files.
\r
202 testMode=1 # Turn on test mode, so we won't copy files.
\r
205 # Need to take care of options with optional args.
\r
206 archiveOpts="${archiveOpts} `getExtOpt $1 z`"
\r
226 sourceDirs="$sourceDirs $1"
\r
227 #echo "---setting sourceDirs=$sourceDirs"
\r
233 if [ "$targetDir" = "" ]; then
\r
234 #echo "---setting targetDir=$targetDir"
\r
237 #echo "---appending sourceDirs=$1"
\r
238 sourceDirs="$sourceDirs $1"
\r
245 # For tar, we can add -a option only if no other equivalent option is specified.
\r
246 if [ $archiveMode -eq 2 ]; then
\r
247 case $archiveOpts in
\r
251 archiveOpts="$archiveOpts -c"
\r
256 if [ x${targetDir}x = xx -a x${targetRoot}x = xx ]; then
\r
257 targetRoot=$BAKUP_ROOT
\r
258 if [ "$targetRoot" = "" ]; then
\r
263 if [ "$targetDir" = "" ]; then
\r
264 targetDir=`generateTargetDirName`
\r
267 if [ "$sourceDirs" = "" ]; then
\r
268 # By default backup all the open files.
\r
273 # Create a dir if it doesn't exist, exit on error.
\r
276 if ! [ -d "$1" ]; then
\r
278 if [ $testMode -eq 1 -o $verboseMode -eq 1 ]; then
\r
279 echo "mkdir -p $1" 1>&4
\r
282 if [ $testMode -eq 0 ]; then
\r
284 if [ $? -ne 0 ]; then
\r
285 echo "Error creating $1" 1>&2
\r
293 #if [ $testMode -eq 1 ]; then
\r
294 # echo "Running in test mode"
\r
297 if [ $archiveMode -eq 0 ]; then
\r
298 createDir $targetDir 4>&1
\r
301 if [ $verboseMode -eq 1 ]; then
\r
302 echo "Copying to target directory: $targetDir"
\r
305 # Testing for $BASH will not work, if you happen to use the cygwin sh instead of
\r
308 codelineRoot=`p4 info | sed -n -e 's;\\\\;/;g' -e 's/Client root: //p'`
\r
309 #echo "---codelineRoot=$codelineRoot"
\r
310 rootDirLength=${#codelineRoot}
\r
312 if [ $archiveMode -eq 1 ]; then
\r
314 if [ ${targetDir%.zip} = $targetDir ]; then
\r
317 pipeCmd="zip ${archiveOpts} -@ ${targetDir}${fileExt}"
\r
318 echo "Using: '${pipeCmd}' to create zip archive"
\r
319 elif [ $archiveMode -eq 2 ]; then
\r
321 if [ $compressedTar -eq 1 -a ${targetDir%.tar.$tarExt} = $targetDir ]; then
\r
322 fileExt=".tar.$tarExt"
\r
323 elif [ $compressedTar -ne 1 -a ${targetDir%.tar} = $targetDir ]; then
\r
326 pipeCmd="tar -vf ${targetDir}${fileExt} ${archiveOpts} -T -"
\r
327 echo "Using: '${pipeCmd}' to create tar archive"
\r
333 for sourceDir in $sourceDirs; do
\r
334 if [ ! -f $sourceDir ]; then
\r
339 sourceDir="${sourceDir}..."
\r
342 sourceDir="${sourceDir}/..."
\r
346 if [ "$changeNumber" = "" ]; then
\r
347 openedCmd="p4 opened $sourceDir"
\r
349 openedCmd="p4 opened -c $changeNumber $sourceDir"
\r
351 if [ $verboseMode -eq 1 ]; then
\r
352 echo "Collecing list of open files using: $openedCmd" 1>&4
\r
355 # FIXME: I couldn't get it working with the following IFS, don't know
\r
356 # why. So as a temp. work-around, I am temporarily substituting spaces
\r
357 # with '|' in sed and converting them back to spaces in the start of the
\r
360 openedFiles=`$openedCmd | \
\r
361 sed -e '/ - delete \(default \)\?change /d' \
\r
364 sed -e 's;.\+/[^/]\+/\([^ /]\+\) //.*\1 \(.*\1\);\2;' \
\r
365 -e "s;^${chDirectory}/*;;" \
\r
368 for file in `echo $openedFiles`; do
\r
370 #echo "---file = $file" 1>&4
\r
371 dir=`dirname "$file"`
\r
372 # Relative to the codeline root.
\r
373 tgtDir="${targetDir}/${dir:$rootDirLength}"
\r
374 #echo "---tgtDir = $tgtDir" 1>&4
\r
376 if [ $archiveMode -eq 0 ]; then
\r
377 createDir "$tgtDir"
\r
380 if [ $archiveMode -ne 0 ]; then
\r
382 elif [ $testMode -eq 1 -o $verboseMode -eq 1 ]; then
\r
383 echo "cp \"$file\" \"$tgtDir\"" 1>&4
\r
385 if [ $testMode -eq 0 ]; then
\r
386 cp "$file" "$tgtDir"
\r
387 if [ $? -ne 0 ]; then
\r
388 echo "Error copying $1" 1>&2
\r