comparison hgext/win32text.py @ 6481:e837dded56c7

win32text: Add macencode/macdecode
author OHASHI Hideya <ohachige@gmail.com>
date Thu, 03 Apr 2008 20:41:31 +0900
parents 7f4257b5cbfc
children 0a803195bb29
comparison
equal deleted inserted replaced
6472:8c4cd80afd3e 6481:e837dded56c7
1 # win32text.py - LF <-> CRLF translation utilities for Windows users 1 # win32text.py - LF <-> CRLF/CR translation utilities for Windows/Mac users
2 # 2 #
3 # This software may be used and distributed according to the terms 3 # This software may be used and distributed according to the terms
4 # of the GNU General Public License, incorporated herein by reference. 4 # of the GNU General Public License, incorporated herein by reference.
5 # 5 #
6 # To perform automatic newline conversion, use: 6 # To perform automatic newline conversion, use:
7 # 7 #
8 # [extensions] 8 # [extensions]
9 # hgext.win32text = 9 # hgext.win32text =
10 # [encode] 10 # [encode]
11 # ** = cleverencode: 11 # ** = cleverencode:
12 # # or ** = macencode:
12 # [decode] 13 # [decode]
13 # ** = cleverdecode: 14 # ** = cleverdecode:
15 # # or ** = macdecode:
14 # 16 #
15 # If not doing conversion, to make sure you do not commit CRLF by accident: 17 # If not doing conversion, to make sure you do not commit CRLF/CR by accident:
16 # 18 #
17 # [hooks] 19 # [hooks]
18 # pretxncommit.crlf = python:hgext.win32text.forbidcrlf 20 # pretxncommit.crlf = python:hgext.win32text.forbidcrlf
21 # # or pretxncommit.cr = python:hgext.win32text.forbidcr
19 # 22 #
20 # To do the same check on a server to prevent CRLF from being pushed or pulled: 23 # To do the same check on a server to prevent CRLF/CR from being pushed or
24 # pulled:
21 # 25 #
22 # [hooks] 26 # [hooks]
23 # pretxnchangegroup.crlf = python:hgext.win32text.forbidcrlf 27 # pretxnchangegroup.crlf = python:hgext.win32text.forbidcrlf
28 # # or pretxnchangegroup.cr = python:hgext.win32text.forbidcr
24 29
25 from mercurial import util 30 from mercurial import util
26 from mercurial.i18n import gettext as _ 31 from mercurial.i18n import gettext as _
27 from mercurial.node import bin, short 32 from mercurial.node import bin, short
28 import re 33 import re
29 34
30 # regexp for single LF without CR preceding. 35 # regexp for single LF without CR preceding.
31 re_single_lf = re.compile('(^|[^\r])\n', re.MULTILINE) 36 re_single_lf = re.compile('(^|[^\r])\n', re.MULTILINE)
32 37
33 def dumbdecode(s, cmd, ui=None, repo=None, filename=None, **kwargs): 38 newlinestr = {'\r\n': 'CRLF', '\r': 'CR'}
34 # warn if already has CRLF in repository. 39 filterstr = {'\r\n': 'clever', '\r': 'mac'}
40
41 def checknewline(s, newline, ui=None, repo=None, filename=None):
42 # warn if already has 'newline' in repository.
35 # it might cause unexpected eol conversion. 43 # it might cause unexpected eol conversion.
36 # see issue 302: 44 # see issue 302:
37 # http://www.selenic.com/mercurial/bts/issue302 45 # http://www.selenic.com/mercurial/bts/issue302
38 if '\r\n' in s and ui and filename and repo: 46 if newline in s and ui and filename and repo:
39 ui.warn(_('WARNING: %s already has CRLF line endings\n' 47 ui.warn(_('WARNING: %s already has %s line endings\n'
40 'and does not need EOL conversion by the win32text plugin.\n' 48 'and does not need EOL conversion by the win32text plugin.\n'
41 'Before your next commit, please reconsider your ' 49 'Before your next commit, please reconsider your '
42 'encode/decode settings in \nMercurial.ini or %s.\n') % 50 'encode/decode settings in \nMercurial.ini or %s.\n') %
43 (filename, repo.join('hgrc'))) 51 (filename, newlinestr[newline], repo.join('hgrc')))
52
53 def dumbdecode(s, cmd, **kwargs):
54 checknewline(s, '\r\n', **kwargs)
44 # replace single LF to CRLF 55 # replace single LF to CRLF
45 return re_single_lf.sub('\\1\r\n', s) 56 return re_single_lf.sub('\\1\r\n', s)
46 57
47 def dumbencode(s, cmd): 58 def dumbencode(s, cmd):
48 return s.replace('\r\n', '\n') 59 return s.replace('\r\n', '\n')
60
61 def macdumbdecode(s, cmd, **kwargs):
62 checknewline(s, '\r', **kwargs)
63 return s.replace('\n', '\r')
64
65 def macdumbencode(s, cmd):
66 return s.replace('\r', '\n')
49 67
50 def cleverdecode(s, cmd, **kwargs): 68 def cleverdecode(s, cmd, **kwargs):
51 if util.binary(s): 69 if util.binary(s):
52 return s 70 return s
53 return dumbdecode(s, cmd, **kwargs) 71 return dumbdecode(s, cmd, **kwargs)
55 def cleverencode(s, cmd): 73 def cleverencode(s, cmd):
56 if util.binary(s): 74 if util.binary(s):
57 return s 75 return s
58 return dumbencode(s, cmd) 76 return dumbencode(s, cmd)
59 77
78 def macdecode(s, cmd, **kwargs):
79 if util.binary(s):
80 return s
81 return macdumbdecode(s, cmd, **kwargs)
82
83 def macencode(s, cmd):
84 if util.binary(s):
85 return s
86 return macdumbencode(s, cmd)
87
60 _filters = { 88 _filters = {
61 'dumbdecode:': dumbdecode, 89 'dumbdecode:': dumbdecode,
62 'dumbencode:': dumbencode, 90 'dumbencode:': dumbencode,
63 'cleverdecode:': cleverdecode, 91 'cleverdecode:': cleverdecode,
64 'cleverencode:': cleverencode, 92 'cleverencode:': cleverencode,
93 'macdumbdecode:': macdumbdecode,
94 'macdumbencode:': macdumbencode,
95 'macdecode:': macdecode,
96 'macencode:': macencode,
65 } 97 }
66 98
67 def forbidcrlf(ui, repo, hooktype, node, **kwargs): 99 def forbidcrlforcr(ui, repo, hooktype, node, newline, **kwargs):
68 halt = False 100 halt = False
69 for rev in xrange(repo.changelog.rev(bin(node)), repo.changelog.count()): 101 for rev in xrange(repo.changelog.rev(bin(node)), repo.changelog.count()):
70 c = repo.changectx(rev) 102 c = repo.changectx(rev)
71 for f in c.files(): 103 for f in c.files():
72 if f not in c: 104 if f not in c:
73 continue 105 continue
74 data = c[f].data() 106 data = c[f].data()
75 if not util.binary(data) and '\r\n' in data: 107 if not util.binary(data) and newline in data:
76 if not halt: 108 if not halt:
77 ui.warn(_('Attempt to commit or push text file(s) ' 109 ui.warn(_('Attempt to commit or push text file(s) '
78 'using CRLF line endings\n')) 110 'using %s line endings\n') %
111 newlinestr[newline])
79 ui.warn(_('in %s: %s\n') % (short(c.node()), f)) 112 ui.warn(_('in %s: %s\n') % (short(c.node()), f))
80 halt = True 113 halt = True
81 if halt and hooktype == 'pretxnchangegroup': 114 if halt and hooktype == 'pretxnchangegroup':
115 crlf = newlinestr[newline].lower()
116 filter = filterstr[newline]
82 ui.warn(_('\nTo prevent this mistake in your local repository,\n' 117 ui.warn(_('\nTo prevent this mistake in your local repository,\n'
83 'add to Mercurial.ini or .hg/hgrc:\n' 118 'add to Mercurial.ini or .hg/hgrc:\n'
84 '\n' 119 '\n'
85 '[hooks]\n' 120 '[hooks]\n'
86 'pretxncommit.crlf = python:hgext.win32text.forbidcrlf\n' 121 'pretxncommit.%s = python:hgext.win32text.forbid%s\n'
87 '\n' 122 '\n'
88 'and also consider adding:\n' 123 'and also consider adding:\n'
89 '\n' 124 '\n'
90 '[extensions]\n' 125 '[extensions]\n'
91 'hgext.win32text =\n' 126 'hgext.win32text =\n'
92 '[encode]\n' 127 '[encode]\n'
93 '** = cleverencode:\n' 128 '** = %sencode:\n'
94 '[decode]\n' 129 '[decode]\n'
95 '** = cleverdecode:\n')) 130 '** = %sdecode:\n') % (crlf, crlf, filter, filter))
96 return halt 131 return halt
132
133 def forbidcrlf(ui, repo, hooktype, node, **kwargs):
134 return forbidcrlforcr(ui, repo, hooktype, node, '\r\n', **kwargs)
135
136 def forbidcr(ui, repo, hooktype, node, **kwargs):
137 return forbidcrlforcr(ui, repo, hooktype, node, '\r', **kwargs)
97 138
98 def reposetup(ui, repo): 139 def reposetup(ui, repo):
99 if not repo.local(): 140 if not repo.local():
100 return 141 return
101 for name, fn in _filters.iteritems(): 142 for name, fn in _filters.iteritems():