/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.4 by Parth Malwankar
initial support for color for fixed string grep.
26
from color import color_string, FG
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.41.11 by Parth Malwankar
moved top level grep code to versioned_grep.
132
    wt, relpath = WorkingTree.open_containing('.')
0.40.88 by Parth Malwankar
updated to avoid relocking.
133
    wt.lock_read()
134
    try:
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
135
        # res_cache is used to cache results for dir grep based on fid.
136
        # If the fid is does not change between results, it means that
137
        # the result will be the same apart from revno. In such a case
138
        # we avoid getting file chunks from repo and grepping. The result
139
        # is just printed by replacing old revno with new one.
140
        res_cache = {}
0.40.88 by Parth Malwankar
updated to avoid relocking.
141
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
142
        start_rev = opts.revision[0]
0.40.88 by Parth Malwankar
updated to avoid relocking.
143
        start_revid = start_rev.as_revision_id(wt.branch)
0.40.95 by Parth Malwankar
faster mainline rev grep
144
        if start_revid == None:
145
            start_rev = RevisionSpec_revno.from_string("revno:1")
146
            start_revid = start_rev.as_revision_id(wt.branch)
147
        srevno_tuple = wt.branch.revision_id_to_dotted_revno(start_revid)
0.40.88 by Parth Malwankar
updated to avoid relocking.
148
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
149
        if len(opts.revision) == 2:
150
            end_rev = opts.revision[1]
0.40.95 by Parth Malwankar
faster mainline rev grep
151
            end_revid = end_rev.as_revision_id(wt.branch)
152
            if end_revid == None:
153
                end_revno, end_revid = wt.branch.last_revision_info()
154
            erevno_tuple = wt.branch.revision_id_to_dotted_revno(end_revid)
155
0.40.106 by Parth Malwankar
fixed error in dotted rev reverse search.
156
            grep_mainline = (_rev_on_mainline(srevno_tuple) and
157
                _rev_on_mainline(erevno_tuple))
158
159
            # ensure that we go in reverse order
160
            if srevno_tuple > erevno_tuple:
161
                srevno_tuple, erevno_tuple = erevno_tuple, srevno_tuple
162
                start_revid, end_revid = end_revid, start_revid
0.40.97 by Parth Malwankar
fixed caching bug for rev range.
163
0.40.95 by Parth Malwankar
faster mainline rev grep
164
            # Optimization: Traversing the mainline in reverse order is much
165
            # faster when we don't want to look at merged revs. We try this
166
            # with _linear_view_revisions. If all revs are to be grepped we
167
            # use the slower _graph_view_revisions
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
168
            if opts.levels==1 and grep_mainline:
0.40.95 by Parth Malwankar
faster mainline rev grep
169
                given_revs = _linear_view_revisions(wt.branch, start_revid, end_revid)
170
            else:
0.40.100 by Parth Malwankar
removed dependency on log._graph_view_revisions
171
                given_revs = _graph_view_revisions(wt.branch, start_revid, end_revid)
0.40.88 by Parth Malwankar
updated to avoid relocking.
172
        else:
0.40.94 by Parth Malwankar
code cleanup. moved start_rev_tuple into if cond that uses it.
173
            # We do an optimization below. For grepping a specific revison
174
            # We don't need to call _graph_view_revisions which is slow.
175
            # We create the start_rev_tuple for only that specific revision.
176
            # _graph_view_revisions is used only for revision range.
177
            start_revno = '.'.join(map(str, srevno_tuple))
178
            start_rev_tuple = (start_revid, start_revno, 0)
0.40.88 by Parth Malwankar
updated to avoid relocking.
179
            given_revs = [start_rev_tuple]
180
181
        for revid, revno, merge_depth in given_revs:
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
182
            if opts.levels == 1 and merge_depth != 0:
0.40.88 by Parth Malwankar
updated to avoid relocking.
183
                # with level=1 show only top level
184
                continue
185
186
            rev = RevisionSpec_revid.from_string("revid:"+revid)
0.40.89 by Parth Malwankar
moved tree get call outside loop
187
            tree = rev.as_tree(wt.branch)
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
188
            for path in opts.path_list:
0.41.11 by Parth Malwankar
moved top level grep code to versioned_grep.
189
                path_for_id = osutils.pathjoin(relpath, path)
190
                id = tree.path2id(path_for_id)
191
                if not id:
0.41.22 by Parth Malwankar
added basic --exclude/include tests
192
                    trace.warning("Skipped unknown file '%s'." % path)
0.41.11 by Parth Malwankar
moved top level grep code to versioned_grep.
193
                    continue
194
195
                if osutils.isdir(path):
196
                    path_prefix = path
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
197
                    res_cache = dir_grep(tree, path, relpath, opts,
198
                        revno, path_prefix, res_cache)
0.41.11 by Parth Malwankar
moved top level grep code to versioned_grep.
199
                else:
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
200
                    versioned_file_grep(tree, id, '.', path, opts, revno)
0.40.88 by Parth Malwankar
updated to avoid relocking.
201
    finally:
202
        wt.unlock()
0.41.11 by Parth Malwankar
moved top level grep code to versioned_grep.
203
0.40.117 by Parth Malwankar
cosmetic fix. added two lines between top level functions.
204
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
205
def workingtree_grep(opts):
206
    revno = opts.print_revno = None # for working tree set revno to None
0.40.69 by Parth Malwankar
reduced lock/unlock
207
208
    tree, branch, relpath = \
209
        bzrdir.BzrDir.open_containing_tree_or_branch('.')
210
    tree.lock_read()
211
    try:
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
212
        for path in opts.path_list:
0.40.69 by Parth Malwankar
reduced lock/unlock
213
            if osutils.isdir(path):
214
                path_prefix = path
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
215
                dir_grep(tree, path, relpath, opts, revno, path_prefix)
0.40.69 by Parth Malwankar
reduced lock/unlock
216
            else:
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
217
                _file_grep(open(path).read(), '.', path, opts, revno)
0.40.69 by Parth Malwankar
reduced lock/unlock
218
    finally:
219
        tree.unlock()
0.41.11 by Parth Malwankar
moved top level grep code to versioned_grep.
220
0.40.117 by Parth Malwankar
cosmetic fix. added two lines between top level functions.
221
0.40.74 by Parth Malwankar
optimization. --include/exclude are checked before reading the file.
222
def _skip_file(include, exclude, path):
223
    if include and not _path_in_glob_list(path, include):
224
        return True
225
    if exclude and _path_in_glob_list(path, exclude):
226
        return True
227
    return False
228
229
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
230
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.
231
    _revno_pattern = re.compile("\~[0-9.]+:")
0.40.115 by Parth Malwankar
added test for versioned grep.
232
    _revno_pattern_list_only = re.compile("\~[0-9.]+")
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
233
    dir_res = {}
234
0.40.60 by Parth Malwankar
'binary file skipped' warning is only shown with --verbose flag
235
    # setup relpath to open files relative to cwd
236
    rpath = relpath
237
    if relpath:
238
        rpath = osutils.pathjoin('..',relpath)
239
240
    from_dir = osutils.pathjoin(relpath, path)
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
241
    if opts.from_root:
0.40.60 by Parth Malwankar
'binary file skipped' warning is only shown with --verbose flag
242
        # start searching recursively from root
243
        from_dir=None
244
        recursive=True
245
0.40.85 by Parth Malwankar
optimized versioned grep to use iter_files_bytes.
246
    to_grep = []
0.40.92 by Parth Malwankar
performance tweaks to core cached result print loop.
247
    to_grep_append = to_grep.append
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
248
    outf_write = opts.outf.write
0.40.69 by Parth Malwankar
reduced lock/unlock
249
    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
250
        from_dir=from_dir, recursive=opts.recursive):
0.40.69 by Parth Malwankar
reduced lock/unlock
251
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
252
        if _skip_file(opts.include, opts.exclude, fp):
0.40.74 by Parth Malwankar
optimization. --include/exclude are checked before reading the file.
253
            continue
254
0.40.69 by Parth Malwankar
reduced lock/unlock
255
        if fc == 'V' and fkind == 'file':
256
            if revno != None:
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
257
                # If old result is valid, print results immediately.
258
                # Otherwise, add file info to to_grep so that the
259
                # loop later will get chunks and grep them
0.40.97 by Parth Malwankar
fixed caching bug for rev range.
260
                file_rev = tree.inventory[fid].revision
261
                old_res = res_cache.get(file_rev)
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
262
                if old_res != None:
263
                    res = []
0.40.92 by Parth Malwankar
performance tweaks to core cached result print loop.
264
                    res_append = res.append
0.40.115 by Parth Malwankar
added test for versioned grep.
265
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
266
                    if opts.files_with_matches or opts.files_without_match:
0.40.122 by Parth Malwankar
added test for versioned -L and some fixes.
267
                        new_rev = '~' + revno
268
                    else:
0.40.115 by Parth Malwankar
added test for versioned grep.
269
                        new_rev = ('~%s:' % (revno,))
270
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
271
                    for line in old_res:
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
                            s = _revno_pattern_list_only.sub(new_rev, line)
274
                        else:
0.40.115 by Parth Malwankar
added test for versioned grep.
275
                            s = _revno_pattern.sub(new_rev, line)
0.40.92 by Parth Malwankar
performance tweaks to core cached result print loop.
276
                        res_append(s)
277
                        outf_write(s)
0.40.97 by Parth Malwankar
fixed caching bug for rev range.
278
                    dir_res[file_rev] = res
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
279
                else:
0.40.92 by Parth Malwankar
performance tweaks to core cached result print loop.
280
                    to_grep_append((fid, (fp, fid)))
0.40.69 by Parth Malwankar
reduced lock/unlock
281
            else:
282
                # we are grepping working tree.
283
                if from_dir == None:
284
                    from_dir = '.'
285
286
                path_for_file = osutils.pathjoin(tree.basedir, from_dir, fp)
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
287
                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.
288
                    # Optimize for wtree list-only as we don't need to read the
289
                    # entire file
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
290
                    file = codecs.open(path_for_file, 'r', buffering=4096)
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
291
                    _file_grep_list_only_wtree(file, rpath, fp, opts,
292
                        path_prefix)
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
293
                else:
294
                    file_text = codecs.open(path_for_file, 'r').read()
295
                    _file_grep(file_text, rpath, fp,
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
296
                        opts, revno, path_prefix)
0.40.43 by Parth Malwankar
moved cmd_grep._grep_dir to grep.dir_grep
297
0.40.85 by Parth Malwankar
optimized versioned grep to use iter_files_bytes.
298
    if revno != None: # grep versioned files
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
299
        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.
300
            path = _make_display_path(relpath, path)
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
301
            res = _file_grep(chunks[0], rpath, path, opts, revno, path_prefix)
0.40.97 by Parth Malwankar
fixed caching bug for rev range.
302
            file_rev = tree.inventory[fid].revision
303
            dir_res[file_rev] = res
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
304
    return dir_res
0.40.43 by Parth Malwankar
moved cmd_grep._grep_dir to grep.dir_grep
305
0.40.117 by Parth Malwankar
cosmetic fix. added two lines between top level functions.
306
0.41.8 by Parth Malwankar
code cleanup.
307
def _make_display_path(relpath, path):
308
    """Return path string relative to user cwd.
0.40.42 by Parth Malwankar
fix to make grep paths relative to cwd
309
0.41.8 by Parth Malwankar
code cleanup.
310
    Take tree's 'relpath' and user supplied 'path', and return path
311
    that can be displayed to the user.
312
    """
0.40.15 by Parth Malwankar
some fixes and test updates
313
    if relpath:
0.40.52 by Parth Malwankar
code cleanup and documentation
314
        # update path so to display it w.r.t cwd
315
        # handle windows slash separator
0.40.20 by Parth Malwankar
used path functions from bzrlib.osutils
316
        path = osutils.normpath(osutils.pathjoin(relpath, path))
0.40.22 by Parth Malwankar
fixed display path formatting on windows
317
        path = path.replace('\\', '/')
318
        path = path.replace(relpath + '/', '', 1)
0.41.8 by Parth Malwankar
code cleanup.
319
    return path
320
321
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
322
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
323
    """Create a file object for the specified id and pass it on to _file_grep.
324
    """
325
326
    path = _make_display_path(relpath, path)
0.41.12 by Parth Malwankar
initial support for working tree grep (no test cases yet!)
327
    file_text = tree.get_file_text(id)
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
328
    _file_grep(file_text, relpath, path, opts, revno, path_prefix)
0.41.21 by Parth Malwankar
include/exclude working now. tests not added.
329
0.40.117 by Parth Malwankar
cosmetic fix. added two lines between top level functions.
330
0.41.21 by Parth Malwankar
include/exclude working now. tests not added.
331
def _path_in_glob_list(path, glob_list):
332
    present = False
333
    for glob in glob_list:
334
        if fnmatch(path, glob):
335
            present = True
336
            break
337
    return present
0.41.12 by Parth Malwankar
initial support for working tree grep (no test cases yet!)
338
0.40.117 by Parth Malwankar
cosmetic fix. added two lines between top level functions.
339
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
340
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.
341
    # test and skip binary files
342
    if '\x00' in file.read(1024):
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
343
        if opts.verbose:
0.40.116 by Parth Malwankar
optimization for wtree list-only grep to avoid full file read.
344
            trace.warning("Binary file '%s' skipped." % path)
0.40.118 by Parth Malwankar
further optimization of _file_grep_list_only_wtree.
345
            return
346
347
    file.seek(0) # search from beginning
348
349
    found = False
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
350
    if opts.fixed_string:
351
        pattern = opts.pattern.encode(_user_encoding, 'replace')
352
        if opts.fixed_string and opts.ignore_case:
353
            pattern = opts.pattern.lower()
354
        if opts.ignore_case:
0.40.118 by Parth Malwankar
further optimization of _file_grep_list_only_wtree.
355
            for line in file:
0.40.116 by Parth Malwankar
optimization for wtree list-only grep to avoid full file read.
356
                line = line.lower()
0.40.118 by Parth Malwankar
further optimization of _file_grep_list_only_wtree.
357
                if pattern in line:
358
                    found = True
359
                    break
360
        else: # don't ignore case
361
            for line in file:
362
                if pattern in line:
363
                    found = True
364
                    break
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
365
    else: # not fixed_string
0.40.116 by Parth Malwankar
optimization for wtree list-only grep to avoid full file read.
366
        for line in file:
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
367
            if opts.patternc.search(line):
0.40.118 by Parth Malwankar
further optimization of _file_grep_list_only_wtree.
368
                found = True
0.40.116 by Parth Malwankar
optimization for wtree list-only grep to avoid full file read.
369
                break
370
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
371
    if (opts.files_with_matches and found) or \
372
        (opts.files_without_match and not found):
0.40.118 by Parth Malwankar
further optimization of _file_grep_list_only_wtree.
373
        if path_prefix and path_prefix != '.':
374
            # user has passed a dir arg, show that as result prefix
375
            path = osutils.pathjoin(path_prefix, path)
376
        path = path.encode(_terminal_encoding, 'replace')
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
377
        s = path + opts.eol_marker
378
        opts.outf.write(s)
379
380
381
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.
382
    res = []
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
383
    res_append = res.append
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
384
    outf_write = opts.outf.write
0.40.83 by Parth Malwankar
added support for -F/--fixed-string.
385
0.40.91 by Parth Malwankar
made _terminal_encoding and _user_encoding local for performance.
386
    _te = _terminal_encoding
387
    _ue = _user_encoding
388
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
389
    pattern = opts.pattern.encode(_ue, 'replace')
390
    patternc = opts.patternc
391
    eol_marker = opts.eol_marker
392
393
    if opts.fixed_string and opts.ignore_case:
394
        pattern = opts.pattern.lower()
0.40.83 by Parth Malwankar
added support for -F/--fixed-string.
395
0.41.9 by Parth Malwankar
refactored code towards support for working tree grep.
396
    # test and skip binary files
0.40.62 by Parth Malwankar
performance optimization
397
    if '\x00' in file_text[:1024]:
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
398
        if opts.verbose:
0.40.60 by Parth Malwankar
'binary file skipped' warning is only shown with --verbose flag
399
            trace.warning("Binary file '%s' skipped." % path)
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
400
        return res
0.41.9 by Parth Malwankar
refactored code towards support for working tree grep.
401
0.40.52 by Parth Malwankar
code cleanup and documentation
402
    if path_prefix and path_prefix != '.':
403
        # user has passed a dir arg, show that as result prefix
404
        path = osutils.pathjoin(path_prefix, path)
405
0.40.91 by Parth Malwankar
made _terminal_encoding and _user_encoding local for performance.
406
    path = path.encode(_te, 'replace')
0.40.9 by Parth Malwankar
factored out grep related code to grep.py
407
0.40.64 by Parth Malwankar
cosmetic: improved comment
408
    # for better performance we moved formatting conditionals out
409
    # of the core loop. hence, the core loop is somewhat duplicated
410
    # for various combinations of formatting options.
411
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
412
    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.
413
        # While printing files with matches we only have two case
414
        # print file name or print file name with revno.
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
415
        found = False
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
416
        if opts.print_revno:
417
            if opts.fixed_string:
0.40.112 by Parth Malwankar
support for -l, --files-with-matches. no tests yet.
418
                for line in file_text.splitlines():
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
419
                    if opts.ignore_case:
0.40.112 by Parth Malwankar
support for -l, --files-with-matches. no tests yet.
420
                        line = line.lower()
421
                    if pattern in line:
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
422
                        found = True
0.40.112 by Parth Malwankar
support for -l, --files-with-matches. no tests yet.
423
                        break
424
            else:
425
                for line in file_text.splitlines():
426
                    if patternc.search(line):
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
427
                        found = True
0.40.112 by Parth Malwankar
support for -l, --files-with-matches. no tests yet.
428
                        break
429
        else:
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
430
            if opts.fixed_string:
0.40.112 by Parth Malwankar
support for -l, --files-with-matches. no tests yet.
431
                for line in file_text.splitlines():
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
432
                    if opts.ignore_case:
0.40.112 by Parth Malwankar
support for -l, --files-with-matches. no tests yet.
433
                        line = line.lower()
434
                    if pattern in line:
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
435
                        found = True
0.40.112 by Parth Malwankar
support for -l, --files-with-matches. no tests yet.
436
                        break
437
            else:
438
                for line in file_text.splitlines():
439
                    if patternc.search(line):
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
440
                        found = True
0.40.112 by Parth Malwankar
support for -l, --files-with-matches. no tests yet.
441
                        break
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
442
        if (opts.files_with_matches and found) or \
443
                (opts.files_without_match and not found):
444
            if opts.print_revno:
0.40.122 by Parth Malwankar
added test for versioned -L and some fixes.
445
                pfmt = "~%s".encode(_te, 'replace')
446
                s = path + (pfmt % (revno,)) + eol_marker
447
            else:
448
                s = path + eol_marker
0.40.121 by Parth Malwankar
initial implementation of -L/--files-without-matches. no tests.
449
            res_append(s)
450
            outf_write(s)
0.40.122 by Parth Malwankar
added test for versioned -L and some fixes.
451
        return res # return from files_with|without_matches
0.40.112 by Parth Malwankar
support for -l, --files-with-matches. no tests yet.
452
453
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
454
    if opts.print_revno and opts.line_number:
0.40.63 by Parth Malwankar
performance: moved conditionals out of core loop.
455
0.40.91 by Parth Malwankar
made _terminal_encoding and _user_encoding local for performance.
456
        pfmt = "~%s:%d:%s".encode(_te)
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
457
        if opts.fixed_string:
458
            if opts.ignore_case:
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
459
                for index, line in enumerate(file_text.splitlines()):
460
                    if pattern in line.lower():
461
                        line = line.decode(_te, 'replace')
462
                        s = path + (pfmt % (revno, index+1, line)) + eol_marker
463
                        res_append(s)
464
                        outf_write(s)
465
            else: # don't ignore case
466
                for index, line in enumerate(file_text.splitlines()):
467
                    if pattern in line:
468
                        line = line.decode(_te, 'replace')
469
                        s = path + (pfmt % (revno, index+1, line)) + eol_marker
470
                        res_append(s)
471
                        outf_write(s)
0.40.83 by Parth Malwankar
added support for -F/--fixed-string.
472
        else:
473
            for index, line in enumerate(file_text.splitlines()):
474
                if patternc.search(line):
0.40.91 by Parth Malwankar
made _terminal_encoding and _user_encoding local for performance.
475
                    line = line.decode(_te, 'replace')
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
476
                    s = path + (pfmt % (revno, index+1, line)) + eol_marker
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
477
                    res_append(s)
478
                    outf_write(s)
0.40.63 by Parth Malwankar
performance: moved conditionals out of core loop.
479
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
480
    elif opts.print_revno and not opts.line_number:
0.40.63 by Parth Malwankar
performance: moved conditionals out of core loop.
481
0.40.91 by Parth Malwankar
made _terminal_encoding and _user_encoding local for performance.
482
        pfmt = "~%s:%s".encode(_te, 'replace')
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
483
        if opts.fixed_string:
484
            if opts.ignore_case:
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
485
                for line in file_text.splitlines():
486
                    if pattern in line.lower():
487
                        line = line.decode(_te, 'replace')
488
                        s = path + (pfmt % (revno, line)) + eol_marker
489
                        res_append(s)
490
                        outf_write(s)
491
            else: # don't ignore case
492
                for line in file_text.splitlines():
493
                    if pattern in line:
494
                        line = line.decode(_te, 'replace')
495
                        s = path + (pfmt % (revno, line)) + eol_marker
496
                        res_append(s)
497
                        outf_write(s)
498
0.40.83 by Parth Malwankar
added support for -F/--fixed-string.
499
        else:
500
            for line in file_text.splitlines():
501
                if patternc.search(line):
0.40.91 by Parth Malwankar
made _terminal_encoding and _user_encoding local for performance.
502
                    line = line.decode(_te, 'replace')
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
503
                    s = path + (pfmt % (revno, line)) + eol_marker
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
504
                    res_append(s)
505
                    outf_write(s)
0.40.63 by Parth Malwankar
performance: moved conditionals out of core loop.
506
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
507
    elif not opts.print_revno and opts.line_number:
0.40.63 by Parth Malwankar
performance: moved conditionals out of core loop.
508
0.40.91 by Parth Malwankar
made _terminal_encoding and _user_encoding local for performance.
509
        pfmt = ":%d:%s".encode(_te)
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
510
        if opts.fixed_string:
511
            if opts.ignore_case:
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
512
                for index, line in enumerate(file_text.splitlines()):
513
                    if pattern in line.lower():
514
                        line = line.decode(_te, 'replace')
515
                        s = path + (pfmt % (index+1, line)) + eol_marker
516
                        res_append(s)
517
                        outf_write(s)
518
            else: # don't ignore case
519
                for index, line in enumerate(file_text.splitlines()):
520
                    if pattern in line:
521
                        line = line.decode(_te, 'replace')
522
                        s = path + (pfmt % (index+1, line)) + eol_marker
523
                        res_append(s)
524
                        outf_write(s)
0.40.83 by Parth Malwankar
added support for -F/--fixed-string.
525
        else:
526
            for index, line in enumerate(file_text.splitlines()):
527
                if patternc.search(line):
0.40.91 by Parth Malwankar
made _terminal_encoding and _user_encoding local for performance.
528
                    line = line.decode(_te, 'replace')
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
529
                    s = path + (pfmt % (index+1, line)) + eol_marker
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
530
                    res_append(s)
531
                    outf_write(s)
0.40.63 by Parth Malwankar
performance: moved conditionals out of core loop.
532
533
    else:
0.40.64 by Parth Malwankar
cosmetic: improved comment
534
0.40.91 by Parth Malwankar
made _terminal_encoding and _user_encoding local for performance.
535
        pfmt = ":%s".encode(_te)
0.43.1 by Parth Malwankar
added GrepOptions object for easy parameter passing
536
        if opts.fixed_string:
537
            if opts.ignore_case:
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
538
                for line in file_text.splitlines():
539
                    if pattern in line.lower():
540
                        line = line.decode(_te, 'replace')
541
                        s = path + (pfmt % (line,)) + eol_marker
542
                        res_append(s)
543
                        outf_write(s)
544
            else: # don't ignore case
0.43.4 by Parth Malwankar
initial support for color for fixed string grep.
545
                found_str = color_string(pattern, FG.RED)
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
546
                for line in file_text.splitlines():
547
                    if pattern in line:
548
                        line = line.decode(_te, 'replace')
0.43.4 by Parth Malwankar
initial support for color for fixed string grep.
549
                        if opts.show_color == True:
550
                            line = line.replace(pattern, found_str)
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
551
                        s = path + (pfmt % (line,)) + eol_marker
552
                        res_append(s)
553
                        outf_write(s)
0.40.83 by Parth Malwankar
added support for -F/--fixed-string.
554
        else:
555
            for line in file_text.splitlines():
556
                if patternc.search(line):
0.40.91 by Parth Malwankar
made _terminal_encoding and _user_encoding local for performance.
557
                    line = line.decode(_te, 'replace')
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
558
                    s = path + (pfmt % (line,)) + eol_marker
0.40.119 by Parth Malwankar
optimization: ignore case is not checked for every line.
559
                    res_append(s)
560
                    outf_write(s)
0.40.90 by Parth Malwankar
significant speedup for revision range grep by caching old result.
561
562
    return res
0.40.9 by Parth Malwankar
factored out grep related code to grep.py
563