Source

ml-hgext / checkfiles.py

Diff from to

File checkfiles.py

 # for check_hook to only check for tabs  (and ignore trailing whitespace) set to True. Default, if not present is False
 check_ignores_trailing_ws = False
 
+# for check_hook to ignore CRLF set to True. Default, if not present is False
+# NB: this flag is under development and may convert CRLF ending under some circumstances
+check_ignores_CRLF = False
+
 # to examine only modified lines from check_hook, use:
 # check_diffs = True
 
         self.tab_size = int(ui.config('checkfiles', 'tab_size', default='4'))
         self.use_spaces = ui.configbool('checkfiles', 'use_spaces', True)
         self.check_ignores_trailing_ws = ui.configbool('checkfiles', 'check_ignores_trailing_ws', False)
+        self.check_ignores_CRLF = ui.configbool('checkfiles', 'check_ignores_CRLF', False)
 
         if 'tabsize' in opts:
             self.tab_size = int(opts['tabsize'])
         self.ui.debug('checkfiles: use spaces: %r\n' % self.use_spaces)
         self.ui.debug('checkfiles: tab size: %r\n' % self.tab_size)
         self.ui.debug('checkfiles: ignore trailing ws: %r\n' % self.check_ignores_trailing_ws)
+        self.ui.debug('checkfiles: check ignores CRLF: %r\n' % self.check_ignores_CRLF)
+
 
         if ctx:
             self.set_changectx(ctx)
                         else:
                             state.found_ws_end()
                             self.ui.note('%s: trailing whitespace in %s\n' % (file, hunk))
+                    elif file and label == 'diff.trailingwhitespace' and lastlabel == 'diff.inserted' and chunk == '\r':
+                        if self.check_ignores_CRLF == False:
+                            if self.check_ignores_trailing_ws:
+                                # still check for presence of \t tough
+                                if self.use_spaces and  ('\t' in chunk):
+                                    state.found_ws_end()
+                                    self.ui.note('%s: CRLF and trailing tab in %s\n' % (file, hunk))
+                            else:
+                                state.found_ws_end()
+                                self.ui.note('%s: trailing whitespace and possibly CRLF in %s\n' % (file, hunk))
                     elif file and label == 'diff.inserted' and self.is_ws_before_text(chunk[1:]):
                         state.found_ws_begin()
                         if self.use_spaces:
                 self.ui.debug('checkfiles: checking %s ...\n' % file)
                 fctx = self.ctx[file]
 
-                for num, line in enumerate(fctx.data().splitlines(), 1):
+                for num, line in enumerate(fctx.data().splitlines(1), 1):
+                    line = line.rstrip('\n')
+                    if self.check_ignores_CRLF:
+                        line = line.rstrip('\r')
                     if line.isspace():
                         if self.check_ignores_trailing_ws:
                             # still check for presence of \t
                             state.found_ws_end()
                             self.ui.note('%s (%i): trailing whitespace\n' % (file, num))
 
+                    elif line.endswith(('\r')):
+                        if self.check_ignores_trailing_ws:
+                            # still check for presence of \t
+                            if self.use_spaces and ('\t' in line):
+                                state.found_ws_end()
+                                self.ui.note('%s (%i): trailing tabs\n' % (file, num))
+                        else:
+                            state.found_ws_end()
+                            self.ui.note('%s (%i): CRLF and possibly trailing whitespace\n' % (file, num))
+
                         line = line.expandtabs(self.tab_size)
                         non_ws_len = len(line.rstrip())
                         line_show = ' ' * non_ws_len + '^' * (len(line) - non_ws_len)
 
         self.ui.status('checkfiles: fixing in %s:%d\n' % (file, line_num))
 
-        with open(os.path.join(self.repo.root, file), 'w') as fileobj:
+        with open(os.path.join(self.repo.root, file), 'wb') as fileobj:
             def fixline():
                 if self.use_spaces:
                     for num, line in enumerate(lines, 1):
                         if num == line_num:
-                            yield line.rstrip().expandtabs(self.tab_size)
+                            if self.check_ignores_CRLF and line.rstrip('\n').endswith('\r'):
+                                yield line.rstrip().expandtabs(self.tab_size) + '\r'
+                            else:
+                                yield line.rstrip().expandtabs(self.tab_size)
                         else:
                             yield line
                 else:
                             if match:
                                 ws = match.group(1)
                                 text = line[len(ws):]
-
-                                yield ws.expandtabs(self.tab_size).replace(' ' * self.tab_size, '\t') + text.rstrip()
+                                
+                                if self.check_ignores_CRLF and line.rstrip('\n').endswith('\r'):
+                                    yield ws.expandtabs(self.tab_size).replace(' ' * self.tab_size, '\t') + text.rstrip() + '\r'
+                                else:
+                                    yield ws.expandtabs(self.tab_size).replace(' ' * self.tab_size, '\t') + text.rstrip()
                             else:
-                                yield line.rstrip()
+                                if self.check_ignores_CRLF and line.rstrip('\n').endswith('\r'):
+                                    yield line.rstrip() + '\r'
+                                else:
+                                    yield line.rstrip()
                         else:
                             yield line
             fileobj.writelines('\n'.join(fixline()))
                     elif file and label == 'diff.trailingwhitespace' and lastlabel == 'diff.inserted' and chunk != '\r':
                         self.ui.note('%s:%d: trailing whitespace in %s\n' % (file, line_num, hunk))
                         self.fixup_line_num_in_file(file, line_num)
+                    elif file and label == 'diff.trailingwhitespace' and lastlabel == 'diff.inserted' and chunk == '\r':
+                        self.ui.note('%s:%d: CRLF and possibly trailing whitespace in %s\n' % (file, line_num, hunk))
+                        self.fixup_line_num_in_file(file, line_num)
                     elif file and label == 'diff.inserted' and self.is_ws_before_text(chunk[1:]):
                         if self.use_spaces:
                             self.ui.note('%s:%d: tab character(s) in %s\n' % (file, line_num, hunk))
         else:
             for file in filter(self.is_relevant, self.files):
                 data = self.ctx[file].data()
-                lines = data.splitlines()
+                lines = data.splitlines(1)
                 nl_at_eof = data.endswith('\n')
 
-                if not any(line.isspace() or self.is_ws_before_text(line) or line.endswith((' ', '\t')) for line in lines):
+                if not any(line.rstrip('\n').isspace() or self.is_ws_before_text(line.rstrip('\n')) or line.rstrip('\n').endswith((' ', '\t')) or line.rstrip('\n').endswith(('\r')) for line in lines):
                     self.ui.note('checkfiles: %s ok\n' % file)
                     continue
 
                 self.ui.status('checkfiles: fixing %s\n' % file)
 
-                with open(os.path.join(self.repo.root, file), 'w') as fileobj:
+                with open(os.path.join(self.repo.root, file), 'wb') as fileobj:
                     def fixline():
                         if self.use_spaces:
                             for line in lines:
-                                yield line.rstrip().expandtabs(self.tab_size)
+                                if self.check_ignores_CRLF and line.rstrip('\n').endswith('\r'):
+                                    yield line.rstrip().expandtabs(self.tab_size) + '\r'
+                                else:
+                                    yield line.rstrip().expandtabs(self.tab_size)
                         else:
                             for line in lines:
                                 match = re.match(r'^(\t*( \t*)+)[^ \t]', line)
                                 if match:
                                     ws = match.group(1)
                                     text = line[len(ws):]
-
-                                    yield ws.expandtabs(self.tab_size).replace(' ' * self.tab_size, '\t') + text.rstrip()
+                                    
+                                    if self.check_ignores_CRLF and line.rstrip('\n').endswith('\r'):
+                                        yield ws.expandtabs(self.tab_size).replace(' ' * self.tab_size, '\t') + text.rstrip() + '\r'
+                                    else:
+                                        yield ws.expandtabs(self.tab_size).replace(' ' * self.tab_size, '\t') + text.rstrip()
                                 else:
-                                    yield line.rstrip()
+                                    if self.check_ignores_CRLF and line.rstrip('\n').endswith('\r'):
+                                        yield line.rstrip() + '\r'
+                                    else:
+                                        yield line.rstrip()
 
                     fileobj.writelines('\n'.join(fixline()))
                     if nl_at_eof: