# HG changeset patch # User Denis Laxalde # Date 2017-10-06 12:45:17 # Node ID 890afefa72964184f6464cf57ad6e2c6be21a340 # Parent 35c6a54ec1ff56123cbc0ae48cf1a280f0cf2feb diff: pass a diff hunks filter function from changeset_printer to patch.diff() We add a 'hunksfilterfn' keyword argument in all functions of the call stack from changeset_printer.show() to patch.diff(). This is a callable that will be used to filter out hunks by line range and will be used in the "-L/--line-range" option of "hg log" command introduced in the following changesets. diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -1494,7 +1494,7 @@ def export(repo, revs, fntemplate='hg-%h def diffordiffstat(ui, repo, diffopts, node1, node2, match, changes=None, stat=False, fp=None, prefix='', - root='', listsubrepos=False): + root='', listsubrepos=False, hunksfilterfn=None): '''show diff or diffstat.''' if fp is None: write = ui.write @@ -1522,14 +1522,16 @@ def diffordiffstat(ui, repo, diffopts, n if not ui.plain(): width = ui.termwidth() chunks = patch.diff(repo, node1, node2, match, changes, diffopts, - prefix=prefix, relroot=relroot) + prefix=prefix, relroot=relroot, + hunksfilterfn=hunksfilterfn) for chunk, label in patch.diffstatui(util.iterlines(chunks), width=width): write(chunk, label=label) else: for chunk, label in patch.diffui(repo, node1, node2, match, changes, diffopts, prefix=prefix, - relroot=relroot): + relroot=relroot, + hunksfilterfn=hunksfilterfn): write(chunk, label=label) if listsubrepos: @@ -1591,16 +1593,17 @@ class changeset_printer(object): if self.footer: self.ui.write(self.footer) - def show(self, ctx, copies=None, matchfn=None, **props): + def show(self, ctx, copies=None, matchfn=None, hunksfilterfn=None, + **props): props = pycompat.byteskwargs(props) if self.buffered: self.ui.pushbuffer(labeled=True) - self._show(ctx, copies, matchfn, props) + self._show(ctx, copies, matchfn, hunksfilterfn, props) self.hunk[ctx.rev()] = self.ui.popbuffer() else: - self._show(ctx, copies, matchfn, props) - - def _show(self, ctx, copies, matchfn, props): + self._show(ctx, copies, matchfn, hunksfilterfn, props) + + def _show(self, ctx, copies, matchfn, hunksfilterfn, props): '''show a single changeset or file revision''' changenode = ctx.node() rev = ctx.rev() @@ -1714,7 +1717,7 @@ class changeset_printer(object): label='log.summary') self.ui.write("\n") - self.showpatch(ctx, matchfn) + self.showpatch(ctx, matchfn, hunksfilterfn=hunksfilterfn) def _showobsfate(self, ctx): obsfate = templatekw.showobsfate(repo=self.repo, ctx=ctx, ui=self.ui) @@ -1729,7 +1732,7 @@ class changeset_printer(object): '''empty method used by extension as a hook point ''' - def showpatch(self, ctx, matchfn): + def showpatch(self, ctx, matchfn, hunksfilterfn=None): if not matchfn: matchfn = self.matchfn if matchfn: @@ -1740,12 +1743,14 @@ class changeset_printer(object): prev = ctx.p1().node() if stat: diffordiffstat(self.ui, self.repo, diffopts, prev, node, - match=matchfn, stat=True) + match=matchfn, stat=True, + hunksfilterfn=hunksfilterfn) if diff: if stat: self.ui.write("\n") diffordiffstat(self.ui, self.repo, diffopts, prev, node, - match=matchfn, stat=False) + match=matchfn, stat=False, + hunksfilterfn=hunksfilterfn) self.ui.write("\n") class jsonchangeset(changeset_printer): @@ -1762,7 +1767,7 @@ class jsonchangeset(changeset_printer): else: self.ui.write("[]\n") - def _show(self, ctx, copies, matchfn, props): + def _show(self, ctx, copies, matchfn, hunksfilterfn, props): '''show a single changeset or file revision''' rev = ctx.rev() if rev is None: @@ -1896,7 +1901,7 @@ class changeset_templater(changeset_prin self.footer += templater.stringify(self.t(self._parts['docfooter'])) return super(changeset_templater, self).close() - def _show(self, ctx, copies, matchfn, props): + def _show(self, ctx, copies, matchfn, hunksfilterfn, props): '''show a single changeset or file revision''' props = props.copy() props.update(templatekw.keywords) @@ -1928,7 +1933,7 @@ class changeset_templater(changeset_prin # write changeset metadata, then patch if requested key = self._parts[self._tref] self.ui.write(templater.stringify(self.t(key, **props))) - self.showpatch(ctx, matchfn) + self.showpatch(ctx, matchfn, hunksfilterfn=hunksfilterfn) if self._parts['footer']: if not self.footer: diff --git a/mercurial/patch.py b/mercurial/patch.py --- a/mercurial/patch.py +++ b/mercurial/patch.py @@ -2296,7 +2296,8 @@ def difffeatureopts(ui, opts=None, untru return mdiff.diffopts(**pycompat.strkwargs(buildopts)) def diff(repo, node1=None, node2=None, match=None, changes=None, - opts=None, losedatafn=None, prefix='', relroot='', copy=None): + opts=None, losedatafn=None, prefix='', relroot='', copy=None, + hunksfilterfn=None): '''yields diff of changes to files between two nodes, or node and working directory. @@ -2318,12 +2319,18 @@ def diff(repo, node1=None, node2=None, m patterns that fall outside it will be ignored. copy, if not empty, should contain mappings {dst@y: src@x} of copy - information.''' + information. + + hunksfilterfn, if not None, should be a function taking a filectx and + hunks generator that may yield filtered hunks. + ''' for fctx1, fctx2, hdr, hunks in diffhunks( repo, node1=node1, node2=node2, match=match, changes=changes, opts=opts, losedatafn=losedatafn, prefix=prefix, relroot=relroot, copy=copy, ): + if hunksfilterfn is not None: + hunks = hunksfilterfn(fctx2, hunks) text = ''.join(sum((list(hlines) for hrange, hlines in hunks), [])) if hdr and (text or len(hdr) > 1): yield '\n'.join(hdr) + '\n'