Mercurial > hg > mercurial-crew-with-dirclash
comparison mercurial/patch.py @ 2952:6ba3409f9725
merge.
author | Vadim Gelfer <vadim.gelfer@gmail.com> |
---|---|
date | Fri, 18 Aug 2006 17:02:38 -0700 |
parents | 5ddf7d305a27 2f190e998eb3 |
children | efd26ceedafb |
comparison
equal
deleted
inserted
replaced
2951:5ddf7d305a27 | 2952:6ba3409f9725 |
---|---|
8 from demandload import demandload | 8 from demandload import demandload |
9 from i18n import gettext as _ | 9 from i18n import gettext as _ |
10 from node import * | 10 from node import * |
11 demandload(globals(), "cmdutil mdiff util") | 11 demandload(globals(), "cmdutil mdiff util") |
12 demandload(globals(), "cStringIO email.Parser errno os re shutil sys tempfile") | 12 demandload(globals(), "cStringIO email.Parser errno os re shutil sys tempfile") |
13 | |
14 # helper functions | |
15 | |
16 def copyfile(src, dst, basedir=None): | |
17 if not basedir: | |
18 basedir = os.getcwd() | |
19 | |
20 abssrc, absdst = [os.path.join(basedir, n) for n in (src, dst)] | |
21 if os.path.exists(absdst): | |
22 raise util.Abort(_("cannot create %s: destination already exists") % | |
23 dst) | |
24 | |
25 targetdir = os.path.dirname(absdst) | |
26 if not os.path.isdir(targetdir): | |
27 os.makedirs(targetdir) | |
28 try: | |
29 shutil.copyfile(abssrc, absdst) | |
30 shutil.copymode(abssrc, absdst) | |
31 except shutil.Error, inst: | |
32 raise util.Abort(str(inst)) | |
33 | |
34 # public functions | |
13 | 35 |
14 def extract(ui, fileobj): | 36 def extract(ui, fileobj): |
15 '''extract patch from data read from fileobj. | 37 '''extract patch from data read from fileobj. |
16 | 38 |
17 patch can be normal patch or contained in email message. | 39 patch can be normal patch or contained in email message. |
172 for i in range(len(gitpatches)): | 194 for i in range(len(gitpatches)): |
173 p = gitpatches[i] | 195 p = gitpatches[i] |
174 if not p.copymod: | 196 if not p.copymod: |
175 continue | 197 continue |
176 | 198 |
177 if os.path.exists(p.path): | 199 copyfile(p.oldpath, p.path) |
178 raise util.Abort(_("cannot create %s: destination already exists") % | |
179 p.path) | |
180 | |
181 (src, dst) = [os.path.join(os.getcwd(), n) | |
182 for n in (p.oldpath, p.path)] | |
183 | |
184 targetdir = os.path.dirname(dst) | |
185 if not os.path.isdir(targetdir): | |
186 os.makedirs(targetdir) | |
187 try: | |
188 shutil.copyfile(src, dst) | |
189 shutil.copymode(src, dst) | |
190 except shutil.Error, inst: | |
191 raise util.Abort(str(inst)) | |
192 | 200 |
193 # rewrite patch hunk | 201 # rewrite patch hunk |
194 while pfline < p.lineno: | 202 while pfline < p.lineno: |
195 tmpfp.write(pf.readline()) | 203 tmpfp.write(pf.readline()) |
196 pfline += 1 | 204 pfline += 1 |
279 ignorewsamount=(opts.get('ignore_space_change') or | 287 ignorewsamount=(opts.get('ignore_space_change') or |
280 ui.configbool('diff', 'ignorewsamount', None)), | 288 ui.configbool('diff', 'ignorewsamount', None)), |
281 ignoreblanklines=(opts.get('ignore_blank_lines') or | 289 ignoreblanklines=(opts.get('ignore_blank_lines') or |
282 ui.configbool('diff', 'ignoreblanklines', None))) | 290 ui.configbool('diff', 'ignoreblanklines', None))) |
283 | 291 |
292 def updatedir(ui, repo, patches, wlock=None): | |
293 '''Update dirstate after patch application according to metadata''' | |
294 if not patches: | |
295 return | |
296 copies = [] | |
297 removes = [] | |
298 cfiles = patches.keys() | |
299 copts = {'after': False, 'force': False} | |
300 cwd = repo.getcwd() | |
301 if cwd: | |
302 cfiles = [util.pathto(cwd, f) for f in patches.keys()] | |
303 for f in patches: | |
304 ctype, gp = patches[f] | |
305 if ctype == 'RENAME': | |
306 copies.append((gp.oldpath, gp.path, gp.copymod)) | |
307 removes.append(gp.oldpath) | |
308 elif ctype == 'COPY': | |
309 copies.append((gp.oldpath, gp.path, gp.copymod)) | |
310 elif ctype == 'DELETE': | |
311 removes.append(gp.path) | |
312 for src, dst, after in copies: | |
313 if not after: | |
314 copyfile(src, dst, repo.root) | |
315 repo.copy(src, dst, wlock=wlock) | |
316 if removes: | |
317 repo.remove(removes, True, wlock=wlock) | |
318 for f in patches: | |
319 ctype, gp = patches[f] | |
320 if gp and gp.mode: | |
321 x = gp.mode & 0100 != 0 | |
322 dst = os.path.join(repo.root, gp.path) | |
323 util.set_exec(dst, x) | |
324 cmdutil.addremove(repo, cfiles, wlock=wlock) | |
325 files = patches.keys() | |
326 files.extend([r for r in removes if r not in files]) | |
327 files.sort() | |
328 | |
329 return files | |
330 | |
284 def diff(repo, node1=None, node2=None, files=None, match=util.always, | 331 def diff(repo, node1=None, node2=None, files=None, match=util.always, |
285 fp=None, changes=None, opts=None): | 332 fp=None, changes=None, opts=None): |
286 '''print diff of changes to files between two nodes, or node and | 333 '''print diff of changes to files between two nodes, or node and |
287 working directory. | 334 working directory. |
288 | 335 |
294 if fp is None: | 341 if fp is None: |
295 fp = repo.ui | 342 fp = repo.ui |
296 | 343 |
297 if not node1: | 344 if not node1: |
298 node1 = repo.dirstate.parents()[0] | 345 node1 = repo.dirstate.parents()[0] |
346 | |
347 clcache = {} | |
348 def getchangelog(n): | |
349 if n not in clcache: | |
350 clcache[n] = repo.changelog.read(n) | |
351 return clcache[n] | |
352 mcache = {} | |
353 def getmanifest(n): | |
354 if n not in mcache: | |
355 mcache[n] = repo.manifest.read(n) | |
356 return mcache[n] | |
357 fcache = {} | |
358 def getfile(f): | |
359 if f not in fcache: | |
360 fcache[f] = repo.file(f) | |
361 return fcache[f] | |
362 | |
299 # reading the data for node1 early allows it to play nicely | 363 # reading the data for node1 early allows it to play nicely |
300 # with repo.status and the revlog cache. | 364 # with repo.status and the revlog cache. |
301 change = repo.changelog.read(node1) | 365 change = getchangelog(node1) |
302 mmap = repo.manifest.read(change[0]) | 366 mmap = getmanifest(change[0]) |
303 date1 = util.datestr(change[2]) | 367 date1 = util.datestr(change[2]) |
304 | 368 |
305 if not changes: | 369 if not changes: |
306 changes = repo.status(node1, node2, files, match=match)[:5] | 370 changes = repo.status(node1, node2, files, match=match)[:5] |
307 modified, added, removed, deleted, unknown = changes | 371 modified, added, removed, deleted, unknown = changes |
318 modified, added, removed = map(filterfiles, (modified, added, removed)) | 382 modified, added, removed = map(filterfiles, (modified, added, removed)) |
319 | 383 |
320 if not modified and not added and not removed: | 384 if not modified and not added and not removed: |
321 return | 385 return |
322 | 386 |
387 def renamedbetween(f, n1, n2): | |
388 r1, r2 = map(repo.changelog.rev, (n1, n2)) | |
389 src = None | |
390 while r2 > r1: | |
391 cl = getchangelog(n2)[0] | |
392 m = getmanifest(cl) | |
393 try: | |
394 src = getfile(f).renamed(m[f]) | |
395 except KeyError: | |
396 return None | |
397 if src: | |
398 f = src[0] | |
399 n2 = repo.changelog.parents(n2)[0] | |
400 r2 = repo.changelog.rev(n2) | |
401 return src | |
402 | |
323 if node2: | 403 if node2: |
324 change = repo.changelog.read(node2) | 404 change = getchangelog(node2) |
325 mmap2 = repo.manifest.read(change[0]) | 405 mmap2 = getmanifest(change[0]) |
326 _date2 = util.datestr(change[2]) | 406 _date2 = util.datestr(change[2]) |
327 def date2(f): | 407 def date2(f): |
328 return _date2 | 408 return _date2 |
329 def read(f): | 409 def read(f): |
330 return repo.file(f).read(mmap2[f]) | 410 return getfile(f).read(mmap2[f]) |
331 def renamed(f): | 411 def renamed(f): |
332 src = repo.file(f).renamed(mmap2[f]) | 412 return renamedbetween(f, node1, node2) |
333 return src and src[0] or None | |
334 else: | 413 else: |
335 tz = util.makedate()[1] | 414 tz = util.makedate()[1] |
336 _date2 = util.datestr() | 415 _date2 = util.datestr() |
337 def date2(f): | 416 def date2(f): |
338 try: | 417 try: |
341 if err.errno != errno.ENOENT: raise | 420 if err.errno != errno.ENOENT: raise |
342 return _date2 | 421 return _date2 |
343 def read(f): | 422 def read(f): |
344 return repo.wread(f) | 423 return repo.wread(f) |
345 def renamed(f): | 424 def renamed(f): |
346 return repo.dirstate.copies.get(f) | 425 src = repo.dirstate.copies.get(f) |
426 parent = repo.dirstate.parents()[0] | |
427 if src: | |
428 f = src[0] | |
429 of = renamedbetween(f, node1, parent) | |
430 if of: | |
431 return of | |
432 elif src: | |
433 cl = getchangelog(parent)[0] | |
434 return (src, getmanifest(cl)[src]) | |
435 else: | |
436 return None | |
347 | 437 |
348 if repo.ui.quiet: | 438 if repo.ui.quiet: |
349 r = None | 439 r = None |
350 else: | 440 else: |
351 hexfunc = repo.ui.verbose and hex or short | 441 hexfunc = repo.ui.verbose and hex or short |
355 copied = {} | 445 copied = {} |
356 for f in added: | 446 for f in added: |
357 src = renamed(f) | 447 src = renamed(f) |
358 if src: | 448 if src: |
359 copied[f] = src | 449 copied[f] = src |
360 srcs = [x[1] for x in copied.items()] | 450 srcs = [x[1][0] for x in copied.items()] |
361 | 451 |
362 all = modified + added + removed | 452 all = modified + added + removed |
363 all.sort() | 453 all.sort() |
364 for f in all: | 454 for f in all: |
365 to = None | 455 to = None |
366 tn = None | 456 tn = None |
367 dodiff = True | 457 dodiff = True |
368 if f in mmap: | 458 if f in mmap: |
369 to = repo.file(f).read(mmap[f]) | 459 to = getfile(f).read(mmap[f]) |
370 if f not in removed: | 460 if f not in removed: |
371 tn = read(f) | 461 tn = read(f) |
372 if opts.git: | 462 if opts.git: |
373 def gitmode(x): | 463 def gitmode(x): |
374 return x and '100755' or '100644' | 464 return x and '100755' or '100644' |
383 if node2: | 473 if node2: |
384 mode = gitmode(mmap2.execf(f)) | 474 mode = gitmode(mmap2.execf(f)) |
385 else: | 475 else: |
386 mode = gitmode(util.is_exec(repo.wjoin(f), None)) | 476 mode = gitmode(util.is_exec(repo.wjoin(f), None)) |
387 if f in copied: | 477 if f in copied: |
388 a = copied[f] | 478 a, arev = copied[f] |
389 omode = gitmode(mmap.execf(a)) | 479 omode = gitmode(mmap.execf(a)) |
390 addmodehdr(header, omode, mode) | 480 addmodehdr(header, omode, mode) |
391 op = a in removed and 'rename' or 'copy' | 481 op = a in removed and 'rename' or 'copy' |
392 header.append('%s from %s\n' % (op, a)) | 482 header.append('%s from %s\n' % (op, a)) |
393 header.append('%s to %s\n' % (op, f)) | 483 header.append('%s to %s\n' % (op, f)) |
394 to = repo.file(a).read(mmap[a]) | 484 to = getfile(a).read(arev) |
395 else: | 485 else: |
396 header.append('new file mode %s\n' % mode) | 486 header.append('new file mode %s\n' % mode) |
397 elif f in removed: | 487 elif f in removed: |
398 if f in srcs: | 488 if f in srcs: |
399 dodiff = False | 489 dodiff = False |