##// END OF EJS Templates
windows: make shellquote() quote any path containing '\' (issue4629)...
Matt Harbison -
r24885:eea3977e stable
parent child Browse files
Show More
@@ -1,375 +1,377 b''
1 1 # windows.py - Windows utility function implementations for Mercurial
2 2 #
3 3 # Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from i18n import _
9 9 import osutil, encoding
10 10 import errno, msvcrt, os, re, stat, sys, _winreg
11 11
12 12 import win32
13 13 executablepath = win32.executablepath
14 14 getuser = win32.getuser
15 15 hidewindow = win32.hidewindow
16 16 makedir = win32.makedir
17 17 nlinks = win32.nlinks
18 18 oslink = win32.oslink
19 19 samedevice = win32.samedevice
20 20 samefile = win32.samefile
21 21 setsignalhandler = win32.setsignalhandler
22 22 spawndetached = win32.spawndetached
23 23 split = os.path.split
24 24 termwidth = win32.termwidth
25 25 testpid = win32.testpid
26 26 unlink = win32.unlink
27 27
28 28 umask = 0022
29 29 _SEEK_END = 2 # os.SEEK_END was introduced in Python 2.5
30 30
31 31 def posixfile(name, mode='r', buffering=-1):
32 32 '''Open a file with even more POSIX-like semantics'''
33 33 try:
34 34 fp = osutil.posixfile(name, mode, buffering) # may raise WindowsError
35 35
36 36 # The position when opening in append mode is implementation defined, so
37 37 # make it consistent with other platforms, which position at EOF.
38 38 if 'a' in mode:
39 39 fp.seek(0, _SEEK_END)
40 40
41 41 return fp
42 42 except WindowsError, err:
43 43 # convert to a friendlier exception
44 44 raise IOError(err.errno, '%s: %s' % (name, err.strerror))
45 45
46 46 class winstdout(object):
47 47 '''stdout on windows misbehaves if sent through a pipe'''
48 48
49 49 def __init__(self, fp):
50 50 self.fp = fp
51 51
52 52 def __getattr__(self, key):
53 53 return getattr(self.fp, key)
54 54
55 55 def close(self):
56 56 try:
57 57 self.fp.close()
58 58 except IOError:
59 59 pass
60 60
61 61 def write(self, s):
62 62 try:
63 63 # This is workaround for "Not enough space" error on
64 64 # writing large size of data to console.
65 65 limit = 16000
66 66 l = len(s)
67 67 start = 0
68 68 self.softspace = 0
69 69 while start < l:
70 70 end = start + limit
71 71 self.fp.write(s[start:end])
72 72 start = end
73 73 except IOError, inst:
74 74 if inst.errno != 0:
75 75 raise
76 76 self.close()
77 77 raise IOError(errno.EPIPE, 'Broken pipe')
78 78
79 79 def flush(self):
80 80 try:
81 81 return self.fp.flush()
82 82 except IOError, inst:
83 83 if inst.errno != errno.EINVAL:
84 84 raise
85 85 self.close()
86 86 raise IOError(errno.EPIPE, 'Broken pipe')
87 87
88 88 sys.__stdout__ = sys.stdout = winstdout(sys.stdout)
89 89
90 90 def _is_win_9x():
91 91 '''return true if run on windows 95, 98 or me.'''
92 92 try:
93 93 return sys.getwindowsversion()[3] == 1
94 94 except AttributeError:
95 95 return 'command' in os.environ.get('comspec', '')
96 96
97 97 def openhardlinks():
98 98 return not _is_win_9x()
99 99
100 100 def parsepatchoutput(output_line):
101 101 """parses the output produced by patch and returns the filename"""
102 102 pf = output_line[14:]
103 103 if pf[0] == '`':
104 104 pf = pf[1:-1] # Remove the quotes
105 105 return pf
106 106
107 107 def sshargs(sshcmd, host, user, port):
108 108 '''Build argument list for ssh or Plink'''
109 109 pflag = 'plink' in sshcmd.lower() and '-P' or '-p'
110 110 args = user and ("%s@%s" % (user, host)) or host
111 111 return port and ("%s %s %s" % (args, pflag, port)) or args
112 112
113 113 def setflags(f, l, x):
114 114 pass
115 115
116 116 def copymode(src, dst, mode=None):
117 117 pass
118 118
119 119 def checkexec(path):
120 120 return False
121 121
122 122 def checklink(path):
123 123 return False
124 124
125 125 def setbinary(fd):
126 126 # When run without console, pipes may expose invalid
127 127 # fileno(), usually set to -1.
128 128 fno = getattr(fd, 'fileno', None)
129 129 if fno is not None and fno() >= 0:
130 130 msvcrt.setmode(fno(), os.O_BINARY)
131 131
132 132 def pconvert(path):
133 133 return path.replace(os.sep, '/')
134 134
135 135 def localpath(path):
136 136 return path.replace('/', '\\')
137 137
138 138 def normpath(path):
139 139 return pconvert(os.path.normpath(path))
140 140
141 141 def normcase(path):
142 142 return encoding.upper(path)
143 143
144 144 # see posix.py for definitions
145 145 normcasespec = encoding.normcasespecs.upper
146 146 normcasefallback = encoding.upperfallback
147 147
148 148 def samestat(s1, s2):
149 149 return False
150 150
151 151 # A sequence of backslashes is special iff it precedes a double quote:
152 152 # - if there's an even number of backslashes, the double quote is not
153 153 # quoted (i.e. it ends the quoted region)
154 154 # - if there's an odd number of backslashes, the double quote is quoted
155 155 # - in both cases, every pair of backslashes is unquoted into a single
156 156 # backslash
157 157 # (See http://msdn2.microsoft.com/en-us/library/a1y7w461.aspx )
158 158 # So, to quote a string, we must surround it in double quotes, double
159 159 # the number of backslashes that precede double quotes and add another
160 160 # backslash before every double quote (being careful with the double
161 161 # quote we've appended to the end)
162 162 _quotere = None
163 163 _needsshellquote = None
164 164 def shellquote(s):
165 165 global _quotere
166 166 if _quotere is None:
167 167 _quotere = re.compile(r'(\\*)("|\\$)')
168 168 global _needsshellquote
169 169 if _needsshellquote is None:
170 # ":" and "\\" are also treated as "safe character", because
171 # they are used as a part of path name (and the latter doesn't
172 # work as "escape character", like one on posix) on Windows
173 _needsshellquote = re.compile(r'[^a-zA-Z0-9._:/\\-]').search
170 # ":" is also treated as "safe character", because it is used as a part
171 # of path name on Windows. "\" is also part of a path name, but isn't
172 # safe because shlex.split() (kind of) treats it as an escape char and
173 # drops it. It will leave the next character, even if it is another
174 # "\".
175 _needsshellquote = re.compile(r'[^a-zA-Z0-9._:/-]').search
174 176 if s and not _needsshellquote(s) and not _quotere.search(s):
175 177 # "s" shouldn't have to be quoted
176 178 return s
177 179 return '"%s"' % _quotere.sub(r'\1\1\\\2', s)
178 180
179 181 def quotecommand(cmd):
180 182 """Build a command string suitable for os.popen* calls."""
181 183 if sys.version_info < (2, 7, 1):
182 184 # Python versions since 2.7.1 do this extra quoting themselves
183 185 return '"' + cmd + '"'
184 186 return cmd
185 187
186 188 def popen(command, mode='r'):
187 189 # Work around "popen spawned process may not write to stdout
188 190 # under windows"
189 191 # http://bugs.python.org/issue1366
190 192 command += " 2> %s" % os.devnull
191 193 return os.popen(quotecommand(command), mode)
192 194
193 195 def explainexit(code):
194 196 return _("exited with status %d") % code, code
195 197
196 198 # if you change this stub into a real check, please try to implement the
197 199 # username and groupname functions above, too.
198 200 def isowner(st):
199 201 return True
200 202
201 203 def findexe(command):
202 204 '''Find executable for command searching like cmd.exe does.
203 205 If command is a basename then PATH is searched for command.
204 206 PATH isn't searched if command is an absolute or relative path.
205 207 An extension from PATHEXT is found and added if not present.
206 208 If command isn't found None is returned.'''
207 209 pathext = os.environ.get('PATHEXT', '.COM;.EXE;.BAT;.CMD')
208 210 pathexts = [ext for ext in pathext.lower().split(os.pathsep)]
209 211 if os.path.splitext(command)[1].lower() in pathexts:
210 212 pathexts = ['']
211 213
212 214 def findexisting(pathcommand):
213 215 'Will append extension (if needed) and return existing file'
214 216 for ext in pathexts:
215 217 executable = pathcommand + ext
216 218 if os.path.exists(executable):
217 219 return executable
218 220 return None
219 221
220 222 if os.sep in command:
221 223 return findexisting(command)
222 224
223 225 for path in os.environ.get('PATH', '').split(os.pathsep):
224 226 executable = findexisting(os.path.join(path, command))
225 227 if executable is not None:
226 228 return executable
227 229 return findexisting(os.path.expanduser(os.path.expandvars(command)))
228 230
229 231 _wantedkinds = set([stat.S_IFREG, stat.S_IFLNK])
230 232
231 233 def statfiles(files):
232 234 '''Stat each file in files. Yield each stat, or None if a file
233 235 does not exist or has a type we don't care about.
234 236
235 237 Cluster and cache stat per directory to minimize number of OS stat calls.'''
236 238 dircache = {} # dirname -> filename -> status | None if file does not exist
237 239 getkind = stat.S_IFMT
238 240 for nf in files:
239 241 nf = normcase(nf)
240 242 dir, base = os.path.split(nf)
241 243 if not dir:
242 244 dir = '.'
243 245 cache = dircache.get(dir, None)
244 246 if cache is None:
245 247 try:
246 248 dmap = dict([(normcase(n), s)
247 249 for n, k, s in osutil.listdir(dir, True)
248 250 if getkind(s.st_mode) in _wantedkinds])
249 251 except OSError, err:
250 252 # handle directory not found in Python version prior to 2.5
251 253 # Python <= 2.4 returns native Windows code 3 in errno
252 254 # Python >= 2.5 returns ENOENT and adds winerror field
253 255 # EINVAL is raised if dir is not a directory.
254 256 if err.errno not in (3, errno.ENOENT, errno.EINVAL,
255 257 errno.ENOTDIR):
256 258 raise
257 259 dmap = {}
258 260 cache = dircache.setdefault(dir, dmap)
259 261 yield cache.get(base, None)
260 262
261 263 def username(uid=None):
262 264 """Return the name of the user with the given uid.
263 265
264 266 If uid is None, return the name of the current user."""
265 267 return None
266 268
267 269 def groupname(gid=None):
268 270 """Return the name of the group with the given gid.
269 271
270 272 If gid is None, return the name of the current group."""
271 273 return None
272 274
273 275 def removedirs(name):
274 276 """special version of os.removedirs that does not remove symlinked
275 277 directories or junction points if they actually contain files"""
276 278 if osutil.listdir(name):
277 279 return
278 280 os.rmdir(name)
279 281 head, tail = os.path.split(name)
280 282 if not tail:
281 283 head, tail = os.path.split(head)
282 284 while head and tail:
283 285 try:
284 286 if osutil.listdir(head):
285 287 return
286 288 os.rmdir(head)
287 289 except (ValueError, OSError):
288 290 break
289 291 head, tail = os.path.split(head)
290 292
291 293 def unlinkpath(f, ignoremissing=False):
292 294 """unlink and remove the directory if it is empty"""
293 295 try:
294 296 unlink(f)
295 297 except OSError, e:
296 298 if not (ignoremissing and e.errno == errno.ENOENT):
297 299 raise
298 300 # try removing directories that might now be empty
299 301 try:
300 302 removedirs(os.path.dirname(f))
301 303 except OSError:
302 304 pass
303 305
304 306 def rename(src, dst):
305 307 '''atomically rename file src to dst, replacing dst if it exists'''
306 308 try:
307 309 os.rename(src, dst)
308 310 except OSError, e:
309 311 if e.errno != errno.EEXIST:
310 312 raise
311 313 unlink(dst)
312 314 os.rename(src, dst)
313 315
314 316 def gethgcmd():
315 317 return [sys.executable] + sys.argv[:1]
316 318
317 319 def groupmembers(name):
318 320 # Don't support groups on Windows for now
319 321 raise KeyError
320 322
321 323 def isexec(f):
322 324 return False
323 325
324 326 class cachestat(object):
325 327 def __init__(self, path):
326 328 pass
327 329
328 330 def cacheable(self):
329 331 return False
330 332
331 333 def lookupreg(key, valname=None, scope=None):
332 334 ''' Look up a key/value name in the Windows registry.
333 335
334 336 valname: value name. If unspecified, the default value for the key
335 337 is used.
336 338 scope: optionally specify scope for registry lookup, this can be
337 339 a sequence of scopes to look up in order. Default (CURRENT_USER,
338 340 LOCAL_MACHINE).
339 341 '''
340 342 if scope is None:
341 343 scope = (_winreg.HKEY_CURRENT_USER, _winreg.HKEY_LOCAL_MACHINE)
342 344 elif not isinstance(scope, (list, tuple)):
343 345 scope = (scope,)
344 346 for s in scope:
345 347 try:
346 348 val = _winreg.QueryValueEx(_winreg.OpenKey(s, key), valname)[0]
347 349 # never let a Unicode string escape into the wild
348 350 return encoding.tolocal(val.encode('UTF-8'))
349 351 except EnvironmentError:
350 352 pass
351 353
352 354 expandglobs = True
353 355
354 356 def statislink(st):
355 357 '''check whether a stat result is a symlink'''
356 358 return False
357 359
358 360 def statisexec(st):
359 361 '''check whether a stat result is an executable file'''
360 362 return False
361 363
362 364 def readpipe(pipe):
363 365 """Read all available data from a pipe."""
364 366 chunks = []
365 367 while True:
366 368 size = win32.peekpipe(pipe)
367 369 if not size:
368 370 break
369 371
370 372 s = pipe.read(size)
371 373 if not s:
372 374 break
373 375 chunks.append(s)
374 376
375 377 return ''.join(chunks)
@@ -1,340 +1,364 b''
1 1 $ echo "[extensions]" >> $HGRCPATH
2 2 $ echo "extdiff=" >> $HGRCPATH
3 3
4 4 $ hg init a
5 5 $ cd a
6 6 $ echo a > a
7 7 $ echo b > b
8 8 $ hg add
9 9 adding a
10 10 adding b
11 11
12 12 Should diff cloned directories:
13 13
14 14 $ hg extdiff -o -r $opt
15 15 Only in a: a
16 16 Only in a: b
17 17 [1]
18 18
19 19 $ cat <<EOF >> $HGRCPATH
20 20 > [extdiff]
21 21 > cmd.falabala = echo
22 22 > opts.falabala = diffing
23 23 > cmd.edspace = echo
24 24 > opts.edspace = "name <user@example.com>"
25 25 > EOF
26 26
27 27 $ hg falabala
28 28 diffing a.000000000000 a
29 29 [1]
30 30
31 31 $ hg help falabala
32 32 hg falabala [OPTION]... [FILE]...
33 33
34 34 use 'echo' to diff repository (or selected files)
35 35
36 36 Show differences between revisions for the specified files, using the
37 37 'echo' program.
38 38
39 39 When two revision arguments are given, then changes are shown between
40 40 those revisions. If only one revision is specified then that revision is
41 41 compared to the working directory, and, when no revisions are specified,
42 42 the working directory files are compared to its parent.
43 43
44 44 options ([+] can be repeated):
45 45
46 46 -o --option OPT [+] pass option to comparison program
47 47 -r --rev REV [+] revision
48 48 -c --change REV change made by revision
49 49 -I --include PATTERN [+] include names matching the given patterns
50 50 -X --exclude PATTERN [+] exclude names matching the given patterns
51 51
52 52 (some details hidden, use --verbose to show complete help)
53 53
54 54 $ hg ci -d '0 0' -mtest1
55 55
56 56 $ echo b >> a
57 57 $ hg ci -d '1 0' -mtest2
58 58
59 59 Should diff cloned files directly:
60 60
61 #if windows
62 $ hg falabala -r 0:1
63 diffing "*\\extdiff.*\\a.8a5febb7f867\\a" "a.34eed99112ab\\a" (glob)
64 [1]
65 #else
61 66 $ hg falabala -r 0:1
62 67 diffing */extdiff.*/a.8a5febb7f867/a a.34eed99112ab/a (glob)
63 68 [1]
69 #endif
64 70
65 71 Test diff during merge:
66 72
67 73 $ hg update -C 0
68 74 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
69 75 $ echo c >> c
70 76 $ hg add c
71 77 $ hg ci -m "new branch" -d '1 0'
72 78 created new head
73 79 $ hg merge 1
74 80 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
75 81 (branch merge, don't forget to commit)
76 82
77 83 Should diff cloned file against wc file:
78 84
85 #if windows
86 $ hg falabala
87 diffing "*\\extdiff.*\\a.2a13a4d2da36\\a" "*\\a\\a" (glob)
88 [1]
89 #else
79 90 $ hg falabala
80 91 diffing */extdiff.*/a.2a13a4d2da36/a */a/a (glob)
81 92 [1]
93 #endif
82 94
83 95
84 96 Test --change option:
85 97
86 98 $ hg ci -d '2 0' -mtest3
99 #if windows
100 $ hg falabala -c 1
101 diffing "*\\extdiff.*\\a.8a5febb7f867\\a" "a.34eed99112ab\\a" (glob)
102 [1]
103 #else
87 104 $ hg falabala -c 1
88 105 diffing */extdiff.*/a.8a5febb7f867/a a.34eed99112ab/a (glob)
89 106 [1]
107 #endif
90 108
91 109 Check diff are made from the first parent:
92 110
111 #if windows
112 $ hg falabala -c 3 || echo "diff-like tools yield a non-zero exit code"
113 diffing "*\\extdiff.*\\a.2a13a4d2da36\\a" "a.46c0e4daeb72\\a" (glob)
114 diff-like tools yield a non-zero exit code
115 #else
93 116 $ hg falabala -c 3 || echo "diff-like tools yield a non-zero exit code"
94 117 diffing */extdiff.*/a.2a13a4d2da36/a a.46c0e4daeb72/a (glob)
95 118 diff-like tools yield a non-zero exit code
119 #endif
96 120
97 121 issue4463: usage of command line configuration without additional quoting
98 122
99 123 $ cat <<EOF >> $HGRCPATH
100 124 > [extdiff]
101 125 > cmd.4463a = echo
102 126 > opts.4463a = a-naked 'single quoted' "double quoted"
103 127 > 4463b = echo b-naked 'single quoted' "double quoted"
104 128 > echo =
105 129 > EOF
106 130 $ hg update -q -C 0
107 131 $ echo a >> a
108 132 #if windows
109 133 $ hg --debug 4463a | grep '^running'
110 running 'echo a-naked \'single quoted\' "double quoted" *\\a *\\a' in */extdiff.* (glob)
134 running 'echo a-naked \'single quoted\' "double quoted" "*\\a" "*\\a"' in */extdiff.* (glob)
111 135 $ hg --debug 4463b | grep '^running'
112 running 'echo b-naked \'single quoted\' "double quoted" *\\a *\\a' in */extdiff.* (glob)
136 running 'echo b-naked \'single quoted\' "double quoted" "*\\a" "*\\a"' in */extdiff.* (glob)
113 137 $ hg --debug echo | grep '^running'
114 running '*echo* *\\a *\\a' in */extdiff.* (glob)
138 running '*echo* "*\\a" "*\\a"' in */extdiff.* (glob)
115 139 #else
116 140 $ hg --debug 4463a | grep '^running'
117 141 running 'echo a-naked \'single quoted\' "double quoted" */a $TESTTMP/a/a' in */extdiff.* (glob)
118 142 $ hg --debug 4463b | grep '^running'
119 143 running 'echo b-naked \'single quoted\' "double quoted" */a $TESTTMP/a/a' in */extdiff.* (glob)
120 144 $ hg --debug echo | grep '^running'
121 145 running '*echo */a $TESTTMP/a/a' in */extdiff.* (glob)
122 146 #endif
123 147
124 148 (getting options from other than extdiff section)
125 149
126 150 $ cat <<EOF >> $HGRCPATH
127 151 > [extdiff]
128 152 > # using diff-tools diffargs
129 153 > 4463b2 = echo
130 154 > # using merge-tools diffargs
131 155 > 4463b3 = echo
132 156 > # no diffargs
133 157 > 4463b4 = echo
134 158 > [diff-tools]
135 159 > 4463b2.diffargs = b2-naked 'single quoted' "double quoted"
136 160 > [merge-tools]
137 161 > 4463b3.diffargs = b3-naked 'single quoted' "double quoted"
138 162 > EOF
139 163 #if windows
140 164 $ hg --debug 4463b2 | grep '^running'
141 running 'echo b2-naked \'single quoted\' "double quoted" *\\a *\\a' in */extdiff.* (glob)
165 running 'echo b2-naked \'single quoted\' "double quoted" "*\\a" "*\\a"' in */extdiff.* (glob)
142 166 $ hg --debug 4463b3 | grep '^running'
143 running 'echo b3-naked \'single quoted\' "double quoted" *\\a *\\a' in */extdiff.* (glob)
167 running 'echo b3-naked \'single quoted\' "double quoted" "*\\a" "*\\a"' in */extdiff.* (glob)
144 168 $ hg --debug 4463b4 | grep '^running'
145 running 'echo *\\a *\\a' in */extdiff.* (glob)
169 running 'echo "*\\a" "*\\a"' in */extdiff.* (glob)
146 170 $ hg --debug 4463b4 --option b4-naked --option 'being quoted' | grep '^running'
147 running 'echo b4-naked "being quoted" *\\a *\\a' in */extdiff.* (glob)
171 running 'echo b4-naked "being quoted" "*\\a" "*\\a"' in */extdiff.* (glob)
148 172 $ hg --debug extdiff -p echo --option echo-naked --option 'being quoted' | grep '^running'
149 running 'echo echo-naked "being quoted" *\\a *\\a' in */extdiff.* (glob)
173 running 'echo echo-naked "being quoted" "*\\a" "*\\a"' in */extdiff.* (glob)
150 174 #else
151 175 $ hg --debug 4463b2 | grep '^running'
152 176 running 'echo b2-naked \'single quoted\' "double quoted" */a $TESTTMP/a/a' in */extdiff.* (glob)
153 177 $ hg --debug 4463b3 | grep '^running'
154 178 running 'echo b3-naked \'single quoted\' "double quoted" */a $TESTTMP/a/a' in */extdiff.* (glob)
155 179 $ hg --debug 4463b4 | grep '^running'
156 180 running 'echo */a $TESTTMP/a/a' in */extdiff.* (glob)
157 181 $ hg --debug 4463b4 --option b4-naked --option 'being quoted' | grep '^running'
158 182 running "echo b4-naked 'being quoted' */a $TESTTMP/a/a" in */extdiff.* (glob)
159 183 $ hg --debug extdiff -p echo --option echo-naked --option 'being quoted' | grep '^running'
160 184 running "echo echo-naked 'being quoted' */a $TESTTMP/a/a" in */extdiff.* (glob)
161 185 #endif
162 186
163 187 $ touch 'sp ace'
164 188 $ hg add 'sp ace'
165 189 $ hg ci -m 'sp ace'
166 190 created new head
167 191 $ echo > 'sp ace'
168 192
169 193 Test pre-72a89cf86fcd backward compatibility with half-baked manual quoting
170 194
171 195 $ cat <<EOF >> $HGRCPATH
172 196 > [extdiff]
173 197 > odd =
174 198 > [merge-tools]
175 199 > odd.diffargs = --foo='\$clabel' '\$clabel' "--bar=\$clabel" "\$clabel"
176 200 > odd.executable = echo
177 201 > EOF
178 202 #if windows
179 203 TODO
180 204 #else
181 205 $ hg --debug odd | grep '^running'
182 206 running "*/echo --foo='sp ace' 'sp ace' --bar='sp ace' 'sp ace'" in * (glob)
183 207 #endif
184 208
185 209 Empty argument must be quoted
186 210
187 211 $ cat <<EOF >> $HGRCPATH
188 212 > [extdiff]
189 213 > kdiff3 = echo
190 214 > [merge-tools]
191 215 > kdiff3.diffargs=--L1 \$plabel1 --L2 \$clabel \$parent \$child
192 216 > EOF
193 217 #if windows
194 218 $ hg --debug kdiff3 -r0 | grep '^running'
195 219 running 'echo --L1 "@0" --L2 "" a.8a5febb7f867 a' in * (glob)
196 220 #else
197 221 $ hg --debug kdiff3 -r0 | grep '^running'
198 222 running "echo --L1 '@0' --L2 '' a.8a5febb7f867 a" in * (glob)
199 223 #endif
200 224
201 225 #if execbit
202 226
203 227 Test extdiff of multiple files in tmp dir:
204 228
205 229 $ hg update -C 0 > /dev/null
206 230 $ echo changed > a
207 231 $ echo changed > b
208 232 $ chmod +x b
209 233
210 234 Diff in working directory, before:
211 235
212 236 $ hg diff --git
213 237 diff --git a/a b/a
214 238 --- a/a
215 239 +++ b/a
216 240 @@ -1,1 +1,1 @@
217 241 -a
218 242 +changed
219 243 diff --git a/b b/b
220 244 old mode 100644
221 245 new mode 100755
222 246 --- a/b
223 247 +++ b/b
224 248 @@ -1,1 +1,1 @@
225 249 -b
226 250 +changed
227 251
228 252
229 253 Edit with extdiff -p:
230 254
231 255 Prepare custom diff/edit tool:
232 256
233 257 $ cat > 'diff tool.py' << EOT
234 258 > #!/usr/bin/env python
235 259 > import time
236 260 > time.sleep(1) # avoid unchanged-timestamp problems
237 261 > file('a/a', 'ab').write('edited\n')
238 262 > file('a/b', 'ab').write('edited\n')
239 263 > EOT
240 264
241 265 $ chmod +x 'diff tool.py'
242 266
243 267 will change to /tmp/extdiff.TMP and populate directories a.TMP and a
244 268 and start tool
245 269
246 270 $ hg extdiff -p "`pwd`/diff tool.py"
247 271 [1]
248 272
249 273 Diff in working directory, after:
250 274
251 275 $ hg diff --git
252 276 diff --git a/a b/a
253 277 --- a/a
254 278 +++ b/a
255 279 @@ -1,1 +1,2 @@
256 280 -a
257 281 +changed
258 282 +edited
259 283 diff --git a/b b/b
260 284 old mode 100644
261 285 new mode 100755
262 286 --- a/b
263 287 +++ b/b
264 288 @@ -1,1 +1,2 @@
265 289 -b
266 290 +changed
267 291 +edited
268 292
269 293 Test extdiff with --option:
270 294
271 295 $ hg extdiff -p echo -o this -c 1
272 296 this */extdiff.*/a.8a5febb7f867/a a.34eed99112ab/a (glob)
273 297 [1]
274 298
275 299 $ hg falabala -o this -c 1
276 300 diffing this */extdiff.*/a.8a5febb7f867/a a.34eed99112ab/a (glob)
277 301 [1]
278 302
279 303 Test extdiff's handling of options with spaces in them:
280 304
281 305 $ hg edspace -c 1
282 306 name <user@example.com> */extdiff.*/a.8a5febb7f867/a a.34eed99112ab/a (glob)
283 307 [1]
284 308
285 309 $ hg extdiff -p echo -o "name <user@example.com>" -c 1
286 310 name <user@example.com> */extdiff.*/a.8a5febb7f867/a a.34eed99112ab/a (glob)
287 311 [1]
288 312
289 313 Test with revsets:
290 314
291 315 $ hg extdif -p echo -c "rev(1)"
292 316 */extdiff.*/a.8a5febb7f867/a a.34eed99112ab/a (glob)
293 317 [1]
294 318
295 319 $ hg extdif -p echo -r "0::1"
296 320 */extdiff.*/a.8a5febb7f867/a a.34eed99112ab/a (glob)
297 321 [1]
298 322
299 323 Fallback to merge-tools.tool.executable|regkey
300 324 $ mkdir dir
301 325 $ cat > 'dir/tool.sh' << EOF
302 326 > #!/bin/sh
303 327 > echo "** custom diff **"
304 328 > EOF
305 329 $ chmod +x dir/tool.sh
306 330 $ tool=`pwd`/dir/tool.sh
307 331 $ hg --debug tl --config extdiff.tl= --config merge-tools.tl.executable=$tool
308 332 making snapshot of 2 files from rev * (glob)
309 333 a
310 334 b
311 335 making snapshot of 2 files from working directory
312 336 a
313 337 b
314 338 running '$TESTTMP/a/dir/tool.sh a.* a' in */extdiff.* (glob)
315 339 ** custom diff **
316 340 cleaning up temp directory
317 341 [1]
318 342
319 343 $ cd ..
320 344
321 345 #endif
322 346
323 347 #if symlink
324 348
325 349 Test symlinks handling (issue1909)
326 350
327 351 $ hg init testsymlinks
328 352 $ cd testsymlinks
329 353 $ echo a > a
330 354 $ hg ci -Am adda
331 355 adding a
332 356 $ echo a >> a
333 357 $ ln -s missing linka
334 358 $ hg add linka
335 359 $ hg falabala -r 0 --traceback
336 360 diffing testsymlinks.07f494440405 testsymlinks
337 361 [1]
338 362 $ cd ..
339 363
340 364 #endif
@@ -1,1024 +1,1024 b''
1 1
2 2 $ mkdir -p t
3 3 $ cd t
4 4 $ cat <<EOF > merge
5 5 > import sys, os
6 6 > f = open(sys.argv[1], "wb")
7 7 > f.write("merge %s %s %s" % (sys.argv[1], sys.argv[2], sys.argv[3]))
8 8 > f.close()
9 9 > EOF
10 10
11 11 perform a test merge with possible renaming
12 12 args:
13 13 $1 = action in local branch
14 14 $2 = action in remote branch
15 15 $3 = action in working dir
16 16 $4 = expected result
17 17
18 18 $ tm()
19 19 > {
20 20 > hg init t
21 21 > cd t
22 22 > echo "[merge]" >> .hg/hgrc
23 23 > echo "followcopies = 1" >> .hg/hgrc
24 24 >
25 25 > # base
26 26 > echo base > a
27 27 > echo base > rev # used to force commits
28 28 > hg add a rev
29 29 > hg ci -m "base"
30 30 >
31 31 > # remote
32 32 > echo remote > rev
33 33 > if [ "$2" != "" ] ; then $2 ; fi
34 34 > hg ci -m "remote"
35 35 >
36 36 > # local
37 37 > hg co -q 0
38 38 > echo local > rev
39 39 > if [ "$1" != "" ] ; then $1 ; fi
40 40 > hg ci -m "local"
41 41 >
42 42 > # working dir
43 43 > echo local > rev
44 44 > if [ "$3" != "" ] ; then $3 ; fi
45 45 >
46 46 > # merge
47 47 > echo "--------------"
48 48 > echo "test L:$1 R:$2 W:$3 - $4"
49 49 > echo "--------------"
50 50 > hg merge -y --debug --traceback --tool="python ../merge"
51 51 >
52 52 > echo "--------------"
53 53 > hg status -camC -X rev
54 54 >
55 55 > hg ci -m "merge"
56 56 >
57 57 > echo "--------------"
58 58 > echo
59 59 >
60 60 > cd ..
61 61 > rm -r t
62 62 > }
63 63 $ up() {
64 64 > cp rev $1
65 65 > hg add $1 2> /dev/null
66 66 > if [ "$2" != "" ] ; then
67 67 > cp rev $2
68 68 > hg add $2 2> /dev/null
69 69 > fi
70 70 > }
71 71 $ uc() { up $1; hg cp $1 $2; } # update + copy
72 72 $ um() { up $1; hg mv $1 $2; }
73 73 $ nc() { hg cp $1 $2; } # just copy
74 74 $ nm() { hg mv $1 $2; } # just move
75 75 $ tm "up a " "nc a b" " " "1 get local a to b"
76 76 created new head
77 77 --------------
78 78 test L:up a R:nc a b W: - 1 get local a to b
79 79 --------------
80 80 searching for copies back to rev 1
81 81 unmatched files in other:
82 82 b
83 83 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
84 84 src: 'a' -> dst: 'b' *
85 85 checking for directory renames
86 86 resolving manifests
87 87 branchmerge: True, force: False, partial: False
88 88 ancestor: 924404dff337, local: e300d1c794ec+, remote: 4ce40f5aca24
89 89 preserving a for resolve of b
90 90 preserving rev for resolve of rev
91 91 a: remote unchanged -> k
92 92 b: remote copied from a -> m
93 93 updating: b 1/2 files (50.00%)
94 94 picked tool 'python ../merge' for b (binary False symlink False)
95 95 merging a and b to b
96 96 my b@e300d1c794ec+ other b@4ce40f5aca24 ancestor a@924404dff337
97 97 premerge successful
98 98 rev: versions differ -> m
99 99 updating: rev 2/2 files (100.00%)
100 100 picked tool 'python ../merge' for rev (binary False symlink False)
101 101 merging rev
102 102 my rev@e300d1c794ec+ other rev@4ce40f5aca24 ancestor rev@924404dff337
103 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
103 launching merge tool: python ../merge *$TESTTMP/t/t/rev* * * (glob)
104 104 merge tool returned: 0
105 105 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
106 106 (branch merge, don't forget to commit)
107 107 --------------
108 108 M b
109 109 a
110 110 C a
111 111 --------------
112 112
113 113 $ tm "nc a b" "up a " " " "2 get rem change to a and b"
114 114 created new head
115 115 --------------
116 116 test L:nc a b R:up a W: - 2 get rem change to a and b
117 117 --------------
118 118 searching for copies back to rev 1
119 119 unmatched files in local:
120 120 b
121 121 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
122 122 src: 'a' -> dst: 'b' *
123 123 checking for directory renames
124 124 resolving manifests
125 125 branchmerge: True, force: False, partial: False
126 126 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: f4db7e329e71
127 127 preserving b for resolve of b
128 128 preserving rev for resolve of rev
129 129 a: remote is newer -> g
130 130 getting a
131 131 updating: a 1/3 files (33.33%)
132 132 b: local copied/moved from a -> m
133 133 updating: b 2/3 files (66.67%)
134 134 picked tool 'python ../merge' for b (binary False symlink False)
135 135 merging b and a to b
136 136 my b@86a2aa42fc76+ other a@f4db7e329e71 ancestor a@924404dff337
137 137 premerge successful
138 138 rev: versions differ -> m
139 139 updating: rev 3/3 files (100.00%)
140 140 picked tool 'python ../merge' for rev (binary False symlink False)
141 141 merging rev
142 142 my rev@86a2aa42fc76+ other rev@f4db7e329e71 ancestor rev@924404dff337
143 launching merge tool: python ../merge $TESTTMP/t/t/rev * (glob)
143 launching merge tool: python ../merge *$TESTTMP/t/t/rev* * (glob)
144 144 merge tool returned: 0
145 145 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
146 146 (branch merge, don't forget to commit)
147 147 --------------
148 148 M a
149 149 M b
150 150 a
151 151 --------------
152 152
153 153 $ tm "up a " "nm a b" " " "3 get local a change to b, remove a"
154 154 created new head
155 155 --------------
156 156 test L:up a R:nm a b W: - 3 get local a change to b, remove a
157 157 --------------
158 158 searching for copies back to rev 1
159 159 unmatched files in other:
160 160 b
161 161 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
162 162 src: 'a' -> dst: 'b' *
163 163 checking for directory renames
164 164 resolving manifests
165 165 branchmerge: True, force: False, partial: False
166 166 ancestor: 924404dff337, local: e300d1c794ec+, remote: bdb19105162a
167 167 preserving a for resolve of b
168 168 preserving rev for resolve of rev
169 169 removing a
170 170 b: remote moved from a -> m
171 171 updating: b 1/2 files (50.00%)
172 172 picked tool 'python ../merge' for b (binary False symlink False)
173 173 merging a and b to b
174 174 my b@e300d1c794ec+ other b@bdb19105162a ancestor a@924404dff337
175 175 premerge successful
176 176 rev: versions differ -> m
177 177 updating: rev 2/2 files (100.00%)
178 178 picked tool 'python ../merge' for rev (binary False symlink False)
179 179 merging rev
180 180 my rev@e300d1c794ec+ other rev@bdb19105162a ancestor rev@924404dff337
181 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
181 launching merge tool: python ../merge *$TESTTMP/t/t/rev* * * (glob)
182 182 merge tool returned: 0
183 183 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
184 184 (branch merge, don't forget to commit)
185 185 --------------
186 186 M b
187 187 a
188 188 --------------
189 189
190 190 $ tm "nm a b" "up a " " " "4 get remote change to b"
191 191 created new head
192 192 --------------
193 193 test L:nm a b R:up a W: - 4 get remote change to b
194 194 --------------
195 195 searching for copies back to rev 1
196 196 unmatched files in local:
197 197 b
198 198 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
199 199 src: 'a' -> dst: 'b' *
200 200 checking for directory renames
201 201 resolving manifests
202 202 branchmerge: True, force: False, partial: False
203 203 ancestor: 924404dff337, local: 02963e448370+, remote: f4db7e329e71
204 204 preserving b for resolve of b
205 205 preserving rev for resolve of rev
206 206 b: local copied/moved from a -> m
207 207 updating: b 1/2 files (50.00%)
208 208 picked tool 'python ../merge' for b (binary False symlink False)
209 209 merging b and a to b
210 210 my b@02963e448370+ other a@f4db7e329e71 ancestor a@924404dff337
211 211 premerge successful
212 212 rev: versions differ -> m
213 213 updating: rev 2/2 files (100.00%)
214 214 picked tool 'python ../merge' for rev (binary False symlink False)
215 215 merging rev
216 216 my rev@02963e448370+ other rev@f4db7e329e71 ancestor rev@924404dff337
217 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
217 launching merge tool: python ../merge *$TESTTMP/t/t/rev* * * (glob)
218 218 merge tool returned: 0
219 219 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
220 220 (branch merge, don't forget to commit)
221 221 --------------
222 222 M b
223 223 a
224 224 --------------
225 225
226 226 $ tm " " "nc a b" " " "5 get b"
227 227 created new head
228 228 --------------
229 229 test L: R:nc a b W: - 5 get b
230 230 --------------
231 231 searching for copies back to rev 1
232 232 unmatched files in other:
233 233 b
234 234 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
235 235 src: 'a' -> dst: 'b'
236 236 checking for directory renames
237 237 resolving manifests
238 238 branchmerge: True, force: False, partial: False
239 239 ancestor: 924404dff337, local: 94b33a1b7f2d+, remote: 4ce40f5aca24
240 240 preserving rev for resolve of rev
241 241 b: remote created -> g
242 242 getting b
243 243 updating: b 1/2 files (50.00%)
244 244 rev: versions differ -> m
245 245 updating: rev 2/2 files (100.00%)
246 246 picked tool 'python ../merge' for rev (binary False symlink False)
247 247 merging rev
248 248 my rev@94b33a1b7f2d+ other rev@4ce40f5aca24 ancestor rev@924404dff337
249 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
249 launching merge tool: python ../merge *$TESTTMP/t/t/rev* * * (glob)
250 250 merge tool returned: 0
251 251 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
252 252 (branch merge, don't forget to commit)
253 253 --------------
254 254 M b
255 255 C a
256 256 --------------
257 257
258 258 $ tm "nc a b" " " " " "6 nothing"
259 259 created new head
260 260 --------------
261 261 test L:nc a b R: W: - 6 nothing
262 262 --------------
263 263 searching for copies back to rev 1
264 264 unmatched files in local:
265 265 b
266 266 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
267 267 src: 'a' -> dst: 'b'
268 268 checking for directory renames
269 269 resolving manifests
270 270 branchmerge: True, force: False, partial: False
271 271 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 97c705ade336
272 272 preserving rev for resolve of rev
273 273 rev: versions differ -> m
274 274 updating: rev 1/1 files (100.00%)
275 275 picked tool 'python ../merge' for rev (binary False symlink False)
276 276 merging rev
277 277 my rev@86a2aa42fc76+ other rev@97c705ade336 ancestor rev@924404dff337
278 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
278 launching merge tool: python ../merge *$TESTTMP/t/t/rev* * * (glob)
279 279 merge tool returned: 0
280 280 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
281 281 (branch merge, don't forget to commit)
282 282 --------------
283 283 C a
284 284 C b
285 285 --------------
286 286
287 287 $ tm " " "nm a b" " " "7 get b"
288 288 created new head
289 289 --------------
290 290 test L: R:nm a b W: - 7 get b
291 291 --------------
292 292 searching for copies back to rev 1
293 293 unmatched files in other:
294 294 b
295 295 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
296 296 src: 'a' -> dst: 'b'
297 297 checking for directory renames
298 298 resolving manifests
299 299 branchmerge: True, force: False, partial: False
300 300 ancestor: 924404dff337, local: 94b33a1b7f2d+, remote: bdb19105162a
301 301 preserving rev for resolve of rev
302 302 a: other deleted -> r
303 303 removing a
304 304 updating: a 1/3 files (33.33%)
305 305 b: remote created -> g
306 306 getting b
307 307 updating: b 2/3 files (66.67%)
308 308 rev: versions differ -> m
309 309 updating: rev 3/3 files (100.00%)
310 310 picked tool 'python ../merge' for rev (binary False symlink False)
311 311 merging rev
312 312 my rev@94b33a1b7f2d+ other rev@bdb19105162a ancestor rev@924404dff337
313 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
313 launching merge tool: python ../merge *$TESTTMP/t/t/rev* * * (glob)
314 314 merge tool returned: 0
315 315 1 files updated, 1 files merged, 1 files removed, 0 files unresolved
316 316 (branch merge, don't forget to commit)
317 317 --------------
318 318 M b
319 319 --------------
320 320
321 321 $ tm "nm a b" " " " " "8 nothing"
322 322 created new head
323 323 --------------
324 324 test L:nm a b R: W: - 8 nothing
325 325 --------------
326 326 searching for copies back to rev 1
327 327 unmatched files in local:
328 328 b
329 329 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
330 330 src: 'a' -> dst: 'b'
331 331 checking for directory renames
332 332 resolving manifests
333 333 branchmerge: True, force: False, partial: False
334 334 ancestor: 924404dff337, local: 02963e448370+, remote: 97c705ade336
335 335 preserving rev for resolve of rev
336 336 rev: versions differ -> m
337 337 updating: rev 1/1 files (100.00%)
338 338 picked tool 'python ../merge' for rev (binary False symlink False)
339 339 merging rev
340 340 my rev@02963e448370+ other rev@97c705ade336 ancestor rev@924404dff337
341 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
341 launching merge tool: python ../merge *$TESTTMP/t/t/rev* * * (glob)
342 342 merge tool returned: 0
343 343 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
344 344 (branch merge, don't forget to commit)
345 345 --------------
346 346 C b
347 347 --------------
348 348
349 349 $ tm "um a b" "um a b" " " "9 do merge with ancestor in a"
350 350 created new head
351 351 --------------
352 352 test L:um a b R:um a b W: - 9 do merge with ancestor in a
353 353 --------------
354 354 searching for copies back to rev 1
355 355 unmatched files new in both:
356 356 b
357 357 resolving manifests
358 358 branchmerge: True, force: False, partial: False
359 359 ancestor: 924404dff337, local: 62e7bf090eba+, remote: 49b6d8032493
360 360 preserving b for resolve of b
361 361 preserving rev for resolve of rev
362 362 b: both renamed from a -> m
363 363 updating: b 1/2 files (50.00%)
364 364 picked tool 'python ../merge' for b (binary False symlink False)
365 365 merging b
366 366 my b@62e7bf090eba+ other b@49b6d8032493 ancestor a@924404dff337
367 launching merge tool: python ../merge $TESTTMP/t/t/b * * (glob)
367 launching merge tool: python ../merge *$TESTTMP/t/t/b* * * (glob)
368 368 merge tool returned: 0
369 369 rev: versions differ -> m
370 370 updating: rev 2/2 files (100.00%)
371 371 picked tool 'python ../merge' for rev (binary False symlink False)
372 372 merging rev
373 373 my rev@62e7bf090eba+ other rev@49b6d8032493 ancestor rev@924404dff337
374 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
374 launching merge tool: python ../merge *$TESTTMP/t/t/rev* * * (glob)
375 375 merge tool returned: 0
376 376 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
377 377 (branch merge, don't forget to commit)
378 378 --------------
379 379 M b
380 380 --------------
381 381
382 382
383 383 m "um a c" "um x c" " " "10 do merge with no ancestor"
384 384
385 385 $ tm "nm a b" "nm a c" " " "11 get c, keep b"
386 386 created new head
387 387 --------------
388 388 test L:nm a b R:nm a c W: - 11 get c, keep b
389 389 --------------
390 390 searching for copies back to rev 1
391 391 unmatched files in local:
392 392 b
393 393 unmatched files in other:
394 394 c
395 395 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
396 396 src: 'a' -> dst: 'b' !
397 397 src: 'a' -> dst: 'c' !
398 398 checking for directory renames
399 399 resolving manifests
400 400 branchmerge: True, force: False, partial: False
401 401 ancestor: 924404dff337, local: 02963e448370+, remote: fe905ef2c33e
402 402 preserving rev for resolve of rev
403 403 c: remote created -> g
404 404 getting c
405 405 updating: c 1/2 files (50.00%)
406 406 rev: versions differ -> m
407 407 updating: rev 2/2 files (100.00%)
408 408 picked tool 'python ../merge' for rev (binary False symlink False)
409 409 merging rev
410 410 my rev@02963e448370+ other rev@fe905ef2c33e ancestor rev@924404dff337
411 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
411 launching merge tool: python ../merge *$TESTTMP/t/t/rev* * * (glob)
412 412 merge tool returned: 0
413 413 note: possible conflict - a was renamed multiple times to:
414 414 b
415 415 c
416 416 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
417 417 (branch merge, don't forget to commit)
418 418 --------------
419 419 M c
420 420 C b
421 421 --------------
422 422
423 423 $ tm "nc a b" "up b " " " "12 merge b no ancestor"
424 424 created new head
425 425 --------------
426 426 test L:nc a b R:up b W: - 12 merge b no ancestor
427 427 --------------
428 428 searching for copies back to rev 1
429 429 unmatched files new in both:
430 430 b
431 431 resolving manifests
432 432 branchmerge: True, force: False, partial: False
433 433 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: af30c7647fc7
434 434 preserving b for resolve of b
435 435 preserving rev for resolve of rev
436 436 b: both created -> m
437 437 updating: b 1/2 files (50.00%)
438 438 picked tool 'python ../merge' for b (binary False symlink False)
439 439 merging b
440 440 my b@86a2aa42fc76+ other b@af30c7647fc7 ancestor b@000000000000
441 launching merge tool: python ../merge $TESTTMP/t/t/b * * (glob)
441 launching merge tool: python ../merge *$TESTTMP/t/t/b* * * (glob)
442 442 merge tool returned: 0
443 443 rev: versions differ -> m
444 444 updating: rev 2/2 files (100.00%)
445 445 picked tool 'python ../merge' for rev (binary False symlink False)
446 446 merging rev
447 447 my rev@86a2aa42fc76+ other rev@af30c7647fc7 ancestor rev@924404dff337
448 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
448 launching merge tool: python ../merge *$TESTTMP/t/t/rev* * * (glob)
449 449 merge tool returned: 0
450 450 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
451 451 (branch merge, don't forget to commit)
452 452 --------------
453 453 M b
454 454 C a
455 455 --------------
456 456
457 457 $ tm "up b " "nm a b" " " "13 merge b no ancestor"
458 458 created new head
459 459 --------------
460 460 test L:up b R:nm a b W: - 13 merge b no ancestor
461 461 --------------
462 462 searching for copies back to rev 1
463 463 unmatched files new in both:
464 464 b
465 465 resolving manifests
466 466 branchmerge: True, force: False, partial: False
467 467 ancestor: 924404dff337, local: 59318016310c+, remote: bdb19105162a
468 468 preserving b for resolve of b
469 469 preserving rev for resolve of rev
470 470 a: other deleted -> r
471 471 removing a
472 472 updating: a 1/3 files (33.33%)
473 473 b: both created -> m
474 474 updating: b 2/3 files (66.67%)
475 475 picked tool 'python ../merge' for b (binary False symlink False)
476 476 merging b
477 477 my b@59318016310c+ other b@bdb19105162a ancestor b@000000000000
478 launching merge tool: python ../merge $TESTTMP/t/t/b * * (glob)
478 launching merge tool: python ../merge *$TESTTMP/t/t/b* * * (glob)
479 479 merge tool returned: 0
480 480 rev: versions differ -> m
481 481 updating: rev 3/3 files (100.00%)
482 482 picked tool 'python ../merge' for rev (binary False symlink False)
483 483 merging rev
484 484 my rev@59318016310c+ other rev@bdb19105162a ancestor rev@924404dff337
485 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
485 launching merge tool: python ../merge *$TESTTMP/t/t/rev* * * (glob)
486 486 merge tool returned: 0
487 487 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
488 488 (branch merge, don't forget to commit)
489 489 --------------
490 490 M b
491 491 --------------
492 492
493 493 $ tm "nc a b" "up a b" " " "14 merge b no ancestor"
494 494 created new head
495 495 --------------
496 496 test L:nc a b R:up a b W: - 14 merge b no ancestor
497 497 --------------
498 498 searching for copies back to rev 1
499 499 unmatched files new in both:
500 500 b
501 501 resolving manifests
502 502 branchmerge: True, force: False, partial: False
503 503 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 8dbce441892a
504 504 preserving b for resolve of b
505 505 preserving rev for resolve of rev
506 506 a: remote is newer -> g
507 507 getting a
508 508 updating: a 1/3 files (33.33%)
509 509 b: both created -> m
510 510 updating: b 2/3 files (66.67%)
511 511 picked tool 'python ../merge' for b (binary False symlink False)
512 512 merging b
513 513 my b@86a2aa42fc76+ other b@8dbce441892a ancestor b@000000000000
514 launching merge tool: python ../merge $TESTTMP/t/t/b * * (glob)
514 launching merge tool: python ../merge *$TESTTMP/t/t/b* * * (glob)
515 515 merge tool returned: 0
516 516 rev: versions differ -> m
517 517 updating: rev 3/3 files (100.00%)
518 518 picked tool 'python ../merge' for rev (binary False symlink False)
519 519 merging rev
520 520 my rev@86a2aa42fc76+ other rev@8dbce441892a ancestor rev@924404dff337
521 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
521 launching merge tool: python ../merge *$TESTTMP/t/t/rev* * * (glob)
522 522 merge tool returned: 0
523 523 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
524 524 (branch merge, don't forget to commit)
525 525 --------------
526 526 M a
527 527 M b
528 528 --------------
529 529
530 530 $ tm "up b " "nm a b" " " "15 merge b no ancestor, remove a"
531 531 created new head
532 532 --------------
533 533 test L:up b R:nm a b W: - 15 merge b no ancestor, remove a
534 534 --------------
535 535 searching for copies back to rev 1
536 536 unmatched files new in both:
537 537 b
538 538 resolving manifests
539 539 branchmerge: True, force: False, partial: False
540 540 ancestor: 924404dff337, local: 59318016310c+, remote: bdb19105162a
541 541 preserving b for resolve of b
542 542 preserving rev for resolve of rev
543 543 a: other deleted -> r
544 544 removing a
545 545 updating: a 1/3 files (33.33%)
546 546 b: both created -> m
547 547 updating: b 2/3 files (66.67%)
548 548 picked tool 'python ../merge' for b (binary False symlink False)
549 549 merging b
550 550 my b@59318016310c+ other b@bdb19105162a ancestor b@000000000000
551 launching merge tool: python ../merge $TESTTMP/t/t/b * * (glob)
551 launching merge tool: python ../merge *$TESTTMP/t/t/b* * * (glob)
552 552 merge tool returned: 0
553 553 rev: versions differ -> m
554 554 updating: rev 3/3 files (100.00%)
555 555 picked tool 'python ../merge' for rev (binary False symlink False)
556 556 merging rev
557 557 my rev@59318016310c+ other rev@bdb19105162a ancestor rev@924404dff337
558 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
558 launching merge tool: python ../merge *$TESTTMP/t/t/rev* * * (glob)
559 559 merge tool returned: 0
560 560 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
561 561 (branch merge, don't forget to commit)
562 562 --------------
563 563 M b
564 564 --------------
565 565
566 566 $ tm "nc a b" "up a b" " " "16 get a, merge b no ancestor"
567 567 created new head
568 568 --------------
569 569 test L:nc a b R:up a b W: - 16 get a, merge b no ancestor
570 570 --------------
571 571 searching for copies back to rev 1
572 572 unmatched files new in both:
573 573 b
574 574 resolving manifests
575 575 branchmerge: True, force: False, partial: False
576 576 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 8dbce441892a
577 577 preserving b for resolve of b
578 578 preserving rev for resolve of rev
579 579 a: remote is newer -> g
580 580 getting a
581 581 updating: a 1/3 files (33.33%)
582 582 b: both created -> m
583 583 updating: b 2/3 files (66.67%)
584 584 picked tool 'python ../merge' for b (binary False symlink False)
585 585 merging b
586 586 my b@86a2aa42fc76+ other b@8dbce441892a ancestor b@000000000000
587 launching merge tool: python ../merge $TESTTMP/t/t/b * * (glob)
587 launching merge tool: python ../merge *$TESTTMP/t/t/b* * * (glob)
588 588 merge tool returned: 0
589 589 rev: versions differ -> m
590 590 updating: rev 3/3 files (100.00%)
591 591 picked tool 'python ../merge' for rev (binary False symlink False)
592 592 merging rev
593 593 my rev@86a2aa42fc76+ other rev@8dbce441892a ancestor rev@924404dff337
594 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
594 launching merge tool: python ../merge *$TESTTMP/t/t/rev* * * (glob)
595 595 merge tool returned: 0
596 596 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
597 597 (branch merge, don't forget to commit)
598 598 --------------
599 599 M a
600 600 M b
601 601 --------------
602 602
603 603 $ tm "up a b" "nc a b" " " "17 keep a, merge b no ancestor"
604 604 created new head
605 605 --------------
606 606 test L:up a b R:nc a b W: - 17 keep a, merge b no ancestor
607 607 --------------
608 608 searching for copies back to rev 1
609 609 unmatched files new in both:
610 610 b
611 611 resolving manifests
612 612 branchmerge: True, force: False, partial: False
613 613 ancestor: 924404dff337, local: 0b76e65c8289+, remote: 4ce40f5aca24
614 614 preserving b for resolve of b
615 615 preserving rev for resolve of rev
616 616 a: remote unchanged -> k
617 617 b: both created -> m
618 618 updating: b 1/2 files (50.00%)
619 619 picked tool 'python ../merge' for b (binary False symlink False)
620 620 merging b
621 621 my b@0b76e65c8289+ other b@4ce40f5aca24 ancestor b@000000000000
622 launching merge tool: python ../merge $TESTTMP/t/t/b * * (glob)
622 launching merge tool: python ../merge *$TESTTMP/t/t/b* * * (glob)
623 623 merge tool returned: 0
624 624 rev: versions differ -> m
625 625 updating: rev 2/2 files (100.00%)
626 626 picked tool 'python ../merge' for rev (binary False symlink False)
627 627 merging rev
628 628 my rev@0b76e65c8289+ other rev@4ce40f5aca24 ancestor rev@924404dff337
629 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
629 launching merge tool: python ../merge *$TESTTMP/t/t/rev* * * (glob)
630 630 merge tool returned: 0
631 631 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
632 632 (branch merge, don't forget to commit)
633 633 --------------
634 634 M b
635 635 C a
636 636 --------------
637 637
638 638 $ tm "nm a b" "up a b" " " "18 merge b no ancestor"
639 639 created new head
640 640 --------------
641 641 test L:nm a b R:up a b W: - 18 merge b no ancestor
642 642 --------------
643 643 searching for copies back to rev 1
644 644 unmatched files new in both:
645 645 b
646 646 resolving manifests
647 647 branchmerge: True, force: False, partial: False
648 648 ancestor: 924404dff337, local: 02963e448370+, remote: 8dbce441892a
649 649 remote changed a which local deleted
650 650 use (c)hanged version or leave (d)eleted? c
651 651 preserving b for resolve of b
652 652 preserving rev for resolve of rev
653 653 a: prompt recreating -> g
654 654 getting a
655 655 updating: a 1/3 files (33.33%)
656 656 b: both created -> m
657 657 updating: b 2/3 files (66.67%)
658 658 picked tool 'python ../merge' for b (binary False symlink False)
659 659 merging b
660 660 my b@02963e448370+ other b@8dbce441892a ancestor b@000000000000
661 launching merge tool: python ../merge $TESTTMP/t/t/b * * (glob)
661 launching merge tool: python ../merge *$TESTTMP/t/t/b* * * (glob)
662 662 merge tool returned: 0
663 663 rev: versions differ -> m
664 664 updating: rev 3/3 files (100.00%)
665 665 picked tool 'python ../merge' for rev (binary False symlink False)
666 666 merging rev
667 667 my rev@02963e448370+ other rev@8dbce441892a ancestor rev@924404dff337
668 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
668 launching merge tool: python ../merge *$TESTTMP/t/t/rev* * * (glob)
669 669 merge tool returned: 0
670 670 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
671 671 (branch merge, don't forget to commit)
672 672 --------------
673 673 M a
674 674 M b
675 675 --------------
676 676
677 677 $ tm "up a b" "nm a b" " " "19 merge b no ancestor, prompt remove a"
678 678 created new head
679 679 --------------
680 680 test L:up a b R:nm a b W: - 19 merge b no ancestor, prompt remove a
681 681 --------------
682 682 searching for copies back to rev 1
683 683 unmatched files new in both:
684 684 b
685 685 resolving manifests
686 686 branchmerge: True, force: False, partial: False
687 687 ancestor: 924404dff337, local: 0b76e65c8289+, remote: bdb19105162a
688 688 local changed a which remote deleted
689 689 use (c)hanged version or (d)elete? c
690 690 preserving b for resolve of b
691 691 preserving rev for resolve of rev
692 692 a: prompt keep -> a
693 693 updating: a 1/3 files (33.33%)
694 694 b: both created -> m
695 695 updating: b 2/3 files (66.67%)
696 696 picked tool 'python ../merge' for b (binary False symlink False)
697 697 merging b
698 698 my b@0b76e65c8289+ other b@bdb19105162a ancestor b@000000000000
699 launching merge tool: python ../merge $TESTTMP/t/t/b * * (glob)
699 launching merge tool: python ../merge *$TESTTMP/t/t/b* * * (glob)
700 700 merge tool returned: 0
701 701 rev: versions differ -> m
702 702 updating: rev 3/3 files (100.00%)
703 703 picked tool 'python ../merge' for rev (binary False symlink False)
704 704 merging rev
705 705 my rev@0b76e65c8289+ other rev@bdb19105162a ancestor rev@924404dff337
706 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
706 launching merge tool: python ../merge *$TESTTMP/t/t/rev* * * (glob)
707 707 merge tool returned: 0
708 708 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
709 709 (branch merge, don't forget to commit)
710 710 --------------
711 711 M b
712 712 C a
713 713 --------------
714 714
715 715 $ tm "up a " "um a b" " " "20 merge a and b to b, remove a"
716 716 created new head
717 717 --------------
718 718 test L:up a R:um a b W: - 20 merge a and b to b, remove a
719 719 --------------
720 720 searching for copies back to rev 1
721 721 unmatched files in other:
722 722 b
723 723 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
724 724 src: 'a' -> dst: 'b' *
725 725 checking for directory renames
726 726 resolving manifests
727 727 branchmerge: True, force: False, partial: False
728 728 ancestor: 924404dff337, local: e300d1c794ec+, remote: 49b6d8032493
729 729 preserving a for resolve of b
730 730 preserving rev for resolve of rev
731 731 removing a
732 732 b: remote moved from a -> m
733 733 updating: b 1/2 files (50.00%)
734 734 picked tool 'python ../merge' for b (binary False symlink False)
735 735 merging a and b to b
736 736 my b@e300d1c794ec+ other b@49b6d8032493 ancestor a@924404dff337
737 launching merge tool: python ../merge $TESTTMP/t/t/b * * (glob)
737 launching merge tool: python ../merge *$TESTTMP/t/t/b* * * (glob)
738 738 merge tool returned: 0
739 739 rev: versions differ -> m
740 740 updating: rev 2/2 files (100.00%)
741 741 picked tool 'python ../merge' for rev (binary False symlink False)
742 742 merging rev
743 743 my rev@e300d1c794ec+ other rev@49b6d8032493 ancestor rev@924404dff337
744 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
744 launching merge tool: python ../merge *$TESTTMP/t/t/rev* * * (glob)
745 745 merge tool returned: 0
746 746 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
747 747 (branch merge, don't forget to commit)
748 748 --------------
749 749 M b
750 750 a
751 751 --------------
752 752
753 753 $ tm "um a b" "up a " " " "21 merge a and b to b"
754 754 created new head
755 755 --------------
756 756 test L:um a b R:up a W: - 21 merge a and b to b
757 757 --------------
758 758 searching for copies back to rev 1
759 759 unmatched files in local:
760 760 b
761 761 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
762 762 src: 'a' -> dst: 'b' *
763 763 checking for directory renames
764 764 resolving manifests
765 765 branchmerge: True, force: False, partial: False
766 766 ancestor: 924404dff337, local: 62e7bf090eba+, remote: f4db7e329e71
767 767 preserving b for resolve of b
768 768 preserving rev for resolve of rev
769 769 b: local copied/moved from a -> m
770 770 updating: b 1/2 files (50.00%)
771 771 picked tool 'python ../merge' for b (binary False symlink False)
772 772 merging b and a to b
773 773 my b@62e7bf090eba+ other a@f4db7e329e71 ancestor a@924404dff337
774 launching merge tool: python ../merge $TESTTMP/t/t/b * * (glob)
774 launching merge tool: python ../merge *$TESTTMP/t/t/b* * * (glob)
775 775 merge tool returned: 0
776 776 rev: versions differ -> m
777 777 updating: rev 2/2 files (100.00%)
778 778 picked tool 'python ../merge' for rev (binary False symlink False)
779 779 merging rev
780 780 my rev@62e7bf090eba+ other rev@f4db7e329e71 ancestor rev@924404dff337
781 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
781 launching merge tool: python ../merge *$TESTTMP/t/t/rev* * * (glob)
782 782 merge tool returned: 0
783 783 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
784 784 (branch merge, don't forget to commit)
785 785 --------------
786 786 M b
787 787 a
788 788 --------------
789 789
790 790
791 791 m "nm a b" "um x a" " " "22 get a, keep b"
792 792
793 793 $ tm "nm a b" "up a c" " " "23 get c, keep b"
794 794 created new head
795 795 --------------
796 796 test L:nm a b R:up a c W: - 23 get c, keep b
797 797 --------------
798 798 searching for copies back to rev 1
799 799 unmatched files in local:
800 800 b
801 801 unmatched files in other:
802 802 c
803 803 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
804 804 src: 'a' -> dst: 'b' *
805 805 checking for directory renames
806 806 resolving manifests
807 807 branchmerge: True, force: False, partial: False
808 808 ancestor: 924404dff337, local: 02963e448370+, remote: 2b958612230f
809 809 preserving b for resolve of b
810 810 preserving rev for resolve of rev
811 811 c: remote created -> g
812 812 getting c
813 813 updating: c 1/3 files (33.33%)
814 814 b: local copied/moved from a -> m
815 815 updating: b 2/3 files (66.67%)
816 816 picked tool 'python ../merge' for b (binary False symlink False)
817 817 merging b and a to b
818 818 my b@02963e448370+ other a@2b958612230f ancestor a@924404dff337
819 819 premerge successful
820 820 rev: versions differ -> m
821 821 updating: rev 3/3 files (100.00%)
822 822 picked tool 'python ../merge' for rev (binary False symlink False)
823 823 merging rev
824 824 my rev@02963e448370+ other rev@2b958612230f ancestor rev@924404dff337
825 launching merge tool: python ../merge $TESTTMP/t/t/rev * * (glob)
825 launching merge tool: python ../merge *$TESTTMP/t/t/rev* * * (glob)
826 826 merge tool returned: 0
827 827 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
828 828 (branch merge, don't forget to commit)
829 829 --------------
830 830 M b
831 831 a
832 832 M c
833 833 --------------
834 834
835 835
836 836 $ cd ..
837 837
838 838
839 839 Systematic and terse testing of merge merges and ancestor calculation:
840 840
841 841 Expected result:
842 842
843 843 \ a m1 m2 dst
844 844 0 - f f f "versions differ"
845 845 1 f g g g "versions differ"
846 846 2 f f f f "versions differ"
847 847 3 f f g f+g "remote copied to " + f
848 848 4 f f g g "remote moved to " + f
849 849 5 f g f f+g "local copied to " + f2
850 850 6 f g f g "local moved to " + f2
851 851 7 - (f) f f "remote differs from untracked local"
852 852 8 f (f) f f "remote differs from untracked local"
853 853
854 854 $ hg init ancestortest
855 855 $ cd ancestortest
856 856 $ for x in 1 2 3 4 5 6 8; do mkdir $x; echo a > $x/f; done
857 857 $ hg ci -Aqm "a"
858 858 $ mkdir 0
859 859 $ touch 0/f
860 860 $ hg mv 1/f 1/g
861 861 $ hg cp 5/f 5/g
862 862 $ hg mv 6/f 6/g
863 863 $ hg rm 8/f
864 864 $ for x in */*; do echo m1 > $x; done
865 865 $ hg ci -Aqm "m1"
866 866 $ hg up -qr0
867 867 $ mkdir 0 7
868 868 $ touch 0/f 7/f
869 869 $ hg mv 1/f 1/g
870 870 $ hg cp 3/f 3/g
871 871 $ hg mv 4/f 4/g
872 872 $ for x in */*; do echo m2 > $x; done
873 873 $ hg ci -Aqm "m2"
874 874 $ hg up -qr1
875 875 $ mkdir 7 8
876 876 $ echo m > 7/f
877 877 $ echo m > 8/f
878 878 $ hg merge -f --tool internal:dump -v --debug -r2 | sed '/^updating:/,$d' 2> /dev/null
879 879 searching for copies back to rev 1
880 880 unmatched files in local:
881 881 5/g
882 882 6/g
883 883 unmatched files in other:
884 884 3/g
885 885 4/g
886 886 7/f
887 887 unmatched files new in both:
888 888 0/f
889 889 1/g
890 890 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
891 891 src: '3/f' -> dst: '3/g' *
892 892 src: '4/f' -> dst: '4/g' *
893 893 src: '5/f' -> dst: '5/g' *
894 894 src: '6/f' -> dst: '6/g' *
895 895 checking for directory renames
896 896 resolving manifests
897 897 branchmerge: True, force: True, partial: False
898 898 ancestor: e6cb3cf11019, local: ec44bf929ab5+, remote: c62e34d0b898
899 899 remote changed 8/f which local deleted
900 900 use (c)hanged version or leave (d)eleted? c
901 901 preserving 0/f for resolve of 0/f
902 902 preserving 1/g for resolve of 1/g
903 903 preserving 2/f for resolve of 2/f
904 904 preserving 3/f for resolve of 3/f
905 905 preserving 3/f for resolve of 3/g
906 906 preserving 4/f for resolve of 4/g
907 907 preserving 5/f for resolve of 5/f
908 908 preserving 5/g for resolve of 5/g
909 909 preserving 6/g for resolve of 6/g
910 910 preserving 7/f for resolve of 7/f
911 911 removing 4/f
912 912 8/f: prompt recreating -> g
913 913 getting 8/f
914 914 $ hg mani
915 915 0/f
916 916 1/g
917 917 2/f
918 918 3/f
919 919 4/f
920 920 5/f
921 921 5/g
922 922 6/g
923 923 $ for f in */*; do echo $f:; cat $f; done
924 924 0/f:
925 925 m1
926 926 0/f.base:
927 927 0/f.local:
928 928 m1
929 929 0/f.orig:
930 930 m1
931 931 0/f.other:
932 932 m2
933 933 1/g:
934 934 m1
935 935 1/g.base:
936 936 a
937 937 1/g.local:
938 938 m1
939 939 1/g.orig:
940 940 m1
941 941 1/g.other:
942 942 m2
943 943 2/f:
944 944 m1
945 945 2/f.base:
946 946 a
947 947 2/f.local:
948 948 m1
949 949 2/f.orig:
950 950 m1
951 951 2/f.other:
952 952 m2
953 953 3/f:
954 954 m1
955 955 3/f.base:
956 956 a
957 957 3/f.local:
958 958 m1
959 959 3/f.orig:
960 960 m1
961 961 3/f.other:
962 962 m2
963 963 3/g:
964 964 m1
965 965 3/g.base:
966 966 a
967 967 3/g.local:
968 968 m1
969 969 3/g.orig:
970 970 m1
971 971 3/g.other:
972 972 m2
973 973 4/g:
974 974 m1
975 975 4/g.base:
976 976 a
977 977 4/g.local:
978 978 m1
979 979 4/g.orig:
980 980 m1
981 981 4/g.other:
982 982 m2
983 983 5/f:
984 984 m1
985 985 5/f.base:
986 986 a
987 987 5/f.local:
988 988 m1
989 989 5/f.orig:
990 990 m1
991 991 5/f.other:
992 992 m2
993 993 5/g:
994 994 m1
995 995 5/g.base:
996 996 a
997 997 5/g.local:
998 998 m1
999 999 5/g.orig:
1000 1000 m1
1001 1001 5/g.other:
1002 1002 m2
1003 1003 6/g:
1004 1004 m1
1005 1005 6/g.base:
1006 1006 a
1007 1007 6/g.local:
1008 1008 m1
1009 1009 6/g.orig:
1010 1010 m1
1011 1011 6/g.other:
1012 1012 m2
1013 1013 7/f:
1014 1014 m
1015 1015 7/f.base:
1016 1016 7/f.local:
1017 1017 m
1018 1018 7/f.orig:
1019 1019 m
1020 1020 7/f.other:
1021 1021 m2
1022 1022 8/f:
1023 1023 m2
1024 1024 $ cd ..
@@ -1,228 +1,228 b''
1 1 $ HGMERGE=true; export HGMERGE
2 2
3 3 $ hg init r1
4 4 $ cd r1
5 5 $ echo a > a
6 6 $ hg addremove
7 7 adding a
8 8 $ hg commit -m "1"
9 9
10 10 $ hg clone . ../r2
11 11 updating to branch default
12 12 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
13 13 $ cd ../r2
14 14 $ hg up
15 15 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
16 16 $ echo abc > a
17 17 $ hg diff --nodates
18 18 diff -r c19d34741b0a a
19 19 --- a/a
20 20 +++ b/a
21 21 @@ -1,1 +1,1 @@
22 22 -a
23 23 +abc
24 24
25 25 $ cd ../r1
26 26 $ echo b > b
27 27 $ echo a2 > a
28 28 $ hg addremove
29 29 adding b
30 30 $ hg commit -m "2"
31 31
32 32 $ cd ../r2
33 33 $ hg -q pull ../r1
34 34 $ hg status
35 35 M a
36 36 $ hg parents
37 37 changeset: 0:c19d34741b0a
38 38 user: test
39 39 date: Thu Jan 01 00:00:00 1970 +0000
40 40 summary: 1
41 41
42 42 $ hg --debug up
43 43 searching for copies back to rev 1
44 44 unmatched files in other:
45 45 b
46 46 resolving manifests
47 47 branchmerge: False, force: False, partial: False
48 48 ancestor: c19d34741b0a, local: c19d34741b0a+, remote: 1e71731e6fbb
49 49 preserving a for resolve of a
50 50 b: remote created -> g
51 51 getting b
52 52 updating: b 1/2 files (50.00%)
53 53 a: versions differ -> m
54 54 updating: a 2/2 files (100.00%)
55 55 picked tool 'true' for a (binary False symlink False)
56 56 merging a
57 57 my a@c19d34741b0a+ other a@1e71731e6fbb ancestor a@c19d34741b0a
58 launching merge tool: true $TESTTMP/r2/a * (glob)
58 launching merge tool: true *$TESTTMP/r2/a* * (glob)
59 59 merge tool returned: 0
60 60 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
61 61 $ hg parents
62 62 changeset: 1:1e71731e6fbb
63 63 tag: tip
64 64 user: test
65 65 date: Thu Jan 01 00:00:00 1970 +0000
66 66 summary: 2
67 67
68 68 $ hg --debug up 0
69 69 resolving manifests
70 70 branchmerge: False, force: False, partial: False
71 71 ancestor: 1e71731e6fbb, local: 1e71731e6fbb+, remote: c19d34741b0a
72 72 preserving a for resolve of a
73 73 b: other deleted -> r
74 74 removing b
75 75 updating: b 1/2 files (50.00%)
76 76 a: versions differ -> m
77 77 updating: a 2/2 files (100.00%)
78 78 picked tool 'true' for a (binary False symlink False)
79 79 merging a
80 80 my a@1e71731e6fbb+ other a@c19d34741b0a ancestor a@1e71731e6fbb
81 launching merge tool: true $TESTTMP/r2/a * (glob)
81 launching merge tool: true *$TESTTMP/r2/a* * (glob)
82 82 merge tool returned: 0
83 83 0 files updated, 1 files merged, 1 files removed, 0 files unresolved
84 84 $ hg parents
85 85 changeset: 0:c19d34741b0a
86 86 user: test
87 87 date: Thu Jan 01 00:00:00 1970 +0000
88 88 summary: 1
89 89
90 90 $ hg parents
91 91 changeset: 0:c19d34741b0a
92 92 user: test
93 93 date: Thu Jan 01 00:00:00 1970 +0000
94 94 summary: 1
95 95
96 96 $ hg --debug up
97 97 searching for copies back to rev 1
98 98 unmatched files in other:
99 99 b
100 100 resolving manifests
101 101 branchmerge: False, force: False, partial: False
102 102 ancestor: c19d34741b0a, local: c19d34741b0a+, remote: 1e71731e6fbb
103 103 preserving a for resolve of a
104 104 b: remote created -> g
105 105 getting b
106 106 updating: b 1/2 files (50.00%)
107 107 a: versions differ -> m
108 108 updating: a 2/2 files (100.00%)
109 109 picked tool 'true' for a (binary False symlink False)
110 110 merging a
111 111 my a@c19d34741b0a+ other a@1e71731e6fbb ancestor a@c19d34741b0a
112 launching merge tool: true $TESTTMP/r2/a * (glob)
112 launching merge tool: true *$TESTTMP/r2/a* * (glob)
113 113 merge tool returned: 0
114 114 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
115 115 $ hg parents
116 116 changeset: 1:1e71731e6fbb
117 117 tag: tip
118 118 user: test
119 119 date: Thu Jan 01 00:00:00 1970 +0000
120 120 summary: 2
121 121
122 122 $ hg -v history
123 123 changeset: 1:1e71731e6fbb
124 124 tag: tip
125 125 user: test
126 126 date: Thu Jan 01 00:00:00 1970 +0000
127 127 files: a b
128 128 description:
129 129 2
130 130
131 131
132 132 changeset: 0:c19d34741b0a
133 133 user: test
134 134 date: Thu Jan 01 00:00:00 1970 +0000
135 135 files: a
136 136 description:
137 137 1
138 138
139 139
140 140 $ hg diff --nodates
141 141 diff -r 1e71731e6fbb a
142 142 --- a/a
143 143 +++ b/a
144 144 @@ -1,1 +1,1 @@
145 145 -a2
146 146 +abc
147 147
148 148
149 149 create a second head
150 150
151 151 $ cd ../r1
152 152 $ hg up 0
153 153 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
154 154 $ echo b2 > b
155 155 $ echo a3 > a
156 156 $ hg addremove
157 157 adding b
158 158 $ hg commit -m "3"
159 159 created new head
160 160
161 161 $ cd ../r2
162 162 $ hg -q pull ../r1
163 163 $ hg status
164 164 M a
165 165 $ hg parents
166 166 changeset: 1:1e71731e6fbb
167 167 user: test
168 168 date: Thu Jan 01 00:00:00 1970 +0000
169 169 summary: 2
170 170
171 171 $ hg --debug up
172 172 abort: uncommitted changes
173 173 (commit and merge, or update --clean to discard changes)
174 174 [255]
175 175
176 176 test conflicting untracked files
177 177
178 178 $ hg up -qC 0
179 179 $ echo untracked > b
180 180 $ hg st
181 181 ? b
182 182 $ hg up 1
183 183 b: untracked file differs
184 184 abort: untracked files in working directory differ from files in requested revision
185 185 [255]
186 186 $ rm b
187 187
188 188 test conflicting untracked ignored file
189 189
190 190 $ hg up -qC 0
191 191 $ echo ignored > .hgignore
192 192 $ hg add .hgignore
193 193 $ hg ci -m 'add .hgignore'
194 194 created new head
195 195 $ echo ignored > ignored
196 196 $ hg add ignored
197 197 $ hg ci -m 'add ignored file'
198 198
199 199 $ hg up -q 'desc("add .hgignore")'
200 200 $ echo untracked > ignored
201 201 $ hg st
202 202 $ hg up 'desc("add ignored file")'
203 203 ignored: untracked file differs
204 204 abort: untracked files in working directory differ from files in requested revision
205 205 [255]
206 206
207 207 test a local add
208 208
209 209 $ cd ..
210 210 $ hg init a
211 211 $ hg init b
212 212 $ echo a > a/a
213 213 $ echo a > b/a
214 214 $ hg --cwd a commit -A -m a
215 215 adding a
216 216 $ cd b
217 217 $ hg add a
218 218 $ hg pull -u ../a
219 219 pulling from ../a
220 220 requesting all changes
221 221 adding changesets
222 222 adding manifests
223 223 adding file changes
224 224 added 1 changesets with 1 changes to 1 files
225 225 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
226 226 $ hg st
227 227
228 228 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now