/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.41.12 by Parth Malwankar
initial support for working tree grep (no test cases yet!)
26
from bzrlib import bzrdir
0.41.11 by Parth Malwankar
moved top level grep code to versioned_grep.
27
from bzrlib.workingtree import WorkingTree
0.40.95 by Parth Malwankar
faster mainline rev grep
28
from bzrlib.revisionspec import RevisionSpec, RevisionSpec_revid, RevisionSpec_revno
0.40.9 by Parth Malwankar
factored out grep related code to grep.py
29
from bzrlib import (
30
    errors,
31
    lazy_regex,
0.40.47 by Parth Malwankar
fixes bug #531336. binary files are now skipped.
32
    osutils,
33
    textfile,
34
    trace,
0.40.9 by Parth Malwankar
factored out grep related code to grep.py
35
    )
36
""")
37
0.40.83 by Parth Malwankar
added support for -F/--fixed-string.
38
_terminal_encoding = osutils.get_terminal_encoding()
39
_user_encoding = osutils.get_user_encoding()
40
0.40.117 by Parth Malwankar
cosmetic fix. added two lines between top level functions.
41
0.40.95 by Parth Malwankar
faster mainline rev grep
42
class _RevisionNotLinear(Exception):
43
    """Raised when a revision is not on left-hand history."""
44
0.40.117 by Parth Malwankar
cosmetic fix. added two lines between top level functions.
45
0.40.95 by Parth Malwankar
faster mainline rev grep
46
def _rev_on_mainline(rev_tuple):
47
    """returns True is rev tuple is on mainline"""
48
    if len(rev_tuple) == 1:
49
        return True
50
    return rev_tuple[1] == 0 and rev_tuple[2] == 0
51
0.40.117 by Parth Malwankar
cosmetic fix. added two lines between top level functions.
52
0.40.100 by Parth Malwankar
removed dependency on log._graph_view_revisions
53
# NOTE: _linear_view_revisions is basided on
54
# bzrlib.log._linear_view_revisions.
55
# This should probably be a common public API
0.40.95 by Parth Malwankar
faster mainline rev grep
56
def _linear_view_revisions(branch, start_rev_id, end_rev_id):
0.40.106 by Parth Malwankar
fixed error in dotted rev reverse search.
57
    # requires that start is older than end
0.40.95 by Parth Malwankar
faster mainline rev grep
58
    repo = branch.repository
59
    for revision_id in repo.iter_reverse_revision_history(end_rev_id):
60
        revno = branch.revision_id_to_dotted_revno(revision_id)
61
        revno_str = '.'.join(str(n) for n in revno)
62
        if revision_id == start_rev_id:
63
            yield revision_id, revno_str, 0
64
            break
65
        yield revision_id, revno_str, 0
66
0.40.117 by Parth Malwankar
cosmetic fix. added two lines between top level functions.
67
0.40.100 by Parth Malwankar
removed dependency on log._graph_view_revisions
68
# NOTE: _graph_view_revisions is copied from
69
# bzrlib.log._graph_view_revisions.
70
# This should probably be a common public API
71
def _graph_view_revisions(branch, start_rev_id, end_rev_id,
72
                          rebase_initial_depths=True):
73
    """Calculate revisions to view including merges, newest to oldest.
74
75
    :param branch: the branch
76
    :param start_rev_id: the lower revision-id
77
    :param end_rev_id: the upper revision-id
78
    :param rebase_initial_depth: should depths be rebased until a mainline
79
      revision is found?
80
    :return: An iterator of (revision_id, dotted_revno, merge_depth) tuples.
81
    """
0.40.106 by Parth Malwankar
fixed error in dotted rev reverse search.
82
    # requires that start is older than end
0.40.100 by Parth Malwankar
removed dependency on log._graph_view_revisions
83
    view_revisions = branch.iter_merge_sorted_revisions(
84
        start_revision_id=end_rev_id, stop_revision_id=start_rev_id,
85
        stop_rule="with-merges")
86
    if not rebase_initial_depths:
87
        for (rev_id, merge_depth, revno, end_of_merge
88
             ) in view_revisions:
89
            yield rev_id, '.'.join(map(str, revno)), merge_depth
90
    else:
91
        # We're following a development line starting at a merged revision.
92
        # We need to adjust depths down by the initial depth until we find
93
        # a depth less than it. Then we use that depth as the adjustment.
94
        # If and when we reach the mainline, depth adjustment ends.
95
        depth_adjustment = None
96
        for (rev_id, merge_depth, revno, end_of_merge
97
             ) in view_revisions:
98
            if depth_adjustment is None:
99
                depth_adjustment = merge_depth
100
            if depth_adjustment:
101
                if merge_depth < depth_adjustment:
102
                    # From now on we reduce the depth adjustement, this can be
103
                    # surprising for users. The alternative requires two passes
104
                    # which breaks the fast display of the first revision
105
                    # though.
106
                    depth_adjustment = merge_depth
107
                merge_depth -= depth_adjustment
108
            yield rev_id, '.'.join(map(str, revno)), merge_depth
109
0.40.117 by Parth Malwankar
cosmetic fix. added two lines between top level functions.
110
0.40.9 by Parth Malwankar
factored out grep related code to grep.py
111
def compile_pattern(pattern, flags=0):
112
    patternc = None
113
    try:
114
        # use python's re.compile as we need to catch re.error in case of bad pattern
115
        lazy_regex.reset_compile()
116
        patternc = re.compile(pattern, flags)
117
    except re.error, e:
118
        raise errors.BzrError("Invalid pattern: '%s'" % pattern)
119
    return patternc
120
0.40.117 by Parth Malwankar
cosmetic fix. added two lines between top level functions.
121
0.40.86 by Parth Malwankar
the check for implicit fixed_string now allows for spaces.
122
def is_fixed_string(s):
0.40.101 by Parth Malwankar
added underscore to --fixed-string whitelist
123
    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.
124
        return True
125
    return False
0.41.11 by Parth Malwankar
moved top level grep code to versioned_grep.
126
0.40.117 by Parth Malwankar
cosmetic fix. added two lines between top level functions.
127
0.40.83 by Parth Malwankar
added support for -F/--fixed-string.
128
def versioned_grep(revision, pattern, compiled_pattern, path_list, recursive,
0.41.21 by Parth Malwankar
include/exclude working now. tests not added.
129
        line_number, from_root, eol_marker, print_revno, levels,
0.40.112 by Parth Malwankar
support for -l, --files-with-matches. no tests yet.
130
        include, exclude, verbose, fixed_string, ignore_case, files_with_matches,
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
131
        files_without_matches, outf):
0.41.11 by Parth Malwankar
moved top level grep code to versioned_grep.
132
133
    wt, relpath = WorkingTree.open_containing('.')
0.40.88 by Parth Malwankar
updated to avoid relocking.
134
    wt.lock_read()
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
143
        start_rev = revision[0]
144
        start_revid = start_rev.as_revision_id(wt.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")
147
            start_revid = start_rev.as_revision_id(wt.branch)
148
        srevno_tuple = wt.branch.revision_id_to_dotted_revno(start_revid)
0.40.88 by Parth Malwankar
updated to avoid relocking.
149
150
        if len(revision) == 2:
151
            end_rev = revision[1]
0.40.95 by Parth Malwankar
faster mainline rev grep
152
            end_revid = end_rev.as_revision_id(wt.branch)
153
            if end_revid == None:
154
                end_revno, end_revid = wt.branch.last_revision_info()
155
            erevno_tuple = wt.branch.revision_id_to_dotted_revno(end_revid)
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.40.106 by Parth Malwankar
fixed error in dotted rev reverse search.
169
            if levels==1 and grep_mainline:
0.40.95 by Parth Malwankar
faster mainline rev grep
170
                given_revs = _linear_view_revisions(wt.branch, start_revid, end_revid)
171
            else:
0.40.100 by Parth Malwankar
removed dependency on log._graph_view_revisions
172
                given_revs = _graph_view_revisions(wt.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:
183
            if levels == 1 and merge_depth != 0:
184
                # with level=1 show only top level
185
                continue
186
187
            rev = RevisionSpec_revid.from_string("revid:"+revid)
0.40.89 by Parth Malwankar
moved tree get call outside loop
188
            tree = rev.as_tree(wt.branch)
0.41.11 by Parth Malwankar
moved top level grep code to versioned_grep.
189
            for path in path_list:
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.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
198
                    res_cache = dir_grep(tree, path, relpath, recursive,
199
                        line_number, pattern, compiled_pattern,
200
                        from_root, eol_marker, revno, print_revno,
201
                        include, exclude, verbose, fixed_string,
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
202
                        ignore_case, files_with_matches, files_without_matches,
0.40.112 by Parth Malwankar
support for -l, --files-with-matches. no tests yet.
203
                        outf, path_prefix, res_cache)
0.41.11 by Parth Malwankar
moved top level grep code to versioned_grep.
204
                else:
0.40.69 by Parth Malwankar
reduced lock/unlock
205
                    versioned_file_grep(tree, id, '.', path,
0.40.83 by Parth Malwankar
added support for -F/--fixed-string.
206
                        pattern, compiled_pattern, eol_marker, line_number,
207
                        revno, print_revno, include, exclude, verbose,
0.40.112 by Parth Malwankar
support for -l, --files-with-matches. no tests yet.
208
                        fixed_string, ignore_case, files_with_matches,
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
209
                        files_without_matches, outf)
0.40.88 by Parth Malwankar
updated to avoid relocking.
210
    finally:
211
        wt.unlock()
0.41.11 by Parth Malwankar
moved top level grep code to versioned_grep.
212
0.40.117 by Parth Malwankar
cosmetic fix. added two lines between top level functions.
213
0.40.83 by Parth Malwankar
added support for -F/--fixed-string.
214
def workingtree_grep(pattern, compiled_pattern, path_list, recursive,
215
        line_number, from_root, eol_marker, include, exclude, verbose,
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
216
        fixed_string, ignore_case, files_with_matches, files_without_matches,
217
        outf):
0.41.12 by Parth Malwankar
initial support for working tree grep (no test cases yet!)
218
    revno = print_revno = None # for working tree set revno to None
0.40.69 by Parth Malwankar
reduced lock/unlock
219
220
    tree, branch, relpath = \
221
        bzrdir.BzrDir.open_containing_tree_or_branch('.')
222
    tree.lock_read()
223
    try:
224
        for path in path_list:
225
            if osutils.isdir(path):
226
                path_prefix = path
227
                dir_grep(tree, path, relpath, recursive, line_number,
0.40.83 by Parth Malwankar
added support for -F/--fixed-string.
228
                    pattern, compiled_pattern, from_root, eol_marker, revno,
229
                    print_revno, include, exclude, verbose, fixed_string,
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
230
                    ignore_case, files_with_matches, files_without_matches,
231
                    outf, path_prefix)
0.40.69 by Parth Malwankar
reduced lock/unlock
232
            else:
0.40.83 by Parth Malwankar
added support for -F/--fixed-string.
233
                _file_grep(open(path).read(), '.', path, pattern,
234
                    compiled_pattern, eol_marker, line_number, revno,
235
                    print_revno, include, exclude, verbose,
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
236
                    fixed_string, ignore_case, files_with_matches,
237
                    files_without_matches, outf)
0.40.69 by Parth Malwankar
reduced lock/unlock
238
    finally:
239
        tree.unlock()
0.41.11 by Parth Malwankar
moved top level grep code to versioned_grep.
240
0.40.117 by Parth Malwankar
cosmetic fix. added two lines between top level functions.
241
0.40.74 by Parth Malwankar
optimization. --include/exclude are checked before reading the file.
242
def _skip_file(include, exclude, path):
243
    if include and not _path_in_glob_list(path, include):
244
        return True
245
    if exclude and _path_in_glob_list(path, exclude):
246
        return True
247
    return False
248
249
0.40.83 by Parth Malwankar
added support for -F/--fixed-string.
250
def dir_grep(tree, path, relpath, recursive, line_number, pattern,
251
        compiled_pattern, from_root, eol_marker, revno, print_revno,
0.40.112 by Parth Malwankar
support for -l, --files-with-matches. no tests yet.
252
        include, exclude, verbose, fixed_string, ignore_case,
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
253
        files_with_matches, files_without_matches, outf,
254
        path_prefix, res_cache={}):
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
255
    _revno_pattern = re.compile("\~[0-9.]+:")
0.40.115 by Parth Malwankar
added test for versioned grep.
256
    _revno_pattern_list_only = re.compile("\~[0-9.]+")
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
257
    dir_res = {}
258
0.40.60 by Parth Malwankar
'binary file skipped' warning is only shown with --verbose flag
259
    # setup relpath to open files relative to cwd
260
    rpath = relpath
261
    if relpath:
262
        rpath = osutils.pathjoin('..',relpath)
263
264
    from_dir = osutils.pathjoin(relpath, path)
265
    if from_root:
266
        # start searching recursively from root
267
        from_dir=None
268
        recursive=True
269
0.40.85 by Parth Malwankar
optimized versioned grep to use iter_files_bytes.
270
    to_grep = []
0.40.92 by Parth Malwankar
performance tweaks to core cached result print loop.
271
    to_grep_append = to_grep.append
272
    outf_write = outf.write
0.40.69 by Parth Malwankar
reduced lock/unlock
273
    for fp, fc, fkind, fid, entry in tree.list_files(include_root=False,
274
        from_dir=from_dir, recursive=recursive):
275
0.40.74 by Parth Malwankar
optimization. --include/exclude are checked before reading the file.
276
        if _skip_file(include, exclude, fp):
277
            continue
278
0.40.69 by Parth Malwankar
reduced lock/unlock
279
        if fc == 'V' and fkind == 'file':
280
            if revno != None:
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
281
                # If old result is valid, print results immediately.
282
                # Otherwise, add file info to to_grep so that the
283
                # loop later will get chunks and grep them
0.40.97 by Parth Malwankar
fixed caching bug for rev range.
284
                file_rev = tree.inventory[fid].revision
285
                old_res = res_cache.get(file_rev)
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
286
                if old_res != None:
287
                    res = []
0.40.92 by Parth Malwankar
performance tweaks to core cached result print loop.
288
                    res_append = res.append
0.40.115 by Parth Malwankar
added test for versioned grep.
289
0.40.122 by Parth Malwankar
added test for versioned -L and some fixes.
290
                    if files_with_matches or files_without_matches:
291
                        new_rev = '~' + revno
292
                    else:
0.40.115 by Parth Malwankar
added test for versioned grep.
293
                        new_rev = ('~%s:' % (revno,))
294
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
295
                    for line in old_res:
0.40.122 by Parth Malwankar
added test for versioned -L and some fixes.
296
                        if files_with_matches or files_without_matches:
297
                            s = _revno_pattern_list_only.sub(new_rev, line)
298
                        else:
0.40.115 by Parth Malwankar
added test for versioned grep.
299
                            s = _revno_pattern.sub(new_rev, line)
0.40.92 by Parth Malwankar
performance tweaks to core cached result print loop.
300
                        res_append(s)
301
                        outf_write(s)
0.40.97 by Parth Malwankar
fixed caching bug for rev range.
302
                    dir_res[file_rev] = res
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
303
                else:
0.40.92 by Parth Malwankar
performance tweaks to core cached result print loop.
304
                    to_grep_append((fid, (fp, fid)))
0.40.69 by Parth Malwankar
reduced lock/unlock
305
            else:
306
                # we are grepping working tree.
307
                if from_dir == None:
308
                    from_dir = '.'
309
310
                path_for_file = osutils.pathjoin(tree.basedir, from_dir, fp)
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
311
                if files_with_matches or files_without_matches:
0.40.116 by Parth Malwankar
optimization for wtree list-only grep to avoid full file read.
312
                    # Optimize for wtree list-only as we don't need to read the
313
                    # entire file
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
314
                    file = codecs.open(path_for_file, 'r', buffering=4096)
0.40.116 by Parth Malwankar
optimization for wtree list-only grep to avoid full file read.
315
                    _file_grep_list_only_wtree(file, rpath, fp,
316
                        pattern, compiled_pattern, eol_marker, line_number, revno,
317
                        print_revno, include, exclude, verbose, fixed_string,
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
318
                        ignore_case, files_with_matches, files_without_matches,
319
                        outf, path_prefix)
320
                else:
321
                    file_text = codecs.open(path_for_file, 'r').read()
322
                    _file_grep(file_text, rpath, fp,
323
                        pattern, compiled_pattern, eol_marker, line_number, revno,
324
                        print_revno, include, exclude, verbose, fixed_string,
325
                        ignore_case, files_with_matches, files_without_matches,
326
                        outf, path_prefix)
0.40.43 by Parth Malwankar
moved cmd_grep._grep_dir to grep.dir_grep
327
0.40.85 by Parth Malwankar
optimized versioned grep to use iter_files_bytes.
328
    if revno != None: # grep versioned files
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
329
        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.
330
            path = _make_display_path(relpath, path)
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
331
            res = _file_grep(chunks[0], rpath, path, pattern,
332
                compiled_pattern, eol_marker, line_number, revno,
333
                print_revno, include, exclude, verbose, fixed_string,
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
334
                ignore_case, files_with_matches, files_without_matches,
335
                outf, path_prefix)
0.40.97 by Parth Malwankar
fixed caching bug for rev range.
336
            file_rev = tree.inventory[fid].revision
337
            dir_res[file_rev] = res
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
338
    return dir_res
0.40.43 by Parth Malwankar
moved cmd_grep._grep_dir to grep.dir_grep
339
0.40.117 by Parth Malwankar
cosmetic fix. added two lines between top level functions.
340
0.41.8 by Parth Malwankar
code cleanup.
341
def _make_display_path(relpath, path):
342
    """Return path string relative to user cwd.
0.40.42 by Parth Malwankar
fix to make grep paths relative to cwd
343
0.41.8 by Parth Malwankar
code cleanup.
344
    Take tree's 'relpath' and user supplied 'path', and return path
345
    that can be displayed to the user.
346
    """
0.40.15 by Parth Malwankar
some fixes and test updates
347
    if relpath:
0.40.52 by Parth Malwankar
code cleanup and documentation
348
        # update path so to display it w.r.t cwd
349
        # handle windows slash separator
0.40.20 by Parth Malwankar
used path functions from bzrlib.osutils
350
        path = osutils.normpath(osutils.pathjoin(relpath, path))
0.40.22 by Parth Malwankar
fixed display path formatting on windows
351
        path = path.replace('\\', '/')
352
        path = path.replace(relpath + '/', '', 1)
0.41.8 by Parth Malwankar
code cleanup.
353
    return path
354
355
0.40.83 by Parth Malwankar
added support for -F/--fixed-string.
356
def versioned_file_grep(tree, id, relpath, path, pattern, patternc,
357
        eol_marker, line_number, revno, print_revno, include, exclude,
0.40.112 by Parth Malwankar
support for -l, --files-with-matches. no tests yet.
358
        verbose, fixed_string, ignore_case, files_with_matches,
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
359
        files_without_matches, outf, path_prefix = None):
0.41.10 by Parth Malwankar
code cleanup. added comments. path adjustment is now done
360
    """Create a file object for the specified id and pass it on to _file_grep.
361
    """
362
363
    path = _make_display_path(relpath, path)
0.41.12 by Parth Malwankar
initial support for working tree grep (no test cases yet!)
364
    file_text = tree.get_file_text(id)
0.40.83 by Parth Malwankar
added support for -F/--fixed-string.
365
    _file_grep(file_text, relpath, path, pattern, patternc, eol_marker,
0.40.60 by Parth Malwankar
'binary file skipped' warning is only shown with --verbose flag
366
        line_number, revno, print_revno, include, exclude, verbose,
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
367
        fixed_string, ignore_case, files_with_matches, files_without_matches,
368
        outf, path_prefix)
0.41.21 by Parth Malwankar
include/exclude working now. tests not added.
369
0.40.117 by Parth Malwankar
cosmetic fix. added two lines between top level functions.
370
0.41.21 by Parth Malwankar
include/exclude working now. tests not added.
371
def _path_in_glob_list(path, glob_list):
372
    present = False
373
    for glob in glob_list:
374
        if fnmatch(path, glob):
375
            present = True
376
            break
377
    return present
0.41.12 by Parth Malwankar
initial support for working tree grep (no test cases yet!)
378
0.40.117 by Parth Malwankar
cosmetic fix. added two lines between top level functions.
379
0.40.116 by Parth Malwankar
optimization for wtree list-only grep to avoid full file read.
380
def _file_grep_list_only_wtree(file, relpath, path, pattern, patternc,
381
        eol_marker, line_number, revno, print_revno, include, exclude,
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
382
        verbose, fixed_string, ignore_case, files_with_matches,
383
        files_without_matches, outf, path_prefix=None):
0.40.116 by Parth Malwankar
optimization for wtree list-only grep to avoid full file read.
384
385
    # test and skip binary files
386
    if '\x00' in file.read(1024):
387
        if verbose:
388
            trace.warning("Binary file '%s' skipped." % path)
0.40.118 by Parth Malwankar
further optimization of _file_grep_list_only_wtree.
389
            return
390
391
    file.seek(0) # search from beginning
392
393
    found = False
0.40.116 by Parth Malwankar
optimization for wtree list-only grep to avoid full file read.
394
    if fixed_string:
0.40.118 by Parth Malwankar
further optimization of _file_grep_list_only_wtree.
395
        pattern = pattern.encode(_user_encoding, 'replace')
396
        if fixed_string and ignore_case:
397
            pattern = pattern.lower()
398
        if ignore_case:
399
400
            for line in file:
0.40.116 by Parth Malwankar
optimization for wtree list-only grep to avoid full file read.
401
                line = line.lower()
0.40.118 by Parth Malwankar
further optimization of _file_grep_list_only_wtree.
402
                if pattern in line:
403
                    found = True
404
                    break
405
        else: # don't ignore case
406
407
            for line in file:
408
                if pattern in line:
409
                    found = True
410
                    break
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
411
    else: # not fixed_string
0.40.118 by Parth Malwankar
further optimization of _file_grep_list_only_wtree.
412
0.40.116 by Parth Malwankar
optimization for wtree list-only grep to avoid full file read.
413
        for line in file:
414
            if patternc.search(line):
0.40.118 by Parth Malwankar
further optimization of _file_grep_list_only_wtree.
415
                found = True
0.40.116 by Parth Malwankar
optimization for wtree list-only grep to avoid full file read.
416
                break
417
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
418
    if (files_with_matches and found) or (files_without_matches and not found):
0.40.118 by Parth Malwankar
further optimization of _file_grep_list_only_wtree.
419
        if path_prefix and path_prefix != '.':
420
            # user has passed a dir arg, show that as result prefix
421
            path = osutils.pathjoin(path_prefix, path)
422
        path = path.encode(_terminal_encoding, 'replace')
423
        s = path + eol_marker
424
        outf.write(s)
0.40.70 by Parth Malwankar
lines are decoded correctly before printing.
425
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
426
0.40.83 by Parth Malwankar
added support for -F/--fixed-string.
427
def _file_grep(file_text, relpath, path, pattern, patternc, eol_marker,
428
        line_number, revno, print_revno, include, exclude, verbose,
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
429
        fixed_string, ignore_case, files_with_matches, files_without_matches,
430
        outf, path_prefix=None):
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
431
    res = []
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
432
    res_append = res.append
433
    outf_write = outf.write
0.40.83 by Parth Malwankar
added support for -F/--fixed-string.
434
0.40.91 by Parth Malwankar
made _terminal_encoding and _user_encoding local for performance.
435
    _te = _terminal_encoding
436
    _ue = _user_encoding
437
438
    pattern = pattern.encode(_ue, 'replace')
0.40.83 by Parth Malwankar
added support for -F/--fixed-string.
439
    if fixed_string and ignore_case:
440
        pattern = pattern.lower()
441
0.41.9 by Parth Malwankar
refactored code towards support for working tree grep.
442
    # test and skip binary files
0.40.62 by Parth Malwankar
performance optimization
443
    if '\x00' in file_text[:1024]:
0.40.60 by Parth Malwankar
'binary file skipped' warning is only shown with --verbose flag
444
        if verbose:
445
            trace.warning("Binary file '%s' skipped." % path)
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
446
        return res
0.41.9 by Parth Malwankar
refactored code towards support for working tree grep.
447
0.40.52 by Parth Malwankar
code cleanup and documentation
448
    if path_prefix and path_prefix != '.':
449
        # user has passed a dir arg, show that as result prefix
450
        path = osutils.pathjoin(path_prefix, path)
451
0.40.91 by Parth Malwankar
made _terminal_encoding and _user_encoding local for performance.
452
    path = path.encode(_te, 'replace')
0.40.9 by Parth Malwankar
factored out grep related code to grep.py
453
0.40.64 by Parth Malwankar
cosmetic: improved comment
454
    # for better performance we moved formatting conditionals out
455
    # of the core loop. hence, the core loop is somewhat duplicated
456
    # for various combinations of formatting options.
457
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
458
    if files_with_matches or files_without_matches:
0.40.112 by Parth Malwankar
support for -l, --files-with-matches. no tests yet.
459
        # While printing files with matches we only have two case
460
        # print file name or print file name with revno.
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
461
        found = False
0.40.112 by Parth Malwankar
support for -l, --files-with-matches. no tests yet.
462
        if print_revno:
463
            if fixed_string:
464
                for line in file_text.splitlines():
465
                    if ignore_case:
466
                        line = line.lower()
467
                    if pattern in line:
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
468
                        found = True
0.40.112 by Parth Malwankar
support for -l, --files-with-matches. no tests yet.
469
                        break
470
            else:
471
                for line in file_text.splitlines():
472
                    if patternc.search(line):
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
473
                        found = True
0.40.112 by Parth Malwankar
support for -l, --files-with-matches. no tests yet.
474
                        break
475
        else:
476
            if fixed_string:
477
                for line in file_text.splitlines():
478
                    if ignore_case:
479
                        line = line.lower()
480
                    if pattern in line:
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
481
                        found = True
0.40.112 by Parth Malwankar
support for -l, --files-with-matches. no tests yet.
482
                        break
483
            else:
484
                for line in file_text.splitlines():
485
                    if patternc.search(line):
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
486
                        found = True
0.40.112 by Parth Malwankar
support for -l, --files-with-matches. no tests yet.
487
                        break
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
488
        if (files_with_matches and found) or \
489
                (files_without_matches and not found):
0.40.122 by Parth Malwankar
added test for versioned -L and some fixes.
490
            if print_revno:
491
                pfmt = "~%s".encode(_te, 'replace')
492
                s = path + (pfmt % (revno,)) + eol_marker
493
            else:
494
                s = path + eol_marker
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
495
            res_append(s)
496
            outf_write(s)
0.40.122 by Parth Malwankar
added test for versioned -L and some fixes.
497
        return res # return from files_with|without_matches
0.40.112 by Parth Malwankar
support for -l, --files-with-matches. no tests yet.
498
499
0.40.63 by Parth Malwankar
performance: moved conditionals out of core loop.
500
    if print_revno and line_number:
501
0.40.91 by Parth Malwankar
made _terminal_encoding and _user_encoding local for performance.
502
        pfmt = "~%s:%d:%s".encode(_te)
0.40.83 by Parth Malwankar
added support for -F/--fixed-string.
503
        if fixed_string:
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
504
            if ignore_case:
505
                for index, line in enumerate(file_text.splitlines()):
506
                    if pattern in line.lower():
507
                        line = line.decode(_te, 'replace')
508
                        s = path + (pfmt % (revno, index+1, line)) + eol_marker
509
                        res_append(s)
510
                        outf_write(s)
511
            else: # don't ignore case
512
                for index, line in enumerate(file_text.splitlines()):
513
                    if pattern in line:
514
                        line = line.decode(_te, 'replace')
515
                        s = path + (pfmt % (revno, index+1, line)) + eol_marker
516
                        res_append(s)
517
                        outf_write(s)
0.40.83 by Parth Malwankar
added support for -F/--fixed-string.
518
        else:
519
            for index, line in enumerate(file_text.splitlines()):
520
                if patternc.search(line):
0.40.91 by Parth Malwankar
made _terminal_encoding and _user_encoding local for performance.
521
                    line = line.decode(_te, 'replace')
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
522
                    s = path + (pfmt % (revno, index+1, line)) + eol_marker
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
523
                    res_append(s)
524
                    outf_write(s)
0.40.63 by Parth Malwankar
performance: moved conditionals out of core loop.
525
526
    elif print_revno and not line_number:
527
0.40.91 by Parth Malwankar
made _terminal_encoding and _user_encoding local for performance.
528
        pfmt = "~%s:%s".encode(_te, 'replace')
0.40.83 by Parth Malwankar
added support for -F/--fixed-string.
529
        if fixed_string:
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
530
            if ignore_case:
531
                for line in file_text.splitlines():
532
                    if pattern in line.lower():
533
                        line = line.decode(_te, 'replace')
534
                        s = path + (pfmt % (revno, line)) + eol_marker
535
                        res_append(s)
536
                        outf_write(s)
537
            else: # don't ignore case
538
                for line in file_text.splitlines():
539
                    if pattern in line:
540
                        line = line.decode(_te, 'replace')
541
                        s = path + (pfmt % (revno, line)) + eol_marker
542
                        res_append(s)
543
                        outf_write(s)
544
0.40.83 by Parth Malwankar
added support for -F/--fixed-string.
545
        else:
546
            for line in file_text.splitlines():
547
                if patternc.search(line):
0.40.91 by Parth Malwankar
made _terminal_encoding and _user_encoding local for performance.
548
                    line = line.decode(_te, 'replace')
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
549
                    s = path + (pfmt % (revno, line)) + eol_marker
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
550
                    res_append(s)
551
                    outf_write(s)
0.40.63 by Parth Malwankar
performance: moved conditionals out of core loop.
552
553
    elif not print_revno and line_number:
554
0.40.91 by Parth Malwankar
made _terminal_encoding and _user_encoding local for performance.
555
        pfmt = ":%d:%s".encode(_te)
0.40.83 by Parth Malwankar
added support for -F/--fixed-string.
556
        if fixed_string:
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
557
            if ignore_case:
558
                for index, line in enumerate(file_text.splitlines()):
559
                    if pattern in line.lower():
560
                        line = line.decode(_te, 'replace')
561
                        s = path + (pfmt % (index+1, line)) + eol_marker
562
                        res_append(s)
563
                        outf_write(s)
564
            else: # don't ignore case
565
                for index, line in enumerate(file_text.splitlines()):
566
                    if pattern in line:
567
                        line = line.decode(_te, 'replace')
568
                        s = path + (pfmt % (index+1, line)) + eol_marker
569
                        res_append(s)
570
                        outf_write(s)
0.40.83 by Parth Malwankar
added support for -F/--fixed-string.
571
        else:
572
            for index, line in enumerate(file_text.splitlines()):
573
                if patternc.search(line):
0.40.91 by Parth Malwankar
made _terminal_encoding and _user_encoding local for performance.
574
                    line = line.decode(_te, 'replace')
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.40.83 by Parth Malwankar
added support for -F/--fixed-string.
582
        if fixed_string:
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
583
            if ignore_case:
584
                for line in file_text.splitlines():
585
                    if pattern in line.lower():
586
                        line = line.decode(_te, 'replace')
587
                        s = path + (pfmt % (line,)) + eol_marker
588
                        res_append(s)
589
                        outf_write(s)
590
            else: # don't ignore case
591
                for line in file_text.splitlines():
592
                    if pattern in line:
593
                        line = line.decode(_te, 'replace')
594
                        s = path + (pfmt % (line,)) + eol_marker
595
                        res_append(s)
596
                        outf_write(s)
0.40.83 by Parth Malwankar
added support for -F/--fixed-string.
597
        else:
598
            for line in file_text.splitlines():
599
                if patternc.search(line):
0.40.91 by Parth Malwankar
made _terminal_encoding and _user_encoding local for performance.
600
                    line = line.decode(_te, 'replace')
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
601
                    s = path + (pfmt % (line,)) + eol_marker
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
602
                    res_append(s)
603
                    outf_write(s)
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
604
605
    return res
0.40.9 by Parth Malwankar
factored out grep related code to grep.py
606