/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.40.10 by Parth Malwankar
assigned copyright to canonical
1
# Copyright (C) 2010 Canonical Ltd
0.40.9 by Parth Malwankar
factored out grep related code to grep.py
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
from bzrlib.lazy_import import lazy_import
18
lazy_import(globals(), """
0.40.83 by Parth Malwankar
added support for -F/--fixed-string.
19
import codecs
20
import cStringIO
21
from fnmatch import fnmatch
0.40.9 by Parth Malwankar
factored out grep related code to grep.py
22
import os
23
import re
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
24
import string
0.40.9 by Parth Malwankar
factored out grep related code to grep.py
25
0.43.8 by Parth Malwankar
added color for regex pattern.
26
from termcolor import color_string, re_color_string, FG
0.43.4 by Parth Malwankar
initial support for color for fixed string grep.
27
28
0.41.12 by Parth Malwankar
initial support for working tree grep (no test cases yet!)
29
from bzrlib import bzrdir
0.41.11 by Parth Malwankar
moved top level grep code to versioned_grep.
30
from bzrlib.workingtree import WorkingTree
0.40.95 by Parth Malwankar
faster mainline rev grep
31
from bzrlib.revisionspec import RevisionSpec, RevisionSpec_revid, RevisionSpec_revno
0.40.9 by Parth Malwankar
factored out grep related code to grep.py
32
from bzrlib import (
33
    errors,
34
    lazy_regex,
0.40.47 by Parth Malwankar
fixes bug #531336. binary files are now skipped.
35
    osutils,
36
    textfile,
37
    trace,
0.40.9 by Parth Malwankar
factored out grep related code to grep.py
38
    )
39
""")
40
0.40.83 by Parth Malwankar
added support for -F/--fixed-string.
41
_terminal_encoding = osutils.get_terminal_encoding()
42
_user_encoding = osutils.get_user_encoding()
43
0.40.117 by Parth Malwankar
cosmetic fix. added two lines between top level functions.
44
0.40.95 by Parth Malwankar
faster mainline rev grep
45
class _RevisionNotLinear(Exception):
46
    """Raised when a revision is not on left-hand history."""
47
0.40.117 by Parth Malwankar
cosmetic fix. added two lines between top level functions.
48
0.40.95 by Parth Malwankar
faster mainline rev grep
49
def _rev_on_mainline(rev_tuple):
50
    """returns True is rev tuple is on mainline"""
51
    if len(rev_tuple) == 1:
52
        return True
53
    return rev_tuple[1] == 0 and rev_tuple[2] == 0
54
0.40.117 by Parth Malwankar
cosmetic fix. added two lines between top level functions.
55
0.40.100 by Parth Malwankar
removed dependency on log._graph_view_revisions
56
# NOTE: _linear_view_revisions is basided on
57
# bzrlib.log._linear_view_revisions.
58
# This should probably be a common public API
0.40.95 by Parth Malwankar
faster mainline rev grep
59
def _linear_view_revisions(branch, start_rev_id, end_rev_id):
0.40.106 by Parth Malwankar
fixed error in dotted rev reverse search.
60
    # requires that start is older than end
0.40.95 by Parth Malwankar
faster mainline rev grep
61
    repo = branch.repository
62
    for revision_id in repo.iter_reverse_revision_history(end_rev_id):
63
        revno = branch.revision_id_to_dotted_revno(revision_id)
64
        revno_str = '.'.join(str(n) for n in revno)
65
        if revision_id == start_rev_id:
66
            yield revision_id, revno_str, 0
67
            break
68
        yield revision_id, revno_str, 0
69
0.40.117 by Parth Malwankar
cosmetic fix. added two lines between top level functions.
70
0.40.100 by Parth Malwankar
removed dependency on log._graph_view_revisions
71
# NOTE: _graph_view_revisions is copied from
72
# bzrlib.log._graph_view_revisions.
73
# This should probably be a common public API
74
def _graph_view_revisions(branch, start_rev_id, end_rev_id,
75
                          rebase_initial_depths=True):
76
    """Calculate revisions to view including merges, newest to oldest.
77
78
    :param branch: the branch
79
    :param start_rev_id: the lower revision-id
80
    :param end_rev_id: the upper revision-id
81
    :param rebase_initial_depth: should depths be rebased until a mainline
82
      revision is found?
83
    :return: An iterator of (revision_id, dotted_revno, merge_depth) tuples.
84
    """
0.40.106 by Parth Malwankar
fixed error in dotted rev reverse search.
85
    # requires that start is older than end
0.40.100 by Parth Malwankar
removed dependency on log._graph_view_revisions
86
    view_revisions = branch.iter_merge_sorted_revisions(
87
        start_revision_id=end_rev_id, stop_revision_id=start_rev_id,
88
        stop_rule="with-merges")
89
    if not rebase_initial_depths:
90
        for (rev_id, merge_depth, revno, end_of_merge
91
             ) in view_revisions:
92
            yield rev_id, '.'.join(map(str, revno)), merge_depth
93
    else:
94
        # We're following a development line starting at a merged revision.
95
        # We need to adjust depths down by the initial depth until we find
96
        # a depth less than it. Then we use that depth as the adjustment.
97
        # If and when we reach the mainline, depth adjustment ends.
98
        depth_adjustment = None
99
        for (rev_id, merge_depth, revno, end_of_merge
100
             ) in view_revisions:
101
            if depth_adjustment is None:
102
                depth_adjustment = merge_depth
103
            if depth_adjustment:
104
                if merge_depth < depth_adjustment:
105
                    # From now on we reduce the depth adjustement, this can be
106
                    # surprising for users. The alternative requires two passes
107
                    # which breaks the fast display of the first revision
108
                    # though.
109
                    depth_adjustment = merge_depth
110
                merge_depth -= depth_adjustment
111
            yield rev_id, '.'.join(map(str, revno)), merge_depth
112
0.40.117 by Parth Malwankar
cosmetic fix. added two lines between top level functions.
113
0.40.9 by Parth Malwankar
factored out grep related code to grep.py
114
def compile_pattern(pattern, flags=0):
115
    patternc = None
116
    try:
117
        # use python's re.compile as we need to catch re.error in case of bad pattern
118
        lazy_regex.reset_compile()
119
        patternc = re.compile(pattern, flags)
120
    except re.error, e:
121
        raise errors.BzrError("Invalid pattern: '%s'" % pattern)
122
    return patternc
123
0.40.117 by Parth Malwankar
cosmetic fix. added two lines between top level functions.
124
0.40.86 by Parth Malwankar
the check for implicit fixed_string now allows for spaces.
125
def is_fixed_string(s):
0.40.101 by Parth Malwankar
added underscore to --fixed-string whitelist
126
    if re.match("^([A-Za-z0-9_]|\s)*$", s):
0.40.86 by Parth Malwankar
the check for implicit fixed_string now allows for spaces.
127
        return True
128
    return False
0.41.11 by Parth Malwankar
moved top level grep code to versioned_grep.
129
0.40.117 by Parth Malwankar
cosmetic fix. added two lines between top level functions.
130
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
131
def versioned_grep(opts):
0.40.131 by Parth Malwankar
bzr grep now allows grepping with -r even when no tree exists.
132
    wt, branch, relpath = \
133
        bzrdir.BzrDir.open_containing_tree_or_branch('.')
134
    branch.lock_read()
0.40.88 by Parth Malwankar
updated to avoid relocking.
135
    try:
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
136
        # res_cache is used to cache results for dir grep based on fid.
137
        # If the fid is does not change between results, it means that
138
        # the result will be the same apart from revno. In such a case
139
        # we avoid getting file chunks from repo and grepping. The result
140
        # is just printed by replacing old revno with new one.
141
        res_cache = {}
0.40.88 by Parth Malwankar
updated to avoid relocking.
142
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
143
        start_rev = opts.revision[0]
0.40.131 by Parth Malwankar
bzr grep now allows grepping with -r even when no tree exists.
144
        start_revid = start_rev.as_revision_id(branch)
0.40.95 by Parth Malwankar
faster mainline rev grep
145
        if start_revid == None:
146
            start_rev = RevisionSpec_revno.from_string("revno:1")
0.40.131 by Parth Malwankar
bzr grep now allows grepping with -r even when no tree exists.
147
            start_revid = start_rev.as_revision_id(branch)
148
        srevno_tuple = branch.revision_id_to_dotted_revno(start_revid)
0.40.88 by Parth Malwankar
updated to avoid relocking.
149
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
150
        if len(opts.revision) == 2:
151
            end_rev = opts.revision[1]
0.40.131 by Parth Malwankar
bzr grep now allows grepping with -r even when no tree exists.
152
            end_revid = end_rev.as_revision_id(branch)
0.40.95 by Parth Malwankar
faster mainline rev grep
153
            if end_revid == None:
0.40.131 by Parth Malwankar
bzr grep now allows grepping with -r even when no tree exists.
154
                end_revno, end_revid = branch.last_revision_info()
155
            erevno_tuple = branch.revision_id_to_dotted_revno(end_revid)
0.40.95 by Parth Malwankar
faster mainline rev grep
156
0.40.106 by Parth Malwankar
fixed error in dotted rev reverse search.
157
            grep_mainline = (_rev_on_mainline(srevno_tuple) and
158
                _rev_on_mainline(erevno_tuple))
159
160
            # ensure that we go in reverse order
161
            if srevno_tuple > erevno_tuple:
162
                srevno_tuple, erevno_tuple = erevno_tuple, srevno_tuple
163
                start_revid, end_revid = end_revid, start_revid
0.40.97 by Parth Malwankar
fixed caching bug for rev range.
164
0.40.95 by Parth Malwankar
faster mainline rev grep
165
            # Optimization: Traversing the mainline in reverse order is much
166
            # faster when we don't want to look at merged revs. We try this
167
            # with _linear_view_revisions. If all revs are to be grepped we
168
            # use the slower _graph_view_revisions
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
169
            if opts.levels==1 and grep_mainline:
0.40.131 by Parth Malwankar
bzr grep now allows grepping with -r even when no tree exists.
170
                given_revs = _linear_view_revisions(branch, start_revid, end_revid)
0.40.95 by Parth Malwankar
faster mainline rev grep
171
            else:
0.40.131 by Parth Malwankar
bzr grep now allows grepping with -r even when no tree exists.
172
                given_revs = _graph_view_revisions(branch, start_revid, end_revid)
0.40.88 by Parth Malwankar
updated to avoid relocking.
173
        else:
0.40.94 by Parth Malwankar
code cleanup. moved start_rev_tuple into if cond that uses it.
174
            # We do an optimization below. For grepping a specific revison
175
            # We don't need to call _graph_view_revisions which is slow.
176
            # We create the start_rev_tuple for only that specific revision.
177
            # _graph_view_revisions is used only for revision range.
178
            start_revno = '.'.join(map(str, srevno_tuple))
179
            start_rev_tuple = (start_revid, start_revno, 0)
0.40.88 by Parth Malwankar
updated to avoid relocking.
180
            given_revs = [start_rev_tuple]
181
182
        for revid, revno, merge_depth in given_revs:
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
183
            if opts.levels == 1 and merge_depth != 0:
0.40.88 by Parth Malwankar
updated to avoid relocking.
184
                # with level=1 show only top level
185
                continue
186
187
            rev = RevisionSpec_revid.from_string("revid:"+revid)
0.40.131 by Parth Malwankar
bzr grep now allows grepping with -r even when no tree exists.
188
            tree = rev.as_tree(branch)
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
189
            for path in opts.path_list:
0.41.11 by Parth Malwankar
moved top level grep code to versioned_grep.
190
                path_for_id = osutils.pathjoin(relpath, path)
191
                id = tree.path2id(path_for_id)
192
                if not id:
0.41.22 by Parth Malwankar
added basic --exclude/include tests
193
                    trace.warning("Skipped unknown file '%s'." % path)
0.41.11 by Parth Malwankar
moved top level grep code to versioned_grep.
194
                    continue
195
196
                if osutils.isdir(path):
197
                    path_prefix = path
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
198
                    res_cache = dir_grep(tree, path, relpath, opts,
199
                        revno, path_prefix, res_cache)
0.41.11 by Parth Malwankar
moved top level grep code to versioned_grep.
200
                else:
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
201
                    versioned_file_grep(tree, id, '.', path, opts, revno)
0.40.88 by Parth Malwankar
updated to avoid relocking.
202
    finally:
0.40.131 by Parth Malwankar
bzr grep now allows grepping with -r even when no tree exists.
203
        branch.unlock()
0.41.11 by Parth Malwankar
moved top level grep code to versioned_grep.
204
0.40.117 by Parth Malwankar
cosmetic fix. added two lines between top level functions.
205
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
206
def workingtree_grep(opts):
207
    revno = opts.print_revno = None # for working tree set revno to None
0.40.69 by Parth Malwankar
reduced lock/unlock
208
209
    tree, branch, relpath = \
210
        bzrdir.BzrDir.open_containing_tree_or_branch('.')
0.40.130 by Parth Malwankar
grep in a branch with no tree does not throw stack trace (#572658)
211
    if not tree:
0.40.131 by Parth Malwankar
bzr grep now allows grepping with -r even when no tree exists.
212
        msg = ('Cannot search working tree. Working tree not found.\n'
213
            'To search for specific revision in history use the -r option.')
0.40.130 by Parth Malwankar
grep in a branch with no tree does not throw stack trace (#572658)
214
        raise errors.BzrCommandError(msg)
215
0.40.69 by Parth Malwankar
reduced lock/unlock
216
    tree.lock_read()
217
    try:
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
218
        for path in opts.path_list:
0.40.69 by Parth Malwankar
reduced lock/unlock
219
            if osutils.isdir(path):
220
                path_prefix = path
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
221
                dir_grep(tree, path, relpath, opts, revno, path_prefix)
0.40.69 by Parth Malwankar
reduced lock/unlock
222
            else:
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
223
                _file_grep(open(path).read(), '.', path, opts, revno)
0.40.69 by Parth Malwankar
reduced lock/unlock
224
    finally:
225
        tree.unlock()
0.41.11 by Parth Malwankar
moved top level grep code to versioned_grep.
226
0.40.117 by Parth Malwankar
cosmetic fix. added two lines between top level functions.
227
0.40.74 by Parth Malwankar
optimization. --include/exclude are checked before reading the file.
228
def _skip_file(include, exclude, path):
229
    if include and not _path_in_glob_list(path, include):
230
        return True
231
    if exclude and _path_in_glob_list(path, exclude):
232
        return True
233
    return False
234
235
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
236
def dir_grep(tree, path, relpath, opts, revno, path_prefix, res_cache={}):
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
237
    _revno_pattern = re.compile("\~[0-9.]+:")
0.40.115 by Parth Malwankar
added test for versioned grep.
238
    _revno_pattern_list_only = re.compile("\~[0-9.]+")
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
239
    dir_res = {}
240
0.40.60 by Parth Malwankar
'binary file skipped' warning is only shown with --verbose flag
241
    # setup relpath to open files relative to cwd
242
    rpath = relpath
243
    if relpath:
244
        rpath = osutils.pathjoin('..',relpath)
245
246
    from_dir = osutils.pathjoin(relpath, path)
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
247
    if opts.from_root:
0.40.60 by Parth Malwankar
'binary file skipped' warning is only shown with --verbose flag
248
        # start searching recursively from root
249
        from_dir=None
250
        recursive=True
251
0.40.85 by Parth Malwankar
optimized versioned grep to use iter_files_bytes.
252
    to_grep = []
0.40.92 by Parth Malwankar
performance tweaks to core cached result print loop.
253
    to_grep_append = to_grep.append
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
254
    outf_write = opts.outf.write
0.40.69 by Parth Malwankar
reduced lock/unlock
255
    for fp, fc, fkind, fid, entry in tree.list_files(include_root=False,
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
256
        from_dir=from_dir, recursive=opts.recursive):
0.40.69 by Parth Malwankar
reduced lock/unlock
257
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
258
        if _skip_file(opts.include, opts.exclude, fp):
0.40.74 by Parth Malwankar
optimization. --include/exclude are checked before reading the file.
259
            continue
260
0.40.69 by Parth Malwankar
reduced lock/unlock
261
        if fc == 'V' and fkind == 'file':
262
            if revno != None:
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
263
                # If old result is valid, print results immediately.
264
                # Otherwise, add file info to to_grep so that the
265
                # loop later will get chunks and grep them
0.40.97 by Parth Malwankar
fixed caching bug for rev range.
266
                file_rev = tree.inventory[fid].revision
267
                old_res = res_cache.get(file_rev)
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
268
                if old_res != None:
269
                    res = []
0.40.92 by Parth Malwankar
performance tweaks to core cached result print loop.
270
                    res_append = res.append
0.40.115 by Parth Malwankar
added test for versioned grep.
271
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
272
                    if opts.files_with_matches or opts.files_without_match:
0.40.122 by Parth Malwankar
added test for versioned -L and some fixes.
273
                        new_rev = '~' + revno
274
                    else:
0.40.115 by Parth Malwankar
added test for versioned grep.
275
                        new_rev = ('~%s:' % (revno,))
276
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
277
                    for line in old_res:
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
278
                        if opts.files_with_matches or opts.files_without_match:
0.40.122 by Parth Malwankar
added test for versioned -L and some fixes.
279
                            s = _revno_pattern_list_only.sub(new_rev, line)
280
                        else:
0.40.115 by Parth Malwankar
added test for versioned grep.
281
                            s = _revno_pattern.sub(new_rev, line)
0.40.92 by Parth Malwankar
performance tweaks to core cached result print loop.
282
                        res_append(s)
283
                        outf_write(s)
0.40.97 by Parth Malwankar
fixed caching bug for rev range.
284
                    dir_res[file_rev] = res
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
285
                else:
0.40.92 by Parth Malwankar
performance tweaks to core cached result print loop.
286
                    to_grep_append((fid, (fp, fid)))
0.40.69 by Parth Malwankar
reduced lock/unlock
287
            else:
288
                # we are grepping working tree.
289
                if from_dir == None:
290
                    from_dir = '.'
291
292
                path_for_file = osutils.pathjoin(tree.basedir, from_dir, fp)
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
293
                if opts.files_with_matches or opts.files_without_match:
0.40.116 by Parth Malwankar
optimization for wtree list-only grep to avoid full file read.
294
                    # Optimize for wtree list-only as we don't need to read the
295
                    # entire file
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
296
                    file = codecs.open(path_for_file, 'r', buffering=4096)
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
297
                    _file_grep_list_only_wtree(file, rpath, fp, opts,
298
                        path_prefix)
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
299
                else:
300
                    file_text = codecs.open(path_for_file, 'r').read()
301
                    _file_grep(file_text, rpath, fp,
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
302
                        opts, revno, path_prefix)
0.40.43 by Parth Malwankar
moved cmd_grep._grep_dir to grep.dir_grep
303
0.40.85 by Parth Malwankar
optimized versioned grep to use iter_files_bytes.
304
    if revno != None: # grep versioned files
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
305
        for (path, fid), chunks in tree.iter_files_bytes(to_grep):
0.40.85 by Parth Malwankar
optimized versioned grep to use iter_files_bytes.
306
            path = _make_display_path(relpath, path)
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
307
            res = _file_grep(chunks[0], rpath, path, opts, revno, path_prefix)
0.40.97 by Parth Malwankar
fixed caching bug for rev range.
308
            file_rev = tree.inventory[fid].revision
309
            dir_res[file_rev] = res
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
310
    return dir_res
0.40.43 by Parth Malwankar
moved cmd_grep._grep_dir to grep.dir_grep
311
0.40.117 by Parth Malwankar
cosmetic fix. added two lines between top level functions.
312
0.41.8 by Parth Malwankar
code cleanup.
313
def _make_display_path(relpath, path):
314
    """Return path string relative to user cwd.
0.40.42 by Parth Malwankar
fix to make grep paths relative to cwd
315
0.41.8 by Parth Malwankar
code cleanup.
316
    Take tree's 'relpath' and user supplied 'path', and return path
317
    that can be displayed to the user.
318
    """
0.40.15 by Parth Malwankar
some fixes and test updates
319
    if relpath:
0.40.52 by Parth Malwankar
code cleanup and documentation
320
        # update path so to display it w.r.t cwd
321
        # handle windows slash separator
0.40.20 by Parth Malwankar
used path functions from bzrlib.osutils
322
        path = osutils.normpath(osutils.pathjoin(relpath, path))
0.40.22 by Parth Malwankar
fixed display path formatting on windows
323
        path = path.replace('\\', '/')
324
        path = path.replace(relpath + '/', '', 1)
0.41.8 by Parth Malwankar
code cleanup.
325
    return path
326
327
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
328
def versioned_file_grep(tree, id, relpath, path, opts, revno, path_prefix = None):
0.41.10 by Parth Malwankar
code cleanup. added comments. path adjustment is now done
329
    """Create a file object for the specified id and pass it on to _file_grep.
330
    """
331
332
    path = _make_display_path(relpath, path)
0.41.12 by Parth Malwankar
initial support for working tree grep (no test cases yet!)
333
    file_text = tree.get_file_text(id)
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
334
    _file_grep(file_text, relpath, path, opts, revno, path_prefix)
0.41.21 by Parth Malwankar
include/exclude working now. tests not added.
335
0.40.117 by Parth Malwankar
cosmetic fix. added two lines between top level functions.
336
0.41.21 by Parth Malwankar
include/exclude working now. tests not added.
337
def _path_in_glob_list(path, glob_list):
338
    present = False
339
    for glob in glob_list:
340
        if fnmatch(path, glob):
341
            present = True
342
            break
343
    return present
0.41.12 by Parth Malwankar
initial support for working tree grep (no test cases yet!)
344
0.40.117 by Parth Malwankar
cosmetic fix. added two lines between top level functions.
345
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
346
def _file_grep_list_only_wtree(file, relpath, path, opts, path_prefix=None):
0.40.116 by Parth Malwankar
optimization for wtree list-only grep to avoid full file read.
347
    # test and skip binary files
348
    if '\x00' in file.read(1024):
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
349
        if opts.verbose:
0.40.116 by Parth Malwankar
optimization for wtree list-only grep to avoid full file read.
350
            trace.warning("Binary file '%s' skipped." % path)
0.40.118 by Parth Malwankar
further optimization of _file_grep_list_only_wtree.
351
            return
352
353
    file.seek(0) # search from beginning
354
355
    found = False
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
356
    if opts.fixed_string:
357
        pattern = opts.pattern.encode(_user_encoding, 'replace')
358
        if opts.fixed_string and opts.ignore_case:
359
            pattern = opts.pattern.lower()
360
        if opts.ignore_case:
0.40.118 by Parth Malwankar
further optimization of _file_grep_list_only_wtree.
361
            for line in file:
0.40.116 by Parth Malwankar
optimization for wtree list-only grep to avoid full file read.
362
                line = line.lower()
0.40.118 by Parth Malwankar
further optimization of _file_grep_list_only_wtree.
363
                if pattern in line:
364
                    found = True
365
                    break
366
        else: # don't ignore case
367
            for line in file:
368
                if pattern in line:
369
                    found = True
370
                    break
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
371
    else: # not fixed_string
0.40.116 by Parth Malwankar
optimization for wtree list-only grep to avoid full file read.
372
        for line in file:
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
373
            if opts.patternc.search(line):
0.40.118 by Parth Malwankar
further optimization of _file_grep_list_only_wtree.
374
                found = True
0.40.116 by Parth Malwankar
optimization for wtree list-only grep to avoid full file read.
375
                break
376
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
377
    if (opts.files_with_matches and found) or \
378
        (opts.files_without_match and not found):
0.40.118 by Parth Malwankar
further optimization of _file_grep_list_only_wtree.
379
        if path_prefix and path_prefix != '.':
380
            # user has passed a dir arg, show that as result prefix
381
            path = osutils.pathjoin(path_prefix, path)
382
        path = path.encode(_terminal_encoding, 'replace')
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
383
        s = path + opts.eol_marker
384
        opts.outf.write(s)
385
386
387
def _file_grep(file_text, relpath, path, opts, revno, path_prefix=None):
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
388
    res = []
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
389
    res_append = res.append
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
390
    outf_write = opts.outf.write
0.40.83 by Parth Malwankar
added support for -F/--fixed-string.
391
0.40.91 by Parth Malwankar
made _terminal_encoding and _user_encoding local for performance.
392
    _te = _terminal_encoding
393
    _ue = _user_encoding
394
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
395
    pattern = opts.pattern.encode(_ue, 'replace')
396
    patternc = opts.patternc
397
    eol_marker = opts.eol_marker
398
399
    if opts.fixed_string and opts.ignore_case:
400
        pattern = opts.pattern.lower()
0.40.83 by Parth Malwankar
added support for -F/--fixed-string.
401
0.41.9 by Parth Malwankar
refactored code towards support for working tree grep.
402
    # test and skip binary files
0.40.62 by Parth Malwankar
performance optimization
403
    if '\x00' in file_text[:1024]:
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
404
        if opts.verbose:
0.40.60 by Parth Malwankar
'binary file skipped' warning is only shown with --verbose flag
405
            trace.warning("Binary file '%s' skipped." % path)
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
406
        return res
0.41.9 by Parth Malwankar
refactored code towards support for working tree grep.
407
0.40.52 by Parth Malwankar
code cleanup and documentation
408
    if path_prefix and path_prefix != '.':
409
        # user has passed a dir arg, show that as result prefix
410
        path = osutils.pathjoin(path_prefix, path)
411
0.40.91 by Parth Malwankar
made _terminal_encoding and _user_encoding local for performance.
412
    path = path.encode(_te, 'replace')
0.43.8 by Parth Malwankar
added color for regex pattern.
413
0.43.6 by Parth Malwankar
--color now shows path in color for fixed string grep.
414
    if opts.show_color:
415
        path = color_string(path, FG.MAGENTA)
0.43.10 by Parth Malwankar
field seperators are now colored for --color
416
        color_sep = color_string(':', FG.BOLD_CYAN)
417
        color_rev_sep = color_string('~', FG.BOLD_YELLOW)
0.40.9 by Parth Malwankar
factored out grep related code to grep.py
418
0.40.64 by Parth Malwankar
cosmetic: improved comment
419
    # for better performance we moved formatting conditionals out
420
    # of the core loop. hence, the core loop is somewhat duplicated
421
    # for various combinations of formatting options.
422
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
423
    if opts.files_with_matches or opts.files_without_match:
0.40.112 by Parth Malwankar
support for -l, --files-with-matches. no tests yet.
424
        # While printing files with matches we only have two case
425
        # print file name or print file name with revno.
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
426
        found = False
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
427
        if opts.print_revno:
428
            if opts.fixed_string:
0.40.112 by Parth Malwankar
support for -l, --files-with-matches. no tests yet.
429
                for line in file_text.splitlines():
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
430
                    if opts.ignore_case:
0.40.112 by Parth Malwankar
support for -l, --files-with-matches. no tests yet.
431
                        line = line.lower()
432
                    if pattern in line:
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
433
                        found = True
0.40.112 by Parth Malwankar
support for -l, --files-with-matches. no tests yet.
434
                        break
435
            else:
436
                for line in file_text.splitlines():
437
                    if patternc.search(line):
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
438
                        found = True
0.40.112 by Parth Malwankar
support for -l, --files-with-matches. no tests yet.
439
                        break
440
        else:
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
441
            if opts.fixed_string:
0.40.112 by Parth Malwankar
support for -l, --files-with-matches. no tests yet.
442
                for line in file_text.splitlines():
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
443
                    if opts.ignore_case:
0.40.112 by Parth Malwankar
support for -l, --files-with-matches. no tests yet.
444
                        line = line.lower()
445
                    if pattern in line:
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
446
                        found = True
0.40.112 by Parth Malwankar
support for -l, --files-with-matches. no tests yet.
447
                        break
448
            else:
449
                for line in file_text.splitlines():
450
                    if patternc.search(line):
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
451
                        found = True
0.40.112 by Parth Malwankar
support for -l, --files-with-matches. no tests yet.
452
                        break
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
453
        if (opts.files_with_matches and found) or \
454
                (opts.files_without_match and not found):
455
            if opts.print_revno:
0.40.122 by Parth Malwankar
added test for versioned -L and some fixes.
456
                pfmt = "~%s".encode(_te, 'replace')
0.43.10 by Parth Malwankar
field seperators are now colored for --color
457
                if opts.show_color:
458
                    pfmt = color_rev_sep + "%s"
0.40.122 by Parth Malwankar
added test for versioned -L and some fixes.
459
                s = path + (pfmt % (revno,)) + eol_marker
460
            else:
461
                s = path + eol_marker
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
462
            res_append(s)
463
            outf_write(s)
0.40.122 by Parth Malwankar
added test for versioned -L and some fixes.
464
        return res # return from files_with|without_matches
0.40.112 by Parth Malwankar
support for -l, --files-with-matches. no tests yet.
465
466
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
467
    if opts.print_revno and opts.line_number:
0.40.63 by Parth Malwankar
performance: moved conditionals out of core loop.
468
0.40.91 by Parth Malwankar
made _terminal_encoding and _user_encoding local for performance.
469
        pfmt = "~%s:%d:%s".encode(_te)
0.43.10 by Parth Malwankar
field seperators are now colored for --color
470
        if opts.show_color:
471
            pfmt = color_rev_sep + "%s" + color_sep + "%d" + color_sep + "%s"
472
            pfmt = pfmt.encode(_te)
473
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
474
        if opts.fixed_string:
475
            if opts.ignore_case:
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
476
                for index, line in enumerate(file_text.splitlines()):
477
                    if pattern in line.lower():
478
                        line = line.decode(_te, 'replace')
0.43.9 by Parth Malwankar
added color support for ignore_case with fixed_string
479
                        if opts.show_color:
480
                            line = re_color_string(opts.sub_patternc, line, FG.BOLD_RED)
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
481
                        s = path + (pfmt % (revno, index+1, line)) + eol_marker
482
                        res_append(s)
483
                        outf_write(s)
484
            else: # don't ignore case
0.43.7 by Parth Malwankar
added color support for additional cases.
485
                found_str = color_string(pattern, FG.BOLD_RED)
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
486
                for index, line in enumerate(file_text.splitlines()):
487
                    if pattern in line:
488
                        line = line.decode(_te, 'replace')
0.43.7 by Parth Malwankar
added color support for additional cases.
489
                        if opts.show_color == True:
490
                            line = line.replace(pattern, found_str)
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
491
                        s = path + (pfmt % (revno, index+1, line)) + eol_marker
492
                        res_append(s)
493
                        outf_write(s)
0.40.83 by Parth Malwankar
added support for -F/--fixed-string.
494
        else:
495
            for index, line in enumerate(file_text.splitlines()):
496
                if patternc.search(line):
0.40.91 by Parth Malwankar
made _terminal_encoding and _user_encoding local for performance.
497
                    line = line.decode(_te, 'replace')
0.43.8 by Parth Malwankar
added color for regex pattern.
498
                    if opts.show_color:
499
                        line = re_color_string(opts.sub_patternc, line, FG.BOLD_RED)
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
500
                    s = path + (pfmt % (revno, index+1, line)) + eol_marker
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
501
                    res_append(s)
502
                    outf_write(s)
0.40.63 by Parth Malwankar
performance: moved conditionals out of core loop.
503
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
504
    elif opts.print_revno and not opts.line_number:
0.40.63 by Parth Malwankar
performance: moved conditionals out of core loop.
505
0.40.91 by Parth Malwankar
made _terminal_encoding and _user_encoding local for performance.
506
        pfmt = "~%s:%s".encode(_te, 'replace')
0.43.10 by Parth Malwankar
field seperators are now colored for --color
507
        if opts.show_color:
508
            pfmt = color_rev_sep + "%s" + color_sep + "%s"
509
            pfmt = pfmt.encode(_te)
510
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
511
        if opts.fixed_string:
512
            if opts.ignore_case:
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
513
                for line in file_text.splitlines():
514
                    if pattern in line.lower():
515
                        line = line.decode(_te, 'replace')
0.43.9 by Parth Malwankar
added color support for ignore_case with fixed_string
516
                        if opts.show_color:
517
                            line = re_color_string(opts.sub_patternc, line, FG.BOLD_RED)
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
518
                        s = path + (pfmt % (revno, line)) + eol_marker
519
                        res_append(s)
520
                        outf_write(s)
521
            else: # don't ignore case
0.43.7 by Parth Malwankar
added color support for additional cases.
522
                found_str = color_string(pattern, FG.BOLD_RED)
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
523
                for line in file_text.splitlines():
524
                    if pattern in line:
525
                        line = line.decode(_te, 'replace')
0.43.7 by Parth Malwankar
added color support for additional cases.
526
                        if opts.show_color == True:
527
                            line = line.replace(pattern, found_str)
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
528
                        s = path + (pfmt % (revno, line)) + eol_marker
529
                        res_append(s)
530
                        outf_write(s)
531
0.40.83 by Parth Malwankar
added support for -F/--fixed-string.
532
        else:
533
            for line in file_text.splitlines():
534
                if patternc.search(line):
0.40.91 by Parth Malwankar
made _terminal_encoding and _user_encoding local for performance.
535
                    line = line.decode(_te, 'replace')
0.43.8 by Parth Malwankar
added color for regex pattern.
536
                    if opts.show_color:
537
                        line = re_color_string(opts.sub_patternc, line, FG.BOLD_RED)
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
538
                    s = path + (pfmt % (revno, line)) + eol_marker
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
539
                    res_append(s)
540
                    outf_write(s)
0.40.63 by Parth Malwankar
performance: moved conditionals out of core loop.
541
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
542
    elif not opts.print_revno and opts.line_number:
0.40.63 by Parth Malwankar
performance: moved conditionals out of core loop.
543
0.40.91 by Parth Malwankar
made _terminal_encoding and _user_encoding local for performance.
544
        pfmt = ":%d:%s".encode(_te)
0.43.10 by Parth Malwankar
field seperators are now colored for --color
545
        if opts.show_color:
546
            pfmt = color_sep + "%d" + color_sep + "%s"
547
            pfmt = pfmt.encode(_te)
548
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
549
        if opts.fixed_string:
550
            if opts.ignore_case:
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
551
                for index, line in enumerate(file_text.splitlines()):
552
                    if pattern in line.lower():
553
                        line = line.decode(_te, 'replace')
0.43.9 by Parth Malwankar
added color support for ignore_case with fixed_string
554
                        if opts.show_color:
555
                            line = re_color_string(opts.sub_patternc, line, FG.BOLD_RED)
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
556
                        s = path + (pfmt % (index+1, line)) + eol_marker
557
                        res_append(s)
558
                        outf_write(s)
559
            else: # don't ignore case
560
                for index, line in enumerate(file_text.splitlines()):
0.43.7 by Parth Malwankar
added color support for additional cases.
561
                    found_str = color_string(pattern, FG.BOLD_RED)
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
562
                    if pattern in line:
563
                        line = line.decode(_te, 'replace')
0.43.7 by Parth Malwankar
added color support for additional cases.
564
                        if opts.show_color == True:
565
                            line = line.replace(pattern, found_str)
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
566
                        s = path + (pfmt % (index+1, line)) + eol_marker
567
                        res_append(s)
568
                        outf_write(s)
0.40.83 by Parth Malwankar
added support for -F/--fixed-string.
569
        else:
570
            for index, line in enumerate(file_text.splitlines()):
571
                if patternc.search(line):
0.40.91 by Parth Malwankar
made _terminal_encoding and _user_encoding local for performance.
572
                    line = line.decode(_te, 'replace')
0.43.8 by Parth Malwankar
added color for regex pattern.
573
                    if opts.show_color:
574
                        line = re_color_string(opts.sub_patternc, line, FG.BOLD_RED)
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
575
                    s = path + (pfmt % (index+1, line)) + eol_marker
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
576
                    res_append(s)
577
                    outf_write(s)
0.40.63 by Parth Malwankar
performance: moved conditionals out of core loop.
578
579
    else:
0.40.64 by Parth Malwankar
cosmetic: improved comment
580
0.40.91 by Parth Malwankar
made _terminal_encoding and _user_encoding local for performance.
581
        pfmt = ":%s".encode(_te)
0.43.10 by Parth Malwankar
field seperators are now colored for --color
582
        if opts.show_color:
583
            pfmt = color_sep + "%s"
584
            pfmt = pfmt.encode(_te)
585
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
586
        if opts.fixed_string:
587
            if opts.ignore_case:
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
588
                for line in file_text.splitlines():
589
                    if pattern in line.lower():
590
                        line = line.decode(_te, 'replace')
0.43.9 by Parth Malwankar
added color support for ignore_case with fixed_string
591
                        if opts.show_color:
592
                            line = re_color_string(opts.sub_patternc, line, FG.BOLD_RED)
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
593
                        s = path + (pfmt % (line,)) + eol_marker
594
                        res_append(s)
595
                        outf_write(s)
596
            else: # don't ignore case
0.43.6 by Parth Malwankar
--color now shows path in color for fixed string grep.
597
                found_str = color_string(pattern, FG.BOLD_RED)
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
598
                for line in file_text.splitlines():
599
                    if pattern in line:
600
                        line = line.decode(_te, 'replace')
0.43.8 by Parth Malwankar
added color for regex pattern.
601
                        if opts.show_color:
0.43.4 by Parth Malwankar
initial support for color for fixed string grep.
602
                            line = line.replace(pattern, found_str)
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
603
                        s = path + (pfmt % (line,)) + eol_marker
604
                        res_append(s)
605
                        outf_write(s)
0.40.83 by Parth Malwankar
added support for -F/--fixed-string.
606
        else:
607
            for line in file_text.splitlines():
608
                if patternc.search(line):
0.40.91 by Parth Malwankar
made _terminal_encoding and _user_encoding local for performance.
609
                    line = line.decode(_te, 'replace')
0.43.8 by Parth Malwankar
added color for regex pattern.
610
                    if opts.show_color:
611
                        line = re_color_string(opts.sub_patternc, line, FG.BOLD_RED)
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
612
                    s = path + (pfmt % (line,)) + eol_marker
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
613
                    res_append(s)
614
                    outf_write(s)
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
615
616
    return res
0.40.9 by Parth Malwankar
factored out grep related code to grep.py
617