##// END OF EJS Templates
destupdate: extract logic based on obsolescence marker in its own function...
Pierre-Yves David -
r26723:52d08a93 default
parent child Browse files
Show More
@@ -1,158 +1,167 b''
1 # destutil.py - Mercurial utility function for command destination
1 # destutil.py - Mercurial utility function for command destination
2 #
2 #
3 # Copyright Matt Mackall <mpm@selenic.com> and other
3 # Copyright Matt Mackall <mpm@selenic.com> and other
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from .i18n import _
8 from .i18n import _
9 from . import (
9 from . import (
10 bookmarks,
10 bookmarks,
11 error,
11 error,
12 obsolete,
12 obsolete,
13 )
13 )
14
14
15 def _destupdatevalidate(repo, rev, clean, check):
15 def _destupdatevalidate(repo, rev, clean, check):
16 """validate that the destination comply to various rules
16 """validate that the destination comply to various rules
17
17
18 This exists as its own function to help wrapping from extensions."""
18 This exists as its own function to help wrapping from extensions."""
19 wc = repo[None]
19 wc = repo[None]
20 p1 = wc.p1()
20 p1 = wc.p1()
21 if not clean:
21 if not clean:
22 # Check that the update is linear.
22 # Check that the update is linear.
23 #
23 #
24 # Mercurial do not allow update-merge for non linear pattern
24 # Mercurial do not allow update-merge for non linear pattern
25 # (that would be technically possible but was considered too confusing
25 # (that would be technically possible but was considered too confusing
26 # for user a long time ago)
26 # for user a long time ago)
27 #
27 #
28 # See mercurial.merge.update for details
28 # See mercurial.merge.update for details
29 if p1.rev() not in repo.changelog.ancestors([rev], inclusive=True):
29 if p1.rev() not in repo.changelog.ancestors([rev], inclusive=True):
30 dirty = wc.dirty(missing=True)
30 dirty = wc.dirty(missing=True)
31 foreground = obsolete.foreground(repo, [p1.node()])
31 foreground = obsolete.foreground(repo, [p1.node()])
32 if not repo[rev].node() in foreground:
32 if not repo[rev].node() in foreground:
33 if dirty:
33 if dirty:
34 msg = _("uncommitted changes")
34 msg = _("uncommitted changes")
35 hint = _("commit and merge, or update --clean to"
35 hint = _("commit and merge, or update --clean to"
36 " discard changes")
36 " discard changes")
37 raise error.UpdateAbort(msg, hint=hint)
37 raise error.UpdateAbort(msg, hint=hint)
38 elif not check: # destination is not a descendant.
38 elif not check: # destination is not a descendant.
39 msg = _("not a linear update")
39 msg = _("not a linear update")
40 hint = _("merge or update --check to force update")
40 hint = _("merge or update --check to force update")
41 raise error.UpdateAbort(msg, hint=hint)
41 raise error.UpdateAbort(msg, hint=hint)
42
42
43 def destupdate(repo, clean=False, check=False):
43 def _destupdateobs(repo, clean, check):
44 """destination for bare update operation
44 """decide of an update destination from obsolescence markers"""
45
46 return (rev, movemark, activemark)
47
48 - rev: the revision to update to,
49 - movemark: node to move the active bookmark from
50 (cf bookmark.calculate update),
51 - activemark: a bookmark to activate at the end of the update.
52 """
53 node = None
45 node = None
54 wc = repo[None]
46 wc = repo[None]
55 p1 = wc.p1()
47 p1 = wc.p1()
56 movemark = activemark = None
48 movemark = None
57
49
58 if p1.obsolete() and not p1.children():
50 if p1.obsolete() and not p1.children():
59 # allow updating to successors
51 # allow updating to successors
60 successors = obsolete.successorssets(repo, p1.node())
52 successors = obsolete.successorssets(repo, p1.node())
61
53
62 # behavior of certain cases is as follows,
54 # behavior of certain cases is as follows,
63 #
55 #
64 # divergent changesets: update to highest rev, similar to what
56 # divergent changesets: update to highest rev, similar to what
65 # is currently done when there are more than one head
57 # is currently done when there are more than one head
66 # (i.e. 'tip')
58 # (i.e. 'tip')
67 #
59 #
68 # replaced changesets: same as divergent except we know there
60 # replaced changesets: same as divergent except we know there
69 # is no conflict
61 # is no conflict
70 #
62 #
71 # pruned changeset: no update is done; though, we could
63 # pruned changeset: no update is done; though, we could
72 # consider updating to the first non-obsolete parent,
64 # consider updating to the first non-obsolete parent,
73 # similar to what is current done for 'hg prune'
65 # similar to what is current done for 'hg prune'
74
66
75 if successors:
67 if successors:
76 # flatten the list here handles both divergent (len > 1)
68 # flatten the list here handles both divergent (len > 1)
77 # and the usual case (len = 1)
69 # and the usual case (len = 1)
78 successors = [n for sub in successors for n in sub]
70 successors = [n for sub in successors for n in sub]
79
71
80 # get the max revision for the given successors set,
72 # get the max revision for the given successors set,
81 # i.e. the 'tip' of a set
73 # i.e. the 'tip' of a set
82 node = repo.revs('max(%ln)', successors).first()
74 node = repo.revs('max(%ln)', successors).first()
83 if bookmarks.isactivewdirparent(repo):
75 if bookmarks.isactivewdirparent(repo):
84 movemark = repo['.'].node()
76 movemark = repo['.'].node()
77 return node, movemark, None
78
79 def destupdate(repo, clean=False, check=False):
80 """destination for bare update operation
81
82 return (rev, movemark, activemark)
83
84 - rev: the revision to update to,
85 - movemark: node to move the active bookmark from
86 (cf bookmark.calculate update),
87 - activemark: a bookmark to activate at the end of the update.
88 """
89 node = None
90 wc = repo[None]
91 movemark = activemark = None
92
93 node, movemark, activemark = _destupdateobs(repo, clean, check)
85
94
86 if node is None:
95 if node is None:
87 # we also move the active bookmark, if any
96 # we also move the active bookmark, if any
88 node, movemark = bookmarks.calculateupdate(repo.ui, repo, None)
97 node, movemark = bookmarks.calculateupdate(repo.ui, repo, None)
89 if node is not None:
98 if node is not None:
90 activemark = node
99 activemark = node
91
100
92 if node is None:
101 if node is None:
93 try:
102 try:
94 node = repo.branchtip(wc.branch())
103 node = repo.branchtip(wc.branch())
95 except error.RepoLookupError:
104 except error.RepoLookupError:
96 if wc.branch() == 'default': # no default branch!
105 if wc.branch() == 'default': # no default branch!
97 node = repo.lookup('tip') # update to tip
106 node = repo.lookup('tip') # update to tip
98 else:
107 else:
99 raise error.Abort(_("branch %s not found") % wc.branch())
108 raise error.Abort(_("branch %s not found") % wc.branch())
100 rev = repo[node].rev()
109 rev = repo[node].rev()
101
110
102 _destupdatevalidate(repo, rev, clean, check)
111 _destupdatevalidate(repo, rev, clean, check)
103
112
104 return rev, movemark, activemark
113 return rev, movemark, activemark
105
114
106 def destmerge(repo):
115 def destmerge(repo):
107 if repo._activebookmark:
116 if repo._activebookmark:
108 bmheads = repo.bookmarkheads(repo._activebookmark)
117 bmheads = repo.bookmarkheads(repo._activebookmark)
109 curhead = repo[repo._activebookmark].node()
118 curhead = repo[repo._activebookmark].node()
110 if len(bmheads) == 2:
119 if len(bmheads) == 2:
111 if curhead == bmheads[0]:
120 if curhead == bmheads[0]:
112 node = bmheads[1]
121 node = bmheads[1]
113 else:
122 else:
114 node = bmheads[0]
123 node = bmheads[0]
115 elif len(bmheads) > 2:
124 elif len(bmheads) > 2:
116 raise error.Abort(_("multiple matching bookmarks to merge - "
125 raise error.Abort(_("multiple matching bookmarks to merge - "
117 "please merge with an explicit rev or bookmark"),
126 "please merge with an explicit rev or bookmark"),
118 hint=_("run 'hg heads' to see all heads"))
127 hint=_("run 'hg heads' to see all heads"))
119 elif len(bmheads) <= 1:
128 elif len(bmheads) <= 1:
120 raise error.Abort(_("no matching bookmark to merge - "
129 raise error.Abort(_("no matching bookmark to merge - "
121 "please merge with an explicit rev or bookmark"),
130 "please merge with an explicit rev or bookmark"),
122 hint=_("run 'hg heads' to see all heads"))
131 hint=_("run 'hg heads' to see all heads"))
123 else:
132 else:
124 branch = repo[None].branch()
133 branch = repo[None].branch()
125 bheads = repo.branchheads(branch)
134 bheads = repo.branchheads(branch)
126 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
135 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
127
136
128 if len(nbhs) > 2:
137 if len(nbhs) > 2:
129 raise error.Abort(_("branch '%s' has %d heads - "
138 raise error.Abort(_("branch '%s' has %d heads - "
130 "please merge with an explicit rev")
139 "please merge with an explicit rev")
131 % (branch, len(bheads)),
140 % (branch, len(bheads)),
132 hint=_("run 'hg heads .' to see heads"))
141 hint=_("run 'hg heads .' to see heads"))
133
142
134 parent = repo.dirstate.p1()
143 parent = repo.dirstate.p1()
135 if len(nbhs) <= 1:
144 if len(nbhs) <= 1:
136 if len(bheads) > 1:
145 if len(bheads) > 1:
137 raise error.Abort(_("heads are bookmarked - "
146 raise error.Abort(_("heads are bookmarked - "
138 "please merge with an explicit rev"),
147 "please merge with an explicit rev"),
139 hint=_("run 'hg heads' to see all heads"))
148 hint=_("run 'hg heads' to see all heads"))
140 if len(repo.heads()) > 1:
149 if len(repo.heads()) > 1:
141 raise error.Abort(_("branch '%s' has one head - "
150 raise error.Abort(_("branch '%s' has one head - "
142 "please merge with an explicit rev")
151 "please merge with an explicit rev")
143 % branch,
152 % branch,
144 hint=_("run 'hg heads' to see all heads"))
153 hint=_("run 'hg heads' to see all heads"))
145 msg, hint = _('nothing to merge'), None
154 msg, hint = _('nothing to merge'), None
146 if parent != repo.lookup(branch):
155 if parent != repo.lookup(branch):
147 hint = _("use 'hg update' instead")
156 hint = _("use 'hg update' instead")
148 raise error.Abort(msg, hint=hint)
157 raise error.Abort(msg, hint=hint)
149
158
150 if parent not in bheads:
159 if parent not in bheads:
151 raise error.Abort(_('working directory not at a head revision'),
160 raise error.Abort(_('working directory not at a head revision'),
152 hint=_("use 'hg update' or merge with an "
161 hint=_("use 'hg update' or merge with an "
153 "explicit revision"))
162 "explicit revision"))
154 if parent == nbhs[0]:
163 if parent == nbhs[0]:
155 node = nbhs[-1]
164 node = nbhs[-1]
156 else:
165 else:
157 node = nbhs[0]
166 node = nbhs[0]
158 return repo[node].rev()
167 return repo[node].rev()
General Comments 0
You need to be logged in to leave comments. Login now