##// END OF EJS Templates
merge: changing the mode of a file is also an update...
Mads Kiilerich -
r18334:44bda93d default
parent child Browse files
Show More
@@ -1,651 +1,652
1 1 # merge.py - directory-level update/merge handling for Mercurial
2 2 #
3 3 # Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
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 node import nullid, nullrev, hex, bin
9 9 from i18n import _
10 10 import error, util, filemerge, copies, subrepo
11 11 import errno, os, shutil
12 12
13 13 class mergestate(object):
14 14 '''track 3-way merge state of individual files'''
15 15 def __init__(self, repo):
16 16 self._repo = repo
17 17 self._dirty = False
18 18 self._read()
19 19 def reset(self, node=None):
20 20 self._state = {}
21 21 if node:
22 22 self._local = node
23 23 shutil.rmtree(self._repo.join("merge"), True)
24 24 self._dirty = False
25 25 def _read(self):
26 26 self._state = {}
27 27 try:
28 28 f = self._repo.opener("merge/state")
29 29 for i, l in enumerate(f):
30 30 if i == 0:
31 31 self._local = bin(l[:-1])
32 32 else:
33 33 bits = l[:-1].split("\0")
34 34 self._state[bits[0]] = bits[1:]
35 35 f.close()
36 36 except IOError, err:
37 37 if err.errno != errno.ENOENT:
38 38 raise
39 39 self._dirty = False
40 40 def commit(self):
41 41 if self._dirty:
42 42 f = self._repo.opener("merge/state", "w")
43 43 f.write(hex(self._local) + "\n")
44 44 for d, v in self._state.iteritems():
45 45 f.write("\0".join([d] + v) + "\n")
46 46 f.close()
47 47 self._dirty = False
48 48 def add(self, fcl, fco, fca, fd, flags):
49 49 hash = util.sha1(fcl.path()).hexdigest()
50 50 self._repo.opener.write("merge/" + hash, fcl.data())
51 51 self._state[fd] = ['u', hash, fcl.path(), fca.path(),
52 52 hex(fca.filenode()), fco.path(), flags]
53 53 self._dirty = True
54 54 def __contains__(self, dfile):
55 55 return dfile in self._state
56 56 def __getitem__(self, dfile):
57 57 return self._state[dfile][0]
58 58 def __iter__(self):
59 59 l = self._state.keys()
60 60 l.sort()
61 61 for f in l:
62 62 yield f
63 63 def mark(self, dfile, state):
64 64 self._state[dfile][0] = state
65 65 self._dirty = True
66 66 def resolve(self, dfile, wctx, octx):
67 67 if self[dfile] == 'r':
68 68 return 0
69 69 state, hash, lfile, afile, anode, ofile, flags = self._state[dfile]
70 70 f = self._repo.opener("merge/" + hash)
71 71 self._repo.wwrite(dfile, f.read(), flags)
72 72 f.close()
73 73 fcd = wctx[dfile]
74 74 fco = octx[ofile]
75 75 fca = self._repo.filectx(afile, fileid=anode)
76 76 r = filemerge.filemerge(self._repo, self._local, lfile, fcd, fco, fca)
77 77 if r is None:
78 78 # no real conflict
79 79 del self._state[dfile]
80 80 elif not r:
81 81 self.mark(dfile, 'r')
82 82 return r
83 83
84 84 def _checkunknownfile(repo, wctx, mctx, f):
85 85 return (not repo.dirstate._ignore(f)
86 86 and os.path.isfile(repo.wjoin(f))
87 87 and repo.dirstate.normalize(f) not in repo.dirstate
88 88 and mctx[f].cmp(wctx[f]))
89 89
90 90 def _checkunknown(repo, wctx, mctx):
91 91 "check for collisions between unknown files and files in mctx"
92 92
93 93 error = False
94 94 for f in mctx:
95 95 if f not in wctx and _checkunknownfile(repo, wctx, mctx, f):
96 96 error = True
97 97 wctx._repo.ui.warn(_("%s: untracked file differs\n") % f)
98 98 if error:
99 99 raise util.Abort(_("untracked files in working directory differ "
100 100 "from files in requested revision"))
101 101
102 102 def _remains(f, m, ma, workingctx=False):
103 103 """check whether specified file remains after merge.
104 104
105 105 It is assumed that specified file is not contained in the manifest
106 106 of the other context.
107 107 """
108 108 if f in ma:
109 109 n = m[f]
110 110 if n != ma[f]:
111 111 return True # because it is changed locally
112 112 # even though it doesn't remain, if "remote deleted" is
113 113 # chosen in manifestmerge()
114 114 elif workingctx and n[20:] == "a":
115 115 return True # because it is added locally (linear merge specific)
116 116 else:
117 117 return False # because it is removed remotely
118 118 else:
119 119 return True # because it is added locally
120 120
121 121 def _checkcollision(mctx, extractxs):
122 122 "check for case folding collisions in the destination context"
123 123 folded = {}
124 124 for fn in mctx:
125 125 fold = util.normcase(fn)
126 126 if fold in folded:
127 127 raise util.Abort(_("case-folding collision between %s and %s")
128 128 % (fn, folded[fold]))
129 129 folded[fold] = fn
130 130
131 131 if extractxs:
132 132 wctx, actx = extractxs
133 133 # class to delay looking up copy mapping
134 134 class pathcopies(object):
135 135 @util.propertycache
136 136 def map(self):
137 137 # {dst@mctx: src@wctx} copy mapping
138 138 return copies.pathcopies(wctx, mctx)
139 139 pc = pathcopies()
140 140
141 141 for fn in wctx:
142 142 fold = util.normcase(fn)
143 143 mfn = folded.get(fold, None)
144 144 if (mfn and mfn != fn and pc.map.get(mfn) != fn and
145 145 _remains(fn, wctx.manifest(), actx.manifest(), True) and
146 146 _remains(mfn, mctx.manifest(), actx.manifest())):
147 147 raise util.Abort(_("case-folding collision between %s and %s")
148 148 % (mfn, fn))
149 149
150 150 def _forgetremoved(wctx, mctx, branchmerge):
151 151 """
152 152 Forget removed files
153 153
154 154 If we're jumping between revisions (as opposed to merging), and if
155 155 neither the working directory nor the target rev has the file,
156 156 then we need to remove it from the dirstate, to prevent the
157 157 dirstate from listing the file when it is no longer in the
158 158 manifest.
159 159
160 160 If we're merging, and the other revision has removed a file
161 161 that is not present in the working directory, we need to mark it
162 162 as removed.
163 163 """
164 164
165 165 actions = []
166 166 state = branchmerge and 'r' or 'f'
167 167 for f in wctx.deleted():
168 168 if f not in mctx:
169 169 actions.append((f, state))
170 170
171 171 if not branchmerge:
172 172 for f in wctx.removed():
173 173 if f not in mctx:
174 174 actions.append((f, "f"))
175 175
176 176 return actions
177 177
178 178 def manifestmerge(repo, p1, p2, pa, overwrite, partial):
179 179 """
180 180 Merge p1 and p2 with ancestor pa and generate merge action list
181 181
182 182 overwrite = whether we clobber working files
183 183 partial = function to filter file lists
184 184 """
185 185
186 186 def fmerge(f, f2, fa):
187 187 """merge flags"""
188 188 a, m, n = ma.flags(fa), m1.flags(f), m2.flags(f2)
189 189 if m == n: # flags agree
190 190 return m # unchanged
191 191 if m and n and not a: # flags set, don't agree, differ from parent
192 192 r = repo.ui.promptchoice(
193 193 _(" conflicting flags for %s\n"
194 194 "(n)one, e(x)ec or sym(l)ink?") % f,
195 195 (_("&None"), _("E&xec"), _("Sym&link")), 0)
196 196 if r == 1:
197 197 return "x" # Exec
198 198 if r == 2:
199 199 return "l" # Symlink
200 200 return ""
201 201 if m and m != a: # changed from a to m
202 202 return m
203 203 if n and n != a: # changed from a to n
204 204 if (n == 'l' or a == 'l') and m1.get(f) != ma.get(f):
205 205 # can't automatically merge symlink flag when there
206 206 # are file-level conflicts here, let filemerge take
207 207 # care of it
208 208 return m
209 209 return n
210 210 return '' # flag was cleared
211 211
212 212 def act(msg, m, f, *args):
213 213 repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m))
214 214 actions.append((f, m) + args)
215 215
216 216 actions, copy, movewithdir = [], {}, {}
217 217
218 218 if overwrite:
219 219 pa = p1
220 220 elif pa == p2: # backwards
221 221 pa = p1.p1()
222 222 elif pa and repo.ui.configbool("merge", "followcopies", True):
223 223 ret = copies.mergecopies(repo, p1, p2, pa)
224 224 copy, movewithdir, diverge, renamedelete = ret
225 225 for of, fl in diverge.iteritems():
226 226 act("divergent renames", "dr", of, fl)
227 227 for of, fl in renamedelete.iteritems():
228 228 act("rename and delete", "rd", of, fl)
229 229
230 230 repo.ui.note(_("resolving manifests\n"))
231 231 repo.ui.debug(" overwrite: %s, partial: %s\n"
232 232 % (bool(overwrite), bool(partial)))
233 233 repo.ui.debug(" ancestor: %s, local: %s, remote: %s\n" % (pa, p1, p2))
234 234
235 235 m1, m2, ma = p1.manifest(), p2.manifest(), pa.manifest()
236 236 copied = set(copy.values())
237 237 copied.update(movewithdir.values())
238 238
239 239 if '.hgsubstate' in m1:
240 240 # check whether sub state is modified
241 241 for s in p1.substate:
242 242 if p1.sub(s).dirty():
243 243 m1['.hgsubstate'] += "+"
244 244 break
245 245
246 246 # Compare manifests
247 247 for f, n in m1.iteritems():
248 248 if partial and not partial(f):
249 249 continue
250 250 if f in m2:
251 251 rflags = fmerge(f, f, f)
252 252 a = ma.get(f, nullid)
253 253 if n == m2[f] or m2[f] == a: # same or local newer
254 254 # is file locally modified or flags need changing?
255 255 # dirstate flags may need to be made current
256 256 if m1.flags(f) != rflags or n[20:]:
257 257 act("update permissions", "e", f, rflags)
258 258 elif n == a: # remote newer
259 259 act("remote is newer", "g", f, rflags)
260 260 else: # both changed
261 261 act("versions differ", "m", f, f, f, rflags, False)
262 262 elif f in copied: # files we'll deal with on m2 side
263 263 pass
264 264 elif f in movewithdir: # directory rename
265 265 f2 = movewithdir[f]
266 266 act("remote renamed directory to " + f2, "d", f, None, f2,
267 267 m1.flags(f))
268 268 elif f in copy: # case 2 A,B/B/B or case 4,21 A/B/B
269 269 f2 = copy[f]
270 270 act("local copied/moved to " + f2, "m", f, f2, f,
271 271 fmerge(f, f2, f2), False)
272 272 elif f in ma: # clean, a different, no remote
273 273 if n != ma[f]:
274 274 if repo.ui.promptchoice(
275 275 _(" local changed %s which remote deleted\n"
276 276 "use (c)hanged version or (d)elete?") % f,
277 277 (_("&Changed"), _("&Delete")), 0):
278 278 act("prompt delete", "r", f)
279 279 else:
280 280 act("prompt keep", "a", f)
281 281 elif n[20:] == "a": # added, no remote
282 282 act("remote deleted", "f", f)
283 283 else:
284 284 act("other deleted", "r", f)
285 285
286 286 for f, n in m2.iteritems():
287 287 if partial and not partial(f):
288 288 continue
289 289 if f in m1 or f in copied: # files already visited
290 290 continue
291 291 if f in movewithdir:
292 292 f2 = movewithdir[f]
293 293 act("local renamed directory to " + f2, "d", None, f, f2,
294 294 m2.flags(f))
295 295 elif f in copy:
296 296 f2 = copy[f]
297 297 if f2 in m2: # rename case 1, A/A,B/A
298 298 act("remote copied to " + f, "m",
299 299 f2, f, f, fmerge(f2, f, f2), False)
300 300 else: # case 3,20 A/B/A
301 301 act("remote moved to " + f, "m",
302 302 f2, f, f, fmerge(f2, f, f2), True)
303 303 elif f not in ma:
304 304 if (not overwrite
305 305 and _checkunknownfile(repo, p1, p2, f)):
306 306 rflags = fmerge(f, f, f)
307 307 act("remote differs from untracked local",
308 308 "m", f, f, f, rflags, False)
309 309 else:
310 310 act("remote created", "g", f, m2.flags(f))
311 311 elif n != ma[f]:
312 312 if repo.ui.promptchoice(
313 313 _("remote changed %s which local deleted\n"
314 314 "use (c)hanged version or leave (d)eleted?") % f,
315 315 (_("&Changed"), _("&Deleted")), 0) == 0:
316 316 act("prompt recreating", "g", f, m2.flags(f))
317 317
318 318 return actions
319 319
320 320 def actionkey(a):
321 321 return a[1] == "r" and -1 or 0, a
322 322
323 323 def applyupdates(repo, actions, wctx, mctx, actx, overwrite):
324 324 """apply the merge action list to the working directory
325 325
326 326 wctx is the working copy context
327 327 mctx is the context to be merged into the working copy
328 328 actx is the context of the common ancestor
329 329
330 330 Return a tuple of counts (updated, merged, removed, unresolved) that
331 331 describes how many files were affected by the update.
332 332 """
333 333
334 334 updated, merged, removed, unresolved = 0, 0, 0, 0
335 335 ms = mergestate(repo)
336 336 ms.reset(wctx.p1().node())
337 337 moves = []
338 338 actions.sort(key=actionkey)
339 339
340 340 # prescan for merges
341 341 for a in actions:
342 342 f, m = a[:2]
343 343 if m == "m": # merge
344 344 f2, fd, flags, move = a[2:]
345 345 if fd == '.hgsubstate': # merged internally
346 346 continue
347 347 repo.ui.debug("preserving %s for resolve of %s\n" % (f, fd))
348 348 fcl = wctx[f]
349 349 fco = mctx[f2]
350 350 if mctx == actx: # backwards, use working dir parent as ancestor
351 351 if fcl.parents():
352 352 fca = fcl.p1()
353 353 else:
354 354 fca = repo.filectx(f, fileid=nullrev)
355 355 else:
356 356 fca = fcl.ancestor(fco, actx)
357 357 if not fca:
358 358 fca = repo.filectx(f, fileid=nullrev)
359 359 ms.add(fcl, fco, fca, fd, flags)
360 360 if f != fd and move:
361 361 moves.append(f)
362 362
363 363 audit = repo.wopener.audit
364 364
365 365 # remove renamed files after safely stored
366 366 for f in moves:
367 367 if os.path.lexists(repo.wjoin(f)):
368 368 repo.ui.debug("removing %s\n" % f)
369 369 audit(f)
370 370 util.unlinkpath(repo.wjoin(f))
371 371
372 372 numupdates = len(actions)
373 373 for i, a in enumerate(actions):
374 374 f, m = a[:2]
375 375 repo.ui.progress(_('updating'), i + 1, item=f, total=numupdates,
376 376 unit=_('files'))
377 377 if f and f[0] == "/":
378 378 continue
379 379 if m == "r": # remove
380 380 repo.ui.note(_("removing %s\n") % f)
381 381 audit(f)
382 382 if f == '.hgsubstate': # subrepo states need updating
383 383 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
384 384 try:
385 385 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
386 386 except OSError, inst:
387 387 repo.ui.warn(_("update failed to remove %s: %s!\n") %
388 388 (f, inst.strerror))
389 389 removed += 1
390 390 elif m == "m": # merge
391 391 if fd == '.hgsubstate': # subrepo states need updating
392 392 subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx),
393 393 overwrite)
394 394 continue
395 395 f2, fd, flags, move = a[2:]
396 396 audit(fd)
397 397 r = ms.resolve(fd, wctx, mctx)
398 398 if r is not None and r > 0:
399 399 unresolved += 1
400 400 else:
401 401 if r is None:
402 402 updated += 1
403 403 else:
404 404 merged += 1
405 405 elif m == "g": # get
406 406 flags = a[2]
407 407 repo.ui.note(_("getting %s\n") % f)
408 408 t = mctx.filectx(f).data()
409 409 repo.wwrite(f, t, flags)
410 410 t = None
411 411 updated += 1
412 412 if f == '.hgsubstate': # subrepo states need updating
413 413 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
414 414 elif m == "d": # directory rename
415 415 f2, fd, flags = a[2:]
416 416 if f:
417 417 repo.ui.note(_("moving %s to %s\n") % (f, fd))
418 418 audit(f)
419 419 t = wctx.filectx(f).data()
420 420 repo.wwrite(fd, t, flags)
421 421 util.unlinkpath(repo.wjoin(f))
422 422 if f2:
423 423 repo.ui.note(_("getting %s to %s\n") % (f2, fd))
424 424 t = mctx.filectx(f2).data()
425 425 repo.wwrite(fd, t, flags)
426 426 updated += 1
427 427 elif m == "dr": # divergent renames
428 428 fl = a[2]
429 429 repo.ui.warn(_("note: possible conflict - %s was renamed "
430 430 "multiple times to:\n") % f)
431 431 for nf in fl:
432 432 repo.ui.warn(" %s\n" % nf)
433 433 elif m == "rd": # rename and delete
434 434 fl = a[2]
435 435 repo.ui.warn(_("note: possible conflict - %s was deleted "
436 436 "and renamed to:\n") % f)
437 437 for nf in fl:
438 438 repo.ui.warn(" %s\n" % nf)
439 439 elif m == "e": # exec
440 440 flags = a[2]
441 441 audit(f)
442 442 util.setflags(repo.wjoin(f), 'l' in flags, 'x' in flags)
443 updated += 1
443 444 ms.commit()
444 445 repo.ui.progress(_('updating'), None, total=numupdates, unit=_('files'))
445 446
446 447 return updated, merged, removed, unresolved
447 448
448 449 def calculateupdates(repo, tctx, mctx, ancestor, branchmerge, force, partial):
449 450 "Calculate the actions needed to merge mctx into tctx"
450 451 actions = []
451 452 folding = not util.checkcase(repo.path)
452 453 if folding:
453 454 # collision check is not needed for clean update
454 455 if (not branchmerge and
455 456 (force or not tctx.dirty(missing=True, branch=False))):
456 457 _checkcollision(mctx, None)
457 458 else:
458 459 _checkcollision(mctx, (tctx, ancestor))
459 460 if not force:
460 461 _checkunknown(repo, tctx, mctx)
461 462 if tctx.rev() is None:
462 463 actions += _forgetremoved(tctx, mctx, branchmerge)
463 464 actions += manifestmerge(repo, tctx, mctx,
464 465 ancestor,
465 466 force and not branchmerge,
466 467 partial)
467 468 return actions
468 469
469 470 def recordupdates(repo, actions, branchmerge):
470 471 "record merge actions to the dirstate"
471 472
472 473 for a in actions:
473 474 f, m = a[:2]
474 475 if m == "r": # remove
475 476 if branchmerge:
476 477 repo.dirstate.remove(f)
477 478 else:
478 479 repo.dirstate.drop(f)
479 480 elif m == "a": # re-add
480 481 if not branchmerge:
481 482 repo.dirstate.add(f)
482 483 elif m == "f": # forget
483 484 repo.dirstate.drop(f)
484 485 elif m == "e": # exec change
485 486 repo.dirstate.normallookup(f)
486 487 elif m == "g": # get
487 488 if branchmerge:
488 489 repo.dirstate.otherparent(f)
489 490 else:
490 491 repo.dirstate.normal(f)
491 492 elif m == "m": # merge
492 493 f2, fd, flag, move = a[2:]
493 494 if branchmerge:
494 495 # We've done a branch merge, mark this file as merged
495 496 # so that we properly record the merger later
496 497 repo.dirstate.merge(fd)
497 498 if f != f2: # copy/rename
498 499 if move:
499 500 repo.dirstate.remove(f)
500 501 if f != fd:
501 502 repo.dirstate.copy(f, fd)
502 503 else:
503 504 repo.dirstate.copy(f2, fd)
504 505 else:
505 506 # We've update-merged a locally modified file, so
506 507 # we set the dirstate to emulate a normal checkout
507 508 # of that file some time in the past. Thus our
508 509 # merge will appear as a normal local file
509 510 # modification.
510 511 if f2 == fd: # file not locally copied/moved
511 512 repo.dirstate.normallookup(fd)
512 513 if move:
513 514 repo.dirstate.drop(f)
514 515 elif m == "d": # directory rename
515 516 f2, fd, flag = a[2:]
516 517 if not f2 and f not in repo.dirstate:
517 518 # untracked file moved
518 519 continue
519 520 if branchmerge:
520 521 repo.dirstate.add(fd)
521 522 if f:
522 523 repo.dirstate.remove(f)
523 524 repo.dirstate.copy(f, fd)
524 525 if f2:
525 526 repo.dirstate.copy(f2, fd)
526 527 else:
527 528 repo.dirstate.normal(fd)
528 529 if f:
529 530 repo.dirstate.drop(f)
530 531
531 532 def update(repo, node, branchmerge, force, partial, ancestor=None,
532 533 mergeancestor=False):
533 534 """
534 535 Perform a merge between the working directory and the given node
535 536
536 537 node = the node to update to, or None if unspecified
537 538 branchmerge = whether to merge between branches
538 539 force = whether to force branch merging or file overwriting
539 540 partial = a function to filter file lists (dirstate not updated)
540 541 mergeancestor = if false, merging with an ancestor (fast-forward)
541 542 is only allowed between different named branches. This flag
542 543 is used by rebase extension as a temporary fix and should be
543 544 avoided in general.
544 545
545 546 The table below shows all the behaviors of the update command
546 547 given the -c and -C or no options, whether the working directory
547 548 is dirty, whether a revision is specified, and the relationship of
548 549 the parent rev to the target rev (linear, on the same named
549 550 branch, or on another named branch).
550 551
551 552 This logic is tested by test-update-branches.t.
552 553
553 554 -c -C dirty rev | linear same cross
554 555 n n n n | ok (1) x
555 556 n n n y | ok ok ok
556 557 n n y * | merge (2) (2)
557 558 n y * * | --- discard ---
558 559 y n y * | --- (3) ---
559 560 y n n * | --- ok ---
560 561 y y * * | --- (4) ---
561 562
562 563 x = can't happen
563 564 * = don't-care
564 565 1 = abort: crosses branches (use 'hg merge' or 'hg update -c')
565 566 2 = abort: crosses branches (use 'hg merge' to merge or
566 567 use 'hg update -C' to discard changes)
567 568 3 = abort: uncommitted local changes
568 569 4 = incompatible options (checked in commands.py)
569 570
570 571 Return the same tuple as applyupdates().
571 572 """
572 573
573 574 onode = node
574 575 wlock = repo.wlock()
575 576 try:
576 577 wc = repo[None]
577 578 if node is None:
578 579 # tip of current branch
579 580 try:
580 581 node = repo.branchtip(wc.branch())
581 582 except error.RepoLookupError:
582 583 if wc.branch() == "default": # no default branch!
583 584 node = repo.lookup("tip") # update to tip
584 585 else:
585 586 raise util.Abort(_("branch %s not found") % wc.branch())
586 587 overwrite = force and not branchmerge
587 588 pl = wc.parents()
588 589 p1, p2 = pl[0], repo[node]
589 590 if ancestor:
590 591 pa = repo[ancestor]
591 592 else:
592 593 pa = p1.ancestor(p2)
593 594
594 595 fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
595 596
596 597 ### check phase
597 598 if not overwrite and len(pl) > 1:
598 599 raise util.Abort(_("outstanding uncommitted merges"))
599 600 if branchmerge:
600 601 if pa == p2:
601 602 raise util.Abort(_("merging with a working directory ancestor"
602 603 " has no effect"))
603 604 elif pa == p1:
604 605 if not mergeancestor and p1.branch() == p2.branch():
605 606 raise util.Abort(_("nothing to merge"),
606 607 hint=_("use 'hg update' "
607 608 "or check 'hg heads'"))
608 609 if not force and (wc.files() or wc.deleted()):
609 610 raise util.Abort(_("outstanding uncommitted changes"),
610 611 hint=_("use 'hg status' to list changes"))
611 612 for s in wc.substate:
612 613 if wc.sub(s).dirty():
613 614 raise util.Abort(_("outstanding uncommitted changes in "
614 615 "subrepository '%s'") % s)
615 616
616 617 elif not overwrite:
617 618 if pa == p1 or pa == p2: # linear
618 619 pass # all good
619 620 elif wc.dirty(missing=True):
620 621 raise util.Abort(_("crosses branches (merge branches or use"
621 622 " --clean to discard changes)"))
622 623 elif onode is None:
623 624 raise util.Abort(_("crosses branches (merge branches or update"
624 625 " --check to force update)"))
625 626 else:
626 627 # Allow jumping branches if clean and specific rev given
627 628 pa = p1
628 629
629 630 ### calculate phase
630 631 actions = calculateupdates(repo, wc, p2, pa,
631 632 branchmerge, force, partial)
632 633
633 634 ### apply phase
634 635 if not branchmerge: # just jump to the new rev
635 636 fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
636 637 if not partial:
637 638 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
638 639
639 640 stats = applyupdates(repo, actions, wc, p2, pa, overwrite)
640 641
641 642 if not partial:
642 643 repo.setparents(fp1, fp2)
643 644 recordupdates(repo, actions, branchmerge)
644 645 if not branchmerge:
645 646 repo.dirstate.setbranch(p2.branch())
646 647 finally:
647 648 wlock.release()
648 649
649 650 if not partial:
650 651 repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
651 652 return stats
@@ -1,28 +1,28
1 1 $ "$TESTDIR/hghave" execbit || exit 80
2 2
3 3 $ hg init
4 4 $ echo a > a
5 5 $ hg ci -Am'not executable'
6 6 adding a
7 7
8 8 $ chmod +x a
9 9 $ hg ci -m'executable'
10 10 $ hg id
11 11 79abf14474dc tip
12 12
13 13 Make sure we notice the change of mode if the cached size == -1:
14 14
15 15 $ hg rm a
16 16 $ hg revert -r 0 a
17 17 $ hg debugstate
18 18 n 0 -1 unset a
19 19 $ hg status
20 20 M a
21 21
22 22 $ hg up 0
23 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
23 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
24 24 $ hg id
25 25 d69afc33ff8a
26 26 $ test -x a && echo executable -- bad || echo not executable -- good
27 27 not executable -- good
28 28
@@ -1,151 +1,151
1 1 $ "$TESTDIR/hghave" execbit || exit 80
2 2
3 3 $ umask 027
4 4
5 5 $ hg init test1
6 6 $ cd test1
7 7 $ touch a b
8 8 $ hg add a b
9 9 $ hg ci -m "added a b"
10 10
11 11 $ cd ..
12 12 $ hg clone test1 test3
13 13 updating to branch default
14 14 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
15 15
16 16 $ hg init test2
17 17 $ cd test2
18 18 $ hg pull ../test1
19 19 pulling from ../test1
20 20 requesting all changes
21 21 adding changesets
22 22 adding manifests
23 23 adding file changes
24 24 added 1 changesets with 2 changes to 2 files
25 25 (run 'hg update' to get a working copy)
26 26 $ hg co
27 27 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
28 28 $ chmod +x a
29 29 $ hg ci -m "chmod +x a"
30 30
31 31 the changelog should mention file a:
32 32
33 33 $ hg tip --template '{files}\n'
34 34 a
35 35
36 36 $ cd ../test1
37 37 $ echo 123 >>a
38 38 $ hg ci -m "a updated"
39 39
40 40 $ hg pull ../test2
41 41 pulling from ../test2
42 42 searching for changes
43 43 adding changesets
44 44 adding manifests
45 45 adding file changes
46 46 added 1 changesets with 0 changes to 0 files (+1 heads)
47 47 (run 'hg heads' to see heads, 'hg merge' to merge)
48 48 $ hg heads
49 49 changeset: 2:7f4313b42a34
50 50 tag: tip
51 51 parent: 0:22a449e20da5
52 52 user: test
53 53 date: Thu Jan 01 00:00:00 1970 +0000
54 54 summary: chmod +x a
55 55
56 56 changeset: 1:c6ecefc45368
57 57 user: test
58 58 date: Thu Jan 01 00:00:00 1970 +0000
59 59 summary: a updated
60 60
61 61 $ hg history
62 62 changeset: 2:7f4313b42a34
63 63 tag: tip
64 64 parent: 0:22a449e20da5
65 65 user: test
66 66 date: Thu Jan 01 00:00:00 1970 +0000
67 67 summary: chmod +x a
68 68
69 69 changeset: 1:c6ecefc45368
70 70 user: test
71 71 date: Thu Jan 01 00:00:00 1970 +0000
72 72 summary: a updated
73 73
74 74 changeset: 0:22a449e20da5
75 75 user: test
76 76 date: Thu Jan 01 00:00:00 1970 +0000
77 77 summary: added a b
78 78
79 79
80 80 $ hg -v merge
81 81 resolving manifests
82 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
82 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
83 83 (branch merge, don't forget to commit)
84 84
85 85 $ cd ../test3
86 86 $ echo 123 >>b
87 87 $ hg ci -m "b updated"
88 88
89 89 $ hg pull ../test2
90 90 pulling from ../test2
91 91 searching for changes
92 92 adding changesets
93 93 adding manifests
94 94 adding file changes
95 95 added 1 changesets with 0 changes to 0 files (+1 heads)
96 96 (run 'hg heads' to see heads, 'hg merge' to merge)
97 97 $ hg heads
98 98 changeset: 2:7f4313b42a34
99 99 tag: tip
100 100 parent: 0:22a449e20da5
101 101 user: test
102 102 date: Thu Jan 01 00:00:00 1970 +0000
103 103 summary: chmod +x a
104 104
105 105 changeset: 1:dc57ead75f79
106 106 user: test
107 107 date: Thu Jan 01 00:00:00 1970 +0000
108 108 summary: b updated
109 109
110 110 $ hg history
111 111 changeset: 2:7f4313b42a34
112 112 tag: tip
113 113 parent: 0:22a449e20da5
114 114 user: test
115 115 date: Thu Jan 01 00:00:00 1970 +0000
116 116 summary: chmod +x a
117 117
118 118 changeset: 1:dc57ead75f79
119 119 user: test
120 120 date: Thu Jan 01 00:00:00 1970 +0000
121 121 summary: b updated
122 122
123 123 changeset: 0:22a449e20da5
124 124 user: test
125 125 date: Thu Jan 01 00:00:00 1970 +0000
126 126 summary: added a b
127 127
128 128
129 129 $ hg -v merge
130 130 resolving manifests
131 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
131 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
132 132 (branch merge, don't forget to commit)
133 133
134 134 $ ls -l ../test[123]/a > foo
135 135 $ cut -b 1-10 < foo
136 136 -rwxr-x---
137 137 -rwxr-x---
138 138 -rwxr-x---
139 139
140 140 $ hg debugindex a
141 141 rev offset length ..... linkrev nodeid p1 p2 (re)
142 142 0 0 0 ..... 0 b80de5d13875 000000000000 000000000000 (re)
143 143 $ hg debugindex -R ../test2 a
144 144 rev offset length ..... linkrev nodeid p1 p2 (re)
145 145 0 0 0 ..... 0 b80de5d13875 000000000000 000000000000 (re)
146 146 $ hg debugindex -R ../test1 a
147 147 rev offset length ..... linkrev nodeid p1 p2 (re)
148 148 0 0 0 ..... 0 b80de5d13875 000000000000 000000000000 (re)
149 149 1 0 5 ..... 1 7fe919cc0336 b80de5d13875 000000000000 (re)
150 150
151 151 $ cd ..
@@ -1,1002 +1,1002
1 1 $ "$TESTDIR/hghave" serve || exit 80
2 2
3 3 setting up repo
4 4
5 5 $ hg init test
6 6 $ cd test
7 7 $ echo a > a
8 8 $ echo b > b
9 9 $ hg ci -Ama
10 10 adding a
11 11 adding b
12 12
13 13 change permissions for git diffs
14 14
15 15 $ hg import -q --bypass - <<EOF
16 16 > # HG changeset patch
17 17 > # User test
18 18 > # Date 0 0
19 19 > b
20 20 >
21 21 > diff --git a/a b/a
22 22 > old mode 100644
23 23 > new mode 100755
24 24 > diff --git a/b b/b
25 25 > deleted file mode 100644
26 26 > --- a/b
27 27 > +++ /dev/null
28 28 > @@ -1,1 +0,0 @@
29 29 > -b
30 30 > EOF
31 31
32 32 set up hgweb
33 33
34 34 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
35 35 $ cat hg.pid >> $DAEMON_PIDS
36 36
37 37 revision
38 38
39 39 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'rev/0'
40 40 200 Script output follows
41 41
42 42 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
43 43 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
44 44 <head>
45 45 <link rel="icon" href="/static/hgicon.png" type="image/png" />
46 46 <meta name="robots" content="index, nofollow" />
47 47 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
48 48 <script type="text/javascript" src="/static/mercurial.js"></script>
49 49
50 50 <title>test: 0cd96de13884</title>
51 51 </head>
52 52 <body>
53 53 <div class="container">
54 54 <div class="menu">
55 55 <div class="logo">
56 56 <a href="http://mercurial.selenic.com/">
57 57 <img src="/static/hglogo.png" alt="mercurial" /></a>
58 58 </div>
59 59 <ul>
60 60 <li><a href="/shortlog/0cd96de13884">log</a></li>
61 61 <li><a href="/graph/0cd96de13884">graph</a></li>
62 62 <li><a href="/tags">tags</a></li>
63 63 <li><a href="/bookmarks">bookmarks</a></li>
64 64 <li><a href="/branches">branches</a></li>
65 65 </ul>
66 66 <ul>
67 67 <li class="active">changeset</li>
68 68 <li><a href="/raw-rev/0cd96de13884">raw</a></li>
69 69 <li><a href="/file/0cd96de13884">browse</a></li>
70 70 </ul>
71 71 <ul>
72 72
73 73 </ul>
74 74 <ul>
75 75 <li><a href="/help">help</a></li>
76 76 </ul>
77 77 </div>
78 78
79 79 <div class="main">
80 80
81 81 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
82 82 <h3>changeset 0:0cd96de13884 </h3>
83 83
84 84 <form class="search" action="/log">
85 85
86 86 <p><input name="rev" id="search1" type="text" size="30" /></p>
87 87 <div id="hint">find changesets by author, revision,
88 88 files, or words in the commit message</div>
89 89 </form>
90 90
91 91 <div class="description">a</div>
92 92
93 93 <table id="changesetEntry">
94 94 <tr>
95 95 <th class="author">author</th>
96 96 <td class="author">&#116;&#101;&#115;&#116;</td>
97 97 </tr>
98 98 <tr>
99 99 <th class="date">date</th>
100 100 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td></tr>
101 101 <tr>
102 102 <th class="author">parents</th>
103 103 <td class="author"></td>
104 104 </tr>
105 105 <tr>
106 106 <th class="author">children</th>
107 107 <td class="author"> <a href="/rev/559edbd9ed20">559edbd9ed20</a></td>
108 108 </tr>
109 109 <tr>
110 110 <th class="files">files</th>
111 111 <td class="files"><a href="/file/0cd96de13884/a">a</a> <a href="/file/0cd96de13884/b">b</a> </td>
112 112 </tr>
113 113 <tr>
114 114 <th class="diffstat">diffstat</th>
115 115 <td class="diffstat">
116 116 2 files changed, 2 insertions(+), 0 deletions(-)
117 117
118 118 <a id="diffstatexpand" href="javascript:showDiffstat()"/>[<tt>+</tt>]</a>
119 119 <div id="diffstatdetails" style="display:none;">
120 120 <a href="javascript:hideDiffstat()"/>[<tt>-</tt>]</a>
121 121 <p>
122 122 <table> <tr class="parity0">
123 123 <td class="diffstat-file"><a href="#l1.1">a</a></td>
124 124 <td class="diffstat-total" align="right">1</td>
125 125 <td class="diffstat-graph">
126 126 <span class="diffstat-add" style="width:100.0%;">&nbsp;</span>
127 127 <span class="diffstat-remove" style="width:0.0%;">&nbsp;</span>
128 128 </td>
129 129 </tr>
130 130 <tr class="parity1">
131 131 <td class="diffstat-file"><a href="#l2.1">b</a></td>
132 132 <td class="diffstat-total" align="right">1</td>
133 133 <td class="diffstat-graph">
134 134 <span class="diffstat-add" style="width:100.0%;">&nbsp;</span>
135 135 <span class="diffstat-remove" style="width:0.0%;">&nbsp;</span>
136 136 </td>
137 137 </tr>
138 138 </table>
139 139 </div>
140 140 </td>
141 141 </tr>
142 142 <tr>
143 143 <th class="author">change baseline</th>
144 144 <td class="author"></td>
145 145 </tr>
146 146 <tr>
147 147 <th class="author">current baseline</th>
148 148 <td class="author"><a href="/rev/000000000000">000000000000</a></td>
149 149 </tr>
150 150 </table>
151 151
152 152 <div class="overflow">
153 153 <div class="sourcefirst"> line diff</div>
154 154
155 155 <div class="source bottomline parity0"><pre><a href="#l1.1" id="l1.1"> 1.1</a> <span class="minusline">--- /dev/null Thu Jan 01 00:00:00 1970 +0000
156 156 </span><a href="#l1.2" id="l1.2"> 1.2</a> <span class="plusline">+++ b/a Thu Jan 01 00:00:00 1970 +0000
157 157 </span><a href="#l1.3" id="l1.3"> 1.3</a> <span class="atline">@@ -0,0 +1,1 @@
158 158 </span><a href="#l1.4" id="l1.4"> 1.4</a> <span class="plusline">+a
159 159 </span></pre></div><div class="source bottomline parity1"><pre><a href="#l2.1" id="l2.1"> 2.1</a> <span class="minusline">--- /dev/null Thu Jan 01 00:00:00 1970 +0000
160 160 </span><a href="#l2.2" id="l2.2"> 2.2</a> <span class="plusline">+++ b/b Thu Jan 01 00:00:00 1970 +0000
161 161 </span><a href="#l2.3" id="l2.3"> 2.3</a> <span class="atline">@@ -0,0 +1,1 @@
162 162 </span><a href="#l2.4" id="l2.4"> 2.4</a> <span class="plusline">+b
163 163 </span></pre></div>
164 164 </div>
165 165
166 166 </div>
167 167 </div>
168 168 <script type="text/javascript">process_dates()</script>
169 169
170 170
171 171 </body>
172 172 </html>
173 173
174 174
175 175 raw revision
176 176
177 177 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'raw-rev/0'
178 178 200 Script output follows
179 179
180 180
181 181 # HG changeset patch
182 182 # User test
183 183 # Date 0 0
184 184 # Node ID 0cd96de13884b090099512d4794ae87ad067ea8e
185 185
186 186 a
187 187
188 188 diff -r 000000000000 -r 0cd96de13884 a
189 189 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
190 190 +++ b/a Thu Jan 01 00:00:00 1970 +0000
191 191 @@ -0,0 +1,1 @@
192 192 +a
193 193 diff -r 000000000000 -r 0cd96de13884 b
194 194 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
195 195 +++ b/b Thu Jan 01 00:00:00 1970 +0000
196 196 @@ -0,0 +1,1 @@
197 197 +b
198 198
199 199
200 200 diff removed file
201 201
202 202 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'diff/tip/b'
203 203 200 Script output follows
204 204
205 205 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
206 206 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
207 207 <head>
208 208 <link rel="icon" href="/static/hgicon.png" type="image/png" />
209 209 <meta name="robots" content="index, nofollow" />
210 210 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
211 211 <script type="text/javascript" src="/static/mercurial.js"></script>
212 212
213 213 <title>test: b diff</title>
214 214 </head>
215 215 <body>
216 216
217 217 <div class="container">
218 218 <div class="menu">
219 219 <div class="logo">
220 220 <a href="http://mercurial.selenic.com/">
221 221 <img src="/static/hglogo.png" alt="mercurial" /></a>
222 222 </div>
223 223 <ul>
224 224 <li><a href="/shortlog/559edbd9ed20">log</a></li>
225 225 <li><a href="/graph/559edbd9ed20">graph</a></li>
226 226 <li><a href="/tags">tags</a></li>
227 227 <li><a href="/bookmarks">bookmarks</a></li>
228 228 <li><a href="/branches">branches</a></li>
229 229 </ul>
230 230 <ul>
231 231 <li><a href="/rev/559edbd9ed20">changeset</a></li>
232 232 <li><a href="/file/559edbd9ed20">browse</a></li>
233 233 </ul>
234 234 <ul>
235 235 <li><a href="/file/559edbd9ed20/b">file</a></li>
236 236 <li><a href="/file/tip/b">latest</a></li>
237 237 <li class="active">diff</li>
238 238 <li><a href="/comparison/559edbd9ed20/b">comparison</a></li>
239 239 <li><a href="/annotate/559edbd9ed20/b">annotate</a></li>
240 240 <li><a href="/log/559edbd9ed20/b">file log</a></li>
241 241 <li><a href="/raw-file/559edbd9ed20/b">raw</a></li>
242 242 </ul>
243 243 <ul>
244 244 <li><a href="/help">help</a></li>
245 245 </ul>
246 246 </div>
247 247
248 248 <div class="main">
249 249 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
250 250 <h3>diff b @ 1:559edbd9ed20</h3>
251 251
252 252 <form class="search" action="/log">
253 253 <p></p>
254 254 <p><input name="rev" id="search1" type="text" size="30" /></p>
255 255 <div id="hint">find changesets by author, revision,
256 256 files, or words in the commit message</div>
257 257 </form>
258 258
259 259 <div class="description">b</div>
260 260
261 261 <table id="changesetEntry">
262 262 <tr>
263 263 <th>author</th>
264 264 <td>&#116;&#101;&#115;&#116;</td>
265 265 </tr>
266 266 <tr>
267 267 <th>date</th>
268 268 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
269 269 </tr>
270 270 <tr>
271 271 <th>parents</th>
272 272 <td><a href="/file/0cd96de13884/b">0cd96de13884</a> </td>
273 273 </tr>
274 274 <tr>
275 275 <th>children</th>
276 276 <td></td>
277 277 </tr>
278 278
279 279 </table>
280 280
281 281 <div class="overflow">
282 282 <div class="sourcefirst"> line diff</div>
283 283
284 284 <div class="source bottomline parity0"><pre><a href="#l1.1" id="l1.1"> 1.1</a> <span class="minusline">--- a/b Thu Jan 01 00:00:00 1970 +0000
285 285 </span><a href="#l1.2" id="l1.2"> 1.2</a> <span class="plusline">+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
286 286 </span><a href="#l1.3" id="l1.3"> 1.3</a> <span class="atline">@@ -1,1 +0,0 @@
287 287 </span><a href="#l1.4" id="l1.4"> 1.4</a> <span class="minusline">-b
288 288 </span></pre></div>
289 289 </div>
290 290 </div>
291 291 </div>
292 292
293 293 <script type="text/javascript">process_dates()</script>
294 294
295 295
296 296 </body>
297 297 </html>
298 298
299 299
300 300 set up hgweb with git diffs
301 301
302 302 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
303 303 $ hg serve --config 'diff.git=1' -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
304 304 $ cat hg.pid >> $DAEMON_PIDS
305 305
306 306 revision
307 307
308 308 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'rev/0'
309 309 200 Script output follows
310 310
311 311 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
312 312 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
313 313 <head>
314 314 <link rel="icon" href="/static/hgicon.png" type="image/png" />
315 315 <meta name="robots" content="index, nofollow" />
316 316 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
317 317 <script type="text/javascript" src="/static/mercurial.js"></script>
318 318
319 319 <title>test: 0cd96de13884</title>
320 320 </head>
321 321 <body>
322 322 <div class="container">
323 323 <div class="menu">
324 324 <div class="logo">
325 325 <a href="http://mercurial.selenic.com/">
326 326 <img src="/static/hglogo.png" alt="mercurial" /></a>
327 327 </div>
328 328 <ul>
329 329 <li><a href="/shortlog/0cd96de13884">log</a></li>
330 330 <li><a href="/graph/0cd96de13884">graph</a></li>
331 331 <li><a href="/tags">tags</a></li>
332 332 <li><a href="/bookmarks">bookmarks</a></li>
333 333 <li><a href="/branches">branches</a></li>
334 334 </ul>
335 335 <ul>
336 336 <li class="active">changeset</li>
337 337 <li><a href="/raw-rev/0cd96de13884">raw</a></li>
338 338 <li><a href="/file/0cd96de13884">browse</a></li>
339 339 </ul>
340 340 <ul>
341 341
342 342 </ul>
343 343 <ul>
344 344 <li><a href="/help">help</a></li>
345 345 </ul>
346 346 </div>
347 347
348 348 <div class="main">
349 349
350 350 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
351 351 <h3>changeset 0:0cd96de13884 </h3>
352 352
353 353 <form class="search" action="/log">
354 354
355 355 <p><input name="rev" id="search1" type="text" size="30" /></p>
356 356 <div id="hint">find changesets by author, revision,
357 357 files, or words in the commit message</div>
358 358 </form>
359 359
360 360 <div class="description">a</div>
361 361
362 362 <table id="changesetEntry">
363 363 <tr>
364 364 <th class="author">author</th>
365 365 <td class="author">&#116;&#101;&#115;&#116;</td>
366 366 </tr>
367 367 <tr>
368 368 <th class="date">date</th>
369 369 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td></tr>
370 370 <tr>
371 371 <th class="author">parents</th>
372 372 <td class="author"></td>
373 373 </tr>
374 374 <tr>
375 375 <th class="author">children</th>
376 376 <td class="author"> <a href="/rev/559edbd9ed20">559edbd9ed20</a></td>
377 377 </tr>
378 378 <tr>
379 379 <th class="files">files</th>
380 380 <td class="files"><a href="/file/0cd96de13884/a">a</a> <a href="/file/0cd96de13884/b">b</a> </td>
381 381 </tr>
382 382 <tr>
383 383 <th class="diffstat">diffstat</th>
384 384 <td class="diffstat">
385 385 2 files changed, 2 insertions(+), 0 deletions(-)
386 386
387 387 <a id="diffstatexpand" href="javascript:showDiffstat()"/>[<tt>+</tt>]</a>
388 388 <div id="diffstatdetails" style="display:none;">
389 389 <a href="javascript:hideDiffstat()"/>[<tt>-</tt>]</a>
390 390 <p>
391 391 <table> <tr class="parity0">
392 392 <td class="diffstat-file"><a href="#l1.1">a</a></td>
393 393 <td class="diffstat-total" align="right">1</td>
394 394 <td class="diffstat-graph">
395 395 <span class="diffstat-add" style="width:100.0%;">&nbsp;</span>
396 396 <span class="diffstat-remove" style="width:0.0%;">&nbsp;</span>
397 397 </td>
398 398 </tr>
399 399 <tr class="parity1">
400 400 <td class="diffstat-file"><a href="#l2.1">b</a></td>
401 401 <td class="diffstat-total" align="right">1</td>
402 402 <td class="diffstat-graph">
403 403 <span class="diffstat-add" style="width:100.0%;">&nbsp;</span>
404 404 <span class="diffstat-remove" style="width:0.0%;">&nbsp;</span>
405 405 </td>
406 406 </tr>
407 407 </table>
408 408 </div>
409 409 </td>
410 410 </tr>
411 411 <tr>
412 412 <th class="author">change baseline</th>
413 413 <td class="author"></td>
414 414 </tr>
415 415 <tr>
416 416 <th class="author">current baseline</th>
417 417 <td class="author"><a href="/rev/000000000000">000000000000</a></td>
418 418 </tr>
419 419 </table>
420 420
421 421 <div class="overflow">
422 422 <div class="sourcefirst"> line diff</div>
423 423
424 424 <div class="source bottomline parity0"><pre><a href="#l1.1" id="l1.1"> 1.1</a> new file mode 100644
425 425 <a href="#l1.2" id="l1.2"> 1.2</a> <span class="minusline">--- /dev/null
426 426 </span><a href="#l1.3" id="l1.3"> 1.3</a> <span class="plusline">+++ b/a
427 427 </span><a href="#l1.4" id="l1.4"> 1.4</a> <span class="atline">@@ -0,0 +1,1 @@
428 428 </span><a href="#l1.5" id="l1.5"> 1.5</a> <span class="plusline">+a
429 429 </span></pre></div><div class="source bottomline parity1"><pre><a href="#l2.1" id="l2.1"> 2.1</a> new file mode 100644
430 430 <a href="#l2.2" id="l2.2"> 2.2</a> <span class="minusline">--- /dev/null
431 431 </span><a href="#l2.3" id="l2.3"> 2.3</a> <span class="plusline">+++ b/b
432 432 </span><a href="#l2.4" id="l2.4"> 2.4</a> <span class="atline">@@ -0,0 +1,1 @@
433 433 </span><a href="#l2.5" id="l2.5"> 2.5</a> <span class="plusline">+b
434 434 </span></pre></div>
435 435 </div>
436 436
437 437 </div>
438 438 </div>
439 439 <script type="text/javascript">process_dates()</script>
440 440
441 441
442 442 </body>
443 443 </html>
444 444
445 445
446 446 revision
447 447
448 448 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'raw-rev/0'
449 449 200 Script output follows
450 450
451 451
452 452 # HG changeset patch
453 453 # User test
454 454 # Date 0 0
455 455 # Node ID 0cd96de13884b090099512d4794ae87ad067ea8e
456 456
457 457 a
458 458
459 459 diff --git a/a b/a
460 460 new file mode 100644
461 461 --- /dev/null
462 462 +++ b/a
463 463 @@ -0,0 +1,1 @@
464 464 +a
465 465 diff --git a/b b/b
466 466 new file mode 100644
467 467 --- /dev/null
468 468 +++ b/b
469 469 @@ -0,0 +1,1 @@
470 470 +b
471 471
472 472
473 473 diff removed file
474 474
475 475 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'diff/tip/a'
476 476 200 Script output follows
477 477
478 478 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
479 479 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
480 480 <head>
481 481 <link rel="icon" href="/static/hgicon.png" type="image/png" />
482 482 <meta name="robots" content="index, nofollow" />
483 483 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
484 484 <script type="text/javascript" src="/static/mercurial.js"></script>
485 485
486 486 <title>test: a diff</title>
487 487 </head>
488 488 <body>
489 489
490 490 <div class="container">
491 491 <div class="menu">
492 492 <div class="logo">
493 493 <a href="http://mercurial.selenic.com/">
494 494 <img src="/static/hglogo.png" alt="mercurial" /></a>
495 495 </div>
496 496 <ul>
497 497 <li><a href="/shortlog/559edbd9ed20">log</a></li>
498 498 <li><a href="/graph/559edbd9ed20">graph</a></li>
499 499 <li><a href="/tags">tags</a></li>
500 500 <li><a href="/bookmarks">bookmarks</a></li>
501 501 <li><a href="/branches">branches</a></li>
502 502 </ul>
503 503 <ul>
504 504 <li><a href="/rev/559edbd9ed20">changeset</a></li>
505 505 <li><a href="/file/559edbd9ed20">browse</a></li>
506 506 </ul>
507 507 <ul>
508 508 <li><a href="/file/559edbd9ed20/a">file</a></li>
509 509 <li><a href="/file/tip/a">latest</a></li>
510 510 <li class="active">diff</li>
511 511 <li><a href="/comparison/559edbd9ed20/a">comparison</a></li>
512 512 <li><a href="/annotate/559edbd9ed20/a">annotate</a></li>
513 513 <li><a href="/log/559edbd9ed20/a">file log</a></li>
514 514 <li><a href="/raw-file/559edbd9ed20/a">raw</a></li>
515 515 </ul>
516 516 <ul>
517 517 <li><a href="/help">help</a></li>
518 518 </ul>
519 519 </div>
520 520
521 521 <div class="main">
522 522 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
523 523 <h3>diff a @ 1:559edbd9ed20</h3>
524 524
525 525 <form class="search" action="/log">
526 526 <p></p>
527 527 <p><input name="rev" id="search1" type="text" size="30" /></p>
528 528 <div id="hint">find changesets by author, revision,
529 529 files, or words in the commit message</div>
530 530 </form>
531 531
532 532 <div class="description">b</div>
533 533
534 534 <table id="changesetEntry">
535 535 <tr>
536 536 <th>author</th>
537 537 <td>&#116;&#101;&#115;&#116;</td>
538 538 </tr>
539 539 <tr>
540 540 <th>date</th>
541 541 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
542 542 </tr>
543 543 <tr>
544 544 <th>parents</th>
545 545 <td></td>
546 546 </tr>
547 547 <tr>
548 548 <th>children</th>
549 549 <td></td>
550 550 </tr>
551 551
552 552 </table>
553 553
554 554 <div class="overflow">
555 555 <div class="sourcefirst"> line diff</div>
556 556
557 557 <div class="source bottomline parity0"><pre><a href="#l1.1" id="l1.1"> 1.1</a> old mode 100644
558 558 <a href="#l1.2" id="l1.2"> 1.2</a> new mode 100755
559 559 </pre></div>
560 560 </div>
561 561 </div>
562 562 </div>
563 563
564 564 <script type="text/javascript">process_dates()</script>
565 565
566 566
567 567 </body>
568 568 </html>
569 569
570 570
571 571 comparison new file
572 572
573 573 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'comparison/0/a'
574 574 200 Script output follows
575 575
576 576 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
577 577 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
578 578 <head>
579 579 <link rel="icon" href="/static/hgicon.png" type="image/png" />
580 580 <meta name="robots" content="index, nofollow" />
581 581 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
582 582 <script type="text/javascript" src="/static/mercurial.js"></script>
583 583
584 584 <title>test: a comparison</title>
585 585 </head>
586 586 <body>
587 587
588 588 <div class="container">
589 589 <div class="menu">
590 590 <div class="logo">
591 591 <a href="http://mercurial.selenic.com/">
592 592 <img src="/static/hglogo.png" alt="mercurial" /></a>
593 593 </div>
594 594 <ul>
595 595 <li><a href="/shortlog/0cd96de13884">log</a></li>
596 596 <li><a href="/graph/0cd96de13884">graph</a></li>
597 597 <li><a href="/tags">tags</a></li>
598 598 <li><a href="/bookmarks">bookmarks</a></li>
599 599 <li><a href="/branches">branches</a></li>
600 600 </ul>
601 601 <ul>
602 602 <li><a href="/rev/0cd96de13884">changeset</a></li>
603 603 <li><a href="/file/0cd96de13884">browse</a></li>
604 604 </ul>
605 605 <ul>
606 606 <li><a href="/file/0cd96de13884/a">file</a></li>
607 607 <li><a href="/file/tip/a">latest</a></li>
608 608 <li><a href="/diff/0cd96de13884/a">diff</a></li>
609 609 <li class="active">comparison</li>
610 610 <li><a href="/annotate/0cd96de13884/a">annotate</a></li>
611 611 <li><a href="/log/0cd96de13884/a">file log</a></li>
612 612 <li><a href="/raw-file/0cd96de13884/a">raw</a></li>
613 613 </ul>
614 614 <ul>
615 615 <li><a href="/help">help</a></li>
616 616 </ul>
617 617 </div>
618 618
619 619 <div class="main">
620 620 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
621 621 <h3>comparison a @ 0:0cd96de13884</h3>
622 622
623 623 <form class="search" action="/log">
624 624 <p></p>
625 625 <p><input name="rev" id="search1" type="text" size="30" /></p>
626 626 <div id="hint">find changesets by author, revision,
627 627 files, or words in the commit message</div>
628 628 </form>
629 629
630 630 <div class="description">a</div>
631 631
632 632 <table id="changesetEntry">
633 633 <tr>
634 634 <th>author</th>
635 635 <td>&#116;&#101;&#115;&#116;</td>
636 636 </tr>
637 637 <tr>
638 638 <th>date</th>
639 639 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
640 640 </tr>
641 641 <tr>
642 642 <th>parents</th>
643 643 <td></td>
644 644 </tr>
645 645 <tr>
646 646 <th>children</th>
647 647 <td></td>
648 648 </tr>
649 649
650 650 </table>
651 651
652 652 <div class="overflow">
653 653 <div class="sourcefirst"> comparison</div>
654 654 <div class="legend">
655 655 <span class="legendinfo equal">equal</span>
656 656 <span class="legendinfo delete">deleted</span>
657 657 <span class="legendinfo insert">inserted</span>
658 658 <span class="legendinfo replace">replaced</span>
659 659 </div>
660 660
661 661 <table class="bigtable">
662 662 <thead class="header">
663 663 <tr>
664 664 <th>-1:000000000000</th>
665 665 <th>0:b789fdd96dc2</th>
666 666 </tr>
667 667 </thead>
668 668
669 669 <tbody class="block">
670 670
671 671 <tr>
672 672 <td class="source insert"><a href="#r1" id="r1"> </a> </td>
673 673 <td class="source insert"><a href="#r1" id="r1"> 1</a> a</td>
674 674 </tr>
675 675 </tbody>
676 676 </table>
677 677
678 678 </div>
679 679 </div>
680 680 </div>
681 681
682 682 <script type="text/javascript">process_dates()</script>
683 683
684 684
685 685 </body>
686 686 </html>
687 687
688 688
689 689 comparison existing file
690 690
691 691 $ hg up
692 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
692 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
693 693 $ echo a >> a
694 694 $ hg ci -mc
695 695 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'comparison/tip/a'
696 696 200 Script output follows
697 697
698 698 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
699 699 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
700 700 <head>
701 701 <link rel="icon" href="/static/hgicon.png" type="image/png" />
702 702 <meta name="robots" content="index, nofollow" />
703 703 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
704 704 <script type="text/javascript" src="/static/mercurial.js"></script>
705 705
706 706 <title>test: a comparison</title>
707 707 </head>
708 708 <body>
709 709
710 710 <div class="container">
711 711 <div class="menu">
712 712 <div class="logo">
713 713 <a href="http://mercurial.selenic.com/">
714 714 <img src="/static/hglogo.png" alt="mercurial" /></a>
715 715 </div>
716 716 <ul>
717 717 <li><a href="/shortlog/d73db4d812ff">log</a></li>
718 718 <li><a href="/graph/d73db4d812ff">graph</a></li>
719 719 <li><a href="/tags">tags</a></li>
720 720 <li><a href="/bookmarks">bookmarks</a></li>
721 721 <li><a href="/branches">branches</a></li>
722 722 </ul>
723 723 <ul>
724 724 <li><a href="/rev/d73db4d812ff">changeset</a></li>
725 725 <li><a href="/file/d73db4d812ff">browse</a></li>
726 726 </ul>
727 727 <ul>
728 728 <li><a href="/file/d73db4d812ff/a">file</a></li>
729 729 <li><a href="/file/tip/a">latest</a></li>
730 730 <li><a href="/diff/d73db4d812ff/a">diff</a></li>
731 731 <li class="active">comparison</li>
732 732 <li><a href="/annotate/d73db4d812ff/a">annotate</a></li>
733 733 <li><a href="/log/d73db4d812ff/a">file log</a></li>
734 734 <li><a href="/raw-file/d73db4d812ff/a">raw</a></li>
735 735 </ul>
736 736 <ul>
737 737 <li><a href="/help">help</a></li>
738 738 </ul>
739 739 </div>
740 740
741 741 <div class="main">
742 742 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
743 743 <h3>comparison a @ 2:d73db4d812ff</h3>
744 744
745 745 <form class="search" action="/log">
746 746 <p></p>
747 747 <p><input name="rev" id="search1" type="text" size="30" /></p>
748 748 <div id="hint">find changesets by author, revision,
749 749 files, or words in the commit message</div>
750 750 </form>
751 751
752 752 <div class="description">c</div>
753 753
754 754 <table id="changesetEntry">
755 755 <tr>
756 756 <th>author</th>
757 757 <td>&#116;&#101;&#115;&#116;</td>
758 758 </tr>
759 759 <tr>
760 760 <th>date</th>
761 761 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
762 762 </tr>
763 763 <tr>
764 764 <th>parents</th>
765 765 <td><a href="/file/0cd96de13884/a">0cd96de13884</a> </td>
766 766 </tr>
767 767 <tr>
768 768 <th>children</th>
769 769 <td></td>
770 770 </tr>
771 771
772 772 </table>
773 773
774 774 <div class="overflow">
775 775 <div class="sourcefirst"> comparison</div>
776 776 <div class="legend">
777 777 <span class="legendinfo equal">equal</span>
778 778 <span class="legendinfo delete">deleted</span>
779 779 <span class="legendinfo insert">inserted</span>
780 780 <span class="legendinfo replace">replaced</span>
781 781 </div>
782 782
783 783 <table class="bigtable">
784 784 <thead class="header">
785 785 <tr>
786 786 <th>0:b789fdd96dc2</th>
787 787 <th>1:a80d06849b33</th>
788 788 </tr>
789 789 </thead>
790 790
791 791 <tbody class="block">
792 792
793 793 <tr>
794 794 <td class="source equal"><a href="#l1r1" id="l1r1"> 1</a> a</td>
795 795 <td class="source equal"><a href="#l1r1" id="l1r1"> 1</a> a</td>
796 796 </tr>
797 797 <tr>
798 798 <td class="source insert"><a href="#r2" id="r2"> </a> </td>
799 799 <td class="source insert"><a href="#r2" id="r2"> 2</a> a</td>
800 800 </tr>
801 801 </tbody>
802 802 </table>
803 803
804 804 </div>
805 805 </div>
806 806 </div>
807 807
808 808 <script type="text/javascript">process_dates()</script>
809 809
810 810
811 811 </body>
812 812 </html>
813 813
814 814
815 815 comparison removed file
816 816
817 817 $ hg rm a
818 818 $ hg ci -md
819 819 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'comparison/tip/a'
820 820 200 Script output follows
821 821
822 822 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
823 823 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
824 824 <head>
825 825 <link rel="icon" href="/static/hgicon.png" type="image/png" />
826 826 <meta name="robots" content="index, nofollow" />
827 827 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
828 828 <script type="text/javascript" src="/static/mercurial.js"></script>
829 829
830 830 <title>test: a comparison</title>
831 831 </head>
832 832 <body>
833 833
834 834 <div class="container">
835 835 <div class="menu">
836 836 <div class="logo">
837 837 <a href="http://mercurial.selenic.com/">
838 838 <img src="/static/hglogo.png" alt="mercurial" /></a>
839 839 </div>
840 840 <ul>
841 841 <li><a href="/shortlog/20e80271eb7a">log</a></li>
842 842 <li><a href="/graph/20e80271eb7a">graph</a></li>
843 843 <li><a href="/tags">tags</a></li>
844 844 <li><a href="/bookmarks">bookmarks</a></li>
845 845 <li><a href="/branches">branches</a></li>
846 846 </ul>
847 847 <ul>
848 848 <li><a href="/rev/20e80271eb7a">changeset</a></li>
849 849 <li><a href="/file/20e80271eb7a">browse</a></li>
850 850 </ul>
851 851 <ul>
852 852 <li><a href="/file/20e80271eb7a/a">file</a></li>
853 853 <li><a href="/file/tip/a">latest</a></li>
854 854 <li><a href="/diff/20e80271eb7a/a">diff</a></li>
855 855 <li class="active">comparison</li>
856 856 <li><a href="/annotate/20e80271eb7a/a">annotate</a></li>
857 857 <li><a href="/log/20e80271eb7a/a">file log</a></li>
858 858 <li><a href="/raw-file/20e80271eb7a/a">raw</a></li>
859 859 </ul>
860 860 <ul>
861 861 <li><a href="/help">help</a></li>
862 862 </ul>
863 863 </div>
864 864
865 865 <div class="main">
866 866 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
867 867 <h3>comparison a @ 3:20e80271eb7a</h3>
868 868
869 869 <form class="search" action="/log">
870 870 <p></p>
871 871 <p><input name="rev" id="search1" type="text" size="30" /></p>
872 872 <div id="hint">find changesets by author, revision,
873 873 files, or words in the commit message</div>
874 874 </form>
875 875
876 876 <div class="description">d</div>
877 877
878 878 <table id="changesetEntry">
879 879 <tr>
880 880 <th>author</th>
881 881 <td>&#116;&#101;&#115;&#116;</td>
882 882 </tr>
883 883 <tr>
884 884 <th>date</th>
885 885 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
886 886 </tr>
887 887 <tr>
888 888 <th>parents</th>
889 889 <td><a href="/file/0cd96de13884/a">0cd96de13884</a> </td>
890 890 </tr>
891 891 <tr>
892 892 <th>children</th>
893 893 <td></td>
894 894 </tr>
895 895
896 896 </table>
897 897
898 898 <div class="overflow">
899 899 <div class="sourcefirst"> comparison</div>
900 900 <div class="legend">
901 901 <span class="legendinfo equal">equal</span>
902 902 <span class="legendinfo delete">deleted</span>
903 903 <span class="legendinfo insert">inserted</span>
904 904 <span class="legendinfo replace">replaced</span>
905 905 </div>
906 906
907 907 <table class="bigtable">
908 908 <thead class="header">
909 909 <tr>
910 910 <th>1:a80d06849b33</th>
911 911 <th>-1:000000000000</th>
912 912 </tr>
913 913 </thead>
914 914
915 915 <tbody class="block">
916 916
917 917 <tr>
918 918 <td class="source delete"><a href="#l1" id="l1"> 1</a> a</td>
919 919 <td class="source delete"><a href="#l1" id="l1"> </a> </td>
920 920 </tr>
921 921 <tr>
922 922 <td class="source delete"><a href="#l2" id="l2"> 2</a> a</td>
923 923 <td class="source delete"><a href="#l2" id="l2"> </a> </td>
924 924 </tr>
925 925 </tbody>
926 926 </table>
927 927
928 928 </div>
929 929 </div>
930 930 </div>
931 931
932 932 <script type="text/javascript">process_dates()</script>
933 933
934 934
935 935 </body>
936 936 </html>
937 937
938 938
939 939 $ cd ..
940 940
941 941 test import rev as raw-rev
942 942
943 943 $ hg clone -r0 test test1
944 944 adding changesets
945 945 adding manifests
946 946 adding file changes
947 947 added 1 changesets with 2 changes to 2 files
948 948 updating to branch default
949 949 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
950 950 $ cd test1
951 951 $ hg import -q --bypass --exact http://localhost:$HGPORT/rev/1
952 952
953 953 raw revision with diff block numbers
954 954
955 955 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
956 956 $ cat <<EOF > .hg/hgrc
957 957 > [web]
958 958 > templates = rawdiff
959 959 > EOF
960 960 $ mkdir rawdiff
961 961 $ cat <<EOF > rawdiff/map
962 962 > mimetype = 'text/plain; charset={encoding}'
963 963 > changeset = '{diff}'
964 964 > difflineplus = '{line}'
965 965 > difflineminus = '{line}'
966 966 > difflineat = '{line}'
967 967 > diffline = '{line}'
968 968 > filenodelink = ''
969 969 > filenolink = ''
970 970 > fileline = '{line}'
971 971 > diffblock = 'Block: {blockno}\n{lines}\n'
972 972 > EOF
973 973 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
974 974 $ cat hg.pid >> $DAEMON_PIDS
975 975 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'raw-rev/0'
976 976 200 Script output follows
977 977
978 978 Block: 1
979 979 diff -r 000000000000 -r 0cd96de13884 a
980 980 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
981 981 +++ b/a Thu Jan 01 00:00:00 1970 +0000
982 982 @@ -0,0 +1,1 @@
983 983 +a
984 984
985 985 Block: 2
986 986 diff -r 000000000000 -r 0cd96de13884 b
987 987 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
988 988 +++ b/b Thu Jan 01 00:00:00 1970 +0000
989 989 @@ -0,0 +1,1 @@
990 990 +b
991 991
992 992 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
993 993 $ rm .hg/hgrc rawdiff/map
994 994 $ rmdir rawdiff
995 995 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
996 996 $ cat hg.pid >> $DAEMON_PIDS
997 997
998 998 errors
999 999
1000 1000 $ cat ../test/errors.log
1001 1001
1002 1002 $ cd ..
@@ -1,73 +1,73
1 1 $ "$TESTDIR/hghave" execbit || exit 80
2 2
3 3 Create extension that can disable exec checks:
4 4
5 5 $ cat > noexec.py <<EOF
6 6 > from mercurial import extensions, util
7 7 > def setflags(orig, f, l, x):
8 8 > pass
9 9 > def checkexec(orig, path):
10 10 > return False
11 11 > def extsetup(ui):
12 12 > extensions.wrapfunction(util, 'setflags', setflags)
13 13 > extensions.wrapfunction(util, 'checkexec', checkexec)
14 14 > EOF
15 15
16 16 $ hg init unix-repo
17 17 $ cd unix-repo
18 18 $ touch a
19 19 $ hg add a
20 20 $ hg commit -m 'unix: add a'
21 21 $ hg clone . ../win-repo
22 22 updating to branch default
23 23 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
24 24 $ chmod +x a
25 25 $ hg commit -m 'unix: chmod a'
26 26 $ hg manifest -v
27 27 755 * a
28 28
29 29 $ cd ../win-repo
30 30
31 31 $ touch b
32 32 $ hg add b
33 33 $ hg commit -m 'win: add b'
34 34
35 35 $ hg manifest -v
36 36 644 a
37 37 644 b
38 38
39 39 $ hg pull
40 40 pulling from $TESTTMP/unix-repo
41 41 searching for changes
42 42 adding changesets
43 43 adding manifests
44 44 adding file changes
45 45 added 1 changesets with 0 changes to 0 files (+1 heads)
46 46 (run 'hg heads' to see heads, 'hg merge' to merge)
47 47
48 48 $ hg manifest -v -r tip
49 49 755 * a
50 50
51 51 Simulate a Windows merge:
52 52
53 53 $ hg --config extensions.n=$TESTTMP/noexec.py merge --debug
54 54 searching for copies back to rev 1
55 55 unmatched files in local:
56 56 b
57 57 resolving manifests
58 58 overwrite: False, partial: False
59 59 ancestor: a03b0deabf2b, local: d6fa54f68ae1+, remote: 2d8bcf2dda39
60 60 a: update permissions -> e
61 61 updating: a 1/1 files (100.00%)
62 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
62 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
63 63 (branch merge, don't forget to commit)
64 64
65 65 Simulate a Windows commit:
66 66
67 67 $ hg --config extensions.n=$TESTTMP/noexec.py commit -m 'win: merge'
68 68
69 69 $ hg manifest -v
70 70 755 * a
71 71 644 b
72 72
73 73 $ cd ..
@@ -1,110 +1,110
1 1 $ "$TESTDIR/hghave" symlink execbit || exit 80
2 2
3 3 $ hg init
4 4
5 5 $ echo a > a
6 6 $ hg ci -Amadd
7 7 adding a
8 8
9 9 $ chmod +x a
10 10 $ hg ci -mexecutable
11 11
12 12 $ hg up 0
13 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
13 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
14 14 $ rm a
15 15 $ ln -s symlink a
16 16 $ hg ci -msymlink
17 17 created new head
18 18
19 19 $ hg merge --debug
20 20 searching for copies back to rev 1
21 21 resolving manifests
22 22 overwrite: False, partial: False
23 23 ancestor: c334dc3be0da, local: 521a1e40188f+, remote: 3574f3e69b1c
24 24 conflicting flags for a
25 25 (n)one, e(x)ec or sym(l)ink? n
26 26 a: update permissions -> e
27 27 updating: a 1/1 files (100.00%)
28 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
28 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
29 29 (branch merge, don't forget to commit)
30 30
31 31
32 32 Symlink is local parent, executable is other:
33 33
34 34 $ if [ -h a ]; then
35 35 > echo a is a symlink
36 36 > $TESTDIR/readlink.py a
37 37 > elif [ -x a ]; then
38 38 > echo a is executable
39 39 > else
40 40 > echo "a has no flags (default for conflicts)"
41 41 > fi
42 42 a has no flags (default for conflicts)
43 43
44 44 $ hg update -C 1
45 45 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
46 46
47 47 $ hg merge --debug
48 48 searching for copies back to rev 1
49 49 resolving manifests
50 50 overwrite: False, partial: False
51 51 ancestor: c334dc3be0da, local: 3574f3e69b1c+, remote: 521a1e40188f
52 52 conflicting flags for a
53 53 (n)one, e(x)ec or sym(l)ink? n
54 54 a: remote is newer -> g
55 55 updating: a 1/1 files (100.00%)
56 56 getting a
57 57 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
58 58 (branch merge, don't forget to commit)
59 59
60 60
61 61 Symlink is other parent, executable is local:
62 62
63 63 $ if [ -h a ]; then
64 64 > echo a is a symlink
65 65 > $TESTDIR/readlink.py a
66 66 > elif [ -x a ]; then
67 67 > echo a is executable
68 68 > else
69 69 > echo "a has no flags (default for conflicts)"
70 70 > fi
71 71 a has no flags (default for conflicts)
72 72
73 73 Update to link without local change should get us a symlink (issue3316):
74 74
75 75 $ hg up -C 0
76 76 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
77 77 $ hg up
78 78 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
79 79 $ hg st
80 80
81 81 Update to link with local change should cause a merge prompt (issue3200):
82 82
83 83 $ hg up -C 0
84 84 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
85 85 $ echo data > a
86 86 $ HGMERGE= hg up -y --debug
87 87 searching for copies back to rev 2
88 88 resolving manifests
89 89 overwrite: False, partial: False
90 90 ancestor: c334dc3be0da, local: c334dc3be0da+, remote: 521a1e40188f
91 91 a: versions differ -> m
92 92 preserving a for resolve of a
93 93 updating: a 1/1 files (100.00%)
94 94 (couldn't find merge tool hgmerge|tool hgmerge can't handle symlinks) (re)
95 95 picked tool 'internal:prompt' for a (binary False symlink True)
96 96 no tool found to merge a
97 97 keep (l)ocal or take (o)ther? l
98 98 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
99 99 $ hg diff --git
100 100 diff --git a/a b/a
101 101 old mode 120000
102 102 new mode 100644
103 103 --- a/a
104 104 +++ b/a
105 105 @@ -1,1 +1,1 @@
106 106 -symlink
107 107 \ No newline at end of file
108 108 +data
109 109
110 110
@@ -1,36 +1,36
1 1 $ "$TESTDIR/hghave" execbit || exit 80
2 2
3 3 $ rm -rf a
4 4 $ hg init a
5 5 $ cd a
6 6
7 7 $ echo foo > foo
8 8 $ hg ci -qAm0
9 9 $ chmod +x foo
10 10 $ hg ci -m1
11 11 $ hg co -q 0
12 12 $ echo dirty > foo
13 13 $ hg up -c
14 14 abort: uncommitted local changes
15 15 [255]
16 16 $ hg up -q
17 17 $ cat foo
18 18 dirty
19 19 $ hg st -A
20 20 M foo
21 21
22 22 Validate update of standalone execute bit change:
23 23
24 24 $ hg up -C 0
25 25 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
26 26 $ chmod -x foo
27 27 $ hg ci -m removeexec
28 28 nothing changed
29 29 [1]
30 30 $ hg up -C 0
31 31 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
32 32 $ hg up
33 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
33 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
34 34 $ hg st
35 35
36 36 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now