1#! /bin/sh
2#
3# Copyright (C) 1997-2005 The Free Software Foundation, Inc.
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 2, or (at your option)
8# any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15#	cvs2vendor - move revsisions from files in A to files in B
16#
17# The primary reason for this script is to move deltas from a
18# non-vendor branched repository onto a fresh vendor branched one,
19# skipping the initial checkin in assumption that it is the same in
20# both repositories.  This way you can take a project that was moved
21# into CVS without the benefit of the vendor branch and for all
22# intents and purposes add the vendor branch underneath the existing
23# deltas.
24#
25# This script is also a decent example of repository maintenance using
26# raw RCS commands (if I do say so myself! ;-).
27#
28# Tags are preserved.
29#
30# The timestamp of the initial vendor branch revision will be adjusted
31# to be the same as the 1.1 revision of each source file.
32#
33# Extra branches in the source directory will cause breakage.
34#
35# Intermediate files are created in the current working directory
36# where this script is started.
37#
38# Written by Greg A. Woods <woods@planix.com>, based on rcs2sccs
39# (retains some of the rlog parsing from it).
40#
41# The copyright is in the Public Domain.
42#
43
44if [ $# -ne 2 ]; then
45	echo USAGE: $0 srcdir dstdir
46	exit 2
47fi
48tsrcdir=$1
49tdstdir=$2
50
51revfile=/tmp/cvs2vendor_$$_rev
52rm -f $revfile
53
54commentfile=/tmp/cvs2vendor_$$_comment
55rm -f $commentfile
56
57if sort -k 1,1 /dev/null 2>/dev/null
58then sort_each_field='-k 1 -k 2 -k 3 -k 4 -k 5 -k 6 -k 7 -k 8 -k 9'
59else sort_each_field='+0 +1 +2 +3 +4 +5 +6 +7 +8'
60fi
61
62srcdirs=`cd $tsrcdir && find . -type d -print | sed 's~^\.[/]*~~'`
63
64# the "" is a trick to get $tsrcdir itself without resorting to '.'
65for ldir in "" $srcdirs; do
66
67	srcdir=$tsrcdir/$ldir
68	dstdir=$tdstdir/$ldir
69
70	# Loop over every RCS file in srcdir
71	#
72	for vfile in $srcdir/*,v; do
73		# get rid of the ",v" at the end of the name
74		file=`echo $vfile | sed -e 's/,v$//'`
75		bfile=`basename $file`
76
77		if [ ! -d $dstdir ]; then
78			echo "making locally added directory $dstdir"
79			mkdir -p $dstdir
80		fi
81		if [ ! -f $dstdir/$bfile,v ]; then
82			echo "copying locally added file $dstdir/$bfile ..."
83			cp $vfile $dstdir
84			continue;
85		fi
86
87		# work on each rev of that file in ascending order
88		rlog $file | grep "^revision [0-9][0-9]*\." | awk '{print $2}' | sed -e 's/\./ /g' | sort -n -u $sort_each_field | sed -e 's/ /./g' > $revfile
89
90		for rev in `cat $revfile`; do
91
92			case "$rev" in
93			1.1)
94				newdate=`rlog -r$rev $file | grep "^date: " | awk '{printf("%s.%s\n",$2,$3); exit}' | sed -e 's~/~.~g' -e 's/:/./g' -e 's/;//' -e 's/^19//'`
95				olddate=`rlog -r1.1.1.1 $dstdir/$bfile | grep "^date: " | awk '{printf("%s.%s\n",$2,$3); exit}' | sed -e 's~/~.~g' -e 's/:/./g' -e 's/;//' -e 's/^19//'`
96				sed "s/$olddate/$newdate/" < $dstdir/$bfile,v > $dstdir/$bfile.x
97				mv -f $dstdir/$bfile.x $dstdir/$bfile,v
98				chmod -w $dstdir/$bfile,v
99				symname=`rlog -h $file | sed -e '1,/^symbolic names:/d' -e 's/[ 	]*//g' | awk -F: '$2 == "'"$rev"'" {printf("-n%s:1.1.1.1\n",$1)}'`
100				if [ -n "$symname" ]; then
101					echo "tagging $file with $symname ..."
102					rcs $symname $dstdir/$bfile,v
103					if [ $? != 0 ]; then
104						echo ERROR - rcs $symname $dstdir/$bfile,v
105						exit 1
106					fi
107				fi
108				continue			# skip first rev....
109				;;
110			esac
111
112			# get a lock on the destination local branch tip revision
113			co -r1 -l $dstdir/$bfile
114			if [ $? != 0 ]; then
115				echo ERROR - co -r1 -l $dstdir/$bfile
116				exit 1
117			fi
118			rm -f $dstdir/$bfile
119
120			# get file into current dir and get stats
121			date=`rlog -r$rev $file | grep "^date: " | awk '{printf("%s %s\n",$2,$3); exit}' | sed -e 's/;//'`
122			author=`rlog -r$rev $file | grep "^date: " | awk '{print $5; exit}' | sed -e 's/;//'`
123
124			symname=`rlog -h $file | sed -e '1,/^symbolic names:/d' -e 's/[ 	]*//g' | awk -F: '$2 == "'"$rev"'" {printf("-n%s\n",$1)}'`
125
126			rlog -r$rev $file | sed -e '/^branches: /d' -e '1,/^date: /d' -e '/^===========/d' | awk '{if ((total += length($0) + 1) < 510) print $0}' > $commentfile
127
128			echo "==> file $file, rev=$rev, date=$date, author=$author $symname"
129
130			co -p -r$rev $file > $bfile
131			if [ $? != 0 ]; then
132				echo ERROR - co -p -r$rev $file
133				exit 1
134			fi
135
136			# check file into vendor repository...
137			ci -f -m"`cat $commentfile`" -d"$date" $symname -w"$author" $bfile $dstdir/$bfile,v
138			if [ $? != 0 ]; then
139				echo ERROR - ci -f -m"`cat $commentfile`" -d"$date" $symname -w"$author" $bfile $dstdir/$bfile,v
140				exit 1
141			fi
142			rm -f $bfile
143
144			# set the default branch to the trunk...
145			# XXX really only need to do this once....
146			rcs -b1 $dstdir/$bfile
147			if [ $? != 0 ]; then
148				echo ERROR - rcs -b1 $dstdir/$bfile
149				exit 1
150			fi
151		done
152	done
153done
154
155echo cleaning up...
156rm -f $commentfile
157echo "       Conversion Completed Successfully"
158
159exit 0
160