5 # The contents of this file are subject to the terms of the
6 # Common Development and Distribution License (the "License").
7 # You may not use this file except in compliance with the License.
9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 # or http://www.opensolaris.org/os/licensing.
11 # See the License for the specific language governing permissions
12 # and limitations under the License.
14 # When distributing Covered Code, include this CDDL HEADER in each
15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 # If applicable, add the following below this CDDL HEADER, with the
17 # fields enclosed by brackets "[]" replaced with your own identifying
18 # information: Portions Copyright [yyyy] [name of copyright owner]
24 # Copyright 2009 Sun Microsystems, Inc. All rights reserved.
25 # Use is subject to license terms.
29 # Convert a wx-based workspace to Mercurial.
32 usage
="wx2hg [-u] [-r hg_rev] [-t hg_ws] codemgr_ws"
35 # If "yes", then give some hints about cleanup and rerunning after a
39 tail=/usr
/xpg
4/bin
/tail
41 function has_hg_twin
{
42 [[ -n "$primary_twin" ]]
46 print
-u2 wx2hg
: warning
: "$@"
50 print
-u2 wx2hg
: note
: "$@"
55 if [[ "$can_retry" = yes ]]; then
56 print
-u2 "Please run"
57 print
-u2 " hg --cwd $hg_ws update -C"
58 print
-u2 "before retrying."
63 function clone_twins
{
67 echo "Cloning $primary_twin"
70 hg clone
-r $rev "$primary_twin" "$ws"
74 for dir
in $nested_twins; do
75 echo "Cloning from $primary_twin/$dir"
80 echo "[paths]" > $ws/$dir/.hg
/hgrc
81 echo "default=$primary_twin/$dir" >> $ws/$dir/.hg
/hgrc
82 ( cd $ws/$dir; hg pull
-u -r $rev "$primary_twin"/$dir )
83 if (( $?
!= 0 )); then
84 warn
"Unable to clone $primary_twin/$dir"
90 [[ $rev_warning = "n" ]] || fail \
91 "revision $rev was not present in all workspaces.\n" \
92 "When using -r with nested repositories, you should specify a tag\n" \
93 "name that is valid in each workspace."
97 # Command-line processing, sanity checks, and setup.
100 [[ -n $
(whence workspace
) ]] ||
101 fail
"workspace command not found; please check PATH."
107 # Mercurial workspace to populate. Default is to create, in the same
108 # directory as the Teamware workspace, a new Mercurial workspace cloned
109 # from the hg_twin of the Teamware parent.
114 # Revision in the Mercurial workspace to apply the changes to.
115 # Default is to get the most recent revision (tip), thus avoiding
116 # the need for a merge unless overridden by the caller using -r.
120 while getopts r
:t
:u opt
; do
122 r
) hg_rev
="$OPTARG";;
125 ?
) print
-u2 "usage: $usage"; exit 1;;
128 shift $
(($OPTIND - 1))
130 if [[ $# -ne 1 ]]; then
131 print
-u2 "usage: $usage"
136 [[ "$CODEMGR_WS" = /* ]] || CODEMGR_WS
="$(pwd)/$CODEMGR_WS"
139 if [[ -n "$hg_ws" ]]; then
140 if [[ ! -d "$hg_ws" ||
! -d "$hg_ws/.hg" ]]; then
141 fail
"$hg_ws is not a Mercurial workspace."
143 [[ "$hg_ws" = /* ]] || hg_ws
="$(pwd)/$hg_ws"
146 [[ -d "$CODEMGR_WS" ]] || fail
"$CODEMGR_WS does not exist."
149 codemgr_parent
=$
(workspace parent
)
150 [[ -n "$codemgr_parent" ]] || \
151 fail
"$CODEMGR_WS is not a Teamware workspace or does not have a parent."
152 [[ -d "$codemgr_parent" ]] || fail
"parent ($codemgr_parent) doesn't exist."
156 twinfile
="$codemgr_parent"/Codemgr_wsdata
/hg_twin
157 if [[ -f $twinfile ]]; then
158 primary_twin
=$
(head -1 $twinfile)
159 nested_twins
=$
($tail -n +2 $twinfile |
sort -r)
163 echo "Teamware parent $codemgr_parent has twin $primary_twin"
164 [[ -n "$nested_twins" ]] &&
165 echo "and nested twins $nested_twins"
169 # Do this check before time-consuming operations like creating
172 his
=$
(find Codemgr_wsdata
-name history -mtime -1)
173 if [[ -z "$his" ]]; then
174 warn
"history file is more than one day old; do you need to" \
175 "bringover from $codemgr_parent?"
178 # Less time-consuming than cloning
180 if [[ ! -d wx
]]; then
181 print
"Initializing wx..."
184 if [[ "$do_update" = yes ]]; then
185 print
"Updating wx state..."
193 active_files
=$
(wx list
)
195 if [[ ! -z "$out_files" ]]; then
196 fail
"wx2hg will only migrate checked-in files;" \
197 "please check in these files with wx ci and try again"
200 # more time-consuming than wx update and wx outchk
202 if [[ -z "$hg_ws" ]]; then
203 ws
=$
(basename $
(pwd))
204 hg_ws
=$
(dirname $
(pwd))/"$ws-hg"
207 if [[ -d "$hg_ws" ]]; then
208 echo "Updating preexisting Mercurial workspace $hg_ws to $hg_rev\n"
209 (cd "$hg_ws"; hg update
-C $hg_rev) ||
210 fail
"hg update $hg_rev failed for $hg_ws"
211 if [[ -n "$nested_twins" ]]; then
213 for dir
in $nested_twins; do
214 if [[ ! -d "$hg_ws/$dir" ]]; then
215 warn
"$hw_ws/$dir does not exist"
218 echo "Updating preexisting nested workspace " \
219 "$hg_ws/$dir to $hg_rev\n"
220 (cd "$hg_ws"/$dir ; hg update
-C $hg_rev)
221 if (( $?
!= 0 )); then
222 warn
"hg update $hg_rev failed for $hg_ws/$dir"
228 [[ $update_warning = "n" ]] ||
229 fail
"When using an existing Mercurial workspace with\n" \
230 "nested repositories, all nested repositories must\n" \
231 "already exist in the existing workspace. If also\n" \
232 "specifying -r, then the specified hg_rev must be\n" \
233 "valid in all nested repositories."
237 clone_twins
"$hg_ws" $hg_rev
239 fail
"$codemgr_parent is not recognized as a gate;" \
240 "please provide a Mercurial workspace (-t hg_ws)" \
247 # Make sure hg_ws is an absolute path
248 [[ "$hg_ws" = /* ]] || hg_ws
="$(pwd)/$hg_ws"
251 # usage: which_repo filename
252 function which_repo
{
255 for r
in $nested_twins; do
256 if [ ${f##$r/} != $f ]; then
266 # Do renames first, because they'll be listed with the new name by "wx
267 # list". There's a conflict if the new name already exists or if the
268 # old name does not exist. We can theoretically recover from the
269 # former (move the existing file out of the way, or pick a different
270 # new name), but not the latter. For now, just error out and let the
271 # user fix up the workspace so that there isn't a conflict.
274 renamelist
=/tmp
/wxrename$$
275 wx renamed
> "$renamelist"
277 # usage: do_rename oldname newname
279 typeset old_file old_repo new_file new_repo
281 which_repo
$1 |
read old_file old_repo
282 which_repo
$2 |
read new_file new_repo
284 typeset old
=$old_repo/$old_file
285 typeset new
=$new_repo/$new_file
287 [[ -f "$old" ]] || fail
"can't rename: $old doesn't exist."
288 [[ ! -f "$new" ]] || fail
"can't rename: $new already exists."
290 dir
=$
(dirname "$new")
291 base
=$
(basename "$new")
292 [[ -d "$dir" ]] || mkdir
-p "$dir" || fail
"mkdir failed"
294 if [ $old_repo = $new_repo ]; then
295 print
"rename $old -> $new"
297 ( cd $old_repo; hg
mv $old_file $new_file ) || \
298 fail
"rename failed."
301 print
"moving $old_file from repository $old_repo"
302 print
"to $new_file in repository $new_repo"
305 ( cd $old_repo; hg
rm $old_file ) || fail
"hg rm failed"
306 ( cd $new_repo; hg add
$new_file ) || fail
"hg add failed"
311 if [[ -s "$renamelist" ]]; then
312 cat "$renamelist" |
(
316 [[ -n "$newname" ]] ||
break
317 do_rename
"$oldname" "$newname"
323 # usage: name_in_parent fname
324 # If fname had been renamed, echo the old name. Otherwise echo the
327 function name_in_parent
{
330 if [[ -s "$renamelist" ]]; then
331 cat "$renamelist" |
while :; do
333 [[ -n "$new" ]] ||
break
334 if [[ "$1" = "$new" ]]; then
344 # Now do content changes. There's a likely conflict if the file in
345 # Mercurial is different from the file in the Teamware parent.
348 parentfile
=/tmp
/parent$$
349 patchfile
=/tmp
/patch$$
350 childfile
=/tmp
/child$$
352 [[ -n "$active_files" ]] || warn
"no files in active list."
354 for f
in $active_files; do
356 # Get the name that the file appears in the parent as.
358 oldname
=$
(name_in_parent
"$f")
360 # We need unexpanded SCCS keywords for both parent and child
361 sccs get
-skp "$f" > "$childfile"
363 if [[ -f "$codemgr_parent/$oldname" ]]; then
364 (cd $codemgr_parent; sccs get
-skp "$oldname" > "$parentfile")
369 if [[ ! -r "$parentfile" ]]; then
371 [[ ! -f "$hg_ws/$f" ]] || fail
"$f already exists in $hg_ws."
372 dir
=$
(dirname "$hg_ws/$f")
373 base
=$
(basename "$hg_ws/$f")
374 [[ -d "$dir" ]] || mkdir
-p "$dir" || fail
"mkdir failed"
375 cp "$childfile" "$hg_ws/$f" || fail
"copy failed"
377 (cd "$dir" && hg add
"$base") || fail
"hg add failed."
379 elif diff "$parentfile" "$hg_ws/$f" > /dev
/null
2>&1; then
380 if diff -u "$parentfile" "$childfile" > "$patchfile"; then
381 print
"skipping $f (unchanged)."
384 (cd "$hg_ws"; gpatch
-F0 $f < "$patchfile")
385 [[ $?
-eq 0 ]] || fail
"$f: patch failed."
387 diff -u "$parentfile" "$hg_ws/$f"
390 fail
"For file:\n\n\t$f\n\nthe teamware parent:" \
391 "\n\n\t$codemgr_parent" \
392 "\n\ndoesn't match its mercurial twin;" \
393 "specify the matching revision in mercurial\nwith" \
394 "-r hg_rev, or resynchronize them.\n"
398 note
"remember to commit your changes:"
399 echo "in primary repository ${hg_ws}:"
400 ( cd $hg_ws ; hg status
-mard )
401 for n
in $nested_twins; do
402 echo "in nested repository ${n}:"
403 ( cd $hg_ws/$n ; hg status
-mard )
406 if [[ "$hg_rev" != "tip" ]]; then
407 note
"before you integrate your changes, $hg_ws must be merged to tip"
410 rm -f "$parentfile" "$patchfile" "$renamelist" "$childfile"