update: add comments and test cases for updating across branches
Add comment to merge.py:update() showing various cases of 'hg update': to a
descendant, crossing named branches, and crossing branches within a named
branch; with no option, -c or -C; with or without uncommitted changes; and
with or without a specific revision. Add tests for all of these cases.
--- a/mercurial/merge.py Thu Nov 05 10:49:28 2009 +0100
+++ b/mercurial/merge.py Thu Nov 05 10:53:36 2009 +0100
@@ -397,9 +397,37 @@
"""
Perform a merge between the working directory and the given node
+ node = the node to update to, or None if unspecified
branchmerge = whether to merge between branches
force = whether to force branch merging or file overwriting
partial = a function to filter file lists (dirstate not updated)
+
+ The table below shows all the behaviors of the update command
+ given the -c and -C or no options, whether the working directory
+ is dirty, whether a revision is specified, and the relationship of
+ the parent rev to the target rev (linear, on the same named
+ branch, or on another named branch).
+
+ This logic is tested by test-update-branches.
+
+ -c -C dirty rev | linear same cross
+ n n n n | ok (1) x
+ n n n y | ok (1) ok
+ n n y * | merge (2) (3)
+ n y * * | --- discard ---
+ y n y * | --- (4) ---
+ y n n * | --- ok ---
+ y y * * | --- (5) ---
+
+ x = can't happen
+ * = don't-care
+ 1 = abort: crosses branches (use 'hg merge' or 'hg update -C')
+ 2 = abort: crosses branches (use 'hg merge' or 'hg update -C'
+ to discard changes)
+ 3 = abort: crosses named branches (use 'hg update -C' to
+ discard changes)
+ 4 = abort: uncommitted local changes
+ 5 = incompatible options (checked in commands.py)
"""
wlock = repo.wlock()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-update-branches Thu Nov 05 10:53:36 2009 +0100
@@ -0,0 +1,81 @@
+#!/bin/sh
+
+# Construct the following history tree:
+#
+# @ 5:e1bb631146ca b1
+# |
+# o 4:a4fdb3b883c4 0:b608b9236435 b1
+# |
+# | o 3:4b57d2520816 1:44592833ba9f
+# | |
+# | | o 2:063f31070f65
+# | |/
+# | o 1:44592833ba9f
+# |/
+# o 0:b608b9236435
+
+hg init
+echo foo > foo
+echo zero > a
+hg ci -qAm0
+echo one > a ; hg ci -m1
+echo two > a ; hg ci -m2
+hg up -q 1
+echo three > a ; hg ci -qm3
+hg up -q 0
+hg branch -q b1
+echo four > a ; hg ci -qm4
+echo five > a ; hg ci -qm5
+
+echo % initial repo state
+echo
+hg --config 'extensions.graphlog=' \
+ glog --template '{rev}:{node|short} {parents} {branches}\n'
+
+# Test helper functions.
+
+revtest () {
+ msg=$1
+ dirtyflag=$2 # 'clean' or 'dirty'
+ startrev=$3
+ targetrev=$4
+ opt=$5
+ echo % revtest $msg $startrev $targetrev
+ hg up -qC $startrev
+ test $dirtyflag = dirty && echo dirty > foo
+ hg up $opt $targetrev
+ hg parent --template 'parent={rev}\n'
+ hg stat
+}
+
+norevtest () {
+ msg=$1
+ dirtyflag=$2 # 'clean' or 'dirty'
+ startrev=$3
+ opt=$4
+ echo % norevtest $msg $startrev
+ hg up -qC $startrev
+ test $dirtyflag = dirty && echo dirty > foo
+ hg up $opt
+ hg parent --template 'parent={rev}\n'
+ hg stat
+}
+
+# Test cases are documented in a table in the update function of merge.py.
+# Cases are run as shown in that table, row by row.
+
+norevtest 'none clean linear' clean 4
+norevtest 'none clean same' clean 2
+
+revtest 'none clean linear' clean 1 2
+revtest 'none clean same' clean 2 3
+revtest 'none clean cross' clean 3 4
+
+revtest 'none dirty linear' dirty 1 2
+revtest 'none dirty same' dirty 2 3
+revtest 'none dirty cross' dirty 3 4
+
+revtest '-C dirty linear' dirty 1 2 -C
+revtest '-c dirty linear' dirty 1 2 -c
+norevtest '-c clean same' clean 2 -c
+revtest '-cC dirty linear' dirty 1 2 -cC
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-update-branches.out Thu Nov 05 10:53:36 2009 +0100
@@ -0,0 +1,55 @@
+% initial repo state
+
+@ 5:e1bb631146ca b1
+|
+o 4:a4fdb3b883c4 0:b608b9236435 b1
+|
+| o 3:4b57d2520816 1:44592833ba9f
+| |
+| | o 2:063f31070f65
+| |/
+| o 1:44592833ba9f
+|/
+o 0:b608b9236435
+
+% norevtest none clean linear 4
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+parent=5
+% norevtest none clean same 2
+abort: crosses branches (use 'hg merge' or 'hg update -C')
+parent=2
+% revtest none clean linear 1 2
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+parent=2
+% revtest none clean same 2 3
+abort: crosses branches (use 'hg merge' or 'hg update -C')
+parent=2
+% revtest none clean cross 3 4
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+parent=4
+% revtest none dirty linear 1 2
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+parent=2
+M foo
+% revtest none dirty same 2 3
+abort: crosses branches (use 'hg merge' or 'hg update -C' to discard changes)
+parent=2
+M foo
+% revtest none dirty cross 3 4
+abort: crosses named branches (use 'hg update -C' to discard changes)
+parent=3
+M foo
+% revtest -C dirty linear 1 2
+2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+parent=2
+% revtest -c dirty linear 1 2
+abort: uncommitted local changes
+parent=1
+M foo
+% norevtest -c clean same 2
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+parent=3
+% revtest -cC dirty linear 1 2
+abort: cannot specify both -c/--check and -C/--clean
+parent=1
+M foo