Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/patch.py @ 41657:d4c9eebdd72d
patch: replace "prefix" and "relroot" arguments by "pathfn" (API)
The two arguments serve a very similar purpose: "relroot" is stripped
from the front of the path, and then "prefix" (a subrepo path) is
added (also to the front). Passing in a function that does that is
more generic and will make it easier to respect ui.relative-paths in
later patches (don't worry, I'm not going to respect that option for
regular patches, only for --stat). I'm deliberately not calling it
"uipathfn", because it's generally for producing valid diffs
(including when prefix is non-empty), so things like using backslash
on Windows is not an option.
Differential Revision: https://phab.mercurial-scm.org/D5894
author | Martin von Zweigbergk <martinvonz@google.com> |
---|---|
date | Wed, 06 Feb 2019 23:12:56 -0800 |
parents | 3751595ec45e |
children | aaad36b88298 |
comparison
equal
deleted
inserted
replaced
41656:2306158314e9 | 41657:d4c9eebdd72d |
---|---|
13 import copy | 13 import copy |
14 import email | 14 import email |
15 import errno | 15 import errno |
16 import hashlib | 16 import hashlib |
17 import os | 17 import os |
18 import posixpath | |
19 import re | 18 import re |
20 import shutil | 19 import shutil |
21 import zlib | 20 import zlib |
22 | 21 |
23 from .i18n import _ | 22 from .i18n import _ |
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 |