Example #1
0
def getdiff(ctx, diffopts):
    """plain-text diff without header (user, commit message, etc)"""
    output = util.stringio()
    for chunk, _label in patch.diffui(ctx.repo(), ctx.p1().node(), ctx.node(),
                                      None, opts=diffopts):
        output.write(chunk)
    return output.getvalue()
Example #2
0
def getdiff(ctx, diffopts):
    """plain-text diff without header (user, commit message, etc)"""
    output = util.stringio()
    for chunk, _label in patch.diffui(ctx.repo(), ctx.p1().node(), ctx.node(),
                                      None, opts=diffopts):
        output.write(chunk)
    return output.getvalue()
Example #3
0
def commit_no_print(ui, repo, hooktype, node, parent1, **kwargs):
    """
    Intended for running on commit. I take no responsibility for what might
    happen if attached to other events.

    This hook inspects the diff that was just committed and looks for inserted
    print statements. It does so fairly naively, not caring about the filetype
    or anything.

    Also, it does not fail if a print statement is found, as sometimes you
    might actually mean to do it.
    """
    regex = re.compile(r'^\+\s*print')
    for line, label in patch.diffui(repo, parent1, node):
        if regex.match(line):
            print "YOU COMMITTED A PRINT STATEMENT"
            return
Example #4
0
    def check(self):
        self.ui.debug('checkfiles: considering files:\n  %s\n' %
                      '\n  '.join(self.files))

        if self.use_spaces:
            indicator = '^' * self.tab_size
        else:
            indicator = '^'

        class State:
            def __init__(self, ui):
                self.ui = ui
                self.ws_begin = False
                self.ws_end = False
                self.all_ws = False
                self.filecount = 0
                self.probcount = 0

            def endfile(self, file):
                if file is None:
                    return
                if self.ws_begin or self.ws_end or self.all_ws:
                    self.filecount += 1
                    self.ui.status(
                        'checkfiles: %s:%s%s%s\n' %
                        (file, ' whitespace_begin' if self.ws_begin else '',
                         ' whitespace_end' if self.ws_end else '',
                         ' all_whitespace' if self.all_ws else ''))
                    self.ws_begin = False
                    self.ws_end = False
                    self.all_ws = False
                else:
                    self.ui.note('checkfiles: %s: ok\n' % file)

            def found_all_ws(self):
                self.all_ws = True
                self.probcount += 1

            def found_ws_end(self):
                self.ws_end = True
                self.probcount += 1

            def found_ws_begin(self):
                self.ws_begin = True
                self.probcount += 1

        state = State(self.ui)

        if self.check_diffs:
            if len(self.ctx.parents()) == 1:
                # XXX would be nicer if checked_exts were a proper pattern;
                # then cmdutil.match would work naturally with it
                try:
                    from mercurial.scmutil import match
                    ctx = self.repo[None]
                except ImportError:
                    from mercurial.cmdutil import match
                    ctx = self.repo

                file = None
                hunk = None
                lastlabel = None
                for chunk, label in patch.diffui(self.repo,
                                                 self.ctx.p1().node(),
                                                 self.ctx.node(), match(ctx)):
                    if len(label) > 0 or chunk != '\n':
                        self.ui.debug('checkfiles: %s="%s"\n' % (label, chunk))
                    if label == 'diff.file_b':
                        state.endfile(file)
                        file = re.sub(r'^[+][+][+] b/(.+)\t.+$', r'\1', chunk)
                        if self.is_relevant(file):
                            self.ui.debug('checkfiles: checking %s ...\n' %
                                          file)
                        else:
                            file = None
                    elif label == 'diff.hunk':
                        hunk = chunk
                    elif file and label == 'diff.trailingwhitespace' and lastlabel == 'diff.inserted' and chunk != '\r':
                        state.found_ws_end()
                        self.ui.note('%s: trailing whitespace 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.note('%s: tab character(s) in %s\n' %
                                         (file, hunk))
                        else:
                            self.ui.note('%s: space(s) before text in %s\n' %
                                         (file, hunk))

                    lastlabel = label
                state.endfile(file)
            else:
                self.ui.note('checkfiles: skipping merge changeset\n')
        else:
            for file in filter(self.is_relevant, self.files):
                self.ui.debug('checkfiles: checking %s ...\n' % file)
                fctx = self.ctx[file]

                for num, line in enumerate(fctx.data().splitlines(), 1):
                    if line.isspace():
                        state.found_all_ws()
                        self.ui.note('%s (%i): all whitespace\n' % (file, num))

                    elif line.endswith((' ', '\t')):
                        state.found_ws_end()
                        self.ui.note('%s (%i): 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.note('  %s\n  %s\n' % (line, line_show))

                    self.detect_ws_before_text(file, num, line, indicator,
                                               state)

                state.endfile(file)

        if state.filecount > 0:
            from mercurial.node import short
            self.ui.warn(
                'checkfiles: %i issues(s) found in %i file(s) in %s\n' %
                (state.probcount, state.filecount, short(self.ctx.node())
                 if self.ctx.node() else 'working directory'))

        return state.filecount > 0
Example #5
0
    def diff(self, diffopts, node1, node2, match, changes=None):
        in_hunk = False
        in_diffline = False
        just_saw_newline = False
        print_lines_to = False

        for chunk, label in patch.diffui(self.repo, node1, node2, match,
                                         changes, diffopts):
            if label == 'diff.diffline':
                # we only print the diffline after checking that the hunk is
                # interesting, so push the buffer
                in_diffline = True
                self.ui.pushbuffer()
                self.ui.write(chunk, label=label)
            elif label == 'diff.hunk':
                # once we get to a hunk, determine if it is interesting
                in_diffline = False
                in_hunk = False

                m = re.match(r"^@@ -(\d+),(\d+) \+(\d+),(\d+) @@$", chunk)
                lines_from = (int(m.group(1)), int(m.group(2)))
                lines_to = (int(m.group(3)), int(m.group(4)))

                try:
                    diffline = self.ui.popbuffer(labeled=True)
                except:
                    pass

                if lines_to[0] <= self.line <= lines_to[0] + lines_to[1]:
                    # this is an interesting hunk!
                    in_hunk = True
                    just_saw_newline = False

                    # print the diffline if this is the first good hunk for this file
                    if diffline:
                        self.ui.write(diffline)
                        diffline = None

                    minwidth = len(str(max(lines_to[0], lines_to[0] + lines_to[1])))
                    self.ui.write(chunk, label=label)
                    line_no_from = lines_from[0]
                    line_no_to = lines_to[0]

            elif in_diffline:
                self.ui.write(chunk, label=label)
            elif in_hunk:
                if just_saw_newline:
                    # start a new line
                    just_saw_newline = False
                    fmt = '%' + str(minwidth) + 'i'
                    if label == 'diff.deleted':
                        self.ui.write(fmt % line_no_from)
                        line_no_from += 1
                    elif label == 'diff.inserted':
                        if line_no_to == self.line:
                            self.ui.write((minwidth - 1) * '=' + '>',
                                label='blametrail.currentline')
                        elif print_lines_to:
                            self.ui.write(fmt % line_no_to)
                        else:
                            self.ui.write(minwidth * ' ')
                        line_no_to += 1
                    else:
                        self.ui.write(fmt % line_no_from)
                        line_no_from += 1
                        line_no_to += 1
                    self.ui.write(chunk, label=label)
                else:
                    # print whatever until we get to the end of the line
                    self.ui.write(chunk, label=label)
                    if chunk == '\n':
                        just_saw_newline = True
Example #6
0
    def fixup(self):
        import os.path

        if self.fixup_diffs:
            if len(self.ctx.parents()) == 1:
                ctx = self.repo[None]
                file = None
                hunk = None
                lastlabel = None
                line_num = None
                for chunk, label in patch.diffui(self.repo,
                                                 self.ctx.p1().node(),
                                                 self.ctx.node(),
                                                 match(ctx)):

                    if (len(label) == 0 and chunk != '\n') or \
                                        label == 'diff.inserted':
                        line_num += 1
                    if len(label) > 0 or chunk != '\n':
                        self.ui.debug('checkfiles: %s="%s"\n' % (label, chunk))
                    if label == 'diff.file_b':
                        file = re.sub(r'^[+][+][+] b/(.+)\t.+$', r'\1', chunk)
                        if self.is_relevant(file):
                            self.ui.debug('checkfiles: checking %s ...\n'
                                          % file)
                        else:
                            file = None
                    elif label == 'diff.hunk':
                        hunk = chunk
                        m = re.match(hunk_re, hunk)
                        (start_a, len_a, start_b, len_b) = m.groups()
                        self.ui.debug('checkfiles: parsed: %s,  %s, %s, %s\n'
                                      % m.groups())
                        line_num = int(start_b) - 1
                    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.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:
                            self.ui.note('%s:%d: space(s) before text in %s\n'
                                         % (file, line_num, hunk))
                        self.fixup_line_num_in_file(file, line_num)

                    lastlabel = label
            else:
                self.ui.note('checkfiles: skipping merge changeset\n')
        else:
            for file in filter(self.is_relevant, self.files):
                data = self.ctx[file].data()
                lines = data.splitlines()
                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):
                    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:

                    def fixline():
                        if self.use_spaces:
                            for line in lines:
                                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()
                                else:
                                    yield line.rstrip()

                    fileobj.writelines('\n'.join(fixline()))
                    if nl_at_eof:
                        fileobj.write('\n')
Example #7
0
    def check(self):
        self.ui.debug('checkfiles: considering files:\n  %s\n'
                      % '\n  '.join(self.files))

        if self.use_spaces:
            indicator = '^' * self.tab_size
        else:
            indicator = '^'

        class State:

            def __init__(self, ui):
                self.ui = ui
                self.ws_begin = False
                self.ws_end = False
                self.all_ws = False
                self.filecount = 0
                self.probcount = 0

            def endfile(self, file):
                if file is None:
                    return
                if self.ws_begin or self.ws_end or self.all_ws:
                    self.filecount += 1
                    self.ui.status('checkfiles: %s:%s%s%s\n' %
                        (file, ' whitespace_begin' if self.ws_begin else '',
                         ' whitespace_end' if self.ws_end else '',
                         ' all_whitespace' if self.all_ws else ''))
                    self.ws_begin = False
                    self.ws_end = False
                    self.all_ws = False
                else:
                    self.ui.note('checkfiles: %s: ok\n' % file)

            def found_all_ws(self):
                self.all_ws = True
                self.probcount += 1

            def found_ws_end(self):
                self.ws_end = True
                self.probcount += 1

            def found_ws_begin(self):
                self.ws_begin = True
                self.probcount += 1

        state = State(self.ui)

        if self.check_diffs:
            if len(self.ctx.parents()) == 1:
                ctx = self.repo[None]
                file = None
                hunk = None
                lastlabel = None
                for chunk, label in patch.diffui(self.repo,
                                                 self.ctx.p1().node(),
                                                 self.ctx.node(),
                                                 match(ctx)):
                    if len(label) > 0 or chunk != '\n':
                        self.ui.debug('checkfiles: %s="%s"\n' % (label, chunk))
                    if label == 'diff.file_b':
                        state.endfile(file)
                        file = re.sub(r'^[+][+][+] b/(.+)\t.+$', r'\1', chunk)
                        if self.is_relevant(file):
                            self.ui.debug('checkfiles: checking %s ...\n'
                                          % file)
                        else:
                            file = None
                    elif label == 'diff.hunk':
                        hunk = chunk
                    elif file and label == 'diff.trailingwhitespace' and \
                                lastlabel == 'diff.inserted' and chunk != '\r':
                        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: trailing tab in %s\n'
                                             % (file, hunk))
                        else:
                            state.found_ws_end()
                            self.ui.note('%s: trailing whitespace 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.note('%s: tab character(s) in %s\n'
                                         % (file, hunk))
                        else:
                            self.ui.note('%s: space(s) before text in %s\n'
                                         % (file, hunk))

                    lastlabel = label
                state.endfile(file)
            else:
                self.ui.note('checkfiles: skipping merge changeset\n')
        else:
            for file in filter(self.is_relevant, self.files):
                self.ui.debug('checkfiles: checking %s ...\n' % file)
                fctx = self.ctx[file]

                for num, line in enumerate(fctx.data().splitlines(), 1):
                    if line.isspace():
                        if self.check_ignores_trailing_ws:
                            # still check for presence of \t
                            if self.use_spaces and ('\t' in line):
                                state.found_all_ws()
                                self.ui.note('%s (%i): tabs in all ' \
                                             'whitespace line\n' % (file, num))
                        else:
                            state.found_all_ws()
                            self.ui.note('%s (%i): all whitespace\n'
                                         % (file, num))

                    elif line.endswith((' ', '\t')):
                        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): 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.note('  %s\n  %s\n' % (line, line_show))

                    self.detect_ws_before_text(file, num, line, indicator,
                                               state)

                state.endfile(file)

        if state.filecount > 0:
            from mercurial.node import short
            self.ui.warn('checkfiles: %i issues(s) found in %i file(s) in %s\n'
                         % (state.probcount, state.filecount,
                            short(self.ctx.node()) if self.ctx.node() \
                                                   else 'working directory'))

        return state.filecount > 0