32e4c36b459bebbc7bf28f5ef43256da2473712c
[infrastructure.git] / scripts / import-module.sh
1 #!/bin/bash
2 #
3 # $Id$
4 #
5
6 date=$(date +%Y-%m-%d)
7
8 #### REVIEW this carefully
9 cvstag=planetlab-4_0-rc3
10
11 ####
12 svn="svn+ssh://thierry@svn.one-lab.org/svn"
13 cvs=":pserver:anon@cvs.planet-lab.org:/cvs"
14
15 function message () {
16   echo -n '-------------------- '
17   echo $@
18   echo -n 'Enter return to proceed .. '
19   read x
20 }
21
22 function run () {
23   echo -n '-------------------- '
24   message="$1" ; shift
25   echo $message
26   
27   echo -n 'PWD=' ; pwd
28   echo RUNNING $@
29   $@
30 }
31
32 function run_prompt () {
33   default="$1" ; shift
34   message="$1" ; shift
35   case "$default" in
36     y|Y) label="[y]/n" ;;
37     n|N) label="y/[n]" ;;
38     *) label="y/n (no default)" ;;
39   esac
40
41   echo -n '-------------------- '
42   echo $message
43   
44   echo -n 'PWD= ' ; pwd 
45   echo -n "want to run $@ $label ? "
46   read answer
47   [ -z "$answer" ] && answer=$default
48   while true; do
49     case $answer in
50       y|Y)
51         $@
52         break
53         ;;
54       n|N)
55         echo 'Skipped'
56         break
57         ;;
58       *)
59         echo 'Please enter y or n'
60         ;;
61     esac
62   done
63 }
64
65 function run_loop () {
66   message="$1" ; shift
67   while true; do
68     echo -n '-------------------- '
69     echo $message
70     echo -n PWD= ; pwd
71     echo Running $@
72     $@
73     echo -n 'OK ? y/[n] '
74     read answer
75     [ -z "$answer" ] && answer=n
76     case $answer in
77       y|Y)
78         break ;;
79       *) ;;
80   esac
81 done
82 }
83
84 ### echoes OK on stdout if url exists
85 function svn_url_check () {
86    url=$1; shift
87    svn list $url &> /dev/null && echo OK
88 }
89
90 ### return 'y' or 'n' for being used as prompt
91 function svn_url_needs_creation () {
92    url=$1; shift
93    if [ -n "$(svn_url_check $url)" ] ; then echo n ; else echo y ; fi
94 }
95
96 function dir_needs_creation () {
97    dir=$1; shift
98    if [ -d "$dir" ] ; then echo n ; else echo y ; fi
99 }
100
101 function svn_dir_needs_revert () {
102    dir=$1; shift
103    output=$(svn status $dir 2>&1)
104    if [ -n "$output" ] ; then echo y ; else echo n ; fi
105 }
106
107 function svn_file_needs_commit () {
108    dir=$1; shift
109    output=$(svn status $dir 2>&1)
110    if [ -n "$output" ] ; then echo y ; else echo n ; fi
111 }
112
113 ##############################
114 # guess spec files and extract from there
115 # search for <module.spec> otherwise expects a single *.spec file
116 function figure_module_spec () {
117     src=$1; shift
118     module=$1; shift
119     if [ -f $src/$module.spec ] ; then
120         echo $src/$module.spec
121     else
122         nbspecs=$(ls $src/*.spec | wc -l)
123         if [ $nbspecs = 1 ] ; then
124             echo $(ls $src/*.spec)
125           else
126               echo "$0: could not guess spec file in $src"
127               exit 1
128           fi
129     fi
130 }
131
132 function extract_from_spec () {
133     specfile=$1; shift
134     varname=$1; shift
135     if [ ! -f $specfile ] ; then
136       echo "Could not locate $specfile -- exiting"
137       exit 1
138     fi
139     line=$(grep "^%define[ \t][ \t]*$varname" $specfile)
140     value=$(echo $line | sed -e "s,%define[ \t][ \t]*$varname[ \t][ \t]*,,")
141     echo $value
142 }
143
144 function patch_in_spec () {
145     specfile=$1; shift
146     varname=$1; shift
147     value=$1; shift
148
149     ### sed -i unsupported on MACOS
150     sed -e "s,^%define[ \t][ \t]*$varname[ \t].*$,%define $varname $value," $specfile > ${specfile}.new
151     mv ${specfile}.new $specfile
152 }
153
154 ##############################
155 ##############################
156 ##############################
157
158 function print_warning () {
159
160     cat <<EOF
161 ####### WARNING
162
163  this script is quite rough and should be used with care
164
165  I am slowly trying to automate this painful process,
166
167  so again : USE WITH CARE
168
169 ========== Your input :
170 module=$module
171 ========== Hard-wired :
172 cvstag=$cvstag
173 svn=$svn
174 cvs=$cvs
175 ========== Computed :
176 previous=$previous
177 next=$next
178 date=$date
179 import=$import
180 ####### WARNING
181
182 EOF
183 }
184
185 function run_test () {
186   message Hi there
187   run_prompt n "going to /etc" cd /etc
188   run_prompt y "going to /etc" cd /etc
189   run_prompt y "Cleaning up /foobar" rmdir /foobar
190   run_prompt $(dir_needs_creation /foobar) "create unexisting dir /foobar" mkdir /foobar
191   run_prompt $(dir_needs_creation /var) "create existing dir /var" mkdir /var
192   run_prompt y "Cleaning up /foobar" rmdir /foobar
193   
194   run_loop "Check this and that" ls -ls passwd
195   run "Listing passwd" ls -ls passwd
196   exit 0
197 }
198
199 function figure_last_import () {
200     module=$1; shift
201     last_import=$(svn list $svn/$module/imports | grep '^import-' | sort | tail -1 | sed -e s,import-,, -e s,/,,g )
202     echo $last_import
203 }
204
205 function figure_next_import () {
206     last_import=$1; shift
207     current_index=$(echo $last_import | sed -e 's,-.*,,')
208     # remove leading 0 that confuse printf (takes it as octal)
209     decimal_index=$(echo  $current_index | sed 's,^0*,,' )
210     next_index=$(printf "%03d" $(($decimal_index+1)))
211     echo ${next_index}-${cvstag}-${date}
212 }
213
214 function import_usage () {
215    echo "Usage: $0 module"
216    echo "All other parameters to be entered in the source file for now - sorry"
217    exit 1
218 }
219
220 function import_module () {
221
222     [[ -z "$@" ]] && import_usage
223     module=$1; shift
224     import=$HOME/import-$module-$date
225     [[ -n "$@" ]] && import_usage
226
227     echo -n 'Figuring previous import ..'
228     previous=$(figure_last_import $module)
229     next=$(figure_next_import $previous)
230     echo " found $previous - next=$next"
231
232     print_warning
233
234     # checks current status
235     echo -n "-------------------- Checking $module/imports/import-$previous "
236     if [ -z "$(svn_url_check $svn/$module/imports/import-$previous)" ] ; then
237         echo FATAL : import-$previous not found
238         exit 1
239     fi
240     echo 'OK'
241
242     # snapshot current status
243     prompt=$(svn_url_needs_creation $svn/$module/imports/before-$next)
244     run_prompt $prompt "Creating snapshot of current status" \
245         svn copy -mBefore-${next} $svn/$module/trunk $svn/$module/imports/before-$next
246
247     # init import dir from previous import
248     prompt=$(svn_url_needs_creation $svn/$module/imports/import-$next)
249     run_prompt $prompt "Preparing import-$next from import-$previous" \
250         svn copy -mCreation-from-import-${previous} $svn/$module/imports/import-$previous $svn/$module/imports/import-$next
251
252     ####
253     run_prompt $(dir_needs_creation $import/$module/imports) "Creating working dir " \
254         mkdir -p $import/$module/imports
255
256     ###
257     run_prompt $(dir_needs_creation $import/$module/imports/import-$next) \
258         "Checking out import-$next for applying changes" \
259         svn co $svn/$module/imports/import-$next $import/$module/imports/import-$next
260
261     run "Going there" \
262         cd $import/$module/imports
263
264     message 'NOTE: the way we merge changes right below might need to be tested/improved'
265
266     run_prompt n "Incorporating changes since import-$previous in import-$next" \
267         cvs -d $cvs export -r $cvstag -d import-$next $module
268
269     run "Going to import-$next" \
270         cd $import/$module/imports/import-$next
271
272     run_loop "Check the changes in import-$next -- no conflict expected" \
273         svn status $import/$module/imports/import-$next
274
275     run_prompt n "CHECKING IN imported changes in import-$next" \
276         svn ci -mApplied-changes-since-$previous
277
278     ###
279     run "Going to $import/$module" \
280         cd $import/$module
281
282     run_prompt $(dir_needs_creation $svn/$module/trunk) "Checking out trunk for applying changes" \
283         svn co $svn/$module/trunk 
284
285     run_prompt n "Merging changes from import-$previous to import-$next into trunk" \
286         svn merge $svn/$module/imports/import-$previous $svn/$module/imports/import-$next trunk
287
288     run_loop "CHECK CHANGES in $import/$module/trunk -- conflicts should get resolved" \
289         svn status trunk
290
291     run_prompt n "CHECKING IN changes in trunk" \
292         svn ci -m "Merged changes from import-$previous to import-$next"
293
294     prompt=$(svn_url_needs_creation $svn/$module/imports/after-$next)
295     run_prompt $prompt "Backing up into after-$next" \
296         svn copy $svn/$module/$trunk $svn/$module/imports/after-$next
297
298     run_prompt n "Want to rename $import as $import-to-trash" \
299         mv $import $import-totrash
300
301     echo 'Done'
302 }
303
304 ##############################
305 function tag_usage () {
306    echo "Usage: $0 module"
307    exit 1
308 }
309
310 function tag_module () {
311
312     [[ -z "$@" ]] && tag_usage
313     module=$1; shift
314     tagwork=$HOME/tags/$module
315     tagtrunk=$HOME/tags/$module/trunk
316     [[ -n "$@" ]] && tag_usage
317
318     echo 'Tagging' $module
319
320     run_prompt $(dir_needs_creation $tagtrunk) "Checking out $tagtrunk" \
321         svn co $svn/$module/trunk $tagtrunk
322
323     run_prompt y "Updating $tagtrunk" \
324         svn up $tagtrunk
325
326     run_prompt $(svn_dir_needs_revert $tagtrunk) "Reverting $tagtrunk for safety " \
327         svn revert -R $tagtrunk
328
329     run "cd $tagtrunk" \
330        cd $tagtrunk
331
332     ### extracting current version info
333     spec=$(figure_module_spec $tagtrunk $module)
334     version=$(extract_from_spec $spec version)
335     subversion=$(extract_from_spec $spec subversion)
336     newsubversion=$(($subversion+1))
337
338     message "FOUND spec=$spec version=$version subversion=$subversion"
339
340     # check that the tags relating to subversion and newsubversion does (resp. does not) exist
341     oldtag=$svn/$module/tags/$module-${version}.${subversion}
342     newtag=$svn/$module/tags/$module-${version}.${newsubversion}
343
344     echo -n "Checking tags status ..."
345     old_check=$(svn_url_check $oldtag)
346     if [ -z "$old_check" ] ; then
347       echo "Former tag does not exist -- exiting"
348       echo "URL was $oldtag"
349       exit 1
350     fi
351     echo -n " old tag OK ... "
352     
353     new_check=$(svn_url_check $newtag)
354     if [ -n "$new_check" ] ; then
355       echo "New tag does exist -- exiting"
356       echo "URL was $newtag"
357       exit 1
358     fi
359     echo " new tag OK"
360     
361     patch_in_spec $spec subversion $newsubversion
362
363     run_loop "Checking differences" \
364        svn diff $tagtrunk
365
366     run_prompt y "Display differences from previous tag" \
367        svn diff $oldtag $svn/$module/trunk
368     
369     run_prompt y "Committing changes in $tagtrunk" \
370        svn ci --editor-cmd=vi $tagtrunk
371         
372     # putting spaces in the message does not work 
373     run_prompt y "Creating tag $newtag" \
374        svn copy --message "$module-${version}.${newsubversion}" $svn/$module/trunk $newtag
375
376     # make changes in build/*-tags.mk
377     tagbuild=$HOME/tags/build/trunk
378     oldname=$module-${version}.${subversion}
379     newname=$module-${version}.${newsubversion}
380
381     run_prompt $(dir_needs_creation $tagbuild) "Checking out $tagbuild" \
382         svn co $svn/$module/build $tagbuild
383
384     run_prompt y "Updating $tagbuild" \
385         svn up $tagbuild
386
387     run_prompt $(svn_dir_needs_revert $tagbuild) "Reverting $tagbuild for safety " \
388         svn revert -R $tagbuild
389
390     run "cd $tagbuild" \
391        cd $tagbuild
392
393     for tagsmk in *-tags.mk; do
394        echo "Managing $tagsmk"
395        sed -i -e "s,$oldname,$newname,g" $tagsmk
396        if [ $(svn_file_needs_commit $tagsmk) = "y" ] ; then
397            echo "Changes in $tagsmk"
398            svn diff $tagsmk
399            run_prompt y "Adopt $newname in $tagsmk " \
400                svn commit -m"Adopting-$newname" $tagsmk
401        fi
402     done    
403 }
404
405 ####################
406 function diff_modules () {
407     for module in "$@" ; do
408         tagtrunk=$HOME/tags/$module/trunk
409         echo "--------------------Checking $module"
410         run_prompt y "Updating $tagwork" svn update $tagtrunk
411         ### extracting current version info
412         spec=$(figure_module_spec $tagtrunk $module)
413         version=$(extract_from_spec $spec version)
414         subversion=$(extract_from_spec $spec subversion)
415
416         echo "FOUND spec=$spec version=$version subversion=$subversion"
417
418         lasttag=$svn/$module/tags/$module-${version}.${subversion}
419         trunk=$svn/$module/trunk
420         
421         run_prompt y "Diffing : < last tag -- trunk >" svn diff $lasttag $trunk
422         
423     done
424 }
425
426 ####################
427 case $0 in
428     *import-module*)
429         import_module $@;;
430     *tag-module*)
431         tag_module $@;;
432     *diff-module*)
433         diff_modules $@ ;;
434     *test*)
435         x=$(figure_module_spec $@) ; echo $x;;
436     *)
437         echo "Unsupported command $0" ; exit 0
438 esac