/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/plugins/grep/grep.py

  • Committer: Jelmer Vernooij
  • Date: 2018-11-16 23:19:12 UTC
  • mfrom: (7180 work)
  • mto: This revision was merged to the branch mainline in revision 7294.
  • Revision ID: jelmer@jelmer.uk-20181116231912-e043vpq22bdkxa6q
Merge trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
120
120
 
121
121
 
122
122
def compile_pattern(pattern, flags=0):
123
 
    patternc = None
124
123
    try:
125
 
        # use python's re.compile as we need to catch re.error in case of bad pattern
126
 
        lazy_regex.reset_compile()
127
 
        patternc = re.compile(pattern, flags)
 
124
        return re.compile(pattern, flags)
128
125
    except re.error as e:
129
126
        raise errors.BzrError("Invalid pattern: '%s'" % pattern)
130
 
    return patternc
 
127
    return None
131
128
 
132
129
 
133
130
def is_fixed_string(s):
150
147
                self.get_writer = self._get_writer_fixed_highlighted
151
148
            else:
152
149
                flags = opts.patternc.flags
153
 
                self._sub = re.compile(opts.pattern.join(("((?:", ")+)")), flags).sub
 
150
                self._sub = re.compile(
 
151
                    opts.pattern.join(("((?:", ")+)")), flags).sub
154
152
                self._highlight = color_string("\\1", FG.BOLD_RED)
155
153
                self.get_writer = self._get_writer_regexp_highlighted
156
154
        else:
160
158
        """Get function for writing file headers"""
161
159
        write = self.outf.write
162
160
        eol_marker = self.opts.eol_marker
 
161
 
163
162
        def _line_writer(line):
164
163
            write(line + eol_marker)
 
164
 
165
165
        def _line_writer_color(line):
166
166
            write(FG.BOLD_MAGENTA + line + FG.NONE + eol_marker)
167
167
        if self.opts.show_color:
174
174
        """Get function for writing revno lines"""
175
175
        write = self.outf.write
176
176
        eol_marker = self.opts.eol_marker
 
177
 
177
178
        def _line_writer(line):
178
179
            write(line + eol_marker)
 
180
 
179
181
        def _line_writer_color(line):
180
182
            write(FG.BOLD_BLUE + line + FG.NONE + eol_marker)
181
183
        if self.opts.show_color:
188
190
        """Get function for writing uncoloured output"""
189
191
        write = self.outf.write
190
192
        eol_marker = self.opts.eol_marker
 
193
 
191
194
        def _line_writer(line):
192
195
            write(line + eol_marker)
193
196
        return _line_writer
196
199
        """Get function for writing output with regexp match highlighted"""
197
200
        _line_writer = self._get_writer_plain()
198
201
        sub, highlight = self._sub, self._highlight
 
202
 
199
203
        def _line_writer_regexp_highlighted(line):
200
204
            """Write formatted line with matched pattern highlighted"""
201
205
            return _line_writer(line=sub(highlight, line))
205
209
        """Get function for writing output with search string highlighted"""
206
210
        _line_writer = self._get_writer_plain()
207
211
        old, new = self._old, self._new
 
212
 
208
213
        def _line_writer_fixed_highlighted(line):
209
214
            """Write formatted line with string searched for highlighted"""
210
215
            return _line_writer(line=line.replace(old, new))
220
225
        else:
221
226
            # if no revision is sepcified for diff grep we grep all changesets.
222
227
            opts.revision = [RevisionSpec.from_string('revno:1'),
223
 
                RevisionSpec.from_string('last:1')]
 
228
                             RevisionSpec.from_string('last:1')]
224
229
            start_rev = opts.revision[0]
225
230
        start_revid = start_rev.as_revision_id(branch)
226
231
        if start_revid == b'null:':
233
238
                end_revno, end_revid = branch.last_revision_info()
234
239
            erevno_tuple = branch.revision_id_to_dotted_revno(end_revid)
235
240
 
236
 
            grep_mainline = (_rev_on_mainline(srevno_tuple) and
237
 
                _rev_on_mainline(erevno_tuple))
 
241
            grep_mainline = (_rev_on_mainline(srevno_tuple)
 
242
                             and _rev_on_mainline(erevno_tuple))
238
243
 
239
244
            # ensure that we go in reverse order
240
245
            if srevno_tuple > erevno_tuple:
245
250
            # faster when we don't want to look at merged revs. We try this
246
251
            # with _linear_view_revisions. If all revs are to be grepped we
247
252
            # use the slower _graph_view_revisions
248
 
            if opts.levels==1 and grep_mainline:
249
 
                given_revs = _linear_view_revisions(branch, start_revid, end_revid)
 
253
            if opts.levels == 1 and grep_mainline:
 
254
                given_revs = _linear_view_revisions(
 
255
                    branch, start_revid, end_revid)
250
256
            else:
251
 
                given_revs = _graph_view_revisions(branch, start_revid, end_revid)
 
257
                given_revs = _graph_view_revisions(
 
258
                    branch, start_revid, end_revid)
252
259
        else:
253
260
            # We do an optimization below. For grepping a specific revison
254
261
            # We don't need to call _graph_view_revisions which is slow.
258
265
            start_rev_tuple = (start_revid, start_revno, 0)
259
266
            given_revs = [start_rev_tuple]
260
267
        repo = branch.repository
261
 
        diff_pattern = re.compile(b"^[+\\-].*(" + opts.pattern.encode(_user_encoding) + b")")
 
268
        diff_pattern = re.compile(
 
269
            b"^[+\\-].*(" + opts.pattern.encode(_user_encoding) + b")")
262
270
        file_pattern = re.compile(b"=== (modified|added|removed) file '.*'")
263
271
        outputter = _GrepDiffOutputter(opts)
264
272
        writeline = outputter.get_writer()
270
278
                # with level=1 show only top level
271
279
                continue
272
280
 
273
 
            rev_spec = RevisionSpec_revid.from_string("revid:"+revid.decode('utf-8'))
 
281
            rev_spec = RevisionSpec_revid.from_string(
 
282
                "revid:" + revid.decode('utf-8'))
274
283
            new_rev = repo.get_revision(revid)
275
284
            new_tree = rev_spec.as_tree(branch)
276
285
            if len(new_rev.parent_ids) == 0:
280
289
            old_tree = repo.revision_tree(ancestor_id)
281
290
            s = BytesIO()
282
291
            diff.show_diff_trees(old_tree, new_tree, s,
283
 
                old_label='', new_label='')
 
292
                                 old_label='', new_label='')
284
293
            display_revno = True
285
294
            display_file = False
286
295
            file_header = None
294
303
                        writerevno("=== revno:%s ===" % (revno,))
295
304
                        display_revno = False
296
305
                    if display_file:
297
 
                        writefileheader("  %s" % (file_header.decode(file_encoding, 'replace'),))
 
306
                        writefileheader(
 
307
                            "  %s" % (file_header.decode(file_encoding, 'replace'),))
298
308
                        display_file = False
299
309
                    line = line.decode(file_encoding, 'replace')
300
310
                    writeline("    %s" % (line,))
318
328
                end_revno, end_revid = branch.last_revision_info()
319
329
            erevno_tuple = branch.revision_id_to_dotted_revno(end_revid)
320
330
 
321
 
            grep_mainline = (_rev_on_mainline(srevno_tuple) and
322
 
                _rev_on_mainline(erevno_tuple))
 
331
            grep_mainline = (_rev_on_mainline(srevno_tuple)
 
332
                             and _rev_on_mainline(erevno_tuple))
323
333
 
324
334
            # ensure that we go in reverse order
325
335
            if srevno_tuple > erevno_tuple:
331
341
            # with _linear_view_revisions. If all revs are to be grepped we
332
342
            # use the slower _graph_view_revisions
333
343
            if opts.levels == 1 and grep_mainline:
334
 
                given_revs = _linear_view_revisions(branch, start_revid, end_revid)
 
344
                given_revs = _linear_view_revisions(
 
345
                    branch, start_revid, end_revid)
335
346
            else:
336
 
                given_revs = _graph_view_revisions(branch, start_revid, end_revid)
 
347
                given_revs = _graph_view_revisions(
 
348
                    branch, start_revid, end_revid)
337
349
        else:
338
350
            # We do an optimization below. For grepping a specific revison
339
351
            # We don't need to call _graph_view_revisions which is slow.
351
363
                # with level=1 show only top level
352
364
                continue
353
365
 
354
 
            rev = RevisionSpec_revid.from_string("revid:"+revid.decode('utf-8'))
 
366
            rev = RevisionSpec_revid.from_string(
 
367
                "revid:" + revid.decode('utf-8'))
355
368
            tree = rev.as_tree(branch)
356
369
            for path in opts.path_list:
357
370
                tree_path = osutils.pathjoin(relpath, path)
363
376
                    path_prefix = path
364
377
                    dir_grep(tree, path, relpath, opts, revno, path_prefix)
365
378
                else:
366
 
                    versioned_file_grep(tree, tree_path, '.', path, opts, revno)
 
379
                    versioned_file_grep(
 
380
                        tree, tree_path, '.', path, opts, revno)
367
381
 
368
382
 
369
383
def workingtree_grep(opts):
370
 
    revno = opts.print_revno = None # for working tree set revno to None
 
384
    revno = opts.print_revno = None  # for working tree set revno to None
371
385
 
372
386
    tree, branch, relpath = \
373
387
        controldir.ControlDir.open_containing_tree_or_branch('.')
374
388
    if not tree:
375
389
        msg = ('Cannot search working tree. Working tree not found.\n'
376
 
            'To search for specific revision in history use the -r option.')
 
390
               'To search for specific revision in history use the -r option.')
377
391
        raise errors.BzrCommandError(msg)
378
392
 
379
393
    # GZ 2010-06-02: Shouldn't be smuggling this on opts, but easy for now
416
430
    #                for a good reason, otherwise cache might want purging.
417
431
    outputter = opts.outputter
418
432
    for fp, fc, fkind, fid, entry in tree.list_files(include_root=False,
419
 
        from_dir=from_dir, recursive=opts.recursive):
 
433
                                                     from_dir=from_dir, recursive=opts.recursive):
420
434
 
421
435
        if _skip_file(opts.include, opts.exclude, fp):
422
436
            continue
450
464
                    with open(path_for_file, 'rb') as f:
451
465
                        _file_grep(f.read(), fp, opts, revno, path_prefix)
452
466
 
453
 
    if revno is not None: # grep versioned files
 
467
    if revno is not None:  # grep versioned files
454
468
        for (path, tree_path), chunks in tree.iter_files_bytes(to_grep):
455
469
            path = _make_display_path(relpath, path)
456
470
            _file_grep(b''.join(chunks), path, opts, revno, path_prefix,
457
 
                tree.get_file_revision(tree_path))
 
471
                       tree.get_file_revision(tree_path))
458
472
 
459
473
 
460
474
def _make_display_path(relpath, path):
472
486
    return path
473
487
 
474
488
 
475
 
def versioned_file_grep(tree, tree_path, relpath, path, opts, revno, path_prefix = None):
 
489
def versioned_file_grep(tree, tree_path, relpath, path, opts, revno, path_prefix=None):
476
490
    """Create a file object for the specified id and pass it on to _file_grep.
477
491
    """
478
492
 
495
509
            trace.warning("Binary file '%s' skipped.", path)
496
510
        return
497
511
 
498
 
    file.seek(0) # search from beginning
 
512
    file.seek(0)  # search from beginning
499
513
 
500
514
    found = False
501
515
    if opts.fixed_string:
504
518
            if pattern in line:
505
519
                found = True
506
520
                break
507
 
    else: # not fixed_string
 
521
    else:  # not fixed_string
508
522
        for line in file:
509
523
            if opts.patternc.search(line):
510
524
                found = True
511
525
                break
512
526
 
513
527
    if (opts.files_with_matches and found) or \
514
 
        (opts.files_without_match and not found):
 
528
            (opts.files_without_match and not found):
515
529
        if path_prefix and path_prefix != '.':
516
530
            # user has passed a dir arg, show that as result prefix
517
531
            path = osutils.pathjoin(path_prefix, path)
524
538
    The idea here is to do this work only once per run, and finally return a
525
539
    function that will do the minimum amount possible for each match.
526
540
    """
 
541
 
527
542
    def __init__(self, opts, use_cache=False):
528
543
        self.outf = opts.outf
529
544
        if use_cache:
546
561
                self.get_writer = self._get_writer_fixed_highlighted
547
562
            else:
548
563
                flags = opts.patternc.flags
549
 
                self._sub = re.compile(opts.pattern.join(("((?:", ")+)")), flags).sub
 
564
                self._sub = re.compile(
 
565
                    opts.pattern.join(("((?:", ")+)")), flags).sub
550
566
                self._highlight = color_string("\\1", FG.BOLD_RED)
551
567
                self.get_writer = self._get_writer_regexp_highlighted
552
568
            path_start = FG.MAGENTA
577
593
    def _get_writer_plain(self, path, revno, cache_id):
578
594
        """Get function for writing uncoloured output"""
579
595
        per_line = self._format_perline
580
 
        start = self._format_initial % {"path":path, "revno":revno}
 
596
        start = self._format_initial % {"path": path, "revno": revno}
581
597
        write = self.outf.write
582
598
        if self.cache is not None and cache_id is not None:
583
599
            result_list = []
584
600
            self.cache[cache_id] = path, result_list
585
601
            add_to_cache = result_list.append
 
602
 
586
603
            def _line_cache_and_writer(**kwargs):
587
604
                """Write formatted line and cache arguments"""
588
605
                end = per_line % kwargs
589
606
                add_to_cache(end)
590
607
                write(start + end)
591
608
            return _line_cache_and_writer
 
609
 
592
610
        def _line_writer(**kwargs):
593
611
            """Write formatted line from arguments given by underlying opts"""
594
612
            write(start + per_line % kwargs)
597
615
    def write_cached_lines(self, cache_id, revno):
598
616
        """Write cached results out again for new revision"""
599
617
        cached_path, cached_matches = self.cache[cache_id]
600
 
        start = self._format_initial % {"path":cached_path, "revno":revno}
 
618
        start = self._format_initial % {"path": cached_path, "revno": revno}
601
619
        write = self.outf.write
602
620
        for end in cached_matches:
603
621
            write(start + end)
606
624
        """Get function for writing output with regexp match highlighted"""
607
625
        _line_writer = self._get_writer_plain(path, revno, cache_id)
608
626
        sub, highlight = self._sub, self._highlight
 
627
 
609
628
        def _line_writer_regexp_highlighted(line, **kwargs):
610
629
            """Write formatted line with matched pattern highlighted"""
611
630
            return _line_writer(line=sub(highlight, line), **kwargs)
615
634
        """Get function for writing output with search string highlighted"""
616
635
        _line_writer = self._get_writer_plain(path, revno, cache_id)
617
636
        old, new = self._old, self._new
 
637
 
618
638
        def _line_writer_fixed_highlighted(line, **kwargs):
619
639
            """Write formatted line with string searched for highlighted"""
620
640
            return _line_writer(line=line.replace(old, new), **kwargs)
671
691
            for index, line in enumerate(file_text.splitlines()):
672
692
                if pattern in line:
673
693
                    line = line.decode(file_encoding, 'replace')
674
 
                    writeline(lineno=index+start, line=line)
 
694
                    writeline(lineno=index + start, line=line)
675
695
        else:
676
696
            for line in file_text.splitlines():
677
697
                if pattern in line:
699
719
            for index, line in enumerate(file_text.splitlines()):
700
720
                if search(line):
701
721
                    line = line.decode(file_encoding, 'replace')
702
 
                    writeline(lineno=index+start, line=line)
 
722
                    writeline(lineno=index + start, line=line)
703
723
        else:
704
724
            for line in file_text.splitlines():
705
725
                if search(line):
706
726
                    line = line.decode(file_encoding, 'replace')
707
727
                    writeline(line=line)
708