2017-02-23 22:27:52 +03:00
|
|
|
# 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)
|
|
|
|
|
|
|
|
backup = ui.backupconfig('ui', 'interactive')
|
|
|
|
try:
|
|
|
|
ui.setconfig('ui', 'interactive', True)
|
|
|
|
originaldorecord(ui, repo, commitfunc, cmdsuggest, backupall, filterfn,
|
|
|
|
*pats, **opts)
|
|
|
|
finally:
|
|
|
|
ui.restoreconfig(backup)
|
|
|
|
|
|
|
|
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)\n
|
|
|
|
"""))
|
|
|
|
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)
|
|
|
|
|
|
|
|
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
|
|
|
|
|
2017-02-24 00:09:59 +03:00
|
|
|
return (sum([i for i in applied.itervalues()
|
|
|
|
if i[0].special() or len(i) > 1], []), {})
|