# HG changeset patch # User Pulkit Goyal <7895pulkit@gmail.com> # Date 2020-07-06 10:01:53 # Node ID 20a65e397943599bcf5ac759b119296443b699d1 # Parent dff208398ede91d478e7b765b5c899c9e794d0b7 patch: refactor content diffing part in separate fn so extensions can wrap Right now extdiff uses it's own logic using archival to diff two versions of file using external diff tools. This makes the extdiff functionality non-extensible. This series is an attempt to refactor core patch and diff functionality so that extdiff can wrap and reuse it. This will help us in using external diffing tools at more places and not just extdiff command only then. Differential Revision: https://phab.mercurial-scm.org/D8685 diff --git a/mercurial/patch.py b/mercurial/patch.py --- a/mercurial/patch.py +++ b/mercurial/patch.py @@ -2922,6 +2922,18 @@ def _filepairs(modified, added, removed, yield f1, f2, copyop +def _gitindex(text): + if not text: + text = b"" + l = len(text) + s = hashutil.sha1(b'blob %d\0' % l) + s.update(text) + return hex(s.digest()) + + +_gitmode = {b'l': b'120000', b'x': b'100755', b'': b'100644'} + + def trydiff( repo, revs, @@ -2944,14 +2956,6 @@ def trydiff( pathfn is applied to every path in the diff output. ''' - def gitindex(text): - if not text: - text = b"" - l = len(text) - s = hashutil.sha1(b'blob %d\0' % l) - s.update(text) - return hex(s.digest()) - if opts.noprefix: aprefix = bprefix = b'' else: @@ -2968,8 +2972,6 @@ def trydiff( date1 = dateutil.datestr(ctx1.date()) date2 = dateutil.datestr(ctx2.date()) - gitmode = {b'l': b'120000', b'x': b'100755', b'': b'100644'} - if not pathfn: pathfn = lambda f: f @@ -3023,11 +3025,11 @@ def trydiff( b'diff --git %s%s %s%s' % (aprefix, path1, bprefix, path2) ) if not f1: # added - header.append(b'new file mode %s' % gitmode[flag2]) + header.append(b'new file mode %s' % _gitmode[flag2]) elif not f2: # removed - header.append(b'deleted file mode %s' % gitmode[flag1]) + header.append(b'deleted file mode %s' % _gitmode[flag1]) else: # modified/copied/renamed - mode1, mode2 = gitmode[flag1], gitmode[flag2] + mode1, mode2 = _gitmode[flag1], _gitmode[flag2] if mode1 != mode2: header.append(b'old mode %s' % mode1) header.append(b'new mode %s' % mode2) @@ -3071,39 +3073,66 @@ def trydiff( if fctx2 is not None: content2 = fctx2.data() - if binary and opts.git and not opts.nobinary: - text = mdiff.b85diff(content1, content2) - if text: - header.append( - b'index %s..%s' % (gitindex(content1), gitindex(content2)) + data1 = (ctx1, fctx1, path1, flag1, content1, date1) + data2 = (ctx2, fctx2, path2, flag2, content2, date2) + yield diffcontent(data1, data2, header, binary, opts) + + +def diffcontent(data1, data2, header, binary, opts): + """ diffs two versions of a file. + + data1 and data2 are tuples containg: + + * ctx: changeset for the file + * fctx: file context for that file + * path1: name of the file + * flag: flags of the file + * content: full content of the file (can be null in case of binary) + * date: date of the changeset + + header: the patch header + binary: whether the any of the version of file is binary or not + opts: user passed options + + It exists as a separate function so that extensions like extdiff can wrap + it and use the file content directly. + """ + + ctx1, fctx1, path1, flag1, content1, date1 = data1 + ctx2, fctx2, path2, flag2, content2, date2 = data2 + if binary and opts.git and not opts.nobinary: + text = mdiff.b85diff(content1, content2) + if text: + header.append( + b'index %s..%s' % (_gitindex(content1), _gitindex(content2)) + ) + hunks = ((None, [text]),) + else: + if opts.git and opts.index > 0: + flag = flag1 + if flag is None: + flag = flag2 + header.append( + b'index %s..%s %s' + % ( + _gitindex(content1)[0 : opts.index], + _gitindex(content2)[0 : opts.index], + _gitmode[flag], ) - hunks = ((None, [text]),) - else: - if opts.git and opts.index > 0: - flag = flag1 - if flag is None: - flag = flag2 - header.append( - b'index %s..%s %s' - % ( - gitindex(content1)[0 : opts.index], - gitindex(content2)[0 : opts.index], - gitmode[flag], - ) - ) - - uheaders, hunks = mdiff.unidiff( - content1, - date1, - content2, - date2, - path1, - path2, - binary=binary, - opts=opts, ) - header.extend(uheaders) - yield fctx1, fctx2, header, hunks + + uheaders, hunks = mdiff.unidiff( + content1, + date1, + content2, + date2, + path1, + path2, + binary=binary, + opts=opts, + ) + header.extend(uheaders) + return fctx1, fctx2, header, hunks def diffstatsum(stats):