aboutsummaryrefslogtreecommitdiffstats
path: root/tools/kgit-checkpoint
blob: da19e9312f679bcc909d2eabce1890b6e91bc820 (plain)
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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0-only

#  (kgit-checkpoint), (checkpoint and restore for meta-information)

#  Copyright (c) 2008-2012 Wind River Systems, Inc.

#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License version 2 as
#  published by the Free Software Foundation.

#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#  See the GNU General Public License for more details.

#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

# For consistent behaviour with "grep -w"
LC_ALL=C
export LC_ALL

usage()
{
cat <<EOF

 kgit-checkpoint -b <target checkpoint branch> 
                 [-c] [-r] [-d] [-v] <action>
 
   -b:  branch that stores checkpointed files
   -r:  restore checkpoint commit
   -c:  create a checkpoint commit
   -m:  checkpoint message (the date will be used if not supplied)
   -v:  verbose 

   <action>: 'restore' or 'create'. equivalent to -r and -c

EOF
}

# command line processing
while [ $# -gt 0 ]; do
	case "$1" in
                -b|--b)
                        cmd_branch=$2
                        shift
                        ;;
                -m|--m)
                        checkpoint_msg="$2"
                        shift
                        ;;
	        -v|--v)
                        verbose=t
                        ;;
	        -r|--r)
                        restoring=t
			checkpointing=
                        ;;
	        -c|--c)
                        restoring=
			checkpointing=t
                        ;;
	        -h|--h)
                        usage
			exit
                        ;;
	        -*)   
                        usage
			exit
			;;
		*)
			break
			;;
	esac
	shift
done

if [ -z "$1" ] ; then
    if [ -z "$checkpointing" ] && [ -z "$restoring" ]; then
	usage
	exit
    fi
fi

# source utility functions
. `dirname $0`/kgit

action=$@
case $action in
    create)
	restoring=
	checkpointing=t
	;;
    restore)
	restoring=t
	checkpointing=
	;;
esac

if [ ! -d .git ]; then
    echo "ERROR. Not a git repository"
    exit 1
fi

# set some defaults
if [ -z "$checkpoint_msg" ]; then
    checkpoint_msg="checkpoint: `date`"
fi

# save this so we can go back later ...
current_branch=`get_current_git_branch`
checkpoint_branch=

get_meta_dir()
{
    meta_branch=$1

    # if there's already a located and logged meta directory, just use that and
    # return. Otherwise, we'll look around to see what we can find.
    if [ -f ".metadir" ]; then
        md=`cat .metadir`
        echo $md
        return
    fi

    # determine the meta directory name
    meta_dir_options=`git ls-files -o --directory`
    for m in $meta_dir_options; do
	if [ -d "$m/cfg" ]; then
	    md=`echo $m | sed 's%/%%'`
	fi
    done

    # store our results where other scripts can quickly find the answer
    if [ -n "$md" ]; then
        echo "$md" > .metadir
    fi

    # return the directory to he caller
    echo $md
}

checkpoint_branch=$KMETA
if [ -n "$cmd_branch" ]; then
    checkpoint_branch=$cmd_branch
fi

# verify we have a checkpoint branch and exit if one wasn't found
if [ -z "$checkpoint_branch" ]; then
    echo "[ERROR]: no checkpoint/meta branch found. Either set KMETA or pass it via -b."
    exit 1
fi

git show-ref --quiet --verify -- "refs/heads/$checkpoint_branch"
if [ $? -eq 1 ]; then
    if [ -n "$verbose" ]; then
        echo "Checkpoint branch [$checkpoint_branch] does not exist, using default meta directory"
    fi
    meta_dir=$checkpoint_branch
else
    meta_dir=`get_meta_dir`
fi

echo $meta_dir

if [ -z "$files_to_checkpoint" ]; then
    dirs_to_checkpoint="$meta_dir/cfg/kernel-*cache $meta_dir/cfg/scratch \
                        $meta_dir/patches $meta_dir/scripts $meta_dir"
fi

if [ -n "$checkpointing" ]; then    
    if [ -n "$verbose" ]; then
	echo "[INFO]: Creating checkpoint on branch $checkpoint_branch"
    fi

    # if the branch doesn't already exist. Create it as an orphan.
    git show-ref --quiet --verify -- "refs/heads/$checkpoint_branch"
    if [ $? -eq 1 ]; then
        # create a meta-information branch
	git checkout --orphan $checkpoint_branch
	if [ $? != 0 ]; then
		echo "[ERROR]: orphan branch creation failed"
		exit -1
	fi
        # remove the unwanted files/directories
	git rm -rfq `ls -d .gitignore .mailmap * | grep -v $checkpoint_branch`
	if [ $? != 0 ]; then
		echo "[ERROR]: git rm -rfq failed"
		exit -1
	fi
    else
	git checkout $checkpoint_branch
	if [ $? != 0 ]; then
		echo "[ERROR]: checkpoint branch checkout failed"
		exit -1
	fi
    fi

    echo "kernel repository meta data base" >> README.txt
    git add -f README.txt
    if [ $? != 0 ]; then
	echo "[ERROR]: git add failed"
	exit -1
    fi
    git commit -s -m "meta: add README"
    if [ $? != 0 ]; then
	echo "[ERROR]: git commit README failed"
	exit -1
    fi
    
    # either we just created an orphan branch .. or it already
    # existed. Either way, iterate the directories that should be added to
    # the branch and add them.
    for d in $dirs_to_checkpoint; do
	count=`git ls-files -dmo $d | wc -l`
	if [ $count -eq 0 ]; then
	    # if there aren't any untracked files, then there's nothing to commit
	    continue
	fi
	git add -f $d
	if [ $? != 0 ]; then
		echo "[ERROR]: git add dirs failed"
		exit -1
	fi
	if [ -f "$d/00-README" ]; then
	    TXT=`mktemp`
	    echo "checkpoint dir: $d" > $TXT
	    echo >> $TXT
	    echo "What follows is the 00-README from dir \"$d\"." >> $TXT
	    echo >> $TXT
	    echo " ----------------------" >> $TXT
	    cat $d/00-README >> $TXT
	    echo " ----------------------" >> $TXT
	    git commit -q -s -F $TXT  &> /dev/null
	    if [ $? != 0 ]; then
		echo "[ERROR]: git commit 00-README failed"
		exit -1
	    fi
	    rm -f $TXT
	else
	    git commit -q -s -m "checkpoint dir: $d" &> /dev/null
	    if [ $? != 0 ]; then
		echo "[ERROR]: git commit checkpoint dir failed"
		exit -1
	    fi
	fi
    done

    if [ -z "$verbose" ]; then
	q="-q"
    fi

    # tag the branch so it can be found later
    git show-ref --quiet --verify -- "refs/tags/checkpoint-$checkpoint_branch"
    if [ $? -eq 1 ]; then
	git tag checkpoint-$checkpoint_branch
        if [ $? != 0 ]; then
		echo "[ERROR]: git tag checkpoint failed"
		exit -1
        fi
    fi

    # return to the current branch
    if [ "$checkpoint_branch" != "$current_branch" ]; then
	git checkout -q $current_branch
        if [ $? != 0 ]; then
		echo "[ERROR]: git checkout current failed"
		exit -1
        fi
    fi

else # restoring ...

    if [ -n "$verbose" ]; then
	echo "[INFO]: Restoring checkpoint from branch $checkpoint_branch"
    fi

    # check if '$meta_dir' is tracked or not. If it is untracked, we don't
    # have anything to do.
    meta_dir=`get_meta_dir`
    if [ -n "$meta_dir" ]; then
     	echo "[INFO]: checkpoint is already restored, nothing to do"
     	exit 0
    fi

    # We consider everything on the checkpoint branch to be part of the stored
    # state. If the branch was an orphan branch, the merge_base will be zero. In
    # that case, we just get all commits on the branch via git rev-list
    merge_base=`git merge-base $checkpoint_branch master`
    if [ -z "$merge_base" ]; then
	merge_base=`git rev-list $checkpoint_branch -- | tail -1`
    fi

    # save the old branch, and make the data untracked.
    git checkout -q -f -b $checkpoint_branch-temp $checkpoint_branch &> /dev/null
    if [ $? != 0 ]; then
	echo "[ERROR]: git checkout -q -b failed"
	exit -1
    fi
    git reset --mixed $merge_base &> /dev/null
    if [ $? != 0 ]; then
	echo "[ERROR]: git reset mixed failed"
	exit -1
    fi

    # At this point, we've reset the branch and the meta data is now
    # reset and can persist when we change the branch, but we need to
    # make a copy of them to *something* else, or git will complain about
    # them being clobbered when we switch away.

    if [ -d "$checkpoint_branch" ]; then
	checkpoint_dir=$checkpoint_branch
    else
	for f in `find -maxdepth 1 -type d -not -name .git -and -not -name . -printf '%f'`; do
	    if [ -d "$f" ]; then
	        # a directory is our meta dir
		checkpoint_dir=$f
	    fi
	done
    fi

    if [ ! -d ".$checkpoint_dir" ]; then
	mv $checkpoint_dir .$checkpoint_dir
    fi

    # delete our working branch, and return to the original one
    if [ "$checkpoint_branch" != "$current_branch" ]; then
	git checkout -f -q $current_branch
	if [ $? != 0 ]; then
	    echo "[ERROR]: git checkout -q failed"
	    exit -1
	fi
    else
	git checkout -f -q master
	if [ $? != 0 ]; then
	    echo "[ERROR]: git checkout -q failed"
	    exit -1
	fi
    fi

    git branch -D $checkpoint_branch-temp
    if [ $? != 0 ]; then
	echo "[ERROR]: git branch -D failed"
	exit -1
    fi

    # Double check the meta_dir, and write the results for following scripts
    meta_dir=`get_meta_dir`
fi