2008-04-03 15:41:31 +04:00
|
|
|
# win32text.py - LF <-> CRLF/CR translation utilities for Windows/Mac users
|
2007-12-20 01:02:31 +03:00
|
|
|
#
|
2009-04-26 03:49:12 +04:00
|
|
|
# Copyright 2005, 2007-2009 Matt Mackall <mpm@selenic.com> and others
|
|
|
|
#
|
|
|
|
# This software may be used and distributed according to the terms of the
|
2010-01-20 07:20:08 +03:00
|
|
|
# GNU General Public License version 2 or any later version.
|
2009-06-21 18:45:47 +04:00
|
|
|
|
2014-03-02 05:51:22 +04:00
|
|
|
'''perform automatic newline conversion (DEPRECATED)
|
2009-06-21 18:45:47 +04:00
|
|
|
|
2010-06-02 16:54:25 +04:00
|
|
|
Deprecation: The win32text extension requires each user to configure
|
|
|
|
the extension again and again for each clone since the configuration
|
|
|
|
is not copied when cloning.
|
|
|
|
|
|
|
|
We have therefore made the ``eol`` as an alternative. The ``eol``
|
|
|
|
uses a version controlled file for its configuration and each clone
|
|
|
|
will therefore use the right settings from the start.
|
|
|
|
|
2009-07-23 02:26:26 +04:00
|
|
|
To perform automatic newline conversion, use::
|
2009-06-21 18:45:47 +04:00
|
|
|
|
2009-07-23 02:26:26 +04:00
|
|
|
[extensions]
|
2009-12-22 02:50:03 +03:00
|
|
|
win32text =
|
2009-07-23 02:26:26 +04:00
|
|
|
[encode]
|
|
|
|
** = cleverencode:
|
|
|
|
# or ** = macencode:
|
2009-06-21 18:45:47 +04:00
|
|
|
|
2009-07-23 02:26:26 +04:00
|
|
|
[decode]
|
|
|
|
** = cleverdecode:
|
|
|
|
# or ** = macdecode:
|
2009-06-21 18:45:47 +04:00
|
|
|
|
2009-07-23 02:26:26 +04:00
|
|
|
If not doing conversion, to make sure you do not commit CRLF/CR by accident::
|
2009-06-21 18:45:47 +04:00
|
|
|
|
2009-07-23 02:26:26 +04:00
|
|
|
[hooks]
|
|
|
|
pretxncommit.crlf = python:hgext.win32text.forbidcrlf
|
|
|
|
# or pretxncommit.cr = python:hgext.win32text.forbidcr
|
2009-06-21 18:45:47 +04:00
|
|
|
|
|
|
|
To do the same check on a server to prevent CRLF/CR from being
|
2009-07-23 02:26:26 +04:00
|
|
|
pushed or pulled::
|
2009-06-21 18:45:47 +04:00
|
|
|
|
2009-07-23 02:26:26 +04:00
|
|
|
[hooks]
|
|
|
|
pretxnchangegroup.crlf = python:hgext.win32text.forbidcrlf
|
|
|
|
# or pretxnchangegroup.cr = python:hgext.win32text.forbidcr
|
2009-06-21 18:45:47 +04:00
|
|
|
'''
|
2007-12-20 01:02:31 +03:00
|
|
|
|
2016-07-03 19:58:24 +03:00
|
|
|
from __future__ import absolute_import
|
|
|
|
|
2007-07-09 21:59:49 +04:00
|
|
|
import re
|
2016-07-03 19:58:24 +03:00
|
|
|
from mercurial.i18n import _
|
|
|
|
from mercurial.node import (
|
|
|
|
short,
|
|
|
|
)
|
|
|
|
from mercurial import (
|
2017-06-30 04:45:56 +03:00
|
|
|
registrar,
|
2016-07-03 19:58:24 +03:00
|
|
|
util,
|
|
|
|
)
|
2007-07-09 21:59:49 +04:00
|
|
|
|
2016-08-23 18:26:08 +03:00
|
|
|
# Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
|
2015-04-28 23:44:37 +03:00
|
|
|
# extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
|
|
|
|
# be specifying the version(s) of Mercurial they are tested with, or
|
|
|
|
# leave the attribute unspecified.
|
2016-08-23 18:26:08 +03:00
|
|
|
testedwith = 'ships-with-hg-core'
|
2012-05-15 23:37:49 +04:00
|
|
|
|
2017-06-30 04:45:56 +03:00
|
|
|
configtable = {}
|
|
|
|
configitem = registrar.configitem(configtable)
|
|
|
|
|
|
|
|
configitem('win32text', 'warn',
|
|
|
|
default=True,
|
|
|
|
)
|
|
|
|
|
2007-07-09 21:59:49 +04:00
|
|
|
# regexp for single LF without CR preceding.
|
|
|
|
re_single_lf = re.compile('(^|[^\r])\n', re.MULTILINE)
|
|
|
|
|
2008-04-03 15:41:31 +04:00
|
|
|
newlinestr = {'\r\n': 'CRLF', '\r': 'CR'}
|
|
|
|
filterstr = {'\r\n': 'clever', '\r': 'mac'}
|
|
|
|
|
flake8: enable F821 check
Summary:
This check is useful and detects real errors (ex. fbconduit). Unfortunately
`arc lint` will run it with both py2 and py3 so a lot of py2 builtins will
still be warned.
I didn't find a clean way to disable py3 check. So this diff tries to fix them.
For `xrange`, the change was done by a script:
```
import sys
import redbaron
headertypes = {'comment', 'endl', 'from_import', 'import', 'string',
'assignment', 'atomtrailers'}
xrangefix = '''try:
xrange(0)
except NameError:
xrange = range
'''
def isxrange(x):
try:
return x[0].value == 'xrange'
except Exception:
return False
def main(argv):
for i, path in enumerate(argv):
print('(%d/%d) scanning %s' % (i + 1, len(argv), path))
content = open(path).read()
try:
red = redbaron.RedBaron(content)
except Exception:
print(' warning: failed to parse')
continue
hasxrange = red.find('atomtrailersnode', value=isxrange)
hasxrangefix = 'xrange = range' in content
if hasxrangefix or not hasxrange:
print(' no need to change')
continue
# find a place to insert the compatibility statement
changed = False
for node in red:
if node.type in headertypes:
continue
# node.insert_before is an easier API, but it has bugs changing
# other "finally" and "except" positions. So do the insert
# manually.
# # node.insert_before(xrangefix)
line = node.absolute_bounding_box.top_left.line - 1
lines = content.splitlines(1)
content = ''.join(lines[:line]) + xrangefix + ''.join(lines[line:])
changed = True
break
if changed:
# "content" is faster than "red.dumps()"
open(path, 'w').write(content)
print(' updated')
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))
```
For other py2 builtins that do not have a py3 equivalent, some `# noqa`
were added as a workaround for now.
Reviewed By: DurhamG
Differential Revision: D6934535
fbshipit-source-id: 546b62830af144bc8b46788d2e0fd00496838939
2018-02-10 04:31:44 +03:00
|
|
|
try:
|
|
|
|
xrange(0)
|
|
|
|
except NameError:
|
|
|
|
xrange = range
|
|
|
|
|
2008-04-03 15:41:31 +04:00
|
|
|
def checknewline(s, newline, ui=None, repo=None, filename=None):
|
|
|
|
# warn if already has 'newline' in repository.
|
2007-07-09 21:59:49 +04:00
|
|
|
# it might cause unexpected eol conversion.
|
|
|
|
# see issue 302:
|
2015-09-30 23:31:07 +03:00
|
|
|
# https://bz.mercurial-scm.org/302
|
2008-04-03 15:41:31 +04:00
|
|
|
if newline in s and ui and filename and repo:
|
|
|
|
ui.warn(_('WARNING: %s already has %s line endings\n'
|
2007-12-22 07:21:17 +03:00
|
|
|
'and does not need EOL conversion by the win32text plugin.\n'
|
|
|
|
'Before your next commit, please reconsider your '
|
|
|
|
'encode/decode settings in \nMercurial.ini or %s.\n') %
|
2017-03-09 03:52:57 +03:00
|
|
|
(filename, newlinestr[newline], repo.vfs.join('hgrc')))
|
2008-04-03 15:41:31 +04:00
|
|
|
|
|
|
|
def dumbdecode(s, cmd, **kwargs):
|
|
|
|
checknewline(s, '\r\n', **kwargs)
|
2007-07-09 21:59:49 +04:00
|
|
|
# replace single LF to CRLF
|
|
|
|
return re_single_lf.sub('\\1\r\n', s)
|
|
|
|
|
|
|
|
def dumbencode(s, cmd):
|
|
|
|
return s.replace('\r\n', '\n')
|
|
|
|
|
2008-04-03 15:41:31 +04:00
|
|
|
def macdumbdecode(s, cmd, **kwargs):
|
|
|
|
checknewline(s, '\r', **kwargs)
|
|
|
|
return s.replace('\n', '\r')
|
|
|
|
|
|
|
|
def macdumbencode(s, cmd):
|
|
|
|
return s.replace('\r', '\n')
|
|
|
|
|
2007-12-22 07:21:17 +03:00
|
|
|
def cleverdecode(s, cmd, **kwargs):
|
2008-04-10 02:49:20 +04:00
|
|
|
if not util.binary(s):
|
2008-04-05 01:09:54 +04:00
|
|
|
return dumbdecode(s, cmd, **kwargs)
|
|
|
|
return s
|
2007-07-09 21:59:49 +04:00
|
|
|
|
|
|
|
def cleverencode(s, cmd):
|
2008-04-10 02:49:20 +04:00
|
|
|
if not util.binary(s):
|
2008-04-05 01:09:54 +04:00
|
|
|
return dumbencode(s, cmd)
|
|
|
|
return s
|
2007-07-09 21:59:49 +04:00
|
|
|
|
2008-04-03 15:41:31 +04:00
|
|
|
def macdecode(s, cmd, **kwargs):
|
2008-04-10 02:49:20 +04:00
|
|
|
if not util.binary(s):
|
2008-04-05 21:33:34 +04:00
|
|
|
return macdumbdecode(s, cmd, **kwargs)
|
|
|
|
return s
|
2008-04-03 15:41:31 +04:00
|
|
|
|
|
|
|
def macencode(s, cmd):
|
2008-04-10 02:49:20 +04:00
|
|
|
if not util.binary(s):
|
2008-04-05 21:33:34 +04:00
|
|
|
return macdumbencode(s, cmd)
|
|
|
|
return s
|
2008-04-03 15:41:31 +04:00
|
|
|
|
2008-01-28 23:39:47 +03:00
|
|
|
_filters = {
|
2007-07-09 21:59:49 +04:00
|
|
|
'dumbdecode:': dumbdecode,
|
|
|
|
'dumbencode:': dumbencode,
|
|
|
|
'cleverdecode:': cleverdecode,
|
|
|
|
'cleverencode:': cleverencode,
|
2008-04-03 15:41:31 +04:00
|
|
|
'macdumbdecode:': macdumbdecode,
|
|
|
|
'macdumbencode:': macdumbencode,
|
|
|
|
'macdecode:': macdecode,
|
|
|
|
'macencode:': macencode,
|
2008-01-28 23:39:47 +03:00
|
|
|
}
|
2007-12-20 01:02:31 +03:00
|
|
|
|
2008-04-05 21:06:16 +04:00
|
|
|
def forbidnewline(ui, repo, hooktype, node, newline, **kwargs):
|
2007-12-20 01:02:31 +03:00
|
|
|
halt = False
|
2009-04-22 02:55:32 +04:00
|
|
|
seen = set()
|
2009-04-24 11:06:01 +04:00
|
|
|
# we try to walk changesets in reverse order from newest to
|
|
|
|
# oldest, so that if we see a file multiple times, we take the
|
|
|
|
# newest version as canonical. this prevents us from blocking a
|
|
|
|
# changegroup that contains an unacceptable commit followed later
|
|
|
|
# by a commit that fixes the problem.
|
|
|
|
tip = repo['tip']
|
2012-12-10 02:33:16 +04:00
|
|
|
for rev in xrange(len(repo) - 1, repo[node].rev() - 1, -1):
|
2008-06-26 23:35:46 +04:00
|
|
|
c = repo[rev]
|
2007-12-20 01:02:31 +03:00
|
|
|
for f in c.files():
|
2009-04-24 11:06:01 +04:00
|
|
|
if f in seen or f not in tip or f not in c:
|
2007-12-20 01:02:31 +03:00
|
|
|
continue
|
2009-04-24 11:06:01 +04:00
|
|
|
seen.add(f)
|
2007-12-20 01:02:31 +03:00
|
|
|
data = c[f].data()
|
2008-04-10 02:49:20 +04:00
|
|
|
if not util.binary(data) and newline in data:
|
2007-12-20 01:02:31 +03:00
|
|
|
if not halt:
|
2012-06-12 16:18:18 +04:00
|
|
|
ui.warn(_('attempt to commit or push text file(s) '
|
2008-04-03 15:41:31 +04:00
|
|
|
'using %s line endings\n') %
|
|
|
|
newlinestr[newline])
|
2007-12-20 01:02:31 +03:00
|
|
|
ui.warn(_('in %s: %s\n') % (short(c.node()), f))
|
|
|
|
halt = True
|
|
|
|
if halt and hooktype == 'pretxnchangegroup':
|
2008-04-03 15:41:31 +04:00
|
|
|
crlf = newlinestr[newline].lower()
|
|
|
|
filter = filterstr[newline]
|
2007-12-20 01:02:31 +03:00
|
|
|
ui.warn(_('\nTo prevent this mistake in your local repository,\n'
|
|
|
|
'add to Mercurial.ini or .hg/hgrc:\n'
|
|
|
|
'\n'
|
|
|
|
'[hooks]\n'
|
2008-04-03 15:41:31 +04:00
|
|
|
'pretxncommit.%s = python:hgext.win32text.forbid%s\n'
|
2007-12-20 01:02:31 +03:00
|
|
|
'\n'
|
|
|
|
'and also consider adding:\n'
|
|
|
|
'\n'
|
|
|
|
'[extensions]\n'
|
2009-12-23 22:31:35 +03:00
|
|
|
'win32text =\n'
|
2007-12-20 01:02:31 +03:00
|
|
|
'[encode]\n'
|
2008-04-03 15:41:31 +04:00
|
|
|
'** = %sencode:\n'
|
2007-12-20 01:02:31 +03:00
|
|
|
'[decode]\n'
|
2008-04-03 15:41:31 +04:00
|
|
|
'** = %sdecode:\n') % (crlf, crlf, filter, filter))
|
2007-12-20 01:02:31 +03:00
|
|
|
return halt
|
2008-01-28 23:39:47 +03:00
|
|
|
|
2008-04-03 15:41:31 +04:00
|
|
|
def forbidcrlf(ui, repo, hooktype, node, **kwargs):
|
2008-04-05 21:06:16 +04:00
|
|
|
return forbidnewline(ui, repo, hooktype, node, '\r\n', **kwargs)
|
2008-04-03 15:41:31 +04:00
|
|
|
|
|
|
|
def forbidcr(ui, repo, hooktype, node, **kwargs):
|
2008-04-05 21:06:16 +04:00
|
|
|
return forbidnewline(ui, repo, hooktype, node, '\r', **kwargs)
|
2008-04-03 15:41:31 +04:00
|
|
|
|
2008-01-28 23:39:47 +03:00
|
|
|
def reposetup(ui, repo):
|
|
|
|
if not repo.local():
|
|
|
|
return
|
|
|
|
for name, fn in _filters.iteritems():
|
|
|
|
repo.adddatafilter(name, fn)
|
|
|
|
|
2010-10-25 20:29:32 +04:00
|
|
|
def extsetup(ui):
|
2015-06-26 01:42:45 +03:00
|
|
|
# deprecated config: win32text.warn
|
2017-06-30 04:45:56 +03:00
|
|
|
if ui.configbool('win32text', 'warn'):
|
2010-10-25 20:29:32 +04:00
|
|
|
ui.warn(_("win32text is deprecated: "
|
2015-09-30 23:43:49 +03:00
|
|
|
"https://mercurial-scm.org/wiki/Win32TextExtension\n"))
|