2237 diffopts = diffutil.diffallopts |
2236 diffopts = diffutil.diffallopts |
2238 diffallopts = diffutil.diffallopts |
2237 diffallopts = diffutil.diffallopts |
2239 difffeatureopts = diffutil.difffeatureopts |
2238 difffeatureopts = diffutil.difffeatureopts |
2240 |
2239 |
2241 def diff(repo, node1=None, node2=None, match=None, changes=None, |
2240 def diff(repo, node1=None, node2=None, match=None, changes=None, |
2242 opts=None, losedatafn=None, prefix='', relroot='', copy=None, |
2241 opts=None, losedatafn=None, pathfn=None, copy=None, |
2243 copysourcematch=None, hunksfilterfn=None): |
2242 copysourcematch=None, hunksfilterfn=None): |
2244 '''yields diff of changes to files between two nodes, or node and |
2243 '''yields diff of changes to files between two nodes, or node and |
2245 working directory. |
2244 working directory. |
2246 |
2245 |
2247 if node1 is None, use first dirstate parent instead. |
2246 if node1 is None, use first dirstate parent instead. |
2275 |
2274 |
2276 ctx1 = repo[node1] |
2275 ctx1 = repo[node1] |
2277 ctx2 = repo[node2] |
2276 ctx2 = repo[node2] |
2278 |
2277 |
2279 for fctx1, fctx2, hdr, hunks in diffhunks( |
2278 for fctx1, fctx2, hdr, hunks in diffhunks( |
2280 repo, ctx1=ctx1, ctx2=ctx2, |
2279 repo, ctx1=ctx1, ctx2=ctx2, match=match, changes=changes, opts=opts, |
2281 match=match, changes=changes, opts=opts, |
2280 losedatafn=losedatafn, pathfn=pathfn, copy=copy, |
2282 losedatafn=losedatafn, prefix=prefix, relroot=relroot, copy=copy, |
|
2283 copysourcematch=copysourcematch): |
2281 copysourcematch=copysourcematch): |
2284 if hunksfilterfn is not None: |
2282 if hunksfilterfn is not None: |
2285 # If the file has been removed, fctx2 is None; but this should |
2283 # If the file has been removed, fctx2 is None; but this should |
2286 # not occur here since we catch removed files early in |
2284 # not occur here since we catch removed files early in |
2287 # logcmdutil.getlinerangerevs() for 'hg log -L'. |
2285 # logcmdutil.getlinerangerevs() for 'hg log -L'. |
2292 if hdr and (text or len(hdr) > 1): |
2290 if hdr and (text or len(hdr) > 1): |
2293 yield '\n'.join(hdr) + '\n' |
2291 yield '\n'.join(hdr) + '\n' |
2294 if text: |
2292 if text: |
2295 yield text |
2293 yield text |
2296 |
2294 |
2297 def diffhunks(repo, ctx1, ctx2, match=None, changes=None, |
2295 def diffhunks(repo, ctx1, ctx2, match=None, changes=None, opts=None, |
2298 opts=None, losedatafn=None, prefix='', relroot='', copy=None, |
2296 losedatafn=None, pathfn=None, copy=None, copysourcematch=None): |
2299 copysourcematch=None): |
|
2300 """Yield diff of changes to files in the form of (`header`, `hunks`) tuples |
2297 """Yield diff of changes to files in the form of (`header`, `hunks`) tuples |
2301 where `header` is a list of diff headers and `hunks` is an iterable of |
2298 where `header` is a list of diff headers and `hunks` is an iterable of |
2302 (`hunkrange`, `hunklines`) tuples. |
2299 (`hunkrange`, `hunklines`) tuples. |
2303 |
2300 |
2304 See diff() for the meaning of parameters. |
2301 See diff() for the meaning of parameters. |
2374 repo, list(modifiedset | addedset | removedset)) |
2371 repo, list(modifiedset | addedset | removedset)) |
2375 scmutil.prefetchfiles(repo, [ctx1.rev(), ctx2.rev()], prefetchmatch) |
2372 scmutil.prefetchfiles(repo, [ctx1.rev(), ctx2.rev()], prefetchmatch) |
2376 |
2373 |
2377 def difffn(opts, losedata): |
2374 def difffn(opts, losedata): |
2378 return trydiff(repo, revs, ctx1, ctx2, modified, added, removed, |
2375 return trydiff(repo, revs, ctx1, ctx2, modified, added, removed, |
2379 copy, getfilectx, opts, losedata, prefix, relroot) |
2376 copy, getfilectx, opts, losedata, pathfn) |
2380 if opts.upgrade and not opts.git: |
2377 if opts.upgrade and not opts.git: |
2381 try: |
2378 try: |
2382 def losedata(fn): |
2379 def losedata(fn): |
2383 if not losedatafn or not losedatafn(fn=fn): |
2380 if not losedatafn or not losedatafn(fn=fn): |
2384 raise GitDiffRequired |
2381 raise GitDiffRequired |
2589 and copy[copyto[f]] == f): |
2586 and copy[copyto[f]] == f): |
2590 continue |
2587 continue |
2591 yield f1, f2, copyop |
2588 yield f1, f2, copyop |
2592 |
2589 |
2593 def trydiff(repo, revs, ctx1, ctx2, modified, added, removed, |
2590 def trydiff(repo, revs, ctx1, ctx2, modified, added, removed, |
2594 copy, getfilectx, opts, losedatafn, prefix, relroot): |
2591 copy, getfilectx, opts, losedatafn, pathfn): |
2595 '''given input data, generate a diff and yield it in blocks |
2592 '''given input data, generate a diff and yield it in blocks |
2596 |
2593 |
2597 If generating a diff would lose data like flags or binary data and |
2594 If generating a diff would lose data like flags or binary data and |
2598 losedatafn is not None, it will be called. |
2595 losedatafn is not None, it will be called. |
2599 |
2596 |
2600 relroot is removed and prefix is added to every path in the diff output. |
2597 pathfn is applied to every path in the diff output. |
2601 |
2598 ''' |
2602 If relroot is not empty, this function expects every path in modified, |
|
2603 added, removed and copy to start with it.''' |
|
2604 |
2599 |
2605 def gitindex(text): |
2600 def gitindex(text): |
2606 if not text: |
2601 if not text: |
2607 text = "" |
2602 text = "" |
2608 l = len(text) |
2603 l = len(text) |
2626 date1 = dateutil.datestr(ctx1.date()) |
2621 date1 = dateutil.datestr(ctx1.date()) |
2627 date2 = dateutil.datestr(ctx2.date()) |
2622 date2 = dateutil.datestr(ctx2.date()) |
2628 |
2623 |
2629 gitmode = {'l': '120000', 'x': '100755', '': '100644'} |
2624 gitmode = {'l': '120000', 'x': '100755', '': '100644'} |
2630 |
2625 |
2631 if relroot != '' and (repo.ui.configbool('devel', 'all-warnings') |
2626 if not pathfn: |
2632 or repo.ui.configbool('devel', 'check-relroot')): |
2627 pathfn = lambda f: f |
2633 for f in modified + added + removed + list(copy) + list(copy.values()): |
|
2634 if f is not None and not f.startswith(relroot): |
|
2635 raise AssertionError( |
|
2636 "file %s doesn't start with relroot %s" % (f, relroot)) |
|
2637 |
2628 |
2638 for f1, f2, copyop in _filepairs(modified, added, removed, copy, opts): |
2629 for f1, f2, copyop in _filepairs(modified, added, removed, copy, opts): |
2639 content1 = None |
2630 content1 = None |
2640 content2 = None |
2631 content2 = None |
2641 fctx1 = None |
2632 fctx1 = None |
2668 (not f1 and flag2) or |
2659 (not f1 and flag2) or |
2669 # change flags |
2660 # change flags |
2670 (f1 and f2 and flag1 != flag2)): |
2661 (f1 and f2 and flag1 != flag2)): |
2671 losedatafn(f2 or f1) |
2662 losedatafn(f2 or f1) |
2672 |
2663 |
2673 path1 = f1 or f2 |
2664 path1 = pathfn(f1 or f2) |
2674 path2 = f2 or f1 |
2665 path2 = pathfn(f2 or f1) |
2675 path1 = posixpath.join(prefix, path1[len(relroot):]) |
|
2676 path2 = posixpath.join(prefix, path2[len(relroot):]) |
|
2677 header = [] |
2666 header = [] |
2678 if opts.git: |
2667 if opts.git: |
2679 header.append('diff --git %s%s %s%s' % |
2668 header.append('diff --git %s%s %s%s' % |
2680 (aprefix, path1, bprefix, path2)) |
2669 (aprefix, path1, bprefix, path2)) |
2681 if not f1: # added |
2670 if not f1: # added |