##// END OF EJS Templates
merge: expand environment variables and ~/ in tool.executable...
Greg Ward -
r15264:157d93c4 default
parent child Browse files
Show More
@@ -1,270 +1,271 b''
1 # filemerge.py - file-level merge handling for Mercurial
1 # filemerge.py - file-level merge handling for Mercurial
2 #
2 #
3 # Copyright 2006, 2007, 2008 Matt Mackall <mpm@selenic.com>
3 # Copyright 2006, 2007, 2008 Matt Mackall <mpm@selenic.com>
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 node import short
8 from node import short
9 from i18n import _
9 from i18n import _
10 import util, simplemerge, match, error
10 import util, simplemerge, match, error
11 import os, tempfile, re, filecmp
11 import os, tempfile, re, filecmp
12
12
13 def _toolstr(ui, tool, part, default=""):
13 def _toolstr(ui, tool, part, default=""):
14 return ui.config("merge-tools", tool + "." + part, default)
14 return ui.config("merge-tools", tool + "." + part, default)
15
15
16 def _toolbool(ui, tool, part, default=False):
16 def _toolbool(ui, tool, part, default=False):
17 return ui.configbool("merge-tools", tool + "." + part, default)
17 return ui.configbool("merge-tools", tool + "." + part, default)
18
18
19 def _toollist(ui, tool, part, default=[]):
19 def _toollist(ui, tool, part, default=[]):
20 return ui.configlist("merge-tools", tool + "." + part, default)
20 return ui.configlist("merge-tools", tool + "." + part, default)
21
21
22 _internal = ['internal:' + s
22 _internal = ['internal:' + s
23 for s in 'fail local other merge prompt dump'.split()]
23 for s in 'fail local other merge prompt dump'.split()]
24
24
25 def _findtool(ui, tool):
25 def _findtool(ui, tool):
26 if tool in _internal:
26 if tool in _internal:
27 return tool
27 return tool
28 for kn in ("regkey", "regkeyalt"):
28 for kn in ("regkey", "regkeyalt"):
29 k = _toolstr(ui, tool, kn)
29 k = _toolstr(ui, tool, kn)
30 if not k:
30 if not k:
31 continue
31 continue
32 p = util.lookupreg(k, _toolstr(ui, tool, "regname"))
32 p = util.lookupreg(k, _toolstr(ui, tool, "regname"))
33 if p:
33 if p:
34 p = util.findexe(p + _toolstr(ui, tool, "regappend"))
34 p = util.findexe(p + _toolstr(ui, tool, "regappend"))
35 if p:
35 if p:
36 return p
36 return p
37 return util.findexe(_toolstr(ui, tool, "executable", tool))
37 exe = _toolstr(ui, tool, "executable", tool)
38 return util.findexe(util.expandpath(exe))
38
39
39 def _picktool(repo, ui, path, binary, symlink):
40 def _picktool(repo, ui, path, binary, symlink):
40 def check(tool, pat, symlink, binary):
41 def check(tool, pat, symlink, binary):
41 tmsg = tool
42 tmsg = tool
42 if pat:
43 if pat:
43 tmsg += " specified for " + pat
44 tmsg += " specified for " + pat
44 if not _findtool(ui, tool):
45 if not _findtool(ui, tool):
45 if pat: # explicitly requested tool deserves a warning
46 if pat: # explicitly requested tool deserves a warning
46 ui.warn(_("couldn't find merge tool %s\n") % tmsg)
47 ui.warn(_("couldn't find merge tool %s\n") % tmsg)
47 else: # configured but non-existing tools are more silent
48 else: # configured but non-existing tools are more silent
48 ui.note(_("couldn't find merge tool %s\n") % tmsg)
49 ui.note(_("couldn't find merge tool %s\n") % tmsg)
49 elif symlink and not _toolbool(ui, tool, "symlink"):
50 elif symlink and not _toolbool(ui, tool, "symlink"):
50 ui.warn(_("tool %s can't handle symlinks\n") % tmsg)
51 ui.warn(_("tool %s can't handle symlinks\n") % tmsg)
51 elif binary and not _toolbool(ui, tool, "binary"):
52 elif binary and not _toolbool(ui, tool, "binary"):
52 ui.warn(_("tool %s can't handle binary\n") % tmsg)
53 ui.warn(_("tool %s can't handle binary\n") % tmsg)
53 elif not util.gui() and _toolbool(ui, tool, "gui"):
54 elif not util.gui() and _toolbool(ui, tool, "gui"):
54 ui.warn(_("tool %s requires a GUI\n") % tmsg)
55 ui.warn(_("tool %s requires a GUI\n") % tmsg)
55 else:
56 else:
56 return True
57 return True
57 return False
58 return False
58
59
59 # forcemerge comes from command line arguments, highest priority
60 # forcemerge comes from command line arguments, highest priority
60 force = ui.config('ui', 'forcemerge')
61 force = ui.config('ui', 'forcemerge')
61 if force:
62 if force:
62 toolpath = _findtool(ui, force)
63 toolpath = _findtool(ui, force)
63 if toolpath:
64 if toolpath:
64 return (force, '"' + toolpath + '"')
65 return (force, '"' + toolpath + '"')
65 else:
66 else:
66 # mimic HGMERGE if given tool not found
67 # mimic HGMERGE if given tool not found
67 return (force, force)
68 return (force, force)
68
69
69 # HGMERGE takes next precedence
70 # HGMERGE takes next precedence
70 hgmerge = os.environ.get("HGMERGE")
71 hgmerge = os.environ.get("HGMERGE")
71 if hgmerge:
72 if hgmerge:
72 return (hgmerge, hgmerge)
73 return (hgmerge, hgmerge)
73
74
74 # then patterns
75 # then patterns
75 for pat, tool in ui.configitems("merge-patterns"):
76 for pat, tool in ui.configitems("merge-patterns"):
76 mf = match.match(repo.root, '', [pat])
77 mf = match.match(repo.root, '', [pat])
77 if mf(path) and check(tool, pat, symlink, False):
78 if mf(path) and check(tool, pat, symlink, False):
78 toolpath = _findtool(ui, tool)
79 toolpath = _findtool(ui, tool)
79 return (tool, '"' + toolpath + '"')
80 return (tool, '"' + toolpath + '"')
80
81
81 # then merge tools
82 # then merge tools
82 tools = {}
83 tools = {}
83 for k, v in ui.configitems("merge-tools"):
84 for k, v in ui.configitems("merge-tools"):
84 t = k.split('.')[0]
85 t = k.split('.')[0]
85 if t not in tools:
86 if t not in tools:
86 tools[t] = int(_toolstr(ui, t, "priority", "0"))
87 tools[t] = int(_toolstr(ui, t, "priority", "0"))
87 names = tools.keys()
88 names = tools.keys()
88 tools = sorted([(-p, t) for t, p in tools.items()])
89 tools = sorted([(-p, t) for t, p in tools.items()])
89 uimerge = ui.config("ui", "merge")
90 uimerge = ui.config("ui", "merge")
90 if uimerge:
91 if uimerge:
91 if uimerge not in names:
92 if uimerge not in names:
92 return (uimerge, uimerge)
93 return (uimerge, uimerge)
93 tools.insert(0, (None, uimerge)) # highest priority
94 tools.insert(0, (None, uimerge)) # highest priority
94 tools.append((None, "hgmerge")) # the old default, if found
95 tools.append((None, "hgmerge")) # the old default, if found
95 for p, t in tools:
96 for p, t in tools:
96 if check(t, None, symlink, binary):
97 if check(t, None, symlink, binary):
97 toolpath = _findtool(ui, t)
98 toolpath = _findtool(ui, t)
98 return (t, '"' + toolpath + '"')
99 return (t, '"' + toolpath + '"')
99 # internal merge as last resort
100 # internal merge as last resort
100 return (not (symlink or binary) and "internal:merge" or None, None)
101 return (not (symlink or binary) and "internal:merge" or None, None)
101
102
102 def _eoltype(data):
103 def _eoltype(data):
103 "Guess the EOL type of a file"
104 "Guess the EOL type of a file"
104 if '\0' in data: # binary
105 if '\0' in data: # binary
105 return None
106 return None
106 if '\r\n' in data: # Windows
107 if '\r\n' in data: # Windows
107 return '\r\n'
108 return '\r\n'
108 if '\r' in data: # Old Mac
109 if '\r' in data: # Old Mac
109 return '\r'
110 return '\r'
110 if '\n' in data: # UNIX
111 if '\n' in data: # UNIX
111 return '\n'
112 return '\n'
112 return None # unknown
113 return None # unknown
113
114
114 def _matcheol(file, origfile):
115 def _matcheol(file, origfile):
115 "Convert EOL markers in a file to match origfile"
116 "Convert EOL markers in a file to match origfile"
116 tostyle = _eoltype(util.readfile(origfile))
117 tostyle = _eoltype(util.readfile(origfile))
117 if tostyle:
118 if tostyle:
118 data = util.readfile(file)
119 data = util.readfile(file)
119 style = _eoltype(data)
120 style = _eoltype(data)
120 if style:
121 if style:
121 newdata = data.replace(style, tostyle)
122 newdata = data.replace(style, tostyle)
122 if newdata != data:
123 if newdata != data:
123 util.writefile(file, newdata)
124 util.writefile(file, newdata)
124
125
125 def filemerge(repo, mynode, orig, fcd, fco, fca):
126 def filemerge(repo, mynode, orig, fcd, fco, fca):
126 """perform a 3-way merge in the working directory
127 """perform a 3-way merge in the working directory
127
128
128 mynode = parent node before merge
129 mynode = parent node before merge
129 orig = original local filename before merge
130 orig = original local filename before merge
130 fco = other file context
131 fco = other file context
131 fca = ancestor file context
132 fca = ancestor file context
132 fcd = local file context for current/destination file
133 fcd = local file context for current/destination file
133 """
134 """
134
135
135 def temp(prefix, ctx):
136 def temp(prefix, ctx):
136 pre = "%s~%s." % (os.path.basename(ctx.path()), prefix)
137 pre = "%s~%s." % (os.path.basename(ctx.path()), prefix)
137 (fd, name) = tempfile.mkstemp(prefix=pre)
138 (fd, name) = tempfile.mkstemp(prefix=pre)
138 data = repo.wwritedata(ctx.path(), ctx.data())
139 data = repo.wwritedata(ctx.path(), ctx.data())
139 f = os.fdopen(fd, "wb")
140 f = os.fdopen(fd, "wb")
140 f.write(data)
141 f.write(data)
141 f.close()
142 f.close()
142 return name
143 return name
143
144
144 def isbin(ctx):
145 def isbin(ctx):
145 try:
146 try:
146 return util.binary(ctx.data())
147 return util.binary(ctx.data())
147 except IOError:
148 except IOError:
148 return False
149 return False
149
150
150 if not fco.cmp(fcd): # files identical?
151 if not fco.cmp(fcd): # files identical?
151 return None
152 return None
152
153
153 ui = repo.ui
154 ui = repo.ui
154 fd = fcd.path()
155 fd = fcd.path()
155 binary = isbin(fcd) or isbin(fco) or isbin(fca)
156 binary = isbin(fcd) or isbin(fco) or isbin(fca)
156 symlink = 'l' in fcd.flags() + fco.flags()
157 symlink = 'l' in fcd.flags() + fco.flags()
157 tool, toolpath = _picktool(repo, ui, fd, binary, symlink)
158 tool, toolpath = _picktool(repo, ui, fd, binary, symlink)
158 ui.debug("picked tool '%s' for %s (binary %s symlink %s)\n" %
159 ui.debug("picked tool '%s' for %s (binary %s symlink %s)\n" %
159 (tool, fd, binary, symlink))
160 (tool, fd, binary, symlink))
160
161
161 if not tool or tool == 'internal:prompt':
162 if not tool or tool == 'internal:prompt':
162 tool = "internal:local"
163 tool = "internal:local"
163 if ui.promptchoice(_(" no tool found to merge %s\n"
164 if ui.promptchoice(_(" no tool found to merge %s\n"
164 "keep (l)ocal or take (o)ther?") % fd,
165 "keep (l)ocal or take (o)ther?") % fd,
165 (_("&Local"), _("&Other")), 0):
166 (_("&Local"), _("&Other")), 0):
166 tool = "internal:other"
167 tool = "internal:other"
167 if tool == "internal:local":
168 if tool == "internal:local":
168 return 0
169 return 0
169 if tool == "internal:other":
170 if tool == "internal:other":
170 repo.wwrite(fd, fco.data(), fco.flags())
171 repo.wwrite(fd, fco.data(), fco.flags())
171 return 0
172 return 0
172 if tool == "internal:fail":
173 if tool == "internal:fail":
173 return 1
174 return 1
174
175
175 # do the actual merge
176 # do the actual merge
176 a = repo.wjoin(fd)
177 a = repo.wjoin(fd)
177 b = temp("base", fca)
178 b = temp("base", fca)
178 c = temp("other", fco)
179 c = temp("other", fco)
179 out = ""
180 out = ""
180 back = a + ".orig"
181 back = a + ".orig"
181 util.copyfile(a, back)
182 util.copyfile(a, back)
182
183
183 if orig != fco.path():
184 if orig != fco.path():
184 ui.status(_("merging %s and %s to %s\n") % (orig, fco.path(), fd))
185 ui.status(_("merging %s and %s to %s\n") % (orig, fco.path(), fd))
185 else:
186 else:
186 ui.status(_("merging %s\n") % fd)
187 ui.status(_("merging %s\n") % fd)
187
188
188 ui.debug("my %s other %s ancestor %s\n" % (fcd, fco, fca))
189 ui.debug("my %s other %s ancestor %s\n" % (fcd, fco, fca))
189
190
190 # do we attempt to simplemerge first?
191 # do we attempt to simplemerge first?
191 try:
192 try:
192 premerge = _toolbool(ui, tool, "premerge", not (binary or symlink))
193 premerge = _toolbool(ui, tool, "premerge", not (binary or symlink))
193 except error.ConfigError:
194 except error.ConfigError:
194 premerge = _toolstr(ui, tool, "premerge").lower()
195 premerge = _toolstr(ui, tool, "premerge").lower()
195 valid = 'keep'.split()
196 valid = 'keep'.split()
196 if premerge not in valid:
197 if premerge not in valid:
197 _valid = ', '.join(["'" + v + "'" for v in valid])
198 _valid = ', '.join(["'" + v + "'" for v in valid])
198 raise error.ConfigError(_("%s.premerge not valid "
199 raise error.ConfigError(_("%s.premerge not valid "
199 "('%s' is neither boolean nor %s)") %
200 "('%s' is neither boolean nor %s)") %
200 (tool, premerge, _valid))
201 (tool, premerge, _valid))
201
202
202 if premerge:
203 if premerge:
203 r = simplemerge.simplemerge(ui, a, b, c, quiet=True)
204 r = simplemerge.simplemerge(ui, a, b, c, quiet=True)
204 if not r:
205 if not r:
205 ui.debug(" premerge successful\n")
206 ui.debug(" premerge successful\n")
206 os.unlink(back)
207 os.unlink(back)
207 os.unlink(b)
208 os.unlink(b)
208 os.unlink(c)
209 os.unlink(c)
209 return 0
210 return 0
210 if premerge != 'keep':
211 if premerge != 'keep':
211 util.copyfile(back, a) # restore from backup and try again
212 util.copyfile(back, a) # restore from backup and try again
212
213
213 env = dict(HG_FILE=fd,
214 env = dict(HG_FILE=fd,
214 HG_MY_NODE=short(mynode),
215 HG_MY_NODE=short(mynode),
215 HG_OTHER_NODE=str(fco.changectx()),
216 HG_OTHER_NODE=str(fco.changectx()),
216 HG_BASE_NODE=str(fca.changectx()),
217 HG_BASE_NODE=str(fca.changectx()),
217 HG_MY_ISLINK='l' in fcd.flags(),
218 HG_MY_ISLINK='l' in fcd.flags(),
218 HG_OTHER_ISLINK='l' in fco.flags(),
219 HG_OTHER_ISLINK='l' in fco.flags(),
219 HG_BASE_ISLINK='l' in fca.flags())
220 HG_BASE_ISLINK='l' in fca.flags())
220
221
221 if tool == "internal:merge":
222 if tool == "internal:merge":
222 r = simplemerge.simplemerge(ui, a, b, c, label=['local', 'other'])
223 r = simplemerge.simplemerge(ui, a, b, c, label=['local', 'other'])
223 elif tool == 'internal:dump':
224 elif tool == 'internal:dump':
224 a = repo.wjoin(fd)
225 a = repo.wjoin(fd)
225 util.copyfile(a, a + ".local")
226 util.copyfile(a, a + ".local")
226 repo.wwrite(fd + ".other", fco.data(), fco.flags())
227 repo.wwrite(fd + ".other", fco.data(), fco.flags())
227 repo.wwrite(fd + ".base", fca.data(), fca.flags())
228 repo.wwrite(fd + ".base", fca.data(), fca.flags())
228 return 1 # unresolved
229 return 1 # unresolved
229 else:
230 else:
230 args = _toolstr(ui, tool, "args", '$local $base $other')
231 args = _toolstr(ui, tool, "args", '$local $base $other')
231 if "$output" in args:
232 if "$output" in args:
232 out, a = a, back # read input from backup, write to original
233 out, a = a, back # read input from backup, write to original
233 replace = dict(local=a, base=b, other=c, output=out)
234 replace = dict(local=a, base=b, other=c, output=out)
234 args = util.interpolate(r'\$', replace, args,
235 args = util.interpolate(r'\$', replace, args,
235 lambda s: '"%s"' % util.localpath(s))
236 lambda s: '"%s"' % util.localpath(s))
236 r = util.system(toolpath + ' ' + args, cwd=repo.root, environ=env,
237 r = util.system(toolpath + ' ' + args, cwd=repo.root, environ=env,
237 out=ui.fout)
238 out=ui.fout)
238
239
239 if not r and (_toolbool(ui, tool, "checkconflicts") or
240 if not r and (_toolbool(ui, tool, "checkconflicts") or
240 'conflicts' in _toollist(ui, tool, "check")):
241 'conflicts' in _toollist(ui, tool, "check")):
241 if re.search("^(<<<<<<< .*|=======|>>>>>>> .*)$", fcd.data(),
242 if re.search("^(<<<<<<< .*|=======|>>>>>>> .*)$", fcd.data(),
242 re.MULTILINE):
243 re.MULTILINE):
243 r = 1
244 r = 1
244
245
245 checked = False
246 checked = False
246 if 'prompt' in _toollist(ui, tool, "check"):
247 if 'prompt' in _toollist(ui, tool, "check"):
247 checked = True
248 checked = True
248 if ui.promptchoice(_("was merge of '%s' successful (yn)?") % fd,
249 if ui.promptchoice(_("was merge of '%s' successful (yn)?") % fd,
249 (_("&Yes"), _("&No")), 1):
250 (_("&Yes"), _("&No")), 1):
250 r = 1
251 r = 1
251
252
252 if not r and not checked and (_toolbool(ui, tool, "checkchanged") or
253 if not r and not checked and (_toolbool(ui, tool, "checkchanged") or
253 'changed' in _toollist(ui, tool, "check")):
254 'changed' in _toollist(ui, tool, "check")):
254 if filecmp.cmp(repo.wjoin(fd), back):
255 if filecmp.cmp(repo.wjoin(fd), back):
255 if ui.promptchoice(_(" output file %s appears unchanged\n"
256 if ui.promptchoice(_(" output file %s appears unchanged\n"
256 "was merge successful (yn)?") % fd,
257 "was merge successful (yn)?") % fd,
257 (_("&Yes"), _("&No")), 1):
258 (_("&Yes"), _("&No")), 1):
258 r = 1
259 r = 1
259
260
260 if _toolbool(ui, tool, "fixeol"):
261 if _toolbool(ui, tool, "fixeol"):
261 _matcheol(repo.wjoin(fd), back)
262 _matcheol(repo.wjoin(fd), back)
262
263
263 if r:
264 if r:
264 ui.warn(_("merging %s failed!\n") % fd)
265 ui.warn(_("merging %s failed!\n") % fd)
265 else:
266 else:
266 os.unlink(back)
267 os.unlink(back)
267
268
268 os.unlink(b)
269 os.unlink(b)
269 os.unlink(c)
270 os.unlink(c)
270 return r
271 return r
@@ -1,720 +1,744 b''
1 test merge-tools configuration - mostly exercising filemerge.py
1 test merge-tools configuration - mostly exercising filemerge.py
2
2
3 $ unset HGMERGE # make sure HGMERGE doesn't interfere with the test
3 $ unset HGMERGE # make sure HGMERGE doesn't interfere with the test
4 $ hg init
4 $ hg init
5
5
6 revision 0
6 revision 0
7
7
8 $ echo "revision 0" > f
8 $ echo "revision 0" > f
9 $ echo "space" >> f
9 $ echo "space" >> f
10 $ hg commit -Am "revision 0"
10 $ hg commit -Am "revision 0"
11 adding f
11 adding f
12
12
13 revision 1
13 revision 1
14
14
15 $ echo "revision 1" > f
15 $ echo "revision 1" > f
16 $ echo "space" >> f
16 $ echo "space" >> f
17 $ hg commit -Am "revision 1"
17 $ hg commit -Am "revision 1"
18 $ hg update 0 > /dev/null
18 $ hg update 0 > /dev/null
19
19
20 revision 2
20 revision 2
21
21
22 $ echo "revision 2" > f
22 $ echo "revision 2" > f
23 $ echo "space" >> f
23 $ echo "space" >> f
24 $ hg commit -Am "revision 2"
24 $ hg commit -Am "revision 2"
25 created new head
25 created new head
26 $ hg update 0 > /dev/null
26 $ hg update 0 > /dev/null
27
27
28 revision 3 - simple to merge
28 revision 3 - simple to merge
29
29
30 $ echo "revision 3" >> f
30 $ echo "revision 3" >> f
31 $ hg commit -Am "revision 3"
31 $ hg commit -Am "revision 3"
32 created new head
32 created new head
33 $ echo "[merge-tools]" > .hg/hgrc
33 $ echo "[merge-tools]" > .hg/hgrc
34
34
35 $ beforemerge() {
35 $ beforemerge() {
36 > cat .hg/hgrc
36 > cat .hg/hgrc
37 > echo "# hg update -C 1"
37 > echo "# hg update -C 1"
38 > hg update -C 1 > /dev/null
38 > hg update -C 1 > /dev/null
39 > }
39 > }
40 $ aftermerge() {
40 $ aftermerge() {
41 > echo "# cat f"
41 > echo "# cat f"
42 > cat f
42 > cat f
43 > echo "# hg stat"
43 > echo "# hg stat"
44 > hg stat
44 > hg stat
45 > rm -f f.orig
45 > rm -f f.orig
46 > }
46 > }
47 $ domerge() {
47 $ domerge() {
48 > beforemerge
48 > beforemerge
49 > echo "# hg merge $*"
49 > echo "# hg merge $*"
50 > hg merge $*
50 > hg merge $*
51 > aftermerge
51 > aftermerge
52 > }
52 > }
53
53
54 Tool selection
54 Tool selection
55
55
56 default is internal merge:
56 default is internal merge:
57
57
58 $ beforemerge
58 $ beforemerge
59 [merge-tools]
59 [merge-tools]
60 # hg update -C 1
60 # hg update -C 1
61
61
62 hg merge -r 2
62 hg merge -r 2
63 override $PATH to ensure hgmerge not visible; use $PYTHON in case we're
63 override $PATH to ensure hgmerge not visible; use $PYTHON in case we're
64 running from a devel copy, not a temp installation
64 running from a devel copy, not a temp installation
65
65
66 $ PATH="$BINDIR" $PYTHON "$BINDIR"/hg merge -r 2
66 $ PATH="$BINDIR" $PYTHON "$BINDIR"/hg merge -r 2
67 merging f
67 merging f
68 warning: conflicts during merge.
68 warning: conflicts during merge.
69 merging f failed!
69 merging f failed!
70 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
70 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
71 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
71 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
72 [1]
72 [1]
73 $ aftermerge
73 $ aftermerge
74 # cat f
74 # cat f
75 <<<<<<< local
75 <<<<<<< local
76 revision 1
76 revision 1
77 =======
77 =======
78 revision 2
78 revision 2
79 >>>>>>> other
79 >>>>>>> other
80 space
80 space
81 # hg stat
81 # hg stat
82 M f
82 M f
83 ? f.orig
83 ? f.orig
84
84
85 simplest hgrc using false for merge:
85 simplest hgrc using false for merge:
86
86
87 $ echo "false.whatever=" >> .hg/hgrc
87 $ echo "false.whatever=" >> .hg/hgrc
88 $ domerge -r 2
88 $ domerge -r 2
89 [merge-tools]
89 [merge-tools]
90 false.whatever=
90 false.whatever=
91 # hg update -C 1
91 # hg update -C 1
92 # hg merge -r 2
92 # hg merge -r 2
93 merging f
93 merging f
94 merging f failed!
94 merging f failed!
95 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
95 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
96 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
96 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
97 # cat f
97 # cat f
98 revision 1
98 revision 1
99 space
99 space
100 # hg stat
100 # hg stat
101 M f
101 M f
102 ? f.orig
102 ? f.orig
103
103
104 true with higher .priority gets precedence:
104 true with higher .priority gets precedence:
105
105
106 $ echo "true.priority=1" >> .hg/hgrc
106 $ echo "true.priority=1" >> .hg/hgrc
107 $ domerge -r 2
107 $ domerge -r 2
108 [merge-tools]
108 [merge-tools]
109 false.whatever=
109 false.whatever=
110 true.priority=1
110 true.priority=1
111 # hg update -C 1
111 # hg update -C 1
112 # hg merge -r 2
112 # hg merge -r 2
113 merging f
113 merging f
114 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
114 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
115 (branch merge, don't forget to commit)
115 (branch merge, don't forget to commit)
116 # cat f
116 # cat f
117 revision 1
117 revision 1
118 space
118 space
119 # hg stat
119 # hg stat
120 M f
120 M f
121
121
122 unless lowered on command line:
122 unless lowered on command line:
123
123
124 $ domerge -r 2 --config merge-tools.true.priority=-7
124 $ domerge -r 2 --config merge-tools.true.priority=-7
125 [merge-tools]
125 [merge-tools]
126 false.whatever=
126 false.whatever=
127 true.priority=1
127 true.priority=1
128 # hg update -C 1
128 # hg update -C 1
129 # hg merge -r 2 --config merge-tools.true.priority=-7
129 # hg merge -r 2 --config merge-tools.true.priority=-7
130 merging f
130 merging f
131 merging f failed!
131 merging f failed!
132 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
132 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
133 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
133 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
134 # cat f
134 # cat f
135 revision 1
135 revision 1
136 space
136 space
137 # hg stat
137 # hg stat
138 M f
138 M f
139 ? f.orig
139 ? f.orig
140
140
141 or false set higher on command line:
141 or false set higher on command line:
142
142
143 $ domerge -r 2 --config merge-tools.false.priority=117
143 $ domerge -r 2 --config merge-tools.false.priority=117
144 [merge-tools]
144 [merge-tools]
145 false.whatever=
145 false.whatever=
146 true.priority=1
146 true.priority=1
147 # hg update -C 1
147 # hg update -C 1
148 # hg merge -r 2 --config merge-tools.false.priority=117
148 # hg merge -r 2 --config merge-tools.false.priority=117
149 merging f
149 merging f
150 merging f failed!
150 merging f failed!
151 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
151 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
152 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
152 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
153 # cat f
153 # cat f
154 revision 1
154 revision 1
155 space
155 space
156 # hg stat
156 # hg stat
157 M f
157 M f
158 ? f.orig
158 ? f.orig
159
159
160 or true.executable not found in PATH:
160 or true.executable not found in PATH:
161
161
162 $ domerge -r 2 --config merge-tools.true.executable=nonexistingmergetool
162 $ domerge -r 2 --config merge-tools.true.executable=nonexistingmergetool
163 [merge-tools]
163 [merge-tools]
164 false.whatever=
164 false.whatever=
165 true.priority=1
165 true.priority=1
166 # hg update -C 1
166 # hg update -C 1
167 # hg merge -r 2 --config merge-tools.true.executable=nonexistingmergetool
167 # hg merge -r 2 --config merge-tools.true.executable=nonexistingmergetool
168 merging f
168 merging f
169 merging f failed!
169 merging f failed!
170 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
170 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
171 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
171 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
172 # cat f
172 # cat f
173 revision 1
173 revision 1
174 space
174 space
175 # hg stat
175 # hg stat
176 M f
176 M f
177 ? f.orig
177 ? f.orig
178
178
179 or true.executable with bogus path:
179 or true.executable with bogus path:
180
180
181 $ domerge -r 2 --config merge-tools.true.executable=/nonexisting/mergetool
181 $ domerge -r 2 --config merge-tools.true.executable=/nonexisting/mergetool
182 [merge-tools]
182 [merge-tools]
183 false.whatever=
183 false.whatever=
184 true.priority=1
184 true.priority=1
185 # hg update -C 1
185 # hg update -C 1
186 # hg merge -r 2 --config merge-tools.true.executable=/nonexisting/mergetool
186 # hg merge -r 2 --config merge-tools.true.executable=/nonexisting/mergetool
187 merging f
187 merging f
188 merging f failed!
188 merging f failed!
189 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
189 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
190 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
190 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
191 # cat f
191 # cat f
192 revision 1
192 revision 1
193 space
193 space
194 # hg stat
194 # hg stat
195 M f
195 M f
196 ? f.orig
196 ? f.orig
197
197
198 but true.executable set to cat found in PATH works:
198 but true.executable set to cat found in PATH works:
199
199
200 $ echo "true.executable=cat" >> .hg/hgrc
200 $ echo "true.executable=cat" >> .hg/hgrc
201 $ domerge -r 2
201 $ domerge -r 2
202 [merge-tools]
202 [merge-tools]
203 false.whatever=
203 false.whatever=
204 true.priority=1
204 true.priority=1
205 true.executable=cat
205 true.executable=cat
206 # hg update -C 1
206 # hg update -C 1
207 # hg merge -r 2
207 # hg merge -r 2
208 merging f
208 merging f
209 revision 1
209 revision 1
210 space
210 space
211 revision 0
211 revision 0
212 space
212 space
213 revision 2
213 revision 2
214 space
214 space
215 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
215 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
216 (branch merge, don't forget to commit)
216 (branch merge, don't forget to commit)
217 # cat f
217 # cat f
218 revision 1
218 revision 1
219 space
219 space
220 # hg stat
220 # hg stat
221 M f
221 M f
222
222
223 and true.executable set to cat with path works:
223 and true.executable set to cat with path works:
224
224
225 $ domerge -r 2 --config merge-tools.true.executable=cat
225 $ domerge -r 2 --config merge-tools.true.executable=cat
226 [merge-tools]
226 [merge-tools]
227 false.whatever=
227 false.whatever=
228 true.priority=1
228 true.priority=1
229 true.executable=cat
229 true.executable=cat
230 # hg update -C 1
230 # hg update -C 1
231 # hg merge -r 2 --config merge-tools.true.executable=cat
231 # hg merge -r 2 --config merge-tools.true.executable=cat
232 merging f
232 merging f
233 revision 1
233 revision 1
234 space
234 space
235 revision 0
235 revision 0
236 space
236 space
237 revision 2
237 revision 2
238 space
238 space
239 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
239 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
240 (branch merge, don't forget to commit)
240 (branch merge, don't forget to commit)
241 # cat f
241 # cat f
242 revision 1
242 revision 1
243 space
243 space
244 # hg stat
244 # hg stat
245 M f
245 M f
246
246
247 environment variables in true.executable are handled:
248
249 $ cat > $HGTMP/merge.sh <<EOF
250 > #!/bin/sh
251 > echo 'custom merge tool'
252 > EOF
253 $ chmod +x $HGTMP/merge.sh
254 $ domerge -r 2 --config merge-tools.true.executable='$HGTMP/merge.sh'
255 [merge-tools]
256 false.whatever=
257 true.priority=1
258 true.executable=cat
259 # hg update -C 1
260 # hg merge -r 2 --config merge-tools.true.executable=$HGTMP/merge.sh
261 merging f
262 custom merge tool
263 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
264 (branch merge, don't forget to commit)
265 # cat f
266 revision 1
267 space
268 # hg stat
269 M f
270
247 Tool selection and merge-patterns
271 Tool selection and merge-patterns
248
272
249 merge-patterns specifies new tool false:
273 merge-patterns specifies new tool false:
250
274
251 $ domerge -r 2 --config merge-patterns.f=false
275 $ domerge -r 2 --config merge-patterns.f=false
252 [merge-tools]
276 [merge-tools]
253 false.whatever=
277 false.whatever=
254 true.priority=1
278 true.priority=1
255 true.executable=cat
279 true.executable=cat
256 # hg update -C 1
280 # hg update -C 1
257 # hg merge -r 2 --config merge-patterns.f=false
281 # hg merge -r 2 --config merge-patterns.f=false
258 merging f
282 merging f
259 merging f failed!
283 merging f failed!
260 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
284 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
261 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
285 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
262 # cat f
286 # cat f
263 revision 1
287 revision 1
264 space
288 space
265 # hg stat
289 # hg stat
266 M f
290 M f
267 ? f.orig
291 ? f.orig
268
292
269 merge-patterns specifies executable not found in PATH and gets warning:
293 merge-patterns specifies executable not found in PATH and gets warning:
270
294
271 $ domerge -r 2 --config merge-patterns.f=true --config merge-tools.true.executable=nonexistingmergetool
295 $ domerge -r 2 --config merge-patterns.f=true --config merge-tools.true.executable=nonexistingmergetool
272 [merge-tools]
296 [merge-tools]
273 false.whatever=
297 false.whatever=
274 true.priority=1
298 true.priority=1
275 true.executable=cat
299 true.executable=cat
276 # hg update -C 1
300 # hg update -C 1
277 # hg merge -r 2 --config merge-patterns.f=true --config merge-tools.true.executable=nonexistingmergetool
301 # hg merge -r 2 --config merge-patterns.f=true --config merge-tools.true.executable=nonexistingmergetool
278 couldn't find merge tool true specified for f
302 couldn't find merge tool true specified for f
279 merging f
303 merging f
280 merging f failed!
304 merging f failed!
281 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
305 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
282 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
306 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
283 # cat f
307 # cat f
284 revision 1
308 revision 1
285 space
309 space
286 # hg stat
310 # hg stat
287 M f
311 M f
288 ? f.orig
312 ? f.orig
289
313
290 merge-patterns specifies executable with bogus path and gets warning:
314 merge-patterns specifies executable with bogus path and gets warning:
291
315
292 $ domerge -r 2 --config merge-patterns.f=true --config merge-tools.true.executable=/nonexisting/mergetool
316 $ domerge -r 2 --config merge-patterns.f=true --config merge-tools.true.executable=/nonexisting/mergetool
293 [merge-tools]
317 [merge-tools]
294 false.whatever=
318 false.whatever=
295 true.priority=1
319 true.priority=1
296 true.executable=cat
320 true.executable=cat
297 # hg update -C 1
321 # hg update -C 1
298 # hg merge -r 2 --config merge-patterns.f=true --config merge-tools.true.executable=/nonexisting/mergetool
322 # hg merge -r 2 --config merge-patterns.f=true --config merge-tools.true.executable=/nonexisting/mergetool
299 couldn't find merge tool true specified for f
323 couldn't find merge tool true specified for f
300 merging f
324 merging f
301 merging f failed!
325 merging f failed!
302 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
326 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
303 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
327 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
304 # cat f
328 # cat f
305 revision 1
329 revision 1
306 space
330 space
307 # hg stat
331 # hg stat
308 M f
332 M f
309 ? f.orig
333 ? f.orig
310
334
311 ui.merge overrules priority
335 ui.merge overrules priority
312
336
313 ui.merge specifies false:
337 ui.merge specifies false:
314
338
315 $ domerge -r 2 --config ui.merge=false
339 $ domerge -r 2 --config ui.merge=false
316 [merge-tools]
340 [merge-tools]
317 false.whatever=
341 false.whatever=
318 true.priority=1
342 true.priority=1
319 true.executable=cat
343 true.executable=cat
320 # hg update -C 1
344 # hg update -C 1
321 # hg merge -r 2 --config ui.merge=false
345 # hg merge -r 2 --config ui.merge=false
322 merging f
346 merging f
323 merging f failed!
347 merging f failed!
324 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
348 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
325 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
349 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
326 # cat f
350 # cat f
327 revision 1
351 revision 1
328 space
352 space
329 # hg stat
353 # hg stat
330 M f
354 M f
331 ? f.orig
355 ? f.orig
332
356
333 ui.merge specifies internal:fail:
357 ui.merge specifies internal:fail:
334
358
335 $ domerge -r 2 --config ui.merge=internal:fail
359 $ domerge -r 2 --config ui.merge=internal:fail
336 [merge-tools]
360 [merge-tools]
337 false.whatever=
361 false.whatever=
338 true.priority=1
362 true.priority=1
339 true.executable=cat
363 true.executable=cat
340 # hg update -C 1
364 # hg update -C 1
341 # hg merge -r 2 --config ui.merge=internal:fail
365 # hg merge -r 2 --config ui.merge=internal:fail
342 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
366 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
343 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
367 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
344 # cat f
368 # cat f
345 revision 1
369 revision 1
346 space
370 space
347 # hg stat
371 # hg stat
348 M f
372 M f
349
373
350 ui.merge specifies internal:local:
374 ui.merge specifies internal:local:
351
375
352 $ domerge -r 2 --config ui.merge=internal:local
376 $ domerge -r 2 --config ui.merge=internal:local
353 [merge-tools]
377 [merge-tools]
354 false.whatever=
378 false.whatever=
355 true.priority=1
379 true.priority=1
356 true.executable=cat
380 true.executable=cat
357 # hg update -C 1
381 # hg update -C 1
358 # hg merge -r 2 --config ui.merge=internal:local
382 # hg merge -r 2 --config ui.merge=internal:local
359 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
383 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
360 (branch merge, don't forget to commit)
384 (branch merge, don't forget to commit)
361 # cat f
385 # cat f
362 revision 1
386 revision 1
363 space
387 space
364 # hg stat
388 # hg stat
365 M f
389 M f
366
390
367 ui.merge specifies internal:other:
391 ui.merge specifies internal:other:
368
392
369 $ domerge -r 2 --config ui.merge=internal:other
393 $ domerge -r 2 --config ui.merge=internal:other
370 [merge-tools]
394 [merge-tools]
371 false.whatever=
395 false.whatever=
372 true.priority=1
396 true.priority=1
373 true.executable=cat
397 true.executable=cat
374 # hg update -C 1
398 # hg update -C 1
375 # hg merge -r 2 --config ui.merge=internal:other
399 # hg merge -r 2 --config ui.merge=internal:other
376 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
400 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
377 (branch merge, don't forget to commit)
401 (branch merge, don't forget to commit)
378 # cat f
402 # cat f
379 revision 2
403 revision 2
380 space
404 space
381 # hg stat
405 # hg stat
382 M f
406 M f
383
407
384 ui.merge specifies internal:prompt:
408 ui.merge specifies internal:prompt:
385
409
386 $ domerge -r 2 --config ui.merge=internal:prompt
410 $ domerge -r 2 --config ui.merge=internal:prompt
387 [merge-tools]
411 [merge-tools]
388 false.whatever=
412 false.whatever=
389 true.priority=1
413 true.priority=1
390 true.executable=cat
414 true.executable=cat
391 # hg update -C 1
415 # hg update -C 1
392 # hg merge -r 2 --config ui.merge=internal:prompt
416 # hg merge -r 2 --config ui.merge=internal:prompt
393 no tool found to merge f
417 no tool found to merge f
394 keep (l)ocal or take (o)ther? l
418 keep (l)ocal or take (o)ther? l
395 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
419 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
396 (branch merge, don't forget to commit)
420 (branch merge, don't forget to commit)
397 # cat f
421 # cat f
398 revision 1
422 revision 1
399 space
423 space
400 # hg stat
424 # hg stat
401 M f
425 M f
402
426
403 ui.merge specifies internal:dump:
427 ui.merge specifies internal:dump:
404
428
405 $ domerge -r 2 --config ui.merge=internal:dump
429 $ domerge -r 2 --config ui.merge=internal:dump
406 [merge-tools]
430 [merge-tools]
407 false.whatever=
431 false.whatever=
408 true.priority=1
432 true.priority=1
409 true.executable=cat
433 true.executable=cat
410 # hg update -C 1
434 # hg update -C 1
411 # hg merge -r 2 --config ui.merge=internal:dump
435 # hg merge -r 2 --config ui.merge=internal:dump
412 merging f
436 merging f
413 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
437 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
414 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
438 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
415 # cat f
439 # cat f
416 revision 1
440 revision 1
417 space
441 space
418 # hg stat
442 # hg stat
419 M f
443 M f
420 ? f.base
444 ? f.base
421 ? f.local
445 ? f.local
422 ? f.orig
446 ? f.orig
423 ? f.other
447 ? f.other
424
448
425 f.base:
449 f.base:
426
450
427 $ cat f.base
451 $ cat f.base
428 revision 0
452 revision 0
429 space
453 space
430
454
431 f.local:
455 f.local:
432
456
433 $ cat f.local
457 $ cat f.local
434 revision 1
458 revision 1
435 space
459 space
436
460
437 f.other:
461 f.other:
438
462
439 $ cat f.other
463 $ cat f.other
440 revision 2
464 revision 2
441 space
465 space
442 $ rm f.base f.local f.other
466 $ rm f.base f.local f.other
443
467
444 ui.merge specifies internal:other but is overruled by pattern for false:
468 ui.merge specifies internal:other but is overruled by pattern for false:
445
469
446 $ domerge -r 2 --config ui.merge=internal:other --config merge-patterns.f=false
470 $ domerge -r 2 --config ui.merge=internal:other --config merge-patterns.f=false
447 [merge-tools]
471 [merge-tools]
448 false.whatever=
472 false.whatever=
449 true.priority=1
473 true.priority=1
450 true.executable=cat
474 true.executable=cat
451 # hg update -C 1
475 # hg update -C 1
452 # hg merge -r 2 --config ui.merge=internal:other --config merge-patterns.f=false
476 # hg merge -r 2 --config ui.merge=internal:other --config merge-patterns.f=false
453 merging f
477 merging f
454 merging f failed!
478 merging f failed!
455 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
479 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
456 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
480 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
457 # cat f
481 # cat f
458 revision 1
482 revision 1
459 space
483 space
460 # hg stat
484 # hg stat
461 M f
485 M f
462 ? f.orig
486 ? f.orig
463
487
464 Premerge
488 Premerge
465
489
466 ui.merge specifies internal:other but is overruled by --tool=false
490 ui.merge specifies internal:other but is overruled by --tool=false
467
491
468 $ domerge -r 2 --config ui.merge=internal:other --tool=false
492 $ domerge -r 2 --config ui.merge=internal:other --tool=false
469 [merge-tools]
493 [merge-tools]
470 false.whatever=
494 false.whatever=
471 true.priority=1
495 true.priority=1
472 true.executable=cat
496 true.executable=cat
473 # hg update -C 1
497 # hg update -C 1
474 # hg merge -r 2 --config ui.merge=internal:other --tool=false
498 # hg merge -r 2 --config ui.merge=internal:other --tool=false
475 merging f
499 merging f
476 merging f failed!
500 merging f failed!
477 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
501 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
478 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
502 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
479 # cat f
503 # cat f
480 revision 1
504 revision 1
481 space
505 space
482 # hg stat
506 # hg stat
483 M f
507 M f
484 ? f.orig
508 ? f.orig
485
509
486 HGMERGE specifies internal:other but is overruled by --tool=false
510 HGMERGE specifies internal:other but is overruled by --tool=false
487
511
488 $ HGMERGE=internal:other ; export HGMERGE
512 $ HGMERGE=internal:other ; export HGMERGE
489 $ domerge -r 2 --tool=false
513 $ domerge -r 2 --tool=false
490 [merge-tools]
514 [merge-tools]
491 false.whatever=
515 false.whatever=
492 true.priority=1
516 true.priority=1
493 true.executable=cat
517 true.executable=cat
494 # hg update -C 1
518 # hg update -C 1
495 # hg merge -r 2 --tool=false
519 # hg merge -r 2 --tool=false
496 merging f
520 merging f
497 merging f failed!
521 merging f failed!
498 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
522 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
499 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
523 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
500 # cat f
524 # cat f
501 revision 1
525 revision 1
502 space
526 space
503 # hg stat
527 # hg stat
504 M f
528 M f
505 ? f.orig
529 ? f.orig
506
530
507 $ unset HGMERGE # make sure HGMERGE doesn't interfere with remaining tests
531 $ unset HGMERGE # make sure HGMERGE doesn't interfere with remaining tests
508
532
509 Default is silent simplemerge:
533 Default is silent simplemerge:
510
534
511 $ domerge -r 3
535 $ domerge -r 3
512 [merge-tools]
536 [merge-tools]
513 false.whatever=
537 false.whatever=
514 true.priority=1
538 true.priority=1
515 true.executable=cat
539 true.executable=cat
516 # hg update -C 1
540 # hg update -C 1
517 # hg merge -r 3
541 # hg merge -r 3
518 merging f
542 merging f
519 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
543 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
520 (branch merge, don't forget to commit)
544 (branch merge, don't forget to commit)
521 # cat f
545 # cat f
522 revision 1
546 revision 1
523 space
547 space
524 revision 3
548 revision 3
525 # hg stat
549 # hg stat
526 M f
550 M f
527
551
528 .premerge=True is same:
552 .premerge=True is same:
529
553
530 $ domerge -r 3 --config merge-tools.true.premerge=True
554 $ domerge -r 3 --config merge-tools.true.premerge=True
531 [merge-tools]
555 [merge-tools]
532 false.whatever=
556 false.whatever=
533 true.priority=1
557 true.priority=1
534 true.executable=cat
558 true.executable=cat
535 # hg update -C 1
559 # hg update -C 1
536 # hg merge -r 3 --config merge-tools.true.premerge=True
560 # hg merge -r 3 --config merge-tools.true.premerge=True
537 merging f
561 merging f
538 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
562 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
539 (branch merge, don't forget to commit)
563 (branch merge, don't forget to commit)
540 # cat f
564 # cat f
541 revision 1
565 revision 1
542 space
566 space
543 revision 3
567 revision 3
544 # hg stat
568 # hg stat
545 M f
569 M f
546
570
547 .premerge=False executes merge-tool:
571 .premerge=False executes merge-tool:
548
572
549 $ domerge -r 3 --config merge-tools.true.premerge=False
573 $ domerge -r 3 --config merge-tools.true.premerge=False
550 [merge-tools]
574 [merge-tools]
551 false.whatever=
575 false.whatever=
552 true.priority=1
576 true.priority=1
553 true.executable=cat
577 true.executable=cat
554 # hg update -C 1
578 # hg update -C 1
555 # hg merge -r 3 --config merge-tools.true.premerge=False
579 # hg merge -r 3 --config merge-tools.true.premerge=False
556 merging f
580 merging f
557 revision 1
581 revision 1
558 space
582 space
559 revision 0
583 revision 0
560 space
584 space
561 revision 0
585 revision 0
562 space
586 space
563 revision 3
587 revision 3
564 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
588 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
565 (branch merge, don't forget to commit)
589 (branch merge, don't forget to commit)
566 # cat f
590 # cat f
567 revision 1
591 revision 1
568 space
592 space
569 # hg stat
593 # hg stat
570 M f
594 M f
571
595
572 Tool execution
596 Tool execution
573
597
574 set tools.args explicit to include $base $local $other $output:
598 set tools.args explicit to include $base $local $other $output:
575
599
576 $ beforemerge
600 $ beforemerge
577 [merge-tools]
601 [merge-tools]
578 false.whatever=
602 false.whatever=
579 true.priority=1
603 true.priority=1
580 true.executable=cat
604 true.executable=cat
581 # hg update -C 1
605 # hg update -C 1
582 $ hg merge -r 2 --config merge-tools.true.executable=head --config merge-tools.true.args='$base $local $other $output' \
606 $ hg merge -r 2 --config merge-tools.true.executable=head --config merge-tools.true.args='$base $local $other $output' \
583 > | sed 's,==> .* <==,==> ... <==,g'
607 > | sed 's,==> .* <==,==> ... <==,g'
584 merging f
608 merging f
585 ==> ... <==
609 ==> ... <==
586 revision 0
610 revision 0
587 space
611 space
588
612
589 ==> ... <==
613 ==> ... <==
590 revision 1
614 revision 1
591 space
615 space
592
616
593 ==> ... <==
617 ==> ... <==
594 revision 2
618 revision 2
595 space
619 space
596
620
597 ==> ... <==
621 ==> ... <==
598 revision 1
622 revision 1
599 space
623 space
600 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
624 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
601 (branch merge, don't forget to commit)
625 (branch merge, don't forget to commit)
602 $ aftermerge
626 $ aftermerge
603 # cat f
627 # cat f
604 revision 1
628 revision 1
605 space
629 space
606 # hg stat
630 # hg stat
607 M f
631 M f
608
632
609 Merge with "echo mergeresult > $local":
633 Merge with "echo mergeresult > $local":
610
634
611 $ beforemerge
635 $ beforemerge
612 [merge-tools]
636 [merge-tools]
613 false.whatever=
637 false.whatever=
614 true.priority=1
638 true.priority=1
615 true.executable=cat
639 true.executable=cat
616 # hg update -C 1
640 # hg update -C 1
617 $ hg merge -r 2 --config merge-tools.true.executable=echo --config merge-tools.true.args='mergeresult > $local'
641 $ hg merge -r 2 --config merge-tools.true.executable=echo --config merge-tools.true.args='mergeresult > $local'
618 merging f
642 merging f
619 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
643 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
620 (branch merge, don't forget to commit)
644 (branch merge, don't forget to commit)
621 $ aftermerge
645 $ aftermerge
622 # cat f
646 # cat f
623 mergeresult
647 mergeresult
624 # hg stat
648 # hg stat
625 M f
649 M f
626
650
627 - and $local is the file f:
651 - and $local is the file f:
628
652
629 $ beforemerge
653 $ beforemerge
630 [merge-tools]
654 [merge-tools]
631 false.whatever=
655 false.whatever=
632 true.priority=1
656 true.priority=1
633 true.executable=cat
657 true.executable=cat
634 # hg update -C 1
658 # hg update -C 1
635 $ hg merge -r 2 --config merge-tools.true.executable=echo --config merge-tools.true.args='mergeresult > f'
659 $ hg merge -r 2 --config merge-tools.true.executable=echo --config merge-tools.true.args='mergeresult > f'
636 merging f
660 merging f
637 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
661 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
638 (branch merge, don't forget to commit)
662 (branch merge, don't forget to commit)
639 $ aftermerge
663 $ aftermerge
640 # cat f
664 # cat f
641 mergeresult
665 mergeresult
642 # hg stat
666 # hg stat
643 M f
667 M f
644
668
645 Merge with "echo mergeresult > $output" - the variable is a bit magic:
669 Merge with "echo mergeresult > $output" - the variable is a bit magic:
646
670
647 $ beforemerge
671 $ beforemerge
648 [merge-tools]
672 [merge-tools]
649 false.whatever=
673 false.whatever=
650 true.priority=1
674 true.priority=1
651 true.executable=cat
675 true.executable=cat
652 # hg update -C 1
676 # hg update -C 1
653 $ hg merge -r 2 --config merge-tools.true.executable=echo --config merge-tools.true.args='mergeresult > $output'
677 $ hg merge -r 2 --config merge-tools.true.executable=echo --config merge-tools.true.args='mergeresult > $output'
654 merging f
678 merging f
655 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
679 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
656 (branch merge, don't forget to commit)
680 (branch merge, don't forget to commit)
657 $ aftermerge
681 $ aftermerge
658 # cat f
682 # cat f
659 mergeresult
683 mergeresult
660 # hg stat
684 # hg stat
661 M f
685 M f
662
686
663 Merge using tool with a path that must be quoted:
687 Merge using tool with a path that must be quoted:
664
688
665 $ beforemerge
689 $ beforemerge
666 [merge-tools]
690 [merge-tools]
667 false.whatever=
691 false.whatever=
668 true.priority=1
692 true.priority=1
669 true.executable=cat
693 true.executable=cat
670 # hg update -C 1
694 # hg update -C 1
671 $ cat <<EOF > 'my merge tool'
695 $ cat <<EOF > 'my merge tool'
672 > #!/bin/sh
696 > #!/bin/sh
673 > cat "\$1" "\$2" "\$3" > "\$4"
697 > cat "\$1" "\$2" "\$3" > "\$4"
674 > EOF
698 > EOF
675 $ chmod +x 'my merge tool'
699 $ chmod +x 'my merge tool'
676 $ hg merge -r 2 --config merge-tools.true.executable='./my merge tool' --config merge-tools.true.args='$base $local $other $output'
700 $ hg merge -r 2 --config merge-tools.true.executable='./my merge tool' --config merge-tools.true.args='$base $local $other $output'
677 merging f
701 merging f
678 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
702 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
679 (branch merge, don't forget to commit)
703 (branch merge, don't forget to commit)
680 $ rm -f 'my merge tool'
704 $ rm -f 'my merge tool'
681 $ aftermerge
705 $ aftermerge
682 # cat f
706 # cat f
683 revision 0
707 revision 0
684 space
708 space
685 revision 1
709 revision 1
686 space
710 space
687 revision 2
711 revision 2
688 space
712 space
689 # hg stat
713 # hg stat
690 M f
714 M f
691
715
692 Merge post-processing
716 Merge post-processing
693
717
694 cat is a bad merge-tool and doesn't change:
718 cat is a bad merge-tool and doesn't change:
695
719
696 $ domerge -y -r 2 --config merge-tools.true.checkchanged=1
720 $ domerge -y -r 2 --config merge-tools.true.checkchanged=1
697 [merge-tools]
721 [merge-tools]
698 false.whatever=
722 false.whatever=
699 true.priority=1
723 true.priority=1
700 true.executable=cat
724 true.executable=cat
701 # hg update -C 1
725 # hg update -C 1
702 # hg merge -y -r 2 --config merge-tools.true.checkchanged=1
726 # hg merge -y -r 2 --config merge-tools.true.checkchanged=1
703 merging f
727 merging f
704 revision 1
728 revision 1
705 space
729 space
706 revision 0
730 revision 0
707 space
731 space
708 revision 2
732 revision 2
709 space
733 space
710 output file f appears unchanged
734 output file f appears unchanged
711 was merge successful (yn)? n
735 was merge successful (yn)? n
712 merging f failed!
736 merging f failed!
713 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
737 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
714 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
738 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
715 # cat f
739 # cat f
716 revision 1
740 revision 1
717 space
741 space
718 # hg stat
742 # hg stat
719 M f
743 M f
720 ? f.orig
744 ? f.orig
General Comments 0
You need to be logged in to leave comments. Login now