mirror of
https://github.com/facebook/sapling.git
synced 2024-10-11 09:17:30 +03:00
9b91e50f77
Summary: a user may want to use a special-purpose 'editor' to do chunk selection, but not have to use that same 'editor' to write commit messages and resolve merge conflicts This is hacked together to make it work. I'm not super familiar with the correct way to do this in python. Test Plan: added test case Reviewers: rmcelroy, simonfar, most, quark Reviewed By: quark Subscribers: mjpieters Differential Revision: https://phabricator.intern.facebook.com/D4832207 Tasks: 15728734 Signature: t1:4832207:1491519433:82a3e62d5ae03f456abe97caf1bd352a02fe35c3
112 lines
3.7 KiB
Python
112 lines
3.7 KiB
Python
# edrecord.py
|
|
#
|
|
# Copyright 2017 Facebook, Inc.
|
|
#
|
|
# This software may be used and distributed according to the terms of the
|
|
# GNU General Public License version 2 or any later version.
|
|
|
|
from mercurial import (
|
|
cmdutil,
|
|
crecord as crecordmod,
|
|
patch as patchmod,
|
|
util,
|
|
)
|
|
from mercurial.i18n import _
|
|
|
|
testedwith = 'ships-with-fb-hgext'
|
|
|
|
stringio = util.stringio
|
|
originaldorecord = cmdutil.dorecord
|
|
originalrecordfilter = cmdutil.recordfilter
|
|
|
|
def uisetup(ui):
|
|
# "editor" is otherwise not allowed as a valid option for "ui.interface"
|
|
class edrecordui(ui.__class__):
|
|
def interface(self, feature):
|
|
if feature == "chunkselector":
|
|
if (self.config("ui", "interface.%s" % feature, None) ==
|
|
"editor"):
|
|
return "editor"
|
|
elif self.config("ui", "interface.%s" % feature, None) is None:
|
|
if self.config("ui", "interface", None) == "editor":
|
|
return "editor"
|
|
return super(edrecordui, self).interface(feature)
|
|
|
|
ui.__class__ = edrecordui
|
|
cmdutil.recordfilter = recordfilter
|
|
cmdutil.dorecord = dorecord
|
|
|
|
def dorecord(ui, repo, commitfunc, cmdsuggest, backupall,
|
|
filterfn, *pats, **opts):
|
|
if ui.interface("chunkselector") != "editor":
|
|
return originaldorecord(ui, repo, commitfunc, cmdsuggest, backupall,
|
|
filterfn, *pats, **opts)
|
|
|
|
overrides = {('ui', 'interactive'): True}
|
|
with ui.configoverride(overrides, 'edrecord'):
|
|
originaldorecord(ui, repo, commitfunc, cmdsuggest, backupall, filterfn,
|
|
*pats, **opts)
|
|
|
|
def recordfilter(ui, headers, operation=None):
|
|
|
|
if ui.interface("chunkselector") != "editor":
|
|
return originalrecordfilter(ui, headers, operation)
|
|
|
|
# construct diff string from headers
|
|
if len(headers) == 0:
|
|
return [], {}
|
|
|
|
patch = stringio()
|
|
patch.write(crecordmod.diffhelptext)
|
|
|
|
specials = {}
|
|
|
|
for header in headers:
|
|
patch.write('#\n')
|
|
if header.special():
|
|
# this is useful for special changes, we are able to get away with
|
|
# only including the parts of headers that offer useful info
|
|
specials[header.filename()] = header
|
|
for h in header.header:
|
|
if h.startswith('index '):
|
|
# starting at 'index', the headers for binary files tend to
|
|
# stop offering useful info for the viewer
|
|
patch.write(_("""\
|
|
# this modifies a binary file (all or nothing)
|
|
"""))
|
|
break
|
|
if not h.startswith('diff '):
|
|
# For specials, we only care about the filename header.
|
|
# The rest can be displayed as comments
|
|
patch.write('# ')
|
|
patch.write(h)
|
|
else:
|
|
header.write(patch)
|
|
for hunk in header.hunks:
|
|
hunk.write(patch)
|
|
|
|
patcheditor = ui.config('ui', 'editor.chunkselector', None)
|
|
if patcheditor is not None:
|
|
override = {('ui', 'editor'): patcheditor}
|
|
else:
|
|
override = {}
|
|
|
|
with ui.configoverride(override):
|
|
patch = ui.edit(patch.getvalue(), "", extra={'suffix': '.diff'})
|
|
|
|
# remove comments from patch
|
|
# if there's an empty line, add a space to it
|
|
patch = [(line if len(line) > 0 else ' ') + '\n'
|
|
for line in patch.splitlines() if not line.startswith('#')]
|
|
|
|
headers = patchmod.parsepatch(patch)
|
|
|
|
applied = {}
|
|
for h in headers:
|
|
if h.filename() in specials:
|
|
h = specials[h.filename()]
|
|
applied[h.filename()] = [h] + h.hunks
|
|
|
|
return (sum([i for i in applied.itervalues()
|
|
if i[0].special() or len(i) > 1], []), {})
|