##// END OF EJS Templates
ui.prompt: Show prompt and selection in non-interactive mode...
Mads Kiilerich -
r8940:01ada7b1 default
parent child Browse files
Show More
@@ -1,346 +1,346 b''
1 # ui.py - user interface bits for mercurial
1 # ui.py - user interface bits for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 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, incorporated herein by reference.
6 # GNU General Public License version 2, incorporated herein by reference.
7
7
8 from i18n import _
8 from i18n import _
9 import errno, getpass, os, socket, sys, tempfile, traceback
9 import errno, getpass, os, socket, sys, tempfile, traceback
10 import config, util, error
10 import config, util, error
11
11
12 _booleans = {'1': True, 'yes': True, 'true': True, 'on': True,
12 _booleans = {'1': True, 'yes': True, 'true': True, 'on': True,
13 '0': False, 'no': False, 'false': False, 'off': False}
13 '0': False, 'no': False, 'false': False, 'off': False}
14
14
15 class ui(object):
15 class ui(object):
16 def __init__(self, src=None):
16 def __init__(self, src=None):
17 self._buffers = []
17 self._buffers = []
18 self.quiet = self.verbose = self.debugflag = self._traceback = False
18 self.quiet = self.verbose = self.debugflag = self._traceback = False
19 self._reportuntrusted = True
19 self._reportuntrusted = True
20 self._ocfg = config.config() # overlay
20 self._ocfg = config.config() # overlay
21 self._tcfg = config.config() # trusted
21 self._tcfg = config.config() # trusted
22 self._ucfg = config.config() # untrusted
22 self._ucfg = config.config() # untrusted
23 self._trustusers = set()
23 self._trustusers = set()
24 self._trustgroups = set()
24 self._trustgroups = set()
25
25
26 if src:
26 if src:
27 self._tcfg = src._tcfg.copy()
27 self._tcfg = src._tcfg.copy()
28 self._ucfg = src._ucfg.copy()
28 self._ucfg = src._ucfg.copy()
29 self._ocfg = src._ocfg.copy()
29 self._ocfg = src._ocfg.copy()
30 self._trustusers = src._trustusers.copy()
30 self._trustusers = src._trustusers.copy()
31 self._trustgroups = src._trustgroups.copy()
31 self._trustgroups = src._trustgroups.copy()
32 self.fixconfig()
32 self.fixconfig()
33 else:
33 else:
34 # we always trust global config files
34 # we always trust global config files
35 for f in util.rcpath():
35 for f in util.rcpath():
36 self.readconfig(f, trust=True)
36 self.readconfig(f, trust=True)
37
37
38 def copy(self):
38 def copy(self):
39 return self.__class__(self)
39 return self.__class__(self)
40
40
41 def _is_trusted(self, fp, f):
41 def _is_trusted(self, fp, f):
42 st = util.fstat(fp)
42 st = util.fstat(fp)
43 if util.isowner(st):
43 if util.isowner(st):
44 return True
44 return True
45
45
46 tusers, tgroups = self._trustusers, self._trustgroups
46 tusers, tgroups = self._trustusers, self._trustgroups
47 if '*' in tusers or '*' in tgroups:
47 if '*' in tusers or '*' in tgroups:
48 return True
48 return True
49
49
50 user = util.username(st.st_uid)
50 user = util.username(st.st_uid)
51 group = util.groupname(st.st_gid)
51 group = util.groupname(st.st_gid)
52 if user in tusers or group in tgroups or user == util.username():
52 if user in tusers or group in tgroups or user == util.username():
53 return True
53 return True
54
54
55 if self._reportuntrusted:
55 if self._reportuntrusted:
56 self.warn(_('Not trusting file %s from untrusted '
56 self.warn(_('Not trusting file %s from untrusted '
57 'user %s, group %s\n') % (f, user, group))
57 'user %s, group %s\n') % (f, user, group))
58 return False
58 return False
59
59
60 def readconfig(self, filename, root=None, trust=False,
60 def readconfig(self, filename, root=None, trust=False,
61 sections=None, remap=None):
61 sections=None, remap=None):
62 try:
62 try:
63 fp = open(filename)
63 fp = open(filename)
64 except IOError:
64 except IOError:
65 if not sections: # ignore unless we were looking for something
65 if not sections: # ignore unless we were looking for something
66 return
66 return
67 raise
67 raise
68
68
69 cfg = config.config()
69 cfg = config.config()
70 trusted = sections or trust or self._is_trusted(fp, filename)
70 trusted = sections or trust or self._is_trusted(fp, filename)
71
71
72 try:
72 try:
73 cfg.read(filename, fp, sections=sections, remap=remap)
73 cfg.read(filename, fp, sections=sections, remap=remap)
74 except error.ConfigError, inst:
74 except error.ConfigError, inst:
75 if trusted:
75 if trusted:
76 raise
76 raise
77 self.warn(_("Ignored: %s\n") % str(inst))
77 self.warn(_("Ignored: %s\n") % str(inst))
78
78
79 if trusted:
79 if trusted:
80 self._tcfg.update(cfg)
80 self._tcfg.update(cfg)
81 self._tcfg.update(self._ocfg)
81 self._tcfg.update(self._ocfg)
82 self._ucfg.update(cfg)
82 self._ucfg.update(cfg)
83 self._ucfg.update(self._ocfg)
83 self._ucfg.update(self._ocfg)
84
84
85 if root is None:
85 if root is None:
86 root = os.path.expanduser('~')
86 root = os.path.expanduser('~')
87 self.fixconfig(root=root)
87 self.fixconfig(root=root)
88
88
89 def fixconfig(self, root=None):
89 def fixconfig(self, root=None):
90 # translate paths relative to root (or home) into absolute paths
90 # translate paths relative to root (or home) into absolute paths
91 root = root or os.getcwd()
91 root = root or os.getcwd()
92 for c in self._tcfg, self._ucfg, self._ocfg:
92 for c in self._tcfg, self._ucfg, self._ocfg:
93 for n, p in c.items('paths'):
93 for n, p in c.items('paths'):
94 if p and "://" not in p and not os.path.isabs(p):
94 if p and "://" not in p and not os.path.isabs(p):
95 c.set("paths", n, os.path.normpath(os.path.join(root, p)))
95 c.set("paths", n, os.path.normpath(os.path.join(root, p)))
96
96
97 # update ui options
97 # update ui options
98 self.debugflag = self.configbool('ui', 'debug')
98 self.debugflag = self.configbool('ui', 'debug')
99 self.verbose = self.debugflag or self.configbool('ui', 'verbose')
99 self.verbose = self.debugflag or self.configbool('ui', 'verbose')
100 self.quiet = not self.debugflag and self.configbool('ui', 'quiet')
100 self.quiet = not self.debugflag and self.configbool('ui', 'quiet')
101 if self.verbose and self.quiet:
101 if self.verbose and self.quiet:
102 self.quiet = self.verbose = False
102 self.quiet = self.verbose = False
103 self._reportuntrusted = self.configbool("ui", "report_untrusted", True)
103 self._reportuntrusted = self.configbool("ui", "report_untrusted", True)
104 self._traceback = self.configbool('ui', 'traceback', False)
104 self._traceback = self.configbool('ui', 'traceback', False)
105
105
106 # update trust information
106 # update trust information
107 self._trustusers.update(self.configlist('trusted', 'users'))
107 self._trustusers.update(self.configlist('trusted', 'users'))
108 self._trustgroups.update(self.configlist('trusted', 'groups'))
108 self._trustgroups.update(self.configlist('trusted', 'groups'))
109
109
110 def setconfig(self, section, name, value):
110 def setconfig(self, section, name, value):
111 for cfg in (self._ocfg, self._tcfg, self._ucfg):
111 for cfg in (self._ocfg, self._tcfg, self._ucfg):
112 cfg.set(section, name, value)
112 cfg.set(section, name, value)
113 self.fixconfig()
113 self.fixconfig()
114
114
115 def _data(self, untrusted):
115 def _data(self, untrusted):
116 return untrusted and self._ucfg or self._tcfg
116 return untrusted and self._ucfg or self._tcfg
117
117
118 def configsource(self, section, name, untrusted=False):
118 def configsource(self, section, name, untrusted=False):
119 return self._data(untrusted).source(section, name) or 'none'
119 return self._data(untrusted).source(section, name) or 'none'
120
120
121 def config(self, section, name, default=None, untrusted=False):
121 def config(self, section, name, default=None, untrusted=False):
122 value = self._data(untrusted).get(section, name, default)
122 value = self._data(untrusted).get(section, name, default)
123 if self.debugflag and not untrusted and self._reportuntrusted:
123 if self.debugflag and not untrusted and self._reportuntrusted:
124 uvalue = self._ucfg.get(section, name)
124 uvalue = self._ucfg.get(section, name)
125 if uvalue is not None and uvalue != value:
125 if uvalue is not None and uvalue != value:
126 self.debug(_("ignoring untrusted configuration option "
126 self.debug(_("ignoring untrusted configuration option "
127 "%s.%s = %s\n") % (section, name, uvalue))
127 "%s.%s = %s\n") % (section, name, uvalue))
128 return value
128 return value
129
129
130 def configbool(self, section, name, default=False, untrusted=False):
130 def configbool(self, section, name, default=False, untrusted=False):
131 v = self.config(section, name, None, untrusted)
131 v = self.config(section, name, None, untrusted)
132 if v is None:
132 if v is None:
133 return default
133 return default
134 if v.lower() not in _booleans:
134 if v.lower() not in _booleans:
135 raise error.ConfigError(_("%s.%s not a boolean ('%s')")
135 raise error.ConfigError(_("%s.%s not a boolean ('%s')")
136 % (section, name, v))
136 % (section, name, v))
137 return _booleans[v.lower()]
137 return _booleans[v.lower()]
138
138
139 def configlist(self, section, name, default=None, untrusted=False):
139 def configlist(self, section, name, default=None, untrusted=False):
140 """Return a list of comma/space separated strings"""
140 """Return a list of comma/space separated strings"""
141 result = self.config(section, name, untrusted=untrusted)
141 result = self.config(section, name, untrusted=untrusted)
142 if result is None:
142 if result is None:
143 result = default or []
143 result = default or []
144 if isinstance(result, basestring):
144 if isinstance(result, basestring):
145 result = result.replace(",", " ").split()
145 result = result.replace(",", " ").split()
146 return result
146 return result
147
147
148 def has_section(self, section, untrusted=False):
148 def has_section(self, section, untrusted=False):
149 '''tell whether section exists in config.'''
149 '''tell whether section exists in config.'''
150 return section in self._data(untrusted)
150 return section in self._data(untrusted)
151
151
152 def configitems(self, section, untrusted=False):
152 def configitems(self, section, untrusted=False):
153 items = self._data(untrusted).items(section)
153 items = self._data(untrusted).items(section)
154 if self.debugflag and not untrusted and self._reportuntrusted:
154 if self.debugflag and not untrusted and self._reportuntrusted:
155 for k, v in self._ucfg.items(section):
155 for k, v in self._ucfg.items(section):
156 if self._tcfg.get(section, k) != v:
156 if self._tcfg.get(section, k) != v:
157 self.debug(_("ignoring untrusted configuration option "
157 self.debug(_("ignoring untrusted configuration option "
158 "%s.%s = %s\n") % (section, k, v))
158 "%s.%s = %s\n") % (section, k, v))
159 return items
159 return items
160
160
161 def walkconfig(self, untrusted=False):
161 def walkconfig(self, untrusted=False):
162 cfg = self._data(untrusted)
162 cfg = self._data(untrusted)
163 for section in cfg.sections():
163 for section in cfg.sections():
164 for name, value in self.configitems(section, untrusted):
164 for name, value in self.configitems(section, untrusted):
165 yield section, name, str(value).replace('\n', '\\n')
165 yield section, name, str(value).replace('\n', '\\n')
166
166
167 def username(self):
167 def username(self):
168 """Return default username to be used in commits.
168 """Return default username to be used in commits.
169
169
170 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
170 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
171 and stop searching if one of these is set.
171 and stop searching if one of these is set.
172 If not found and ui.askusername is True, ask the user, else use
172 If not found and ui.askusername is True, ask the user, else use
173 ($LOGNAME or $USER or $LNAME or $USERNAME) + "@full.hostname".
173 ($LOGNAME or $USER or $LNAME or $USERNAME) + "@full.hostname".
174 """
174 """
175 user = os.environ.get("HGUSER")
175 user = os.environ.get("HGUSER")
176 if user is None:
176 if user is None:
177 user = self.config("ui", "username")
177 user = self.config("ui", "username")
178 if user is None:
178 if user is None:
179 user = os.environ.get("EMAIL")
179 user = os.environ.get("EMAIL")
180 if user is None and self.configbool("ui", "askusername"):
180 if user is None and self.configbool("ui", "askusername"):
181 user = self.prompt(_("enter a commit username:"), default=None)
181 user = self.prompt(_("enter a commit username:"), default=None)
182 if user is None:
182 if user is None:
183 try:
183 try:
184 user = '%s@%s' % (util.getuser(), socket.getfqdn())
184 user = '%s@%s' % (util.getuser(), socket.getfqdn())
185 self.warn(_("No username found, using '%s' instead\n") % user)
185 self.warn(_("No username found, using '%s' instead\n") % user)
186 except KeyError:
186 except KeyError:
187 pass
187 pass
188 if not user:
188 if not user:
189 raise util.Abort(_("Please specify a username."))
189 raise util.Abort(_("Please specify a username."))
190 if "\n" in user:
190 if "\n" in user:
191 raise util.Abort(_("username %s contains a newline\n") % repr(user))
191 raise util.Abort(_("username %s contains a newline\n") % repr(user))
192 return user
192 return user
193
193
194 def shortuser(self, user):
194 def shortuser(self, user):
195 """Return a short representation of a user name or email address."""
195 """Return a short representation of a user name or email address."""
196 if not self.verbose: user = util.shortuser(user)
196 if not self.verbose: user = util.shortuser(user)
197 return user
197 return user
198
198
199 def _path(self, loc):
199 def _path(self, loc):
200 p = self.config('paths', loc)
200 p = self.config('paths', loc)
201 if p and '%%' in p:
201 if p and '%%' in p:
202 self.warn('(deprecated \'%%\' in path %s=%s from %s)\n' %
202 self.warn('(deprecated \'%%\' in path %s=%s from %s)\n' %
203 (loc, p, self.configsource('paths', loc)))
203 (loc, p, self.configsource('paths', loc)))
204 p = p.replace('%%', '%')
204 p = p.replace('%%', '%')
205 return p
205 return p
206
206
207 def expandpath(self, loc, default=None):
207 def expandpath(self, loc, default=None):
208 """Return repository location relative to cwd or from [paths]"""
208 """Return repository location relative to cwd or from [paths]"""
209 if "://" in loc or os.path.isdir(os.path.join(loc, '.hg')):
209 if "://" in loc or os.path.isdir(os.path.join(loc, '.hg')):
210 return loc
210 return loc
211
211
212 path = self._path(loc)
212 path = self._path(loc)
213 if not path and default is not None:
213 if not path and default is not None:
214 path = self._path(default)
214 path = self._path(default)
215 return path or loc
215 return path or loc
216
216
217 def pushbuffer(self):
217 def pushbuffer(self):
218 self._buffers.append([])
218 self._buffers.append([])
219
219
220 def popbuffer(self):
220 def popbuffer(self):
221 return "".join(self._buffers.pop())
221 return "".join(self._buffers.pop())
222
222
223 def write(self, *args):
223 def write(self, *args):
224 if self._buffers:
224 if self._buffers:
225 self._buffers[-1].extend([str(a) for a in args])
225 self._buffers[-1].extend([str(a) for a in args])
226 else:
226 else:
227 for a in args:
227 for a in args:
228 sys.stdout.write(str(a))
228 sys.stdout.write(str(a))
229
229
230 def write_err(self, *args):
230 def write_err(self, *args):
231 try:
231 try:
232 if not sys.stdout.closed: sys.stdout.flush()
232 if not sys.stdout.closed: sys.stdout.flush()
233 for a in args:
233 for a in args:
234 sys.stderr.write(str(a))
234 sys.stderr.write(str(a))
235 # stderr may be buffered under win32 when redirected to files,
235 # stderr may be buffered under win32 when redirected to files,
236 # including stdout.
236 # including stdout.
237 if not sys.stderr.closed: sys.stderr.flush()
237 if not sys.stderr.closed: sys.stderr.flush()
238 except IOError, inst:
238 except IOError, inst:
239 if inst.errno != errno.EPIPE:
239 if inst.errno != errno.EPIPE:
240 raise
240 raise
241
241
242 def flush(self):
242 def flush(self):
243 try: sys.stdout.flush()
243 try: sys.stdout.flush()
244 except: pass
244 except: pass
245 try: sys.stderr.flush()
245 try: sys.stderr.flush()
246 except: pass
246 except: pass
247
247
248 def interactive(self):
248 def interactive(self):
249 i = self.configbool("ui", "interactive", None)
249 i = self.configbool("ui", "interactive", None)
250 if i is None:
250 if i is None:
251 return sys.stdin.isatty()
251 return sys.stdin.isatty()
252 return i
252 return i
253
253
254 def _readline(self, prompt=''):
254 def _readline(self, prompt=''):
255 if sys.stdin.isatty():
255 if sys.stdin.isatty():
256 try:
256 try:
257 # magically add command line editing support, where
257 # magically add command line editing support, where
258 # available
258 # available
259 import readline
259 import readline
260 # force demandimport to really load the module
260 # force demandimport to really load the module
261 readline.read_history_file
261 readline.read_history_file
262 # windows sometimes raises something other than ImportError
262 # windows sometimes raises something other than ImportError
263 except Exception:
263 except Exception:
264 pass
264 pass
265 line = raw_input(prompt)
265 line = raw_input(prompt)
266 # When stdin is in binary mode on Windows, it can cause
266 # When stdin is in binary mode on Windows, it can cause
267 # raw_input() to emit an extra trailing carriage return
267 # raw_input() to emit an extra trailing carriage return
268 if os.linesep == '\r\n' and line and line[-1] == '\r':
268 if os.linesep == '\r\n' and line and line[-1] == '\r':
269 line = line[:-1]
269 line = line[:-1]
270 return line
270 return line
271
271
272 def prompt(self, msg, choices=None, default="y"):
272 def prompt(self, msg, choices=None, default="y"):
273 """Prompt user with msg, read response, and ensure it matches
273 """Prompt user with msg, read response, and ensure it matches
274 one of the provided choices. choices is a sequence of acceptable
274 one of the provided choices. choices is a sequence of acceptable
275 responses with the format: ('&None', 'E&xec', 'Sym&link')
275 responses with the format: ('&None', 'E&xec', 'Sym&link')
276 No sequence implies no response checking. Responses are case
276 No sequence implies no response checking. Responses are case
277 insensitive. If ui is not interactive, the default is returned.
277 insensitive. If ui is not interactive, the default is returned.
278 """
278 """
279 if not self.interactive():
279 if not self.interactive():
280 self.note(msg, ' ', default, "\n")
280 self.write(msg, ' ', default, "\n")
281 return default
281 return default
282 while True:
282 while True:
283 try:
283 try:
284 r = self._readline(msg + ' ')
284 r = self._readline(msg + ' ')
285 if not r:
285 if not r:
286 return default
286 return default
287 if not choices:
287 if not choices:
288 return r
288 return r
289 resps = [s[s.index('&')+1].lower() for s in choices]
289 resps = [s[s.index('&')+1].lower() for s in choices]
290 if r.lower() in resps:
290 if r.lower() in resps:
291 return r.lower()
291 return r.lower()
292 else:
292 else:
293 self.write(_("unrecognized response\n"))
293 self.write(_("unrecognized response\n"))
294 except EOFError:
294 except EOFError:
295 raise util.Abort(_('response expected'))
295 raise util.Abort(_('response expected'))
296
296
297 def getpass(self, prompt=None, default=None):
297 def getpass(self, prompt=None, default=None):
298 if not self.interactive(): return default
298 if not self.interactive(): return default
299 try:
299 try:
300 return getpass.getpass(prompt or _('password: '))
300 return getpass.getpass(prompt or _('password: '))
301 except EOFError:
301 except EOFError:
302 raise util.Abort(_('response expected'))
302 raise util.Abort(_('response expected'))
303 def status(self, *msg):
303 def status(self, *msg):
304 if not self.quiet: self.write(*msg)
304 if not self.quiet: self.write(*msg)
305 def warn(self, *msg):
305 def warn(self, *msg):
306 self.write_err(*msg)
306 self.write_err(*msg)
307 def note(self, *msg):
307 def note(self, *msg):
308 if self.verbose: self.write(*msg)
308 if self.verbose: self.write(*msg)
309 def debug(self, *msg):
309 def debug(self, *msg):
310 if self.debugflag: self.write(*msg)
310 if self.debugflag: self.write(*msg)
311 def edit(self, text, user):
311 def edit(self, text, user):
312 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt",
312 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt",
313 text=True)
313 text=True)
314 try:
314 try:
315 f = os.fdopen(fd, "w")
315 f = os.fdopen(fd, "w")
316 f.write(text)
316 f.write(text)
317 f.close()
317 f.close()
318
318
319 editor = self.geteditor()
319 editor = self.geteditor()
320
320
321 util.system("%s \"%s\"" % (editor, name),
321 util.system("%s \"%s\"" % (editor, name),
322 environ={'HGUSER': user},
322 environ={'HGUSER': user},
323 onerr=util.Abort, errprefix=_("edit failed"))
323 onerr=util.Abort, errprefix=_("edit failed"))
324
324
325 f = open(name)
325 f = open(name)
326 t = f.read()
326 t = f.read()
327 f.close()
327 f.close()
328 finally:
328 finally:
329 os.unlink(name)
329 os.unlink(name)
330
330
331 return t
331 return t
332
332
333 def traceback(self):
333 def traceback(self):
334 '''print exception traceback if traceback printing enabled.
334 '''print exception traceback if traceback printing enabled.
335 only to call in exception handler. returns true if traceback
335 only to call in exception handler. returns true if traceback
336 printed.'''
336 printed.'''
337 if self._traceback:
337 if self._traceback:
338 traceback.print_exc()
338 traceback.print_exc()
339 return self._traceback
339 return self._traceback
340
340
341 def geteditor(self):
341 def geteditor(self):
342 '''return editor to use'''
342 '''return editor to use'''
343 return (os.environ.get("HGEDITOR") or
343 return (os.environ.get("HGEDITOR") or
344 self.config("ui", "editor") or
344 self.config("ui", "editor") or
345 os.environ.get("VISUAL") or
345 os.environ.get("VISUAL") or
346 os.environ.get("EDITOR", "vi"))
346 os.environ.get("EDITOR", "vi"))
@@ -1,65 +1,69 b''
1 adding file1
1 adding file1
2 adding file2
2 adding file2
3 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
3 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
4 created new head
4 created new head
5
5
6 # non-interactive merge
6 # non-interactive merge
7 local changed file1 which remote deleted
8 use (c)hanged version or (d)elete? c
9 remote changed file2 which local deleted
10 use (c)hanged version or leave (d)eleted? c
7 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
11 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
8 (branch merge, don't forget to commit)
12 (branch merge, don't forget to commit)
9 status:
13 status:
10 M file2
14 M file2
11 C file1
15 C file1
12 file1:
16 file1:
13 1
17 1
14 changed
18 changed
15 file2:
19 file2:
16 2
20 2
17 changed
21 changed
18
22
19 # interactive merge
23 # interactive merge
20 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
24 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
21 local changed file1 which remote deleted
25 local changed file1 which remote deleted
22 use (c)hanged version or (d)elete? remote changed file2 which local deleted
26 use (c)hanged version or (d)elete? remote changed file2 which local deleted
23 use (c)hanged version or leave (d)eleted? 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
27 use (c)hanged version or leave (d)eleted? 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
24 (branch merge, don't forget to commit)
28 (branch merge, don't forget to commit)
25 status:
29 status:
26 file2: No such file or directory
30 file2: No such file or directory
27 C file1
31 C file1
28 file1:
32 file1:
29 1
33 1
30 changed
34 changed
31 file2 does not exist
35 file2 does not exist
32
36
33 # interactive merge with bad input
37 # interactive merge with bad input
34 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
38 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
35 local changed file1 which remote deleted
39 local changed file1 which remote deleted
36 use (c)hanged version or (d)elete? unrecognized response
40 use (c)hanged version or (d)elete? unrecognized response
37 local changed file1 which remote deleted
41 local changed file1 which remote deleted
38 use (c)hanged version or (d)elete? unrecognized response
42 use (c)hanged version or (d)elete? unrecognized response
39 local changed file1 which remote deleted
43 local changed file1 which remote deleted
40 use (c)hanged version or (d)elete? remote changed file2 which local deleted
44 use (c)hanged version or (d)elete? remote changed file2 which local deleted
41 use (c)hanged version or leave (d)eleted? unrecognized response
45 use (c)hanged version or leave (d)eleted? unrecognized response
42 remote changed file2 which local deleted
46 remote changed file2 which local deleted
43 use (c)hanged version or leave (d)eleted? 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
47 use (c)hanged version or leave (d)eleted? 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
44 (branch merge, don't forget to commit)
48 (branch merge, don't forget to commit)
45 status:
49 status:
46 M file2
50 M file2
47 R file1
51 R file1
48 file1 does not exist
52 file1 does not exist
49 file2:
53 file2:
50 2
54 2
51 changed
55 changed
52
56
53 # interactive merge with not enough input
57 # interactive merge with not enough input
54 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
58 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
55 local changed file1 which remote deleted
59 local changed file1 which remote deleted
56 use (c)hanged version or (d)elete? remote changed file2 which local deleted
60 use (c)hanged version or (d)elete? remote changed file2 which local deleted
57 use (c)hanged version or leave (d)eleted? abort: response expected
61 use (c)hanged version or leave (d)eleted? abort: response expected
58 failed
62 failed
59 status:
63 status:
60 file2: No such file or directory
64 file2: No such file or directory
61 C file1
65 C file1
62 file1:
66 file1:
63 1
67 1
64 changed
68 changed
65 file2 does not exist
69 file2 does not exist
@@ -1,524 +1,528 b''
1 # revision 0
1 # revision 0
2 adding f
2 adding f
3 # revision 1
3 # revision 1
4 # revision 2
4 # revision 2
5 created new head
5 created new head
6 # revision 3 - simple to merge
6 # revision 3 - simple to merge
7 created new head
7 created new head
8
8
9
9
10 Tool selection
10 Tool selection
11
11
12 # default is internal merge:
12 # default is internal merge:
13 [merge-tools]
13 [merge-tools]
14 # hg update -C 1
14 # hg update -C 1
15 # hg merge -r 2
15 # hg merge -r 2
16 merging f
16 merging f
17 warning: conflicts during merge.
17 warning: conflicts during merge.
18 merging f failed!
18 merging f failed!
19 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
19 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
20 use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
20 use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
21 # cat f
21 # cat f
22 <<<<<<< local
22 <<<<<<< local
23 revision 1
23 revision 1
24 =======
24 =======
25 revision 2
25 revision 2
26 >>>>>>> other
26 >>>>>>> other
27 space
27 space
28 # hg stat
28 # hg stat
29 M f
29 M f
30 ? f.orig
30 ? f.orig
31
31
32 # simplest hgrc using false for merge:
32 # simplest hgrc using false for merge:
33 [merge-tools]
33 [merge-tools]
34 false.whatever=
34 false.whatever=
35 # hg update -C 1
35 # hg update -C 1
36 # hg merge -r 2
36 # hg merge -r 2
37 merging f
37 merging f
38 merging f failed!
38 merging f failed!
39 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
39 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
40 use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
40 use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
41 # cat f
41 # cat f
42 revision 1
42 revision 1
43 space
43 space
44 # hg stat
44 # hg stat
45 M f
45 M f
46 ? f.orig
46 ? f.orig
47
47
48 # true with higher .priority gets precedence:
48 # true with higher .priority gets precedence:
49 [merge-tools]
49 [merge-tools]
50 false.whatever=
50 false.whatever=
51 true.priority=1
51 true.priority=1
52 # hg update -C 1
52 # hg update -C 1
53 # hg merge -r 2
53 # hg merge -r 2
54 merging f
54 merging f
55 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
55 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
56 (branch merge, don't forget to commit)
56 (branch merge, don't forget to commit)
57 # cat f
57 # cat f
58 revision 1
58 revision 1
59 space
59 space
60 # hg stat
60 # hg stat
61 M f
61 M f
62
62
63 # unless lowered on command line:
63 # unless lowered on command line:
64 [merge-tools]
64 [merge-tools]
65 false.whatever=
65 false.whatever=
66 true.priority=1
66 true.priority=1
67 # hg update -C 1
67 # hg update -C 1
68 # hg merge -r 2 --config merge-tools.true.priority=-7
68 # hg merge -r 2 --config merge-tools.true.priority=-7
69 merging f
69 merging f
70 merging f failed!
70 merging f failed!
71 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
71 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
72 use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
72 use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
73 # cat f
73 # cat f
74 revision 1
74 revision 1
75 space
75 space
76 # hg stat
76 # hg stat
77 M f
77 M f
78 ? f.orig
78 ? f.orig
79
79
80 # or false set higher on command line:
80 # or false set higher on command line:
81 [merge-tools]
81 [merge-tools]
82 false.whatever=
82 false.whatever=
83 true.priority=1
83 true.priority=1
84 # hg update -C 1
84 # hg update -C 1
85 # hg merge -r 2 --config merge-tools.false.priority=117
85 # hg merge -r 2 --config merge-tools.false.priority=117
86 merging f
86 merging f
87 merging f failed!
87 merging f failed!
88 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
88 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
89 use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
89 use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
90 # cat f
90 # cat f
91 revision 1
91 revision 1
92 space
92 space
93 # hg stat
93 # hg stat
94 M f
94 M f
95 ? f.orig
95 ? f.orig
96
96
97 # or true.executable not found in PATH:
97 # or true.executable not found in PATH:
98 [merge-tools]
98 [merge-tools]
99 false.whatever=
99 false.whatever=
100 true.priority=1
100 true.priority=1
101 # hg update -C 1
101 # hg update -C 1
102 # hg merge -r 2 --config merge-tools.true.executable=nonexistingmergetool
102 # hg merge -r 2 --config merge-tools.true.executable=nonexistingmergetool
103 merging f
103 merging f
104 merging f failed!
104 merging f failed!
105 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
105 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
106 use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
106 use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
107 # cat f
107 # cat f
108 revision 1
108 revision 1
109 space
109 space
110 # hg stat
110 # hg stat
111 M f
111 M f
112 ? f.orig
112 ? f.orig
113
113
114 # or true.executable with bogus path:
114 # or true.executable with bogus path:
115 [merge-tools]
115 [merge-tools]
116 false.whatever=
116 false.whatever=
117 true.priority=1
117 true.priority=1
118 # hg update -C 1
118 # hg update -C 1
119 # hg merge -r 2 --config merge-tools.true.executable=/bin/nonexistingmergetool
119 # hg merge -r 2 --config merge-tools.true.executable=/bin/nonexistingmergetool
120 merging f
120 merging f
121 merging f failed!
121 merging f failed!
122 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
122 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
123 use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
123 use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
124 # cat f
124 # cat f
125 revision 1
125 revision 1
126 space
126 space
127 # hg stat
127 # hg stat
128 M f
128 M f
129 ? f.orig
129 ? f.orig
130
130
131 # but true.executable set to cat found in PATH works:
131 # but true.executable set to cat found in PATH works:
132 [merge-tools]
132 [merge-tools]
133 false.whatever=
133 false.whatever=
134 true.priority=1
134 true.priority=1
135 true.executable=cat
135 true.executable=cat
136 # hg update -C 1
136 # hg update -C 1
137 # hg merge -r 2
137 # hg merge -r 2
138 revision 1
138 revision 1
139 space
139 space
140 revision 0
140 revision 0
141 space
141 space
142 revision 2
142 revision 2
143 space
143 space
144 merging f
144 merging f
145 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
145 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
146 (branch merge, don't forget to commit)
146 (branch merge, don't forget to commit)
147 # cat f
147 # cat f
148 revision 1
148 revision 1
149 space
149 space
150 # hg stat
150 # hg stat
151 M f
151 M f
152
152
153 # and true.executable set to cat with path works:
153 # and true.executable set to cat with path works:
154 [merge-tools]
154 [merge-tools]
155 false.whatever=
155 false.whatever=
156 true.priority=1
156 true.priority=1
157 true.executable=cat
157 true.executable=cat
158 # hg update -C 1
158 # hg update -C 1
159 # hg merge -r 2 --config merge-tools.true.executable=cat
159 # hg merge -r 2 --config merge-tools.true.executable=cat
160 revision 1
160 revision 1
161 space
161 space
162 revision 0
162 revision 0
163 space
163 space
164 revision 2
164 revision 2
165 space
165 space
166 merging f
166 merging f
167 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
167 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
168 (branch merge, don't forget to commit)
168 (branch merge, don't forget to commit)
169 # cat f
169 # cat f
170 revision 1
170 revision 1
171 space
171 space
172 # hg stat
172 # hg stat
173 M f
173 M f
174
174
175
175
176 Tool selection and merge-patterns
176 Tool selection and merge-patterns
177
177
178 # merge-patterns specifies new tool false:
178 # merge-patterns specifies new tool false:
179 [merge-tools]
179 [merge-tools]
180 false.whatever=
180 false.whatever=
181 true.priority=1
181 true.priority=1
182 true.executable=cat
182 true.executable=cat
183 # hg update -C 1
183 # hg update -C 1
184 # hg merge -r 2 --config merge-patterns.f=false
184 # hg merge -r 2 --config merge-patterns.f=false
185 merging f
185 merging f
186 merging f failed!
186 merging f failed!
187 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
187 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
188 use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
188 use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
189 # cat f
189 # cat f
190 revision 1
190 revision 1
191 space
191 space
192 # hg stat
192 # hg stat
193 M f
193 M f
194 ? f.orig
194 ? f.orig
195
195
196 # merge-patterns specifies executable not found in PATH and gets warning:
196 # merge-patterns specifies executable not found in PATH and gets warning:
197 [merge-tools]
197 [merge-tools]
198 false.whatever=
198 false.whatever=
199 true.priority=1
199 true.priority=1
200 true.executable=cat
200 true.executable=cat
201 # hg update -C 1
201 # hg update -C 1
202 # hg merge -r 2 --config merge-patterns.f=true --config merge-tools.true.executable=nonexistingmergetool
202 # hg merge -r 2 --config merge-patterns.f=true --config merge-tools.true.executable=nonexistingmergetool
203 couldn't find merge tool true specified for f
203 couldn't find merge tool true specified for f
204 merging f
204 merging f
205 merging f failed!
205 merging f failed!
206 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
206 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
207 use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
207 use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
208 # cat f
208 # cat f
209 revision 1
209 revision 1
210 space
210 space
211 # hg stat
211 # hg stat
212 M f
212 M f
213 ? f.orig
213 ? f.orig
214
214
215 # merge-patterns specifies executable with bogus path and gets warning:
215 # merge-patterns specifies executable with bogus path and gets warning:
216 [merge-tools]
216 [merge-tools]
217 false.whatever=
217 false.whatever=
218 true.priority=1
218 true.priority=1
219 true.executable=cat
219 true.executable=cat
220 # hg update -C 1
220 # hg update -C 1
221 # hg merge -r 2 --config merge-patterns.f=true --config merge-tools.true.executable=/bin/nonexistingmergetool
221 # hg merge -r 2 --config merge-patterns.f=true --config merge-tools.true.executable=/bin/nonexistingmergetool
222 couldn't find merge tool true specified for f
222 couldn't find merge tool true specified for f
223 merging f
223 merging f
224 merging f failed!
224 merging f failed!
225 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
225 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
226 use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
226 use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
227 # cat f
227 # cat f
228 revision 1
228 revision 1
229 space
229 space
230 # hg stat
230 # hg stat
231 M f
231 M f
232 ? f.orig
232 ? f.orig
233
233
234
234
235 ui.merge overrules priority
235 ui.merge overrules priority
236
236
237 # ui.merge specifies false:
237 # ui.merge specifies false:
238 [merge-tools]
238 [merge-tools]
239 false.whatever=
239 false.whatever=
240 true.priority=1
240 true.priority=1
241 true.executable=cat
241 true.executable=cat
242 # hg update -C 1
242 # hg update -C 1
243 # hg merge -r 2 --config ui.merge=false
243 # hg merge -r 2 --config ui.merge=false
244 merging f
244 merging f
245 merging f failed!
245 merging f failed!
246 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
246 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
247 use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
247 use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
248 # cat f
248 # cat f
249 revision 1
249 revision 1
250 space
250 space
251 # hg stat
251 # hg stat
252 M f
252 M f
253 ? f.orig
253 ? f.orig
254
254
255 # ui.merge specifies internal:fail:
255 # ui.merge specifies internal:fail:
256 [merge-tools]
256 [merge-tools]
257 false.whatever=
257 false.whatever=
258 true.priority=1
258 true.priority=1
259 true.executable=cat
259 true.executable=cat
260 # hg update -C 1
260 # hg update -C 1
261 # hg merge -r 2 --config ui.merge=internal:fail
261 # hg merge -r 2 --config ui.merge=internal:fail
262 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
262 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
263 use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
263 use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
264 # cat f
264 # cat f
265 revision 1
265 revision 1
266 space
266 space
267 # hg stat
267 # hg stat
268 M f
268 M f
269
269
270 # ui.merge specifies internal:local:
270 # ui.merge specifies internal:local:
271 [merge-tools]
271 [merge-tools]
272 false.whatever=
272 false.whatever=
273 true.priority=1
273 true.priority=1
274 true.executable=cat
274 true.executable=cat
275 # hg update -C 1
275 # hg update -C 1
276 # hg merge -r 2 --config ui.merge=internal:local
276 # hg merge -r 2 --config ui.merge=internal:local
277 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
277 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
278 (branch merge, don't forget to commit)
278 (branch merge, don't forget to commit)
279 # cat f
279 # cat f
280 revision 1
280 revision 1
281 space
281 space
282 # hg stat
282 # hg stat
283 M f
283 M f
284
284
285 # ui.merge specifies internal:other:
285 # ui.merge specifies internal:other:
286 [merge-tools]
286 [merge-tools]
287 false.whatever=
287 false.whatever=
288 true.priority=1
288 true.priority=1
289 true.executable=cat
289 true.executable=cat
290 # hg update -C 1
290 # hg update -C 1
291 # hg merge -r 2 --config ui.merge=internal:other
291 # hg merge -r 2 --config ui.merge=internal:other
292 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
292 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
293 (branch merge, don't forget to commit)
293 (branch merge, don't forget to commit)
294 # cat f
294 # cat f
295 revision 2
295 revision 2
296 space
296 space
297 # hg stat
297 # hg stat
298 M f
298 M f
299
299
300 # ui.merge specifies internal:prompt:
300 # ui.merge specifies internal:prompt:
301 [merge-tools]
301 [merge-tools]
302 false.whatever=
302 false.whatever=
303 true.priority=1
303 true.priority=1
304 true.executable=cat
304 true.executable=cat
305 # hg update -C 1
305 # hg update -C 1
306 # hg merge -r 2 --config ui.merge=internal:prompt
306 # hg merge -r 2 --config ui.merge=internal:prompt
307 no tool found to merge f
308 keep (l)ocal or take (o)ther? l
307 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
309 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
308 (branch merge, don't forget to commit)
310 (branch merge, don't forget to commit)
309 # cat f
311 # cat f
310 revision 1
312 revision 1
311 space
313 space
312 # hg stat
314 # hg stat
313 M f
315 M f
314
316
315 # ui.merge specifies internal:dump:
317 # ui.merge specifies internal:dump:
316 [merge-tools]
318 [merge-tools]
317 false.whatever=
319 false.whatever=
318 true.priority=1
320 true.priority=1
319 true.executable=cat
321 true.executable=cat
320 # hg update -C 1
322 # hg update -C 1
321 # hg merge -r 2 --config ui.merge=internal:dump
323 # hg merge -r 2 --config ui.merge=internal:dump
322 merging f
324 merging f
323 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
325 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
324 use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
326 use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
325 # cat f
327 # cat f
326 revision 1
328 revision 1
327 space
329 space
328 # hg stat
330 # hg stat
329 M f
331 M f
330 ? f.base
332 ? f.base
331 ? f.local
333 ? f.local
332 ? f.orig
334 ? f.orig
333 ? f.other
335 ? f.other
334
336
335 f.base:
337 f.base:
336 revision 0
338 revision 0
337 space
339 space
338 f.local:
340 f.local:
339 revision 1
341 revision 1
340 space
342 space
341 f.other:
343 f.other:
342 revision 2
344 revision 2
343 space
345 space
344
346
345 # ui.merge specifies internal:other but is overruled by pattern for false:
347 # ui.merge specifies internal:other but is overruled by pattern for false:
346 [merge-tools]
348 [merge-tools]
347 false.whatever=
349 false.whatever=
348 true.priority=1
350 true.priority=1
349 true.executable=cat
351 true.executable=cat
350 # hg update -C 1
352 # hg update -C 1
351 # hg merge -r 2 --config ui.merge=internal:other --config merge-patterns.f=false
353 # hg merge -r 2 --config ui.merge=internal:other --config merge-patterns.f=false
352 merging f
354 merging f
353 merging f failed!
355 merging f failed!
354 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
356 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
355 use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
357 use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
356 # cat f
358 # cat f
357 revision 1
359 revision 1
358 space
360 space
359 # hg stat
361 # hg stat
360 M f
362 M f
361 ? f.orig
363 ? f.orig
362
364
363
365
364 Premerge
366 Premerge
365
367
366 # Default is silent simplemerge:
368 # Default is silent simplemerge:
367 [merge-tools]
369 [merge-tools]
368 false.whatever=
370 false.whatever=
369 true.priority=1
371 true.priority=1
370 true.executable=cat
372 true.executable=cat
371 # hg update -C 1
373 # hg update -C 1
372 # hg merge -r 3
374 # hg merge -r 3
373 merging f
375 merging f
374 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
376 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
375 (branch merge, don't forget to commit)
377 (branch merge, don't forget to commit)
376 # cat f
378 # cat f
377 revision 1
379 revision 1
378 space
380 space
379 revision 3
381 revision 3
380 # hg stat
382 # hg stat
381 M f
383 M f
382
384
383 # .premerge=True is same:
385 # .premerge=True is same:
384 [merge-tools]
386 [merge-tools]
385 false.whatever=
387 false.whatever=
386 true.priority=1
388 true.priority=1
387 true.executable=cat
389 true.executable=cat
388 # hg update -C 1
390 # hg update -C 1
389 # hg merge -r 3 --config merge-tools.true.premerge=True
391 # hg merge -r 3 --config merge-tools.true.premerge=True
390 merging f
392 merging f
391 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
393 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
392 (branch merge, don't forget to commit)
394 (branch merge, don't forget to commit)
393 # cat f
395 # cat f
394 revision 1
396 revision 1
395 space
397 space
396 revision 3
398 revision 3
397 # hg stat
399 # hg stat
398 M f
400 M f
399
401
400 # .premerge=False executes merge-tool:
402 # .premerge=False executes merge-tool:
401 [merge-tools]
403 [merge-tools]
402 false.whatever=
404 false.whatever=
403 true.priority=1
405 true.priority=1
404 true.executable=cat
406 true.executable=cat
405 # hg update -C 1
407 # hg update -C 1
406 # hg merge -r 3 --config merge-tools.true.premerge=False
408 # hg merge -r 3 --config merge-tools.true.premerge=False
407 revision 1
409 revision 1
408 space
410 space
409 revision 0
411 revision 0
410 space
412 space
411 revision 0
413 revision 0
412 space
414 space
413 revision 3
415 revision 3
414 merging f
416 merging f
415 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
417 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
416 (branch merge, don't forget to commit)
418 (branch merge, don't forget to commit)
417 # cat f
419 # cat f
418 revision 1
420 revision 1
419 space
421 space
420 # hg stat
422 # hg stat
421 M f
423 M f
422
424
423
425
424 Tool execution
426 Tool execution
425
427
426 # set tools.args explicit to include $base $local $other $output:
428 # set tools.args explicit to include $base $local $other $output:
427 [merge-tools]
429 [merge-tools]
428 false.whatever=
430 false.whatever=
429 true.priority=1
431 true.priority=1
430 true.executable=cat
432 true.executable=cat
431 # hg update -C 1
433 # hg update -C 1
432 ==> ... <==
434 ==> ... <==
433 revision 0
435 revision 0
434 space
436 space
435
437
436 ==> ... <==
438 ==> ... <==
437 revision 1
439 revision 1
438 space
440 space
439
441
440 ==> ... <==
442 ==> ... <==
441 revision 2
443 revision 2
442 space
444 space
443
445
444 ==> ... <==
446 ==> ... <==
445 revision 1
447 revision 1
446 space
448 space
447 merging f
449 merging f
448 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
450 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
449 (branch merge, don't forget to commit)
451 (branch merge, don't forget to commit)
450 # cat f
452 # cat f
451 revision 1
453 revision 1
452 space
454 space
453 # hg stat
455 # hg stat
454 M f
456 M f
455
457
456 # Merge with "echo mergeresult > $local":
458 # Merge with "echo mergeresult > $local":
457 [merge-tools]
459 [merge-tools]
458 false.whatever=
460 false.whatever=
459 true.priority=1
461 true.priority=1
460 true.executable=cat
462 true.executable=cat
461 # hg update -C 1
463 # hg update -C 1
462 merging f
464 merging f
463 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
465 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
464 (branch merge, don't forget to commit)
466 (branch merge, don't forget to commit)
465 # cat f
467 # cat f
466 mergeresult
468 mergeresult
467 # hg stat
469 # hg stat
468 M f
470 M f
469
471
470 # - and $local is the file f:
472 # - and $local is the file f:
471 [merge-tools]
473 [merge-tools]
472 false.whatever=
474 false.whatever=
473 true.priority=1
475 true.priority=1
474 true.executable=cat
476 true.executable=cat
475 # hg update -C 1
477 # hg update -C 1
476 merging f
478 merging f
477 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
479 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
478 (branch merge, don't forget to commit)
480 (branch merge, don't forget to commit)
479 # cat f
481 # cat f
480 mergeresult
482 mergeresult
481 # hg stat
483 # hg stat
482 M f
484 M f
483
485
484 # Merge with "echo mergeresult > $output" - the variable is a bit magic:
486 # Merge with "echo mergeresult > $output" - the variable is a bit magic:
485 [merge-tools]
487 [merge-tools]
486 false.whatever=
488 false.whatever=
487 true.priority=1
489 true.priority=1
488 true.executable=cat
490 true.executable=cat
489 # hg update -C 1
491 # hg update -C 1
490 merging f
492 merging f
491 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
493 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
492 (branch merge, don't forget to commit)
494 (branch merge, don't forget to commit)
493 # cat f
495 # cat f
494 mergeresult
496 mergeresult
495 # hg stat
497 # hg stat
496 M f
498 M f
497
499
498
500
499 Merge post-processing
501 Merge post-processing
500
502
501 # cat is a bad merge-tool and doesn't change:
503 # cat is a bad merge-tool and doesn't change:
502 [merge-tools]
504 [merge-tools]
503 false.whatever=
505 false.whatever=
504 true.priority=1
506 true.priority=1
505 true.executable=cat
507 true.executable=cat
506 # hg update -C 1
508 # hg update -C 1
507 # hg merge -y -r 2 --config merge-tools.true.checkchanged=1
509 # hg merge -y -r 2 --config merge-tools.true.checkchanged=1
508 revision 1
510 revision 1
509 space
511 space
510 revision 0
512 revision 0
511 space
513 space
512 revision 2
514 revision 2
513 space
515 space
514 merging f
516 merging f
517 output file f appears unchanged
518 was merge successful (yn)? n
515 merging f failed!
519 merging f failed!
516 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
520 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
517 use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
521 use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
518 # cat f
522 # cat f
519 revision 1
523 revision 1
520 space
524 space
521 # hg stat
525 # hg stat
522 M f
526 M f
523 ? f.orig
527 ? f.orig
524
528
General Comments 0
You need to be logged in to leave comments. Login now