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