Merge lp:~jelmer/bzr/merge-grep into lp:bzr

Proposed by Jelmer Vernooij
Status: Merged
Approved by: Jelmer Vernooij
Approved revision: no longer in the source branch.
Merged at revision: 6555
Proposed branch: lp:~jelmer/bzr/merge-grep
Merge into: lp:bzr
Diff against target: 3488 lines (+3435/-0)
9 files modified
bzrlib/_termcolor.py (+78/-0)
bzrlib/plugins/grep/.bzrignore (+1/-0)
bzrlib/plugins/grep/NEWS (+73/-0)
bzrlib/plugins/grep/__init__.py (+38/-0)
bzrlib/plugins/grep/cmds.py (+249/-0)
bzrlib/plugins/grep/grep.py (+728/-0)
bzrlib/plugins/grep/test_grep.py (+2254/-0)
bzrlib/tests/features.py (+12/-0)
doc/en/release-notes/bzr-2.6.txt (+2/-0)
To merge this branch: bzr merge lp:~jelmer/bzr/merge-grep
Reviewer Review Type Date Requested Status
Martin Packman (community) Approve
Review via email: mp+118067@code.launchpad.net

Commit message

Merge the grep plugin into the core.

Description of the change

Merge the grep plugin into core.

Now updated for tests to pass, and with the ColorFeature moved into bzrlib.tests.features.

To post a comment you must log in.
Revision history for this message
Martin Packman (gz) wrote :

Tests now pass.

Idle query, why don't we use bzr join for things like this?

Don't like moving the colour stuff to bzrlib.termcolor, it's not the interface I think we'll want to be supporting in core long term. Can stick it back under grep or rename to _termcolor so it's clear we don't want other plugins basing output off this interface.

Looks good apart from that.

review: Approve
Revision history for this message
Jelmer Vernooij (jelmer) wrote :

This was merged using bzr join.

I've renamed termcolor to _termcolor.

Thanks for the review!

Revision history for this message
Martin Packman (gz) wrote :

> This was merged using bzr join.

Well I obviously fail at using blame then...

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added file 'bzrlib/_termcolor.py'
--- bzrlib/_termcolor.py 1970-01-01 00:00:00 +0000
+++ bzrlib/_termcolor.py 2012-08-23 15:07:23 +0000
@@ -0,0 +1,78 @@
1# Copyright (C) 2010 Canonical Ltd
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
17from __future__ import absolute_import
18
19import os
20import sys
21
22
23class FG(object):
24 """Unix terminal foreground color codes (16-color)."""
25 RED = '\033[31m'
26 GREEN = '\033[32m'
27 YELLOW = '\033[33m'
28 BLUE = '\033[34m'
29 MAGENTA = '\033[35m'
30 CYAN = '\033[36m'
31 WHITE = '\033[37m'
32
33 # Bold Foreground
34 BOLD_RED = '\033[1;31m'
35 BOLD_GREEN = '\033[1;32m'
36 BOLD_YELLOW = '\033[1;33m'
37 BOLD_BLUE = '\033[1;34m'
38 BOLD_MAGENTA = '\033[1;35m'
39 BOLD_CYAN = '\033[1;36m'
40 BOLD_WHITE = '\033[1;37m'
41
42 NONE = '\033[0m'
43
44
45class BG(object):
46 """Unix terminal background color codes (16-color)."""
47 BLACK = '\033[40m'
48 RED = '\033[41m'
49 GREEN = '\033[42m'
50 YELLOW = '\033[43m'
51 BLUE = '\033[44m'
52 MAGENTA = '\033[45m'
53 CYAN = '\033[46m'
54 WHITE = '\033[47m'
55
56 NONE = '\033[0m'
57
58
59def color_string(s, fg, bg=''):
60 return fg + bg + s + FG.NONE
61
62
63def re_color_string(compiled_pattern, s, fg):
64 return compiled_pattern.sub(fg + r'\1' + FG.NONE, s)
65
66
67def allow_color():
68 if os.name != 'posix':
69 return False
70 if not sys.stdout.isatty():
71 return False
72 try:
73 import curses
74 curses.setupterm()
75 return curses.tigetnum('colors') > 2
76 except curses.error:
77 return False
78
079
=== added directory 'bzrlib/plugins/grep'
=== added file 'bzrlib/plugins/grep/.bzrignore'
--- bzrlib/plugins/grep/.bzrignore 1970-01-01 00:00:00 +0000
+++ bzrlib/plugins/grep/.bzrignore 2012-08-23 15:07:23 +0000
@@ -0,0 +1,1 @@
1./build
02
=== added file 'bzrlib/plugins/grep/NEWS'
--- bzrlib/plugins/grep/NEWS 1970-01-01 00:00:00 +0000
+++ bzrlib/plugins/grep/NEWS 2012-08-23 15:07:23 +0000
@@ -0,0 +1,73 @@
1This is the NEWS file from bzr-grep from before it was merged into bzr core.
2For changes before then, please refer to the main bzr log file.
3
4bzr-grep 0.5.0-final - Unreleased
5==================================
6* ``bzr grep`` now supports ``--diff|-p`` option to search through
7 changesets. (Parth Malwankar, #540705)
8
9* Option ``grep_color`` can be set in ``bazaar.conf`` instead of using
10 the option ``--color`` from the command line. (Johan Dahlin)
11
12bzr-grep 0.4.0-final - 08-Jun-2010
13==================================
14* Add seperate output formatter to reduce duplication of search loops,
15 additionally make -Fi use regexp rather than lowercasing pattern and
16 entirety of text for the same reason. This also fixes bug #590589
17 - UnicodeDecodeError with options -Fi. (Martin [gz])
18
19* Added fast path for no match that avoids splitting the file text into
20 seperate lines and testing each one, by checking the entire text for a
21 possible match initially. (Martin [gz])
22
23* Added Makefile. (Parth Malwankar)
24
25* Fixed setup.py to work correctly. (Martin [gz])
26
27bzr-grep 0.3.0-final - 23-May-2010
28==================================
29* Support for --color option (POSIX only). (Parth Malwankar, #571694)
30
31* Revisions in branches without trees can now be searched with
32 -r option. (Parth Malwankar, #584240)
33
34* Trying to search working tree for a treeless branch no longer
35 produces a stack trace but gives an error message suggesting use of
36 -r option. (Parth Malwankar, #572658)
37
38bzr-grep 0.2.0-final - 30-Mar-2010
39==================================
40* 'binary file skipped' warning is not shows without --verbose flag
41 (Parth Malwankar, #539031)
42
43* Added support for -F/--fixed-string for faster search.
44 Simple patterns [a-zA-Z0-9 _] are now implicitly -F and searched faster.
45 (Parth Malwankar, #539263)
46
47* Better unicode handling. bzr-grep no longer crashes with UnicodeDecode
48 error for some outputs. (Parth Malwankar, #539258)
49
50* Faster grep for revision range. bzr-grep now caches results for
51 files that have not changed between revisions.
52 (Parth Malwankar, #542375)
53
54* Faster grep for specific revision. (Parth Malwankar, #539429)
55
56* Significant performance improvement. Working tree grep for bzr.dev
57 has gone from ~7.5s to ~1s. (Parth Malwankar, #539028)
58
59* Support for -L/--files-without-match and -l/files-with-matches
60 (Parth Malwankar, #540097)
61
62bzr-grep 0.1.0-final - 14-Mar-2010
63==================================
64* --recursive is now default. (Parth Malwankar, #536688)
65
66* ``bzr grep`` searches working copy by default. (Parth Malwankar, #537072)
67
68* --include/exclude=GLOB is now supported. (Parth Malwankar, #529889)
69
70bzr-grep 0.0.1-final - 10-Mar-2010
71==================================
72* Initial release (Parth Malwankar)
73
074
=== added file 'bzrlib/plugins/grep/__init__.py'
--- bzrlib/plugins/grep/__init__.py 1970-01-01 00:00:00 +0000
+++ bzrlib/plugins/grep/__init__.py 2012-08-23 15:07:23 +0000
@@ -0,0 +1,38 @@
1# Copyright (C) 2010 Canonical Ltd
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"""Print lines matching PATTERN for specified files and revisions."""
18
19from __future__ import absolute_import
20
21from bzrlib import version_info
22from bzrlib.commands import plugin_cmds
23
24plugin_cmds.register_lazy("cmd_grep", [], "bzrlib.plugins.grep.cmds")
25
26def test_suite():
27 from bzrlib.tests import TestUtil
28
29 suite = TestUtil.TestSuite()
30 loader = TestUtil.TestLoader()
31 testmod_names = [
32 'test_grep',
33 ]
34
35 suite.addTest(loader.loadTestsFromModuleNames(
36 ["%s.%s" % (__name__, tmn) for tmn in testmod_names]))
37 return suite
38
039
=== added file 'bzrlib/plugins/grep/cmds.py'
--- bzrlib/plugins/grep/cmds.py 1970-01-01 00:00:00 +0000
+++ bzrlib/plugins/grep/cmds.py 2012-08-23 15:07:23 +0000
@@ -0,0 +1,249 @@
1# Copyright (C) 2010 Canonical Ltd
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"""Print lines matching PATTERN for specified files and revisions."""
18
19from __future__ import absolute_import
20
21from bzrlib import errors
22from bzrlib.commands import Command, display_command
23from bzrlib.option import Option, ListOption
24from bzrlib.config import GlobalConfig
25
26# FIXME: _parse_levels should be shared with bzrlib.builtins. this is a copy
27# to avoid the error
28# "IllegalUseOfScopeReplacer: ScopeReplacer object '_parse_levels' was used
29# incorrectly: Object already cleaned up, did you assign it to another
30# variable?: _factory
31# with lazy import
32def _parse_levels(s):
33 try:
34 return int(s)
35 except ValueError:
36 msg = "The levels argument must be an integer."
37 raise errors.BzrCommandError(msg)
38
39
40class GrepOptions(object):
41 """Container to pass around grep options.
42
43 This class is used as a container to pass around user option and
44 some other params (like outf) to processing functions. This makes
45 it easier to add more options as grep evolves.
46 """
47 verbose = False
48 ignore_case = False
49 no_recursive = False
50 from_root = False
51 null = False
52 levels = None
53 line_number = False
54 path_list = None
55 revision = None
56 pattern = None
57 include = None
58 exclude = None
59 fixed_string = False
60 files_with_matches = False
61 files_without_match = False
62 color = None
63 diff = False
64
65 # derived options
66 recursive = None
67 eol_marker = None
68 patternc = None
69 sub_patternc = None
70 print_revno = None
71 fixed_string = None
72 outf = None
73 show_color = False
74
75
76class cmd_grep(Command):
77 """Print lines matching PATTERN for specified files and revisions.
78
79 This command searches the specified files and revisions for a given
80 pattern. The pattern is specified as a Python regular expressions[1].
81
82 If the file name is not specified, the revisions starting with the
83 current directory are searched recursively. If the revision number is
84 not specified, the working copy is searched. To search the last committed
85 revision, use the '-r -1' or '-r last:1' option.
86
87 Unversioned files are not searched unless explicitly specified on the
88 command line. Unversioned directores are not searched.
89
90 When searching a pattern, the output is shown in the 'filepath:string'
91 format. If a revision is explicitly searched, the output is shown as
92 'filepath~N:string', where N is the revision number.
93
94 --include and --exclude options can be used to search only (or exclude
95 from search) files with base name matches the specified Unix style GLOB
96 pattern. The GLOB pattern an use *, ?, and [...] as wildcards, and \\
97 to quote wildcard or backslash character literally. Note that the glob
98 pattern is not a regular expression.
99
100 [1] http://docs.python.org/library/re.html#regular-expression-syntax
101 """
102
103 encoding_type = 'replace'
104 takes_args = ['pattern', 'path*']
105 takes_options = [
106 'verbose',
107 'revision',
108 Option('color', type=str, argname='when',
109 help='Show match in color. WHEN is never, always or auto.'),
110 Option('diff', short_name='p',
111 help='Grep for pattern in changeset for each revision.'),
112 ListOption('exclude', type=str, argname='glob', short_name='X',
113 help="Skip files whose base name matches GLOB."),
114 ListOption('include', type=str, argname='glob', short_name='I',
115 help="Search only files whose base name matches GLOB."),
116 Option('files-with-matches', short_name='l',
117 help='Print only the name of each input file in '
118 'which PATTERN is found.'),
119 Option('files-without-match', short_name='L',
120 help='Print only the name of each input file in '
121 'which PATTERN is not found.'),
122 Option('fixed-string', short_name='F',
123 help='Interpret PATTERN is a single fixed string (not regex).'),
124 Option('from-root',
125 help='Search for pattern starting from the root of the branch. '
126 '(implies --recursive)'),
127 Option('ignore-case', short_name='i',
128 help='ignore case distinctions while matching.'),
129 Option('levels',
130 help='Number of levels to display - 0 for all, 1 for collapsed '
131 '(1 is default).',
132 argname='N',
133 type=_parse_levels),
134 Option('line-number', short_name='n',
135 help='show 1-based line number.'),
136 Option('no-recursive',
137 help="Don't recurse into subdirectories. (default is --recursive)"),
138 Option('null', short_name='Z',
139 help='Write an ASCII NUL (\\0) separator '
140 'between output lines rather than a newline.'),
141 ]
142
143
144 @display_command
145 def run(self, verbose=False, ignore_case=False, no_recursive=False,
146 from_root=False, null=False, levels=None, line_number=False,
147 path_list=None, revision=None, pattern=None, include=None,
148 exclude=None, fixed_string=False, files_with_matches=False,
149 files_without_match=False, color=None, diff=False):
150 from bzrlib import _termcolor
151 from bzrlib.plugins.grep import (
152 grep,
153 )
154 import re
155 if path_list is None:
156 path_list = ['.']
157 else:
158 if from_root:
159 raise errors.BzrCommandError('cannot specify both --from-root and PATH.')
160
161 if files_with_matches and files_without_match:
162 raise errors.BzrCommandError('cannot specify both '
163 '-l/--files-with-matches and -L/--files-without-matches.')
164
165 global_config = GlobalConfig()
166
167 if color is None:
168 color = global_config.get_user_option('grep_color')
169
170 if color is None:
171 color = 'never'
172
173 if color not in ['always', 'never', 'auto']:
174 raise errors.BzrCommandError('Valid values for --color are '
175 '"always", "never" or "auto".')
176
177 if levels==None:
178 levels=1
179
180 print_revno = False
181 if revision != None or levels == 0:
182 # print revision numbers as we may be showing multiple revisions
183 print_revno = True
184
185 eol_marker = '\n'
186 if null:
187 eol_marker = '\0'
188
189 if not ignore_case and grep.is_fixed_string(pattern):
190 # if the pattern isalnum, implicitly use to -F for faster grep
191 fixed_string = True
192 elif ignore_case and fixed_string:
193 # GZ 2010-06-02: Fall back to regexp rather than lowercasing
194 # pattern and text which will cause pain later
195 fixed_string = False
196 pattern = re.escape(pattern)
197
198 patternc = None
199 re_flags = re.MULTILINE
200 if ignore_case:
201 re_flags |= re.IGNORECASE
202
203 if not fixed_string:
204 patternc = grep.compile_pattern(pattern, re_flags)
205
206 if color == 'always':
207 show_color = True
208 elif color == 'never':
209 show_color = False
210 elif color == 'auto':
211 show_color = _termcolor.allow_color()
212
213 GrepOptions.verbose = verbose
214 GrepOptions.ignore_case = ignore_case
215 GrepOptions.no_recursive = no_recursive
216 GrepOptions.from_root = from_root
217 GrepOptions.null = null
218 GrepOptions.levels = levels
219 GrepOptions.line_number = line_number
220 GrepOptions.path_list = path_list
221 GrepOptions.revision = revision
222 GrepOptions.pattern = pattern
223 GrepOptions.include = include
224 GrepOptions.exclude = exclude
225 GrepOptions.fixed_string = fixed_string
226 GrepOptions.files_with_matches = files_with_matches
227 GrepOptions.files_without_match = files_without_match
228 GrepOptions.color = color
229 GrepOptions.diff = False
230
231 GrepOptions.eol_marker = eol_marker
232 GrepOptions.print_revno = print_revno
233 GrepOptions.patternc = patternc
234 GrepOptions.recursive = not no_recursive
235 GrepOptions.fixed_string = fixed_string
236 GrepOptions.outf = self.outf
237 GrepOptions.show_color = show_color
238
239 if diff:
240 # options not used:
241 # files_with_matches, files_without_match
242 # levels(?), line_number, from_root
243 # include, exclude
244 # These are silently ignored.
245 grep.grep_diff(GrepOptions)
246 elif revision is None:
247 grep.workingtree_grep(GrepOptions)
248 else:
249 grep.versioned_grep(GrepOptions)
0250
=== added file 'bzrlib/plugins/grep/grep.py'
--- bzrlib/plugins/grep/grep.py 1970-01-01 00:00:00 +0000
+++ bzrlib/plugins/grep/grep.py 2012-08-23 15:07:23 +0000
@@ -0,0 +1,728 @@
1# Copyright (C) 2010 Canonical Ltd
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
17from __future__ import absolute_import
18
19import sys
20
21from bzrlib.lazy_import import lazy_import
22lazy_import(globals(), """
23from fnmatch import fnmatch
24import re
25from cStringIO import StringIO
26
27from bzrlib._termcolor import color_string, re_color_string, FG
28
29from bzrlib.revisionspec import (
30 RevisionSpec,
31 RevisionSpec_revid,
32 RevisionSpec_revno,
33 )
34from bzrlib import (
35 bzrdir,
36 diff,
37 errors,
38 lazy_regex,
39 osutils,
40 revision as _mod_revision,
41 trace,
42 )
43""")
44
45_user_encoding = osutils.get_user_encoding()
46
47
48class _RevisionNotLinear(Exception):
49 """Raised when a revision is not on left-hand history."""
50
51
52def _rev_on_mainline(rev_tuple):
53 """returns True is rev tuple is on mainline"""
54 if len(rev_tuple) == 1:
55 return True
56 return rev_tuple[1] == 0 and rev_tuple[2] == 0
57
58
59# NOTE: _linear_view_revisions is basided on
60# bzrlib.log._linear_view_revisions.
61# This should probably be a common public API
62def _linear_view_revisions(branch, start_rev_id, end_rev_id):
63 # requires that start is older than end
64 repo = branch.repository
65 graph = repo.get_graph()
66 for revision_id in graph.iter_lefthand_ancestry(
67 end_rev_id, (_mod_revision.NULL_REVISION, )):
68 revno = branch.revision_id_to_dotted_revno(revision_id)
69 revno_str = '.'.join(str(n) for n in revno)
70 if revision_id == start_rev_id:
71 yield revision_id, revno_str, 0
72 break
73 yield revision_id, revno_str, 0
74
75
76# NOTE: _graph_view_revisions is copied from
77# bzrlib.log._graph_view_revisions.
78# This should probably be a common public API
79def _graph_view_revisions(branch, start_rev_id, end_rev_id,
80 rebase_initial_depths=True):
81 """Calculate revisions to view including merges, newest to oldest.
82
83 :param branch: the branch
84 :param start_rev_id: the lower revision-id
85 :param end_rev_id: the upper revision-id
86 :param rebase_initial_depth: should depths be rebased until a mainline
87 revision is found?
88 :return: An iterator of (revision_id, dotted_revno, merge_depth) tuples.
89 """
90 # requires that start is older than end
91 view_revisions = branch.iter_merge_sorted_revisions(
92 start_revision_id=end_rev_id, stop_revision_id=start_rev_id,
93 stop_rule="with-merges")
94 if not rebase_initial_depths:
95 for (rev_id, merge_depth, revno, end_of_merge
96 ) in view_revisions:
97 yield rev_id, '.'.join(map(str, revno)), merge_depth
98 else:
99 # We're following a development line starting at a merged revision.
100 # We need to adjust depths down by the initial depth until we find
101 # a depth less than it. Then we use that depth as the adjustment.
102 # If and when we reach the mainline, depth adjustment ends.
103 depth_adjustment = None
104 for (rev_id, merge_depth, revno, end_of_merge
105 ) in view_revisions:
106 if depth_adjustment is None:
107 depth_adjustment = merge_depth
108 if depth_adjustment:
109 if merge_depth < depth_adjustment:
110 # From now on we reduce the depth adjustement, this can be
111 # surprising for users. The alternative requires two passes
112 # which breaks the fast display of the first revision
113 # though.
114 depth_adjustment = merge_depth
115 merge_depth -= depth_adjustment
116 yield rev_id, '.'.join(map(str, revno)), merge_depth
117
118
119def compile_pattern(pattern, flags=0):
120 patternc = None
121 try:
122 # use python's re.compile as we need to catch re.error in case of bad pattern
123 lazy_regex.reset_compile()
124 patternc = re.compile(pattern, flags)
125 except re.error, e:
126 raise errors.BzrError("Invalid pattern: '%s'" % pattern)
127 return patternc
128
129
130def is_fixed_string(s):
131 if re.match("^([A-Za-z0-9_]|\s)*$", s):
132 return True
133 return False
134
135
136class _GrepDiffOutputter(object):
137 """Precalculate formatting based on options given for diff grep.
138 """
139
140 def __init__(self, opts):
141 self.opts = opts
142 self.outf = opts.outf
143 if opts.show_color:
144 pat = opts.pattern.encode(_user_encoding, 'replace')
145 if opts.fixed_string:
146 self._old = pat
147 self._new = color_string(pat, FG.BOLD_RED)
148 self.get_writer = self._get_writer_fixed_highlighted
149 else:
150 flags = opts.patternc.flags
151 self._sub = re.compile(pat.join(("((?:",")+)")), flags).sub
152 self._highlight = color_string("\\1", FG.BOLD_RED)
153 self.get_writer = self._get_writer_regexp_highlighted
154 else:
155 self.get_writer = self._get_writer_plain
156
157 def get_file_header_writer(self):
158 """Get function for writing file headers"""
159 write = self.outf.write
160 eol_marker = self.opts.eol_marker
161 def _line_writer(line):
162 write(line + eol_marker)
163 def _line_writer_color(line):
164 write(FG.BOLD_MAGENTA + line + FG.NONE + eol_marker)
165 if self.opts.show_color:
166 return _line_writer_color
167 else:
168 return _line_writer
169 return _line_writer
170
171 def get_revision_header_writer(self):
172 """Get function for writing revno lines"""
173 write = self.outf.write
174 eol_marker = self.opts.eol_marker
175 def _line_writer(line):
176 write(line + eol_marker)
177 def _line_writer_color(line):
178 write(FG.BOLD_BLUE + line + FG.NONE + eol_marker)
179 if self.opts.show_color:
180 return _line_writer_color
181 else:
182 return _line_writer
183 return _line_writer
184
185 def _get_writer_plain(self):
186 """Get function for writing uncoloured output"""
187 write = self.outf.write
188 eol_marker = self.opts.eol_marker
189 def _line_writer(line):
190 write(line + eol_marker)
191 return _line_writer
192
193 def _get_writer_regexp_highlighted(self):
194 """Get function for writing output with regexp match highlighted"""
195 _line_writer = self._get_writer_plain()
196 sub, highlight = self._sub, self._highlight
197 def _line_writer_regexp_highlighted(line):
198 """Write formatted line with matched pattern highlighted"""
199 return _line_writer(line=sub(highlight, line))
200 return _line_writer_regexp_highlighted
201
202 def _get_writer_fixed_highlighted(self):
203 """Get function for writing output with search string highlighted"""
204 _line_writer = self._get_writer_plain()
205 old, new = self._old, self._new
206 def _line_writer_fixed_highlighted(line):
207 """Write formatted line with string searched for highlighted"""
208 return _line_writer(line=line.replace(old, new))
209 return _line_writer_fixed_highlighted
210
211
212def grep_diff(opts):
213 wt, branch, relpath = \
214 bzrdir.BzrDir.open_containing_tree_or_branch('.')
215 branch.lock_read()
216 try:
217 if opts.revision:
218 start_rev = opts.revision[0]
219 else:
220 # if no revision is sepcified for diff grep we grep all changesets.
221 opts.revision = [RevisionSpec.from_string('revno:1'),
222 RevisionSpec.from_string('last:1')]
223 start_rev = opts.revision[0]
224 start_revid = start_rev.as_revision_id(branch)
225 if start_revid == 'null:':
226 return
227 srevno_tuple = branch.revision_id_to_dotted_revno(start_revid)
228 if len(opts.revision) == 2:
229 end_rev = opts.revision[1]
230 end_revid = end_rev.as_revision_id(branch)
231 if end_revid is None:
232 end_revno, end_revid = branch.last_revision_info()
233 erevno_tuple = branch.revision_id_to_dotted_revno(end_revid)
234
235 grep_mainline = (_rev_on_mainline(srevno_tuple) and
236 _rev_on_mainline(erevno_tuple))
237
238 # ensure that we go in reverse order
239 if srevno_tuple > erevno_tuple:
240 srevno_tuple, erevno_tuple = erevno_tuple, srevno_tuple
241 start_revid, end_revid = end_revid, start_revid
242
243 # Optimization: Traversing the mainline in reverse order is much
244 # faster when we don't want to look at merged revs. We try this
245 # with _linear_view_revisions. If all revs are to be grepped we
246 # use the slower _graph_view_revisions
247 if opts.levels==1 and grep_mainline:
248 given_revs = _linear_view_revisions(branch, start_revid, end_revid)
249 else:
250 given_revs = _graph_view_revisions(branch, start_revid, end_revid)
251 else:
252 # We do an optimization below. For grepping a specific revison
253 # We don't need to call _graph_view_revisions which is slow.
254 # We create the start_rev_tuple for only that specific revision.
255 # _graph_view_revisions is used only for revision range.
256 start_revno = '.'.join(map(str, srevno_tuple))
257 start_rev_tuple = (start_revid, start_revno, 0)
258 given_revs = [start_rev_tuple]
259 repo = branch.repository
260 diff_pattern = re.compile("^[+\-].*(" + opts.pattern + ")")
261 file_pattern = re.compile("=== (modified|added|removed) file '.*'", re.UNICODE)
262 outputter = _GrepDiffOutputter(opts)
263 writeline = outputter.get_writer()
264 writerevno = outputter.get_revision_header_writer()
265 writefileheader = outputter.get_file_header_writer()
266 file_encoding = _user_encoding
267 for revid, revno, merge_depth in given_revs:
268 if opts.levels == 1 and merge_depth != 0:
269 # with level=1 show only top level
270 continue
271
272 rev_spec = RevisionSpec_revid.from_string("revid:"+revid)
273 new_rev = repo.get_revision(revid)
274 new_tree = rev_spec.as_tree(branch)
275 if len(new_rev.parent_ids) == 0:
276 ancestor_id = _mod_revision.NULL_REVISION
277 else:
278 ancestor_id = new_rev.parent_ids[0]
279 old_tree = repo.revision_tree(ancestor_id)
280 s = StringIO()
281 diff.show_diff_trees(old_tree, new_tree, s,
282 old_label='', new_label='')
283 display_revno = True
284 display_file = False
285 file_header = None
286 text = s.getvalue()
287 for line in text.splitlines():
288 if file_pattern.search(line):
289 file_header = line
290 display_file = True
291 elif diff_pattern.search(line):
292 if display_revno:
293 writerevno("=== revno:%s ===" % (revno,))
294 display_revno = False
295 if display_file:
296 writefileheader(" %s" % (file_header,))
297 display_file = False
298 line = line.decode(file_encoding, 'replace')
299 writeline(" %s" % (line,))
300 finally:
301 branch.unlock()
302
303
304def versioned_grep(opts):
305 wt, branch, relpath = \
306 bzrdir.BzrDir.open_containing_tree_or_branch('.')
307 branch.lock_read()
308 try:
309 start_rev = opts.revision[0]
310 start_revid = start_rev.as_revision_id(branch)
311 if start_revid is None:
312 start_rev = RevisionSpec_revno.from_string("revno:1")
313 start_revid = start_rev.as_revision_id(branch)
314 srevno_tuple = branch.revision_id_to_dotted_revno(start_revid)
315
316 if len(opts.revision) == 2:
317 end_rev = opts.revision[1]
318 end_revid = end_rev.as_revision_id(branch)
319 if end_revid is None:
320 end_revno, end_revid = branch.last_revision_info()
321 erevno_tuple = branch.revision_id_to_dotted_revno(end_revid)
322
323 grep_mainline = (_rev_on_mainline(srevno_tuple) and
324 _rev_on_mainline(erevno_tuple))
325
326 # ensure that we go in reverse order
327 if srevno_tuple > erevno_tuple:
328 srevno_tuple, erevno_tuple = erevno_tuple, srevno_tuple
329 start_revid, end_revid = end_revid, start_revid
330
331 # Optimization: Traversing the mainline in reverse order is much
332 # faster when we don't want to look at merged revs. We try this
333 # with _linear_view_revisions. If all revs are to be grepped we
334 # use the slower _graph_view_revisions
335 if opts.levels == 1 and grep_mainline:
336 given_revs = _linear_view_revisions(branch, start_revid, end_revid)
337 else:
338 given_revs = _graph_view_revisions(branch, start_revid, end_revid)
339 else:
340 # We do an optimization below. For grepping a specific revison
341 # We don't need to call _graph_view_revisions which is slow.
342 # We create the start_rev_tuple for only that specific revision.
343 # _graph_view_revisions is used only for revision range.
344 start_revno = '.'.join(map(str, srevno_tuple))
345 start_rev_tuple = (start_revid, start_revno, 0)
346 given_revs = [start_rev_tuple]
347
348 # GZ 2010-06-02: Shouldn't be smuggling this on opts, but easy for now
349 opts.outputter = _Outputter(opts, use_cache=True)
350
351 for revid, revno, merge_depth in given_revs:
352 if opts.levels == 1 and merge_depth != 0:
353 # with level=1 show only top level
354 continue
355
356 rev = RevisionSpec_revid.from_string("revid:"+revid)
357 tree = rev.as_tree(branch)
358 for path in opts.path_list:
359 path_for_id = osutils.pathjoin(relpath, path)
360 id = tree.path2id(path_for_id)
361 if not id:
362 trace.warning("Skipped unknown file '%s'." % path)
363 continue
364
365 if osutils.isdir(path):
366 path_prefix = path
367 dir_grep(tree, path, relpath, opts, revno, path_prefix)
368 else:
369 versioned_file_grep(tree, id, '.', path, opts, revno)
370 finally:
371 branch.unlock()
372
373
374def workingtree_grep(opts):
375 revno = opts.print_revno = None # for working tree set revno to None
376
377 tree, branch, relpath = \
378 bzrdir.BzrDir.open_containing_tree_or_branch('.')
379 if not tree:
380 msg = ('Cannot search working tree. Working tree not found.\n'
381 'To search for specific revision in history use the -r option.')
382 raise errors.BzrCommandError(msg)
383
384 # GZ 2010-06-02: Shouldn't be smuggling this on opts, but easy for now
385 opts.outputter = _Outputter(opts)
386
387 tree.lock_read()
388 try:
389 for path in opts.path_list:
390 if osutils.isdir(path):
391 path_prefix = path
392 dir_grep(tree, path, relpath, opts, revno, path_prefix)
393 else:
394 _file_grep(open(path).read(), path, opts, revno)
395 finally:
396 tree.unlock()
397
398
399def _skip_file(include, exclude, path):
400 if include and not _path_in_glob_list(path, include):
401 return True
402 if exclude and _path_in_glob_list(path, exclude):
403 return True
404 return False
405
406
407def dir_grep(tree, path, relpath, opts, revno, path_prefix):
408 # setup relpath to open files relative to cwd
409 rpath = relpath
410 if relpath:
411 rpath = osutils.pathjoin('..',relpath)
412
413 from_dir = osutils.pathjoin(relpath, path)
414 if opts.from_root:
415 # start searching recursively from root
416 from_dir=None
417 recursive=True
418
419 to_grep = []
420 to_grep_append = to_grep.append
421 # GZ 2010-06-05: The cache dict used to be recycled every call to dir_grep
422 # and hits manually refilled. Could do this again if it was
423 # for a good reason, otherwise cache might want purging.
424 outputter = opts.outputter
425 for fp, fc, fkind, fid, entry in tree.list_files(include_root=False,
426 from_dir=from_dir, recursive=opts.recursive):
427
428 if _skip_file(opts.include, opts.exclude, fp):
429 continue
430
431 if fc == 'V' and fkind == 'file':
432 if revno != None:
433 # If old result is valid, print results immediately.
434 # Otherwise, add file info to to_grep so that the
435 # loop later will get chunks and grep them
436 cache_id = tree.get_file_revision(fid)
437 if cache_id in outputter.cache:
438 # GZ 2010-06-05: Not really sure caching and re-outputting
439 # the old path is really the right thing,
440 # but it's what the old code seemed to do
441 outputter.write_cached_lines(cache_id, revno)
442 else:
443 to_grep_append((fid, (fp, fid)))
444 else:
445 # we are grepping working tree.
446 if from_dir is None:
447 from_dir = '.'
448
449 path_for_file = osutils.pathjoin(tree.basedir, from_dir, fp)
450 if opts.files_with_matches or opts.files_without_match:
451 # Optimize for wtree list-only as we don't need to read the
452 # entire file
453 file = open(path_for_file, 'r', buffering=4096)
454 _file_grep_list_only_wtree(file, fp, opts, path_prefix)
455 else:
456 file_text = open(path_for_file, 'r').read()
457 _file_grep(file_text, fp, opts, revno, path_prefix)
458
459 if revno != None: # grep versioned files
460 for (path, fid), chunks in tree.iter_files_bytes(to_grep):
461 path = _make_display_path(relpath, path)
462 _file_grep(chunks[0], path, opts, revno, path_prefix,
463 tree.get_file_revision(fid, path))
464
465
466def _make_display_path(relpath, path):
467 """Return path string relative to user cwd.
468
469 Take tree's 'relpath' and user supplied 'path', and return path
470 that can be displayed to the user.
471 """
472 if relpath:
473 # update path so to display it w.r.t cwd
474 # handle windows slash separator
475 path = osutils.normpath(osutils.pathjoin(relpath, path))
476 path = path.replace('\\', '/')
477 path = path.replace(relpath + '/', '', 1)
478 return path
479
480
481def versioned_file_grep(tree, id, relpath, path, opts, revno, path_prefix = None):
482 """Create a file object for the specified id and pass it on to _file_grep.
483 """
484
485 path = _make_display_path(relpath, path)
486 file_text = tree.get_file_text(id)
487 _file_grep(file_text, path, opts, revno, path_prefix)
488
489
490def _path_in_glob_list(path, glob_list):
491 for glob in glob_list:
492 if fnmatch(path, glob):
493 return True
494 return False
495
496
497def _file_grep_list_only_wtree(file, path, opts, path_prefix=None):
498 # test and skip binary files
499 if '\x00' in file.read(1024):
500 if opts.verbose:
501 trace.warning("Binary file '%s' skipped." % path)
502 return
503
504 file.seek(0) # search from beginning
505
506 found = False
507 if opts.fixed_string:
508 pattern = opts.pattern.encode(_user_encoding, 'replace')
509 for line in file:
510 if pattern in line:
511 found = True
512 break
513 else: # not fixed_string
514 for line in file:
515 if opts.patternc.search(line):
516 found = True
517 break
518
519 if (opts.files_with_matches and found) or \
520 (opts.files_without_match and not found):
521 if path_prefix and path_prefix != '.':
522 # user has passed a dir arg, show that as result prefix
523 path = osutils.pathjoin(path_prefix, path)
524 opts.outputter.get_writer(path, None, None)()
525
526
527class _Outputter(object):
528 """Precalculate formatting based on options given
529
530 The idea here is to do this work only once per run, and finally return a
531 function that will do the minimum amount possible for each match.
532 """
533 def __init__(self, opts, use_cache=False):
534 self.outf = opts.outf
535 if use_cache:
536 # self.cache is used to cache results for dir grep based on fid.
537 # If the fid is does not change between results, it means that
538 # the result will be the same apart from revno. In such a case
539 # we avoid getting file chunks from repo and grepping. The result
540 # is just printed by replacing old revno with new one.
541 self.cache = {}
542 else:
543 self.cache = None
544 no_line = opts.files_with_matches or opts.files_without_match
545
546 if opts.show_color:
547 pat = opts.pattern.encode(_user_encoding, 'replace')
548 if no_line:
549 self.get_writer = self._get_writer_plain
550 elif opts.fixed_string:
551 self._old = pat
552 self._new = color_string(pat, FG.BOLD_RED)
553 self.get_writer = self._get_writer_fixed_highlighted
554 else:
555 flags = opts.patternc.flags
556 self._sub = re.compile(pat.join(("((?:",")+)")), flags).sub
557 self._highlight = color_string("\\1", FG.BOLD_RED)
558 self.get_writer = self._get_writer_regexp_highlighted
559 path_start = FG.MAGENTA
560 path_end = FG.NONE
561 sep = color_string(':', FG.BOLD_CYAN)
562 rev_sep = color_string('~', FG.BOLD_YELLOW)
563 else:
564 self.get_writer = self._get_writer_plain
565 path_start = path_end = ""
566 sep = ":"
567 rev_sep = "~"
568
569 parts = [path_start, "%(path)s"]
570 if opts.print_revno:
571 parts.extend([rev_sep, "%(revno)s"])
572 self._format_initial = "".join(parts)
573 parts = []
574 if no_line:
575 if not opts.print_revno:
576 parts.append(path_end)
577 else:
578 if opts.line_number:
579 parts.extend([sep, "%(lineno)s"])
580 parts.extend([sep, "%(line)s"])
581 parts.append(opts.eol_marker)
582 self._format_perline = "".join(parts)
583
584 def _get_writer_plain(self, path, revno, cache_id):
585 """Get function for writing uncoloured output"""
586 per_line = self._format_perline
587 start = self._format_initial % {"path":path, "revno":revno}
588 write = self.outf.write
589 if self.cache is not None and cache_id is not None:
590 result_list = []
591 self.cache[cache_id] = path, result_list
592 add_to_cache = result_list.append
593 def _line_cache_and_writer(**kwargs):
594 """Write formatted line and cache arguments"""
595 end = per_line % kwargs
596 add_to_cache(end)
597 write(start + end)
598 return _line_cache_and_writer
599 def _line_writer(**kwargs):
600 """Write formatted line from arguments given by underlying opts"""
601 write(start + per_line % kwargs)
602 return _line_writer
603
604 def write_cached_lines(self, cache_id, revno):
605 """Write cached results out again for new revision"""
606 cached_path, cached_matches = self.cache[cache_id]
607 start = self._format_initial % {"path":cached_path, "revno":revno}
608 write = self.outf.write
609 for end in cached_matches:
610 write(start + end)
611
612 def _get_writer_regexp_highlighted(self, path, revno, cache_id):
613 """Get function for writing output with regexp match highlighted"""
614 _line_writer = self._get_writer_plain(path, revno, cache_id)
615 sub, highlight = self._sub, self._highlight
616 def _line_writer_regexp_highlighted(line, **kwargs):
617 """Write formatted line with matched pattern highlighted"""
618 return _line_writer(line=sub(highlight, line), **kwargs)
619 return _line_writer_regexp_highlighted
620
621 def _get_writer_fixed_highlighted(self, path, revno, cache_id):
622 """Get function for writing output with search string highlighted"""
623 _line_writer = self._get_writer_plain(path, revno, cache_id)
624 old, new = self._old, self._new
625 def _line_writer_fixed_highlighted(line, **kwargs):
626 """Write formatted line with string searched for highlighted"""
627 return _line_writer(line=line.replace(old, new), **kwargs)
628 return _line_writer_fixed_highlighted
629
630
631def _file_grep(file_text, path, opts, revno, path_prefix=None, cache_id=None):
632 # test and skip binary files
633 if '\x00' in file_text[:1024]:
634 if opts.verbose:
635 trace.warning("Binary file '%s' skipped." % path)
636 return
637
638 if path_prefix and path_prefix != '.':
639 # user has passed a dir arg, show that as result prefix
640 path = osutils.pathjoin(path_prefix, path)
641
642 # GZ 2010-06-07: There's no actual guarentee the file contents will be in
643 # the user encoding, but we have to guess something and it
644 # is a reasonable default without a better mechanism.
645 file_encoding = _user_encoding
646 pattern = opts.pattern.encode(_user_encoding, 'replace')
647
648 writeline = opts.outputter.get_writer(path, revno, cache_id)
649
650 if opts.files_with_matches or opts.files_without_match:
651 if opts.fixed_string:
652 if sys.platform > (2, 5):
653 found = pattern in file_text
654 else:
655 for line in file_text.splitlines():
656 if pattern in line:
657 found = True
658 break
659 else:
660 found = False
661 else:
662 search = opts.patternc.search
663 if "$" not in pattern:
664 found = search(file_text) is not None
665 else:
666 for line in file_text.splitlines():
667 if search(line):
668 found = True
669 break
670 else:
671 found = False
672 if (opts.files_with_matches and found) or \
673 (opts.files_without_match and not found):
674 writeline()
675 elif opts.fixed_string:
676 # Fast path for no match, search through the entire file at once rather
677 # than a line at a time. However, we don't want this without Python 2.5
678 # as the quick string search algorithm wasn't implemented till then:
679 # <http://effbot.org/zone/stringlib.htm>
680 if sys.version_info > (2, 5):
681 i = file_text.find(pattern)
682 if i == -1:
683 return
684 b = file_text.rfind("\n", 0, i) + 1
685 if opts.line_number:
686 start = file_text.count("\n", 0, b) + 1
687 file_text = file_text[b:]
688 else:
689 start = 1
690 if opts.line_number:
691 for index, line in enumerate(file_text.splitlines()):
692 if pattern in line:
693 line = line.decode(file_encoding, 'replace')
694 writeline(lineno=index+start, line=line)
695 else:
696 for line in file_text.splitlines():
697 if pattern in line:
698 line = line.decode(file_encoding, 'replace')
699 writeline(line=line)
700 else:
701 # Fast path on no match, the re module avoids bad behaviour in most
702 # standard cases, but perhaps could try and detect backtracking
703 # patterns here and avoid whole text search in those cases
704 search = opts.patternc.search
705 if "$" not in pattern:
706 # GZ 2010-06-05: Grr, re.MULTILINE can't save us when searching
707 # through revisions as bazaar returns binary mode
708 # and trailing \r breaks $ as line ending match
709 m = search(file_text)
710 if m is None:
711 return
712 b = file_text.rfind("\n", 0, m.start()) + 1
713 if opts.line_number:
714 start = file_text.count("\n", 0, b) + 1
715 file_text = file_text[b:]
716 else:
717 start = 1
718 if opts.line_number:
719 for index, line in enumerate(file_text.splitlines()):
720 if search(line):
721 line = line.decode(file_encoding, 'replace')
722 writeline(lineno=index+start, line=line)
723 else:
724 for line in file_text.splitlines():
725 if search(line):
726 line = line.decode(file_encoding, 'replace')
727 writeline(line=line)
728
0729
=== added file 'bzrlib/plugins/grep/test_grep.py'
--- bzrlib/plugins/grep/test_grep.py 1970-01-01 00:00:00 +0000
+++ bzrlib/plugins/grep/test_grep.py 2012-08-23 15:07:23 +0000
@@ -0,0 +1,2254 @@
1# Copyright (C) 2010 Canonical Ltd
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
17from __future__ import absolute_import
18
19import os
20import re
21import unicodedata as ud
22
23from bzrlib import tests, osutils
24from bzrlib._termcolor import color_string, FG
25
26from bzrlib.tests.features import (
27 ColorFeature,
28 UnicodeFilenameFeature,
29 )
30
31# NOTE: As bzr-grep optimizes PATTERN search to -F/--fixed-string
32# for patterns that are not alphanumeric+whitespace, we test grep
33# specfically with patterns that have special characters so that
34# regex path is tested. alphanumeric patterns test the -F path.
35
36class GrepTestBase(tests.TestCaseWithTransport):
37 """Base class for testing grep.
38
39 Provides support methods for creating directory and file revisions.
40 """
41 _reflags = re.MULTILINE|re.DOTALL
42
43 def _mk_file(self, path, line_prefix, total_lines, versioned):
44 text=''
45 for i in range(total_lines):
46 text += line_prefix + str(i+1) + "\n"
47
48 open(path, 'w').write(text)
49 if versioned:
50 self.run_bzr(['add', path])
51 self.run_bzr(['ci', '-m', '"' + path + '"'])
52
53 def _update_file(self, path, text, checkin=True):
54 """append text to file 'path' and check it in"""
55 open(path, 'a').write(text)
56 if checkin:
57 self.run_bzr(['ci', path, '-m', '"' + path + '"'])
58
59 def _mk_unknown_file(self, path, line_prefix='line', total_lines=10):
60 self._mk_file(path, line_prefix, total_lines, versioned=False)
61
62 def _mk_versioned_file(self, path, line_prefix='line', total_lines=10):
63 self._mk_file(path, line_prefix, total_lines, versioned=True)
64
65 def _mk_dir(self, path, versioned):
66 os.mkdir(path)
67 if versioned:
68 self.run_bzr(['add', path])
69 self.run_bzr(['ci', '-m', '"' + path + '"'])
70
71 def _mk_unknown_dir(self, path):
72 self._mk_dir(path, versioned=False)
73
74 def _mk_versioned_dir(self, path):
75 self._mk_dir(path, versioned=True)
76
77
78class TestGrep(GrepTestBase):
79 """Core functional tests for grep."""
80
81 def test_basic_unknown_file(self):
82 """Search for pattern in specfic file.
83
84 If specified file is unknown, grep it anyway."""
85 wd = 'foobar0'
86 self.make_branch_and_tree(wd)
87 os.chdir(wd)
88 self._mk_unknown_file('file0.txt')
89
90 out, err = self.run_bzr(['grep', 'line1', 'file0.txt'])
91 self.assertContainsRe(out, "file0.txt:line1", flags=TestGrep._reflags)
92 self.assertEqual(len(out.splitlines()), 2) # finds line1 and line10
93
94 out, err = self.run_bzr(['grep', 'line\d+', 'file0.txt'])
95 self.assertContainsRe(out, "file0.txt:line1", flags=TestGrep._reflags)
96 self.assertEqual(len(out.splitlines()), 10)
97
98 # unknown file is not grepped unless explicitely specified
99 out, err = self.run_bzr(['grep', 'line1'])
100 self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags)
101 self.assertEqual(len(out.splitlines()), 0)
102
103 # unknown file is not grepped unless explicitely specified
104 out, err = self.run_bzr(['grep', 'line1$'])
105 self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags)
106 self.assertEqual(len(out.splitlines()), 0)
107
108 def test_ver_basic_file(self):
109 """(versioned) Search for pattern in specfic file.
110 """
111 wd = 'foobar0'
112 self.make_branch_and_tree(wd)
113 os.chdir(wd)
114 self._mk_versioned_file('file0.txt')
115
116 out, err = self.run_bzr(['grep', '-r', '1', 'line1', 'file0.txt'])
117 self.assertContainsRe(out, "file0.txt~1:line1", flags=TestGrep._reflags)
118 self.assertEqual(len(out.splitlines()), 2) # finds line1 and line10
119
120 out, err = self.run_bzr(['grep', '-r', '1', 'line[0-9]$', 'file0.txt'])
121 self.assertContainsRe(out, "file0.txt~1:line1", flags=TestGrep._reflags)
122 self.assertEqual(len(out.splitlines()), 9)
123
124 # finds all the lines
125 out, err = self.run_bzr(['grep', '-r', '1', 'line[0-9]', 'file0.txt'])
126 self.assertContainsRe(out, "file0.txt~1:line1", flags=TestGrep._reflags)
127 self.assertEqual(len(out.splitlines()), 10)
128
129 def test_wtree_basic_file(self):
130 """(wtree) Search for pattern in specfic file.
131 """
132 wd = 'foobar0'
133 self.make_branch_and_tree(wd)
134 os.chdir(wd)
135 self._mk_versioned_file('file0.txt')
136 self._update_file('file0.txt', 'ABC\n', checkin=False)
137
138 out, err = self.run_bzr(['grep', 'ABC', 'file0.txt'])
139 self.assertContainsRe(out, "file0.txt:ABC", flags=TestGrep._reflags)
140 self.assertEqual(len(out.splitlines()), 1)
141
142 out, err = self.run_bzr(['grep', '[A-Z]{3}', 'file0.txt'])
143 self.assertContainsRe(out, "file0.txt:ABC", flags=TestGrep._reflags)
144 self.assertEqual(len(out.splitlines()), 1)
145
146 out, err = self.run_bzr(['grep', '-r', 'last:1', 'ABC', 'file0.txt'])
147 self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags)
148 self.assertEqual(len(out.splitlines()), 0)
149
150 out, err = self.run_bzr(['grep', '-r', 'last:1', '[A-Z]{3}', 'file0.txt'])
151 self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags)
152 self.assertEqual(len(out.splitlines()), 0)
153
154 def test_ver_basic_include(self):
155 """(versioned) Ensure that -I flag is respected.
156 """
157 wd = 'foobar0'
158 self.make_branch_and_tree(wd)
159 os.chdir(wd)
160 self._mk_versioned_file('file0.aa')
161 self._mk_versioned_file('file0.bb')
162 self._mk_versioned_file('file0.cc')
163
164 out, err = self.run_bzr(['grep', '-r', 'last:1',
165 '--include', '*.aa', '--include', '*.bb', 'line1'])
166 self.assertContainsRe(out, "file0.aa~.:line1", flags=TestGrep._reflags)
167 self.assertContainsRe(out, "file0.bb~.:line1", flags=TestGrep._reflags)
168 self.assertNotContainsRe(out, "file0.cc", flags=TestGrep._reflags)
169 # two lines each (line1, line10) from file0.aa and file0.bb
170 self.assertEqual(len(out.splitlines()), 4)
171
172 out, err = self.run_bzr(['grep', '-r', 'last:1',
173 '--include', '*.aa', '--include', '*.bb', 'line1$'])
174 self.assertContainsRe(out, "file0.aa~.:line1", flags=TestGrep._reflags)
175 self.assertContainsRe(out, "file0.bb~.:line1", flags=TestGrep._reflags)
176 self.assertNotContainsRe(out, "file0.cc", flags=TestGrep._reflags)
177 # one lines each (line1) from file0.aa and file0.bb
178 self.assertEqual(len(out.splitlines()), 2)
179
180 out, err = self.run_bzr(['grep', '-r', 'last:1',
181 '-I', '*.aa', '-I', '*.bb', 'line1'])
182 self.assertContainsRe(out, "file0.aa~.:line1", flags=TestGrep._reflags)
183 self.assertContainsRe(out, "file0.bb~.:line1", flags=TestGrep._reflags)
184 self.assertNotContainsRe(out, "file0.cc", flags=TestGrep._reflags)
185 # two lines each (line1, line10) from file0.aa and file0.bb
186 self.assertEqual(len(out.splitlines()), 4)
187
188 out, err = self.run_bzr(['grep', '-r', 'last:1',
189 '-I', '*.aa', '-I', '*.bb', 'line1$'])
190 self.assertContainsRe(out, "file0.aa~.:line1", flags=TestGrep._reflags)
191 self.assertContainsRe(out, "file0.bb~.:line1", flags=TestGrep._reflags)
192 self.assertNotContainsRe(out, "file0.cc", flags=TestGrep._reflags)
193 # one lines each (line1) from file0.aa and file0.bb
194 self.assertEqual(len(out.splitlines()), 2)
195
196 def test_wtree_basic_include(self):
197 """(wtree) Ensure that --include flag is respected.
198 """
199 wd = 'foobar0'
200 self.make_branch_and_tree(wd)
201 os.chdir(wd)
202 self._mk_versioned_file('file0.aa')
203 self._mk_versioned_file('file0.bb')
204 self._mk_versioned_file('file0.cc')
205
206 out, err = self.run_bzr(['grep', '--include', '*.aa',
207 '--include', '*.bb', 'line1'])
208 self.assertContainsRe(out, "file0.aa:line1", flags=TestGrep._reflags)
209 self.assertContainsRe(out, "file0.bb:line1", flags=TestGrep._reflags)
210 self.assertNotContainsRe(out, "file0.cc", flags=TestGrep._reflags)
211 # two lines each (line1, line10) from file0.aa and file0.bb
212 self.assertEqual(len(out.splitlines()), 4)
213
214 out, err = self.run_bzr(['grep', '--include', '*.aa',
215 '--include', '*.bb', 'line1$'])
216 self.assertContainsRe(out, "file0.aa:line1", flags=TestGrep._reflags)
217 self.assertContainsRe(out, "file0.bb:line1", flags=TestGrep._reflags)
218 self.assertNotContainsRe(out, "file0.cc", flags=TestGrep._reflags)
219 # one line each (line1) from file0.aa and file0.bb
220 self.assertEqual(len(out.splitlines()), 2)
221
222 def test_ver_basic_exclude(self):
223 """(versioned) Ensure that --exclude flag is respected.
224 """
225 wd = 'foobar0'
226 self.make_branch_and_tree(wd)
227 os.chdir(wd)
228 self._mk_versioned_file('file0.aa')
229 self._mk_versioned_file('file0.bb')
230 self._mk_versioned_file('file0.cc')
231
232 out, err = self.run_bzr(['grep', '-r', 'last:1',
233 '--exclude', '*.cc', 'line1'])
234 self.assertContainsRe(out, "file0.aa~.:line1$", flags=TestGrep._reflags)
235 self.assertContainsRe(out, "file0.bb~.:line1$", flags=TestGrep._reflags)
236 self.assertContainsRe(out, "file0.aa~.:line10", flags=TestGrep._reflags)
237 self.assertContainsRe(out, "file0.bb~.:line10", flags=TestGrep._reflags)
238 self.assertNotContainsRe(out, "file0.cc", flags=TestGrep._reflags)
239 # two lines each (line1, line10) from file0.aa and file0.bb
240 self.assertEqual(len(out.splitlines()), 4)
241
242 out, err = self.run_bzr(['grep', '-r', 'last:1',
243 '--exclude', '*.cc', 'line1$'])
244 self.assertContainsRe(out, "file0.aa~.:line1", flags=TestGrep._reflags)
245 self.assertContainsRe(out, "file0.bb~.:line1", flags=TestGrep._reflags)
246 self.assertNotContainsRe(out, "file0.cc", flags=TestGrep._reflags)
247 # one line each (line1) from file0.aa and file0.bb
248 self.assertEqual(len(out.splitlines()), 2)
249
250 out, err = self.run_bzr(['grep', '-r', 'last:1',
251 '-X', '*.cc', 'line1'])
252 self.assertContainsRe(out, "file0.aa~.:line1", flags=TestGrep._reflags)
253 self.assertContainsRe(out, "file0.bb~.:line1", flags=TestGrep._reflags)
254 self.assertNotContainsRe(out, "file0.cc", flags=TestGrep._reflags)
255 # two lines each (line1, line10) from file0.aa and file0.bb
256 self.assertEqual(len(out.splitlines()), 4)
257
258 def test_wtree_basic_exclude(self):
259 """(wtree) Ensure that --exclude flag is respected.
260 """
261 wd = 'foobar0'
262 self.make_branch_and_tree(wd)
263 os.chdir(wd)
264 self._mk_versioned_file('file0.aa')
265 self._mk_versioned_file('file0.bb')
266 self._mk_versioned_file('file0.cc')
267
268 out, err = self.run_bzr(['grep', '--exclude', '*.cc', 'line1'])
269 self.assertContainsRe(out, "file0.aa:line1", flags=TestGrep._reflags)
270 self.assertContainsRe(out, "file0.bb:line1", flags=TestGrep._reflags)
271 self.assertNotContainsRe(out, "file0.cc", flags=TestGrep._reflags)
272 # two lines each (line1, line10) from file0.aa and file0.bb
273 self.assertEqual(len(out.splitlines()), 4)
274
275 out, err = self.run_bzr(['grep', '--exclude', '*.cc', 'lin.1$'])
276 self.assertContainsRe(out, "file0.aa:line1", flags=TestGrep._reflags)
277 self.assertContainsRe(out, "file0.bb:line1", flags=TestGrep._reflags)
278 self.assertNotContainsRe(out, "file0.cc", flags=TestGrep._reflags)
279 # one line each (line1) from file0.aa and file0.bb
280 self.assertEqual(len(out.splitlines()), 2)
281
282 def test_ver_multiple_files(self):
283 """(versioned) Search for pattern in multiple files.
284 """
285 wd = 'foobar0'
286 self.make_branch_and_tree(wd)
287 os.chdir(wd)
288 self._mk_versioned_file('file0.txt', total_lines=2)
289 self._mk_versioned_file('file1.txt', total_lines=2)
290 self._mk_versioned_file('file2.txt', total_lines=2)
291
292 out, err = self.run_bzr(['grep', '-r', 'last:1', 'line[1-2]$'])
293 self.assertContainsRe(out, "file0.txt~.:line1", flags=TestGrep._reflags)
294 self.assertContainsRe(out, "file0.txt~.:line2", flags=TestGrep._reflags)
295 self.assertContainsRe(out, "file1.txt~.:line1", flags=TestGrep._reflags)
296 self.assertContainsRe(out, "file1.txt~.:line2", flags=TestGrep._reflags)
297 self.assertContainsRe(out, "file2.txt~.:line1", flags=TestGrep._reflags)
298 self.assertContainsRe(out, "file2.txt~.:line2", flags=TestGrep._reflags)
299 self.assertEqual(len(out.splitlines()), 6)
300
301 out, err = self.run_bzr(['grep', '-r', 'last:1', 'line'])
302 self.assertContainsRe(out, "file0.txt~.:line1", flags=TestGrep._reflags)
303 self.assertContainsRe(out, "file0.txt~.:line2", flags=TestGrep._reflags)
304 self.assertContainsRe(out, "file1.txt~.:line1", flags=TestGrep._reflags)
305 self.assertContainsRe(out, "file1.txt~.:line2", flags=TestGrep._reflags)
306 self.assertContainsRe(out, "file2.txt~.:line1", flags=TestGrep._reflags)
307 self.assertContainsRe(out, "file2.txt~.:line2", flags=TestGrep._reflags)
308 self.assertEqual(len(out.splitlines()), 6)
309
310 def test_multiple_wtree_files(self):
311 """(wtree) Search for pattern in multiple files in working tree.
312 """
313 wd = 'foobar0'
314 self.make_branch_and_tree(wd)
315 os.chdir(wd)
316 self._mk_versioned_file('file0.txt', total_lines=2)
317 self._mk_versioned_file('file1.txt', total_lines=2)
318 self._mk_versioned_file('file2.txt', total_lines=2)
319 self._update_file('file0.txt', 'HELLO\n', checkin=False)
320 self._update_file('file1.txt', 'HELLO\n', checkin=True)
321 self._update_file('file2.txt', 'HELLO\n', checkin=False)
322
323 out, err = self.run_bzr(['grep', 'HELLO',
324 'file0.txt', 'file1.txt', 'file2.txt'])
325
326 self.assertContainsRe(out, "file0.txt:HELLO", flags=TestGrep._reflags)
327 self.assertContainsRe(out, "file1.txt:HELLO", flags=TestGrep._reflags)
328 self.assertContainsRe(out, "file2.txt:HELLO", flags=TestGrep._reflags)
329 self.assertEqual(len(out.splitlines()), 3)
330
331 out, err = self.run_bzr(['grep', 'HELLO', '-r', 'last:1',
332 'file0.txt', 'file1.txt', 'file2.txt'])
333
334 self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags)
335 self.assertContainsRe(out, "file1.txt~.:HELLO", flags=TestGrep._reflags)
336 self.assertNotContainsRe(out, "file2.txt", flags=TestGrep._reflags)
337 self.assertEqual(len(out.splitlines()), 1)
338
339 out, err = self.run_bzr(['grep', 'HE..O',
340 'file0.txt', 'file1.txt', 'file2.txt'])
341
342 self.assertContainsRe(out, "file0.txt:HELLO", flags=TestGrep._reflags)
343 self.assertContainsRe(out, "file1.txt:HELLO", flags=TestGrep._reflags)
344 self.assertContainsRe(out, "file2.txt:HELLO", flags=TestGrep._reflags)
345 self.assertEqual(len(out.splitlines()), 3)
346
347 out, err = self.run_bzr(['grep', 'HE..O', '-r', 'last:1',
348 'file0.txt', 'file1.txt', 'file2.txt'])
349
350 self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags)
351 self.assertContainsRe(out, "file1.txt~.:HELLO", flags=TestGrep._reflags)
352 self.assertNotContainsRe(out, "file2.txt", flags=TestGrep._reflags)
353 self.assertEqual(len(out.splitlines()), 1)
354
355 def test_ver_null_option(self):
356 """(versioned) --null option should use NUL instead of newline.
357 """
358 wd = 'foobar0'
359 self.make_branch_and_tree(wd)
360 os.chdir(wd)
361 self._mk_versioned_file('file0.txt', total_lines=3)
362
363 nref = ud.normalize(u'NFC', u"file0.txt~1:line1\0file0.txt~1:line2\0file0.txt~1:line3\0")
364
365 out, err = self.run_bzr(['grep', '-r', 'last:1', '--null', 'line[1-3]'])
366 nout = ud.normalize(u'NFC', out.decode('utf-8', 'ignore'))
367 self.assertEqual(nout, nref)
368 self.assertEqual(len(out.splitlines()), 1)
369
370 out, err = self.run_bzr(['grep', '-r', 'last:1', '-Z', 'line[1-3]'])
371 nout = ud.normalize(u'NFC', out.decode('utf-8', 'ignore'))
372 self.assertEqual(nout, nref)
373 self.assertEqual(len(out.splitlines()), 1)
374
375 out, err = self.run_bzr(['grep', '-r', 'last:1', '--null', 'line'])
376 nout = ud.normalize(u'NFC', out.decode('utf-8', 'ignore'))
377 self.assertEqual(nout, nref)
378 self.assertEqual(len(out.splitlines()), 1)
379
380 def test_wtree_null_option(self):
381 """(wtree) --null option should use NUL instead of newline.
382 """
383 wd = 'foobar0'
384 self.make_branch_and_tree(wd)
385 os.chdir(wd)
386 self._mk_versioned_file('file0.txt', total_lines=3)
387
388 out, err = self.run_bzr(['grep', '--null', 'line[1-3]'])
389 self.assertEqual(out, "file0.txt:line1\0file0.txt:line2\0file0.txt:line3\0")
390 self.assertEqual(len(out.splitlines()), 1)
391
392 out, err = self.run_bzr(['grep', '-Z', 'line[1-3]'])
393 self.assertEqual(out, "file0.txt:line1\0file0.txt:line2\0file0.txt:line3\0")
394 self.assertEqual(len(out.splitlines()), 1)
395
396 out, err = self.run_bzr(['grep', '-Z', 'line'])
397 self.assertEqual(out, "file0.txt:line1\0file0.txt:line2\0file0.txt:line3\0")
398 self.assertEqual(len(out.splitlines()), 1)
399
400 def test_versioned_file_in_dir_no_recursive(self):
401 """(versioned) Should not recurse with --no-recursive"""
402 wd = 'foobar0'
403 self.make_branch_and_tree(wd)
404 os.chdir(wd)
405 self._mk_versioned_file('fileX.txt', line_prefix='lin')
406 self._mk_versioned_dir('dir0')
407 self._mk_versioned_file('dir0/file0.txt')
408
409 out, err = self.run_bzr(['grep', '-r', 'last:1', '--no-recursive', 'line1'])
410 self.assertNotContainsRe(out, "file0.txt~.:line1", flags=TestGrep._reflags)
411 self.assertEqual(len(out.splitlines()), 0)
412
413 out, err = self.run_bzr(['grep', '-r', 'last:1', '--no-recursive', 'line1$'])
414 self.assertNotContainsRe(out, "file0.txt~.:line1", flags=TestGrep._reflags)
415 self.assertEqual(len(out.splitlines()), 0)
416
417 def test_wtree_file_in_dir_no_recursive(self):
418 """(wtree) Should not recurse with --no-recursive"""
419 wd = 'foobar0'
420 self.make_branch_and_tree(wd)
421 os.chdir(wd)
422 self._mk_versioned_file('fileX.txt', line_prefix='lin')
423 self._mk_versioned_dir('dir0')
424 self._mk_versioned_file('dir0/file0.txt')
425
426 out, err = self.run_bzr(['grep', '--no-recursive', 'line1'])
427 self.assertNotContainsRe(out, "file0.txt:line1", flags=TestGrep._reflags)
428 self.assertEqual(len(out.splitlines()), 0)
429
430 out, err = self.run_bzr(['grep', '--no-recursive', 'lin.1'])
431 self.assertNotContainsRe(out, "file0.txt:line1", flags=TestGrep._reflags)
432 self.assertEqual(len(out.splitlines()), 0)
433
434 def test_versioned_file_in_dir_recurse(self):
435 """(versioned) Should recurse by default.
436 """
437 wd = 'foobar0'
438 self.make_branch_and_tree(wd)
439 os.chdir(wd)
440 self._mk_versioned_dir('dir0')
441 self._mk_versioned_file('dir0/file0.txt')
442
443 out, err = self.run_bzr(['grep', '-r', '-1', '.i.e1'])
444 self.assertContainsRe(out, "^dir0/file0.txt~.:line1", flags=TestGrep._reflags)
445 # find line1 and line10
446 self.assertEqual(len(out.splitlines()), 2)
447
448 out, err = self.run_bzr(['grep', '-r', '-1', 'line1'])
449 self.assertContainsRe(out, "^dir0/file0.txt~.:line1", flags=TestGrep._reflags)
450 # find line1 and line10
451 self.assertEqual(len(out.splitlines()), 2)
452
453 def test_wtree_file_in_dir_recurse(self):
454 """(wtree) Should recurse by default.
455 """
456 wd = 'foobar0'
457 self.make_branch_and_tree(wd)
458 os.chdir(wd)
459 self._mk_versioned_dir('dir0')
460 self._mk_versioned_file('dir0/file0.txt')
461
462 out, err = self.run_bzr(['grep', 'line1'])
463 self.assertContainsRe(out, "^dir0/file0.txt:line1", flags=TestGrep._reflags)
464 # find line1 and line10
465 self.assertEqual(len(out.splitlines()), 2)
466
467 out, err = self.run_bzr(['grep', 'lin.1'])
468 self.assertContainsRe(out, "^dir0/file0.txt:line1", flags=TestGrep._reflags)
469 # find line1 and line10
470 self.assertEqual(len(out.splitlines()), 2)
471
472 def test_versioned_file_within_dir(self):
473 """(versioned) Search for pattern while in nested dir.
474 """
475 wd = 'foobar0'
476 self.make_branch_and_tree(wd)
477 os.chdir(wd)
478 self._mk_versioned_dir('dir0')
479 self._mk_versioned_file('dir0/file0.txt')
480 os.chdir('dir0')
481
482 out, err = self.run_bzr(['grep', '-r', 'last:1', 'line1'])
483 self.assertContainsRe(out, "^file0.txt~.:line1", flags=TestGrep._reflags)
484 # finds line1 and line10
485 self.assertEqual(len(out.splitlines()), 2)
486
487 out, err = self.run_bzr(['grep', '-r', 'last:1', '.i.e1'])
488 self.assertContainsRe(out, "^file0.txt~.:line1", flags=TestGrep._reflags)
489 # finds line1 and line10
490 self.assertEqual(len(out.splitlines()), 2)
491
492 def test_versioned_include_file_within_dir(self):
493 """(versioned) Ensure --include is respected with file within dir.
494 """
495 wd = 'foobar0'
496 self.make_branch_and_tree(wd)
497 os.chdir(wd)
498 self._mk_versioned_dir('dir0') # revno 1
499 self._mk_versioned_file('dir0/file0.txt') # revno 2
500 self._mk_versioned_file('dir0/file1.aa') # revno 3
501 self._update_file('dir0/file1.aa', 'hello\n') # revno 4
502 self._update_file('dir0/file0.txt', 'hello\n') # revno 5
503 os.chdir('dir0')
504
505 out, err = self.run_bzr(['grep', '-r', 'last:1',
506 '--include', '*.aa', 'line1'])
507 self.assertContainsRe(out, "^file1.aa~5:line1$", flags=TestGrep._reflags)
508 self.assertContainsRe(out, "^file1.aa~5:line10$", flags=TestGrep._reflags)
509 self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags)
510 # finds line1 and line10
511 self.assertEqual(len(out.splitlines()), 2)
512
513 out, err = self.run_bzr(['grep', '-r', 'last:2..last:1',
514 '--include', '*.aa', 'line1'])
515 self.assertContainsRe(out, "^file1.aa~4:line1$", flags=TestGrep._reflags)
516 self.assertContainsRe(out, "^file1.aa~4:line10$", flags=TestGrep._reflags)
517 self.assertContainsRe(out, "^file1.aa~5:line1$", flags=TestGrep._reflags)
518 self.assertContainsRe(out, "^file1.aa~5:line10$", flags=TestGrep._reflags)
519 self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags)
520 # finds line1 and line10 over two revisions
521 self.assertEqual(len(out.splitlines()), 4)
522
523 out, err = self.run_bzr(['grep', '-r', 'last:1',
524 '--include', '*.aa', 'lin.1'])
525 self.assertContainsRe(out, "^file1.aa~5:line1$", flags=TestGrep._reflags)
526 self.assertContainsRe(out, "^file1.aa~5:line10$", flags=TestGrep._reflags)
527 self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags)
528 # finds line1 and line10
529 self.assertEqual(len(out.splitlines()), 2)
530
531 out, err = self.run_bzr(['grep', '-r', 'last:3..last:1',
532 '--include', '*.aa', 'lin.1'])
533 self.assertContainsRe(out, "^file1.aa~3:line1$", flags=TestGrep._reflags)
534 self.assertContainsRe(out, "^file1.aa~4:line1$", flags=TestGrep._reflags)
535 self.assertContainsRe(out, "^file1.aa~5:line1$", flags=TestGrep._reflags)
536 self.assertContainsRe(out, "^file1.aa~3:line10$", flags=TestGrep._reflags)
537 self.assertContainsRe(out, "^file1.aa~4:line10$", flags=TestGrep._reflags)
538 self.assertContainsRe(out, "^file1.aa~5:line10$", flags=TestGrep._reflags)
539 self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags)
540 # finds line1 and line10 over 3 revisions
541 self.assertEqual(len(out.splitlines()), 6)
542
543 def test_versioned_exclude_file_within_dir(self):
544 """(versioned) Ensure --exclude is respected with file within dir.
545 """
546 wd = 'foobar0'
547 self.make_branch_and_tree(wd)
548 os.chdir(wd)
549 self._mk_versioned_dir('dir0')
550 self._mk_versioned_file('dir0/file0.txt')
551 self._mk_versioned_file('dir0/file1.aa')
552 os.chdir('dir0')
553
554 out, err = self.run_bzr(['grep', '-r', 'last:1',
555 '--exclude', '*.txt', 'line1'])
556 self.assertContainsRe(out, "^file1.aa~.:line1", flags=TestGrep._reflags)
557 self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags)
558 # finds line1 and line10
559 self.assertEqual(len(out.splitlines()), 2)
560
561 out, err = self.run_bzr(['grep', '-r', 'last:1',
562 '--exclude', '*.txt', 'l[a-z]ne1'])
563 self.assertContainsRe(out, "^file1.aa~.:line1", flags=TestGrep._reflags)
564 self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags)
565 # finds line1 and line10
566 self.assertEqual(len(out.splitlines()), 2)
567
568 def test_wtree_file_within_dir(self):
569 """(wtree) Search for pattern while in nested dir.
570 """
571 wd = 'foobar0'
572 self.make_branch_and_tree(wd)
573 os.chdir(wd)
574 self._mk_versioned_dir('dir0')
575 self._mk_versioned_file('dir0/file0.txt')
576 os.chdir('dir0')
577
578 out, err = self.run_bzr(['grep', 'line1'])
579 self.assertContainsRe(out, "^file0.txt:line1", flags=TestGrep._reflags)
580 # finds line1 and line10
581 self.assertEqual(len(out.splitlines()), 2)
582
583 out, err = self.run_bzr(['grep', 'l[aeiou]ne1'])
584 self.assertContainsRe(out, "^file0.txt:line1", flags=TestGrep._reflags)
585 # finds line1 and line10
586 self.assertEqual(len(out.splitlines()), 2)
587
588 def test_wtree_include_file_within_dir(self):
589 """(wtree) Ensure --include is respected with file within dir.
590 """
591 wd = 'foobar0'
592 self.make_branch_and_tree(wd)
593 os.chdir(wd)
594 self._mk_versioned_dir('dir0')
595 self._mk_versioned_file('dir0/file0.txt')
596 self._mk_versioned_file('dir0/file1.aa')
597 os.chdir('dir0')
598
599 out, err = self.run_bzr(['grep', '--include', '*.aa', 'line1'])
600 self.assertContainsRe(out, "^file1.aa:line1", flags=TestGrep._reflags)
601 # finds line1 and line10
602 self.assertEqual(len(out.splitlines()), 2)
603
604 out, err = self.run_bzr(['grep', '--include', '*.aa', 'l[ixn]ne1'])
605 self.assertContainsRe(out, "^file1.aa:line1", flags=TestGrep._reflags)
606 self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags)
607 # finds line1 and line10
608 self.assertEqual(len(out.splitlines()), 2)
609
610 def test_wtree_exclude_file_within_dir(self):
611 """(wtree) Ensure --exclude is respected with file within dir.
612 """
613 wd = 'foobar0'
614 self.make_branch_and_tree(wd)
615 os.chdir(wd)
616 self._mk_versioned_dir('dir0')
617 self._mk_versioned_file('dir0/file0.txt')
618 self._mk_versioned_file('dir0/file1.aa')
619 os.chdir('dir0')
620
621 out, err = self.run_bzr(['grep', '--exclude', '*.txt', 'li.e1'])
622 self.assertContainsRe(out, "^file1.aa:line1$", flags=TestGrep._reflags)
623 self.assertContainsRe(out, "^file1.aa:line10$", flags=TestGrep._reflags)
624 self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags)
625 # finds line1 and line10
626 self.assertEqual(len(out.splitlines()), 2)
627
628 out, err = self.run_bzr(['grep', '--exclude', '*.txt', 'line1'])
629 self.assertContainsRe(out, "^file1.aa:line1$", flags=TestGrep._reflags)
630 self.assertContainsRe(out, "^file1.aa:line10$", flags=TestGrep._reflags)
631 self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags)
632 # finds line1 and line10
633 self.assertEqual(len(out.splitlines()), 2)
634
635 def test_versioned_include_from_outside_dir(self):
636 """(versioned) Ensure --include is respected during recursive search.
637 """
638 wd = 'foobar0'
639 self.make_branch_and_tree(wd)
640 os.chdir(wd)
641
642 self._mk_versioned_dir('dir0')
643 self._mk_versioned_file('dir0/file0.aa')
644
645 self._mk_versioned_dir('dir1')
646 self._mk_versioned_file('dir1/file1.bb')
647
648 self._mk_versioned_dir('dir2')
649 self._mk_versioned_file('dir2/file2.cc')
650
651 out, err = self.run_bzr(['grep', '-r', 'last:1',
652 '--include', '*.aa', '--include', '*.bb', 'l..e1'])
653 self.assertContainsRe(out, "^dir0/file0.aa~.:line1$", flags=TestGrep._reflags)
654 self.assertContainsRe(out, "^dir1/file1.bb~.:line1$", flags=TestGrep._reflags)
655 self.assertContainsRe(out, "^dir0/file0.aa~.:line10$", flags=TestGrep._reflags)
656 self.assertContainsRe(out, "^dir1/file1.bb~.:line10$", flags=TestGrep._reflags)
657 self.assertNotContainsRe(out, "file1.cc", flags=TestGrep._reflags)
658 # finds line1 and line10
659 self.assertEqual(len(out.splitlines()), 4)
660
661 out, err = self.run_bzr(['grep', '-r', 'last:1',
662 '--include', '*.aa', '--include', '*.bb', 'line1'])
663 self.assertContainsRe(out, "^dir0/file0.aa~.:line1$", flags=TestGrep._reflags)
664 self.assertContainsRe(out, "^dir1/file1.bb~.:line1$", flags=TestGrep._reflags)
665 self.assertContainsRe(out, "^dir0/file0.aa~.:line10$", flags=TestGrep._reflags)
666 self.assertContainsRe(out, "^dir1/file1.bb~.:line10$", flags=TestGrep._reflags)
667 self.assertNotContainsRe(out, "file1.cc", flags=TestGrep._reflags)
668 # finds line1 and line10
669 self.assertEqual(len(out.splitlines()), 4)
670
671 def test_wtree_include_from_outside_dir(self):
672 """(wtree) Ensure --include is respected during recursive search.
673 """
674 wd = 'foobar0'
675 self.make_branch_and_tree(wd)
676 os.chdir(wd)
677
678 self._mk_versioned_dir('dir0')
679 self._mk_versioned_file('dir0/file0.aa')
680
681 self._mk_versioned_dir('dir1')
682 self._mk_versioned_file('dir1/file1.bb')
683
684 self._mk_versioned_dir('dir2')
685 self._mk_versioned_file('dir2/file2.cc')
686
687 out, err = self.run_bzr(['grep', '--include', '*.aa',
688 '--include', '*.bb', 'l.n.1'])
689 self.assertContainsRe(out, "^dir0/file0.aa:line1$", flags=TestGrep._reflags)
690 self.assertContainsRe(out, "^dir1/file1.bb:line1$", flags=TestGrep._reflags)
691 self.assertContainsRe(out, "^dir0/file0.aa:line10$", flags=TestGrep._reflags)
692 self.assertContainsRe(out, "^dir1/file1.bb:line10$", flags=TestGrep._reflags)
693 self.assertNotContainsRe(out, "file1.cc", flags=TestGrep._reflags)
694 # finds line1 and line10
695 self.assertEqual(len(out.splitlines()), 4)
696
697 out, err = self.run_bzr(['grep', '--include', '*.aa',
698 '--include', '*.bb', 'line1'])
699 self.assertContainsRe(out, "^dir0/file0.aa:line1$", flags=TestGrep._reflags)
700 self.assertContainsRe(out, "^dir1/file1.bb:line1$", flags=TestGrep._reflags)
701 self.assertContainsRe(out, "^dir0/file0.aa:line10$", flags=TestGrep._reflags)
702 self.assertContainsRe(out, "^dir1/file1.bb:line10$", flags=TestGrep._reflags)
703 self.assertNotContainsRe(out, "file1.cc", flags=TestGrep._reflags)
704 # finds line1 and line10
705 self.assertEqual(len(out.splitlines()), 4)
706
707 def test_versioned_exclude_from_outside_dir(self):
708 """(versioned) Ensure --exclude is respected during recursive search.
709 """
710 wd = 'foobar0'
711 self.make_branch_and_tree(wd)
712 os.chdir(wd)
713
714 self._mk_versioned_dir('dir0')
715 self._mk_versioned_file('dir0/file0.aa')
716
717 self._mk_versioned_dir('dir1')
718 self._mk_versioned_file('dir1/file1.bb')
719
720 self._mk_versioned_dir('dir2')
721 self._mk_versioned_file('dir2/file2.cc')
722
723 out, err = self.run_bzr(['grep', '-r', 'last:1',
724 '--exclude', '*.cc', 'l..e1'])
725 self.assertContainsRe(out, "^dir0/file0.aa~.:line1", flags=TestGrep._reflags)
726 self.assertContainsRe(out, "^dir1/file1.bb~.:line1", flags=TestGrep._reflags)
727 self.assertNotContainsRe(out, "file1.cc", flags=TestGrep._reflags)
728
729 out, err = self.run_bzr(['grep', '-r', 'last:1',
730 '--exclude', '*.cc', 'line1'])
731 self.assertContainsRe(out, "^dir0/file0.aa~.:line1", flags=TestGrep._reflags)
732 self.assertContainsRe(out, "^dir1/file1.bb~.:line1", flags=TestGrep._reflags)
733 self.assertNotContainsRe(out, "file1.cc", flags=TestGrep._reflags)
734
735 def test_wtree_exclude_from_outside_dir(self):
736 """(wtree) Ensure --exclude is respected during recursive search.
737 """
738 wd = 'foobar0'
739 self.make_branch_and_tree(wd)
740 os.chdir(wd)
741
742 self._mk_versioned_dir('dir0')
743 self._mk_versioned_file('dir0/file0.aa')
744
745 self._mk_versioned_dir('dir1')
746 self._mk_versioned_file('dir1/file1.bb')
747
748 self._mk_versioned_dir('dir2')
749 self._mk_versioned_file('dir2/file2.cc')
750
751 out, err = self.run_bzr(['grep', '--exclude', '*.cc', 'l[hijk]ne1'])
752 self.assertContainsRe(out, "^dir0/file0.aa:line1", flags=TestGrep._reflags)
753 self.assertContainsRe(out, "^dir1/file1.bb:line1", flags=TestGrep._reflags)
754 self.assertNotContainsRe(out, "file1.cc", flags=TestGrep._reflags)
755
756 out, err = self.run_bzr(['grep', '--exclude', '*.cc', 'line1'])
757 self.assertContainsRe(out, "^dir0/file0.aa:line1", flags=TestGrep._reflags)
758 self.assertContainsRe(out, "^dir1/file1.bb:line1", flags=TestGrep._reflags)
759 self.assertNotContainsRe(out, "file1.cc", flags=TestGrep._reflags)
760
761 def test_workingtree_files_from_outside_dir(self):
762 """(wtree) Grep for pattern with dirs passed as argument.
763 """
764 wd = 'foobar0'
765 self.make_branch_and_tree(wd)
766 os.chdir(wd)
767
768 self._mk_versioned_dir('dir0')
769 self._mk_versioned_file('dir0/file0.txt')
770
771 self._mk_versioned_dir('dir1')
772 self._mk_versioned_file('dir1/file1.txt')
773
774 out, err = self.run_bzr(['grep', 'l[aeiou]ne1', 'dir0', 'dir1'])
775 self.assertContainsRe(out, "^dir0/file0.txt:line1", flags=TestGrep._reflags)
776 self.assertContainsRe(out, "^dir1/file1.txt:line1", flags=TestGrep._reflags)
777
778 out, err = self.run_bzr(['grep', 'line1', 'dir0', 'dir1'])
779 self.assertContainsRe(out, "^dir0/file0.txt:line1", flags=TestGrep._reflags)
780 self.assertContainsRe(out, "^dir1/file1.txt:line1", flags=TestGrep._reflags)
781
782 def test_versioned_files_from_outside_dir(self):
783 """(versioned) Grep for pattern with dirs passed as argument.
784 """
785 wd = 'foobar0'
786 self.make_branch_and_tree(wd)
787 os.chdir(wd)
788
789 self._mk_versioned_dir('dir0')
790 self._mk_versioned_file('dir0/file0.txt')
791
792 self._mk_versioned_dir('dir1')
793 self._mk_versioned_file('dir1/file1.txt')
794
795 out, err = self.run_bzr(['grep', '-r', 'last:1', '.ine1', 'dir0', 'dir1'])
796 self.assertContainsRe(out, "^dir0/file0.txt~.:line1", flags=TestGrep._reflags)
797 self.assertContainsRe(out, "^dir1/file1.txt~.:line1", flags=TestGrep._reflags)
798
799 out, err = self.run_bzr(['grep', '-r', 'last:1', 'line1', 'dir0', 'dir1'])
800 self.assertContainsRe(out, "^dir0/file0.txt~.:line1", flags=TestGrep._reflags)
801 self.assertContainsRe(out, "^dir1/file1.txt~.:line1", flags=TestGrep._reflags)
802
803 def test_wtree_files_from_outside_dir(self):
804 """(wtree) Grep for pattern with dirs passed as argument.
805 """
806 wd = 'foobar0'
807 self.make_branch_and_tree(wd)
808 os.chdir(wd)
809
810 self._mk_versioned_dir('dir0')
811 self._mk_versioned_file('dir0/file0.txt')
812
813 self._mk_versioned_dir('dir1')
814 self._mk_versioned_file('dir1/file1.txt')
815
816 out, err = self.run_bzr(['grep', 'li.e1', 'dir0', 'dir1'])
817 self.assertContainsRe(out, "^dir0/file0.txt:line1", flags=TestGrep._reflags)
818 self.assertContainsRe(out, "^dir1/file1.txt:line1", flags=TestGrep._reflags)
819
820 out, err = self.run_bzr(['grep', 'line1', 'dir0', 'dir1'])
821 self.assertContainsRe(out, "^dir0/file0.txt:line1", flags=TestGrep._reflags)
822 self.assertContainsRe(out, "^dir1/file1.txt:line1", flags=TestGrep._reflags)
823
824 def test_versioned_files_from_outside_two_dirs(self):
825 """(versioned) Grep for pattern with two levels of nested dir.
826 """
827 wd = 'foobar0'
828 self.make_branch_and_tree(wd)
829 os.chdir(wd)
830
831 self._mk_versioned_dir('dir0')
832 self._mk_versioned_file('dir0/file0.txt')
833
834 self._mk_versioned_dir('dir1')
835 self._mk_versioned_file('dir1/file1.txt')
836
837 self._mk_versioned_dir('dir0/dir00')
838 self._mk_versioned_file('dir0/dir00/file0.txt')
839
840 out, err = self.run_bzr(['grep', '-r', 'last:1', 'l.ne1', 'dir0/dir00'])
841 self.assertContainsRe(out, "^dir0/dir00/file0.txt~.:line1", flags=TestGrep._reflags)
842
843 out, err = self.run_bzr(['grep', '-r', 'last:1', 'l.ne1'])
844 self.assertContainsRe(out, "^dir0/dir00/file0.txt~.:line1", flags=TestGrep._reflags)
845
846 out, err = self.run_bzr(['grep', '-r', 'last:1', 'line1', 'dir0/dir00'])
847 self.assertContainsRe(out, "^dir0/dir00/file0.txt~.:line1", flags=TestGrep._reflags)
848
849 out, err = self.run_bzr(['grep', '-r', 'last:1', 'line1'])
850 self.assertContainsRe(out, "^dir0/dir00/file0.txt~.:line1", flags=TestGrep._reflags)
851
852 def test_wtree_files_from_outside_two_dirs(self):
853 """(wtree) Grep for pattern with two levels of nested dir.
854 """
855 wd = 'foobar0'
856 self.make_branch_and_tree(wd)
857 os.chdir(wd)
858
859 self._mk_versioned_dir('dir0')
860 self._mk_versioned_file('dir0/file0.txt')
861
862 self._mk_versioned_dir('dir1')
863 self._mk_versioned_file('dir1/file1.txt')
864
865 self._mk_versioned_dir('dir0/dir00')
866 self._mk_versioned_file('dir0/dir00/file0.txt')
867
868 out, err = self.run_bzr(['grep', 'lin.1', 'dir0/dir00'])
869 self.assertContainsRe(out, "^dir0/dir00/file0.txt:line1", flags=TestGrep._reflags)
870
871 out, err = self.run_bzr(['grep', 'li.e1'])
872 self.assertContainsRe(out, "^dir0/dir00/file0.txt:line1", flags=TestGrep._reflags)
873
874 out, err = self.run_bzr(['grep', 'line1', 'dir0/dir00'])
875 self.assertContainsRe(out, "^dir0/dir00/file0.txt:line1", flags=TestGrep._reflags)
876
877 out, err = self.run_bzr(['grep', 'line1'])
878 self.assertContainsRe(out, "^dir0/dir00/file0.txt:line1", flags=TestGrep._reflags)
879
880 def test_versioned_file_within_dir_two_levels(self):
881 """(versioned) Search for pattern while in nested dir (two levels).
882 """
883 wd = 'foobar0'
884 self.make_branch_and_tree(wd)
885 os.chdir(wd)
886 self._mk_versioned_dir('dir0')
887 self._mk_versioned_dir('dir0/dir1')
888 self._mk_versioned_file('dir0/dir1/file0.txt')
889 os.chdir('dir0')
890
891 out, err = self.run_bzr(['grep', '-r', 'last:1', '.ine1'])
892 self.assertContainsRe(out, "^dir1/file0.txt~.:line1", flags=TestGrep._reflags)
893
894 out, err = self.run_bzr(['grep', '-r', 'last:1', '--from-root', 'l.ne1'])
895 self.assertContainsRe(out, "^dir0/dir1/file0.txt~.:line1", flags=TestGrep._reflags)
896
897 out, err = self.run_bzr(['grep', '-r', 'last:1', '--no-recursive', 'line1'])
898 self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags)
899
900 out, err = self.run_bzr(['grep', '-r', 'last:1', 'lin.1'])
901 self.assertContainsRe(out, "^dir1/file0.txt~.:line1", flags=TestGrep._reflags)
902
903 out, err = self.run_bzr(['grep', '-r', 'last:1', '--from-root', 'line1'])
904 self.assertContainsRe(out, "^dir0/dir1/file0.txt~.:line1", flags=TestGrep._reflags)
905
906 out, err = self.run_bzr(['grep', '-r', 'last:1', '--no-recursive', 'line1'])
907 self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags)
908 self.assertEqual(len(out.splitlines()), 0)
909
910 def test_wtree_file_within_dir_two_levels(self):
911 """(wtree) Search for pattern while in nested dir (two levels).
912 """
913 wd = 'foobar0'
914 self.make_branch_and_tree(wd)
915 os.chdir(wd)
916 self._mk_versioned_dir('dir0')
917 self._mk_versioned_dir('dir0/dir1')
918 self._mk_versioned_file('dir0/dir1/file0.txt')
919 os.chdir('dir0')
920
921 out, err = self.run_bzr(['grep', 'l[hij]ne1'])
922 self.assertContainsRe(out, "^dir1/file0.txt:line1", flags=TestGrep._reflags)
923
924 out, err = self.run_bzr(['grep', '--from-root', 'l.ne1'])
925 self.assertContainsRe(out, "^dir0/dir1/file0.txt:line1", flags=TestGrep._reflags)
926
927 out, err = self.run_bzr(['grep', '--no-recursive', 'lin.1'])
928 self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags)
929
930 out, err = self.run_bzr(['grep', 'line1'])
931 self.assertContainsRe(out, "^dir1/file0.txt:line1", flags=TestGrep._reflags)
932
933 out, err = self.run_bzr(['grep', '--from-root', 'line1'])
934 self.assertContainsRe(out, "^dir0/dir1/file0.txt:line1", flags=TestGrep._reflags)
935
936 out, err = self.run_bzr(['grep', '--no-recursive', 'line1'])
937 self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags)
938
939 def test_versioned_ignore_case_no_match(self):
940 """(versioned) Match fails without --ignore-case.
941 """
942 wd = 'foobar0'
943 self.make_branch_and_tree(wd)
944 os.chdir(wd)
945 self._mk_versioned_file('file0.txt')
946
947 out, err = self.run_bzr(['grep', '-r', 'last:1', 'LinE1', 'file0.txt'])
948 self.assertNotContainsRe(out, "file0.txt~.:line1", flags=TestGrep._reflags)
949
950 out, err = self.run_bzr(['grep', '-r', 'last:1', 'Li.E1', 'file0.txt'])
951 self.assertNotContainsRe(out, "file0.txt~.:line1", flags=TestGrep._reflags)
952
953 def test_wtree_ignore_case_no_match(self):
954 """(wtree) Match fails without --ignore-case.
955 """
956 wd = 'foobar0'
957 self.make_branch_and_tree(wd)
958 os.chdir(wd)
959 self._mk_versioned_file('file0.txt')
960
961 out, err = self.run_bzr(['grep', 'LinE1', 'file0.txt'])
962 self.assertNotContainsRe(out, "file0.txt:line1", flags=TestGrep._reflags)
963
964 out, err = self.run_bzr(['grep', '.inE1', 'file0.txt'])
965 self.assertNotContainsRe(out, "file0.txt:line1", flags=TestGrep._reflags)
966
967 def test_versioned_ignore_case_match(self):
968 """(versioned) Match fails without --ignore-case.
969 """
970 wd = 'foobar0'
971 self.make_branch_and_tree(wd)
972 os.chdir(wd)
973 self._mk_versioned_file('file0.txt')
974
975 out, err = self.run_bzr(['grep', '-r', 'last:1',
976 '-i', 'Li.E1', 'file0.txt'])
977 self.assertContainsRe(out, "file0.txt~.:line1", flags=TestGrep._reflags)
978
979 out, err = self.run_bzr(['grep', '-r', 'last:1',
980 '-i', 'LinE1', 'file0.txt'])
981 self.assertContainsRe(out, "file0.txt~.:line1", flags=TestGrep._reflags)
982
983 out, err = self.run_bzr(['grep', '-r', 'last:1',
984 '--ignore-case', 'LinE1', 'file0.txt'])
985 self.assertContainsRe(out, "^file0.txt~.:line1", flags=TestGrep._reflags)
986
987 def test_wtree_ignore_case_match(self):
988 """(wtree) Match fails without --ignore-case.
989 """
990 wd = 'foobar0'
991 self.make_branch_and_tree(wd)
992 os.chdir(wd)
993 self._mk_versioned_file('file0.txt')
994
995 out, err = self.run_bzr(['grep', '-i', 'LinE1', 'file0.txt'])
996 self.assertContainsRe(out, "file0.txt:line1", flags=TestGrep._reflags)
997
998 out, err = self.run_bzr(['grep', '--ignore-case', 'LinE1', 'file0.txt'])
999 self.assertContainsRe(out, "^file0.txt:line1", flags=TestGrep._reflags)
1000
1001 out, err = self.run_bzr(['grep', '--ignore-case', 'Li.E1', 'file0.txt'])
1002 self.assertContainsRe(out, "^file0.txt:line1", flags=TestGrep._reflags)
1003
1004 def test_versioned_from_root_fail(self):
1005 """(versioned) Match should fail without --from-root.
1006 """
1007 wd = 'foobar0'
1008 self.make_branch_and_tree(wd)
1009 os.chdir(wd)
1010 self._mk_versioned_file('file0.txt')
1011 self._mk_versioned_dir('dir0')
1012 os.chdir('dir0')
1013
1014 out, err = self.run_bzr(['grep', '-r', 'last:1', 'li.e1'])
1015 self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags)
1016
1017 out, err = self.run_bzr(['grep', '-r', 'last:1', 'line1'])
1018 self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags)
1019
1020 def test_wtree_from_root_fail(self):
1021 """(wtree) Match should fail without --from-root.
1022 """
1023 wd = 'foobar0'
1024 self.make_branch_and_tree(wd)
1025 os.chdir(wd)
1026 self._mk_versioned_file('file0.txt')
1027 self._mk_versioned_dir('dir0')
1028 os.chdir('dir0')
1029
1030 out, err = self.run_bzr(['grep', 'line1'])
1031 self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags)
1032
1033 out, err = self.run_bzr(['grep', 'li.e1'])
1034 self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags)
1035
1036 def test_versioned_from_root_pass(self):
1037 """(versioned) Match pass with --from-root.
1038 """
1039 wd = 'foobar0'
1040 self.make_branch_and_tree(wd)
1041 os.chdir(wd)
1042 self._mk_versioned_file('file0.txt')
1043 self._mk_versioned_dir('dir0')
1044 os.chdir('dir0')
1045
1046 out, err = self.run_bzr(['grep', '-r', 'last:1',
1047 '--from-root', 'l.ne1'])
1048 self.assertContainsRe(out, "file0.txt~.:line1", flags=TestGrep._reflags)
1049
1050 out, err = self.run_bzr(['grep', '-r', 'last:1',
1051 '--from-root', 'line1'])
1052 self.assertContainsRe(out, "file0.txt~.:line1", flags=TestGrep._reflags)
1053
1054 def test_wtree_from_root_pass(self):
1055 """(wtree) Match pass with --from-root.
1056 """
1057 wd = 'foobar0'
1058 self.make_branch_and_tree(wd)
1059 os.chdir(wd)
1060 self._mk_versioned_file('file0.txt')
1061 self._mk_versioned_dir('dir0')
1062 os.chdir('dir0')
1063
1064 out, err = self.run_bzr(['grep', '--from-root', 'lin.1'])
1065 self.assertContainsRe(out, "file0.txt:line1", flags=TestGrep._reflags)
1066
1067 out, err = self.run_bzr(['grep', '--from-root', 'line1'])
1068 self.assertContainsRe(out, "file0.txt:line1", flags=TestGrep._reflags)
1069
1070 def test_versioned_with_line_number(self):
1071 """(versioned) Search for pattern with --line-number.
1072 """
1073 wd = 'foobar0'
1074 self.make_branch_and_tree(wd)
1075 os.chdir(wd)
1076 self._mk_versioned_file('file0.txt')
1077
1078 out, err = self.run_bzr(['grep', '-r', 'last:1',
1079 '--line-number', 'li.e3', 'file0.txt'])
1080 self.assertContainsRe(out, "file0.txt~.:3:line3", flags=TestGrep._reflags)
1081
1082 out, err = self.run_bzr(['grep', '-r', 'last:1',
1083 '--line-number', 'line3', 'file0.txt'])
1084 self.assertContainsRe(out, "file0.txt~.:3:line3", flags=TestGrep._reflags)
1085
1086 out, err = self.run_bzr(['grep', '-r', 'last:1',
1087 '-n', 'line1', 'file0.txt'])
1088 self.assertContainsRe(out, "file0.txt~.:1:line1", flags=TestGrep._reflags)
1089
1090 out, err = self.run_bzr(['grep', '-n', 'line[0-9]', 'file0.txt'])
1091 self.assertContainsRe(out, "file0.txt:3:line3", flags=TestGrep._reflags)
1092
1093 def test_wtree_with_line_number(self):
1094 """(wtree) Search for pattern with --line-number.
1095 """
1096 wd = 'foobar0'
1097 self.make_branch_and_tree(wd)
1098 os.chdir(wd)
1099 self._mk_versioned_file('file0.txt')
1100
1101 out, err = self.run_bzr(['grep', '--line-number', 'line3', 'file0.txt'])
1102 self.assertContainsRe(out, "file0.txt:3:line3", flags=TestGrep._reflags)
1103
1104 out, err = self.run_bzr(['grep', '-n', 'line1', 'file0.txt'])
1105 self.assertContainsRe(out, "file0.txt:1:line1", flags=TestGrep._reflags)
1106
1107 out, err = self.run_bzr(['grep', '-n', '[hjkl]ine1', 'file0.txt'])
1108 self.assertContainsRe(out, "file0.txt:1:line1", flags=TestGrep._reflags)
1109
1110 out, err = self.run_bzr(['grep', '-n', 'line[0-9]', 'file0.txt'])
1111 self.assertContainsRe(out, "file0.txt:3:line3", flags=TestGrep._reflags)
1112
1113 def test_revno_basic_history_grep_file(self):
1114 """Search for pattern in specific revision number in a file.
1115 """
1116 wd = 'foobar0'
1117 fname = 'file0.txt'
1118 self.make_branch_and_tree(wd)
1119 os.chdir(wd)
1120 self._mk_versioned_file(fname, total_lines=0)
1121 self._update_file(fname, text="v2 text\n")
1122 self._update_file(fname, text="v3 text\n")
1123 self._update_file(fname, text="v4 text\n")
1124
1125 # rev 2 should not have text 'v3'
1126 out, err = self.run_bzr(['grep', '-r', '2', 'v3', fname])
1127 self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags)
1128
1129 # rev 3 should not have text 'v3'
1130 out, err = self.run_bzr(['grep', '-r', '3', 'v3', fname])
1131 self.assertContainsRe(out, "file0.txt~3:v3.*", flags=TestGrep._reflags)
1132
1133 # rev 3 should not have text 'v3' with line number
1134 out, err = self.run_bzr(['grep', '-r', '3', '-n', 'v3', fname])
1135 self.assertContainsRe(out, "file0.txt~3:2:v3.*", flags=TestGrep._reflags)
1136
1137 # rev 2 should not have text 'v3'
1138 out, err = self.run_bzr(['grep', '-r', '2', '[tuv]3', fname])
1139 self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags)
1140
1141 # rev 3 should not have text 'v3'
1142 out, err = self.run_bzr(['grep', '-r', '3', '[tuv]3', fname])
1143 self.assertContainsRe(out, "file0.txt~3:v3.*", flags=TestGrep._reflags)
1144
1145 # rev 3 should not have text 'v3' with line number
1146 out, err = self.run_bzr(['grep', '-r', '3', '-n', '[tuv]3', fname])
1147 self.assertContainsRe(out, "file0.txt~3:2:v3.*", flags=TestGrep._reflags)
1148
1149 def test_revno_basic_history_grep_full(self):
1150 """Search for pattern in specific revision number in a file.
1151 """
1152 wd = 'foobar0'
1153 fname = 'file0.txt'
1154 self.make_branch_and_tree(wd)
1155 os.chdir(wd)
1156 self._mk_versioned_file(fname, total_lines=0) # rev1
1157 self._mk_versioned_file('file1.txt') # rev2
1158 self._update_file(fname, text="v3 text\n") # rev3
1159 self._update_file(fname, text="v4 text\n") # rev4
1160 self._update_file(fname, text="v5 text\n") # rev5
1161
1162 # rev 2 should not have text 'v3'
1163 out, err = self.run_bzr(['grep', '-r', '2', 'v3'])
1164 self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags)
1165
1166 # rev 3 should not have text 'v3'
1167 out, err = self.run_bzr(['grep', '-r', '3', 'v3'])
1168 self.assertContainsRe(out, "file0.txt~3:v3", flags=TestGrep._reflags)
1169
1170 # rev 3 should not have text 'v3' with line number
1171 out, err = self.run_bzr(['grep', '-r', '3', '-n', 'v3'])
1172 self.assertContainsRe(out, "file0.txt~3:1:v3", flags=TestGrep._reflags)
1173
1174 # rev 2 should not have text 'v3'
1175 out, err = self.run_bzr(['grep', '-r', '2', '[tuv]3'])
1176 self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags)
1177
1178 # rev 3 should not have text 'v3'
1179 out, err = self.run_bzr(['grep', '-r', '3', '[tuv]3'])
1180 self.assertContainsRe(out, "file0.txt~3:v3", flags=TestGrep._reflags)
1181
1182 # rev 3 should not have text 'v3' with line number
1183 out, err = self.run_bzr(['grep', '-r', '3', '-n', '[tuv]3'])
1184 self.assertContainsRe(out, "file0.txt~3:1:v3", flags=TestGrep._reflags)
1185
1186 def test_revno_versioned_file_in_dir(self):
1187 """Grep specific version of file withing dir.
1188 """
1189 wd = 'foobar0'
1190 self.make_branch_and_tree(wd)
1191 os.chdir(wd)
1192 self._mk_versioned_dir('dir0') # rev1
1193 self._mk_versioned_file('dir0/file0.txt') # rev2
1194 self._update_file('dir0/file0.txt', "v3 text\n") # rev3
1195 self._update_file('dir0/file0.txt', "v4 text\n") # rev4
1196 self._update_file('dir0/file0.txt', "v5 text\n") # rev5
1197
1198 # v4 should not be present in revno 3
1199 out, err = self.run_bzr(['grep', '-r', 'last:3', 'v4'])
1200 self.assertNotContainsRe(out, "^dir0/file0.txt", flags=TestGrep._reflags)
1201
1202 # v4 should be present in revno 4
1203 out, err = self.run_bzr(['grep', '-r', 'last:2', 'v4'])
1204 self.assertContainsRe(out, "^dir0/file0.txt~4:v4", flags=TestGrep._reflags)
1205
1206 # v4 should not be present in revno 3
1207 out, err = self.run_bzr(['grep', '-r', 'last:3', '[tuv]4'])
1208 self.assertNotContainsRe(out, "^dir0/file0.txt", flags=TestGrep._reflags)
1209
1210 # v4 should be present in revno 4
1211 out, err = self.run_bzr(['grep', '-r', 'last:2', '[tuv]4'])
1212 self.assertContainsRe(out, "^dir0/file0.txt~4:v4", flags=TestGrep._reflags)
1213
1214 def test_revno_range_basic_history_grep(self):
1215 """Search for pattern in revision range for file.
1216 """
1217 wd = 'foobar0'
1218 fname = 'file0.txt'
1219 self.make_branch_and_tree(wd)
1220 os.chdir(wd)
1221 self._mk_versioned_file(fname, total_lines=0) # rev1
1222 self._mk_versioned_file('file1.txt') # rev2
1223 self._update_file(fname, text="v3 text\n") # rev3
1224 self._update_file(fname, text="v4 text\n") # rev4
1225 self._update_file(fname, text="v5 text\n") # rev5
1226 self._update_file(fname, text="v6 text\n") # rev6
1227
1228 out, err = self.run_bzr(['grep', '-r', '1..', 'v3'])
1229 self.assertContainsRe(out, "file0.txt~3:v3", flags=TestGrep._reflags)
1230 self.assertContainsRe(out, "file0.txt~4:v3", flags=TestGrep._reflags)
1231 self.assertContainsRe(out, "file0.txt~5:v3", flags=TestGrep._reflags)
1232 self.assertContainsRe(out, "file0.txt~6:v3", flags=TestGrep._reflags)
1233 self.assertEqual(len(out.splitlines()), 4)
1234
1235 out, err = self.run_bzr(['grep', '-r', '..1', 'v3'])
1236 # searching only rev1 gives nothing
1237 self.assertEqual(len(out.splitlines()), 0)
1238
1239 out, err = self.run_bzr(['grep', '-r', '..6', 'v3'])
1240 self.assertContainsRe(out, "file0.txt~3:v3", flags=TestGrep._reflags)
1241 self.assertContainsRe(out, "file0.txt~4:v3", flags=TestGrep._reflags)
1242 self.assertContainsRe(out, "file0.txt~5:v3", flags=TestGrep._reflags)
1243 self.assertContainsRe(out, "file0.txt~6:v3", flags=TestGrep._reflags)
1244 self.assertEqual(len(out.splitlines()), 4)
1245
1246 out, err = self.run_bzr(['grep', '-r', '..', 'v3'])
1247 self.assertContainsRe(out, "file0.txt~3:v3", flags=TestGrep._reflags)
1248 self.assertContainsRe(out, "file0.txt~4:v3", flags=TestGrep._reflags)
1249 self.assertContainsRe(out, "file0.txt~5:v3", flags=TestGrep._reflags)
1250 self.assertContainsRe(out, "file0.txt~6:v3", flags=TestGrep._reflags)
1251 self.assertEqual(len(out.splitlines()), 4)
1252
1253 out, err = self.run_bzr(['grep', '-r', '1..5', 'v3'])
1254 self.assertContainsRe(out, "file0.txt~3:v3", flags=TestGrep._reflags)
1255 self.assertContainsRe(out, "file0.txt~4:v3", flags=TestGrep._reflags)
1256 self.assertContainsRe(out, "file0.txt~5:v3", flags=TestGrep._reflags)
1257 self.assertNotContainsRe(out, "file0.txt~6:v3", flags=TestGrep._reflags)
1258 self.assertEqual(len(out.splitlines()), 3)
1259
1260 out, err = self.run_bzr(['grep', '-r', '5..1', 'v3'])
1261 self.assertContainsRe(out, "file0.txt~3:v3", flags=TestGrep._reflags)
1262 self.assertContainsRe(out, "file0.txt~4:v3", flags=TestGrep._reflags)
1263 self.assertContainsRe(out, "file0.txt~5:v3", flags=TestGrep._reflags)
1264 self.assertNotContainsRe(out, "file0.txt~6:v3", flags=TestGrep._reflags)
1265 self.assertEqual(len(out.splitlines()), 3)
1266
1267 out, err = self.run_bzr(['grep', '-r', '1..', '[tuv]3'])
1268 self.assertContainsRe(out, "file0.txt~3:v3", flags=TestGrep._reflags)
1269 self.assertContainsRe(out, "file0.txt~4:v3", flags=TestGrep._reflags)
1270 self.assertContainsRe(out, "file0.txt~5:v3", flags=TestGrep._reflags)
1271 self.assertContainsRe(out, "file0.txt~6:v3", flags=TestGrep._reflags)
1272 self.assertEqual(len(out.splitlines()), 4)
1273
1274 out, err = self.run_bzr(['grep', '-r', '1..5', '[tuv]3'])
1275 self.assertContainsRe(out, "file0.txt~3:v3", flags=TestGrep._reflags)
1276 self.assertContainsRe(out, "file0.txt~4:v3", flags=TestGrep._reflags)
1277 self.assertContainsRe(out, "file0.txt~5:v3", flags=TestGrep._reflags)
1278 self.assertNotContainsRe(out, "file0.txt~6:v3", flags=TestGrep._reflags)
1279 self.assertEqual(len(out.splitlines()), 3)
1280
1281 out, err = self.run_bzr(['grep', '-r', '5..1', '[tuv]3'])
1282 self.assertContainsRe(out, "file0.txt~3:v3", flags=TestGrep._reflags)
1283 self.assertContainsRe(out, "file0.txt~4:v3", flags=TestGrep._reflags)
1284 self.assertContainsRe(out, "file0.txt~5:v3", flags=TestGrep._reflags)
1285 self.assertNotContainsRe(out, "file0.txt~6:v3", flags=TestGrep._reflags)
1286 self.assertEqual(len(out.splitlines()), 3)
1287
1288 def test_revno_range_versioned_file_in_dir(self):
1289 """Grep rev-range for pattern for file withing a dir.
1290 """
1291 wd = 'foobar0'
1292 self.make_branch_and_tree(wd)
1293 os.chdir(wd)
1294 self._mk_versioned_dir('dir0') # rev1
1295 self._mk_versioned_file('dir0/file0.txt') # rev2
1296 self._update_file('dir0/file0.txt', "v3 text\n") # rev3
1297 self._update_file('dir0/file0.txt', "v4 text\n") # rev4
1298 self._update_file('dir0/file0.txt', "v5 text\n") # rev5
1299 self._update_file('dir0/file0.txt', "v6 text\n") # rev6
1300
1301 out, err = self.run_bzr(['grep', '-r', '2..5', 'v3'])
1302 self.assertContainsRe(out, "^dir0/file0.txt~3:v3", flags=TestGrep._reflags)
1303 self.assertContainsRe(out, "^dir0/file0.txt~4:v3", flags=TestGrep._reflags)
1304 self.assertContainsRe(out, "^dir0/file0.txt~5:v3", flags=TestGrep._reflags)
1305 self.assertNotContainsRe(out, "^dir0/file0.txt~6:v3", flags=TestGrep._reflags)
1306 self.assertEqual(len(out.splitlines()), 3)
1307
1308 out, err = self.run_bzr(['grep', '-r', '2..5', '[tuv]3'])
1309 self.assertContainsRe(out, "^dir0/file0.txt~3:v3", flags=TestGrep._reflags)
1310 self.assertContainsRe(out, "^dir0/file0.txt~4:v3", flags=TestGrep._reflags)
1311 self.assertContainsRe(out, "^dir0/file0.txt~5:v3", flags=TestGrep._reflags)
1312 self.assertNotContainsRe(out, "^dir0/file0.txt~6:v3", flags=TestGrep._reflags)
1313 self.assertEqual(len(out.splitlines()), 3)
1314
1315 def test_revno_range_versioned_file_from_outside_dir(self):
1316 """Grep rev-range for pattern from outside dir.
1317 """
1318 wd = 'foobar0'
1319 self.make_branch_and_tree(wd)
1320 os.chdir(wd)
1321 self._mk_versioned_dir('dir0') # rev1
1322 self._mk_versioned_file('dir0/file0.txt') # rev2
1323 self._update_file('dir0/file0.txt', "v3 text\n") # rev3
1324 self._update_file('dir0/file0.txt', "v4 text\n") # rev4
1325 self._update_file('dir0/file0.txt', "v5 text\n") # rev5
1326 self._update_file('dir0/file0.txt', "v6 text\n") # rev6
1327
1328 out, err = self.run_bzr(['grep', '-r', '2..5', 'v3', 'dir0'])
1329 self.assertContainsRe(out, "^dir0/file0.txt~3:v3", flags=TestGrep._reflags)
1330 self.assertContainsRe(out, "^dir0/file0.txt~4:v3", flags=TestGrep._reflags)
1331 self.assertContainsRe(out, "^dir0/file0.txt~5:v3", flags=TestGrep._reflags)
1332 self.assertNotContainsRe(out, "^dir0/file0.txt~6:v3", flags=TestGrep._reflags)
1333
1334 out, err = self.run_bzr(['grep', '-r', '2..5', '[tuv]3', 'dir0'])
1335 self.assertContainsRe(out, "^dir0/file0.txt~3:v3", flags=TestGrep._reflags)
1336 self.assertContainsRe(out, "^dir0/file0.txt~4:v3", flags=TestGrep._reflags)
1337 self.assertContainsRe(out, "^dir0/file0.txt~5:v3", flags=TestGrep._reflags)
1338 self.assertNotContainsRe(out, "^dir0/file0.txt~6:v3", flags=TestGrep._reflags)
1339
1340 def test_levels(self):
1341 """--levels=0 should show findings from merged revision.
1342 """
1343 wd0 = 'foobar0'
1344 wd1 = 'foobar1'
1345
1346 self.make_branch_and_tree(wd0)
1347 os.chdir(wd0)
1348 self._mk_versioned_file('file0.txt')
1349 os.chdir('..')
1350
1351 out, err = self.run_bzr(['branch', wd0, wd1])
1352 os.chdir(wd1)
1353 self._mk_versioned_file('file1.txt')
1354 os.chdir(osutils.pathjoin('..', wd0))
1355
1356 out, err = self.run_bzr(['merge', osutils.pathjoin('..', wd1)])
1357 out, err = self.run_bzr(['ci', '-m', 'merged'])
1358
1359 out, err = self.run_bzr(['grep', 'line1'])
1360 self.assertContainsRe(out, "file0.txt:line1", flags=TestGrep._reflags)
1361 self.assertContainsRe(out, "file1.txt:line1", flags=TestGrep._reflags)
1362
1363 # levels should be ignored by wtree grep
1364 out, err = self.run_bzr(['grep', '--levels=0', 'line1'])
1365 self.assertContainsRe(out, "^file0.txt:line1$", flags=TestGrep._reflags)
1366 self.assertContainsRe(out, "^file1.txt:line1$", flags=TestGrep._reflags)
1367 self.assertContainsRe(out, "^file0.txt:line10$", flags=TestGrep._reflags)
1368 self.assertContainsRe(out, "^file1.txt:line10$", flags=TestGrep._reflags)
1369 self.assertEqual(len(out.splitlines()), 4)
1370
1371 out, err = self.run_bzr(['grep', '-r', 'last:1..', '--levels=0', 'line1'])
1372 self.assertContainsRe(out, "^file0.txt~2:line1$", flags=TestGrep._reflags)
1373 self.assertContainsRe(out, "^file1.txt~2:line1$", flags=TestGrep._reflags)
1374 self.assertContainsRe(out, "^file0.txt~1.1.1:line1$", flags=TestGrep._reflags)
1375 self.assertContainsRe(out, "^file1.txt~1.1.1:line1$", flags=TestGrep._reflags)
1376 self.assertContainsRe(out, "^file0.txt~2:line10$", flags=TestGrep._reflags)
1377 self.assertContainsRe(out, "^file1.txt~2:line10$", flags=TestGrep._reflags)
1378 self.assertContainsRe(out, "^file0.txt~1.1.1:line10$", flags=TestGrep._reflags)
1379 self.assertContainsRe(out, "^file1.txt~1.1.1:line10$", flags=TestGrep._reflags)
1380 self.assertEqual(len(out.splitlines()), 8)
1381
1382 out, err = self.run_bzr(['grep', '-r', '-1..', '-n', '--levels=0', 'line1'])
1383 self.assertContainsRe(out, "^file0.txt~2:1:line1$", flags=TestGrep._reflags)
1384 self.assertContainsRe(out, "^file1.txt~2:1:line1$", flags=TestGrep._reflags)
1385 self.assertContainsRe(out, "^file0.txt~1.1.1:1:line1$", flags=TestGrep._reflags)
1386 self.assertContainsRe(out, "^file1.txt~1.1.1:1:line1$", flags=TestGrep._reflags)
1387 self.assertContainsRe(out, "^file0.txt~2:10:line10$", flags=TestGrep._reflags)
1388 self.assertContainsRe(out, "^file1.txt~2:10:line10$", flags=TestGrep._reflags)
1389 self.assertContainsRe(out, "^file0.txt~1.1.1:10:line10$", flags=TestGrep._reflags)
1390 self.assertContainsRe(out, "^file1.txt~1.1.1:10:line10$", flags=TestGrep._reflags)
1391 self.assertEqual(len(out.splitlines()), 8)
1392
1393 # levels should be ignored by wtree grep
1394 out, err = self.run_bzr(['grep', '--levels=0', 'l.ne1'])
1395 self.assertContainsRe(out, "^file0.txt:line1$", flags=TestGrep._reflags)
1396 self.assertContainsRe(out, "^file1.txt:line1$", flags=TestGrep._reflags)
1397 self.assertContainsRe(out, "^file0.txt:line10$", flags=TestGrep._reflags)
1398 self.assertContainsRe(out, "^file1.txt:line10$", flags=TestGrep._reflags)
1399 self.assertEqual(len(out.splitlines()), 4)
1400
1401 out, err = self.run_bzr(['grep', '-r', 'last:1..', '--levels=0', 'lin.1'])
1402 self.assertContainsRe(out, "^file0.txt~2:line1$", flags=TestGrep._reflags)
1403 self.assertContainsRe(out, "^file1.txt~2:line1$", flags=TestGrep._reflags)
1404 self.assertContainsRe(out, "^file0.txt~1.1.1:line1$", flags=TestGrep._reflags)
1405 self.assertContainsRe(out, "^file1.txt~1.1.1:line1$", flags=TestGrep._reflags)
1406 self.assertContainsRe(out, "^file0.txt~2:line10$", flags=TestGrep._reflags)
1407 self.assertContainsRe(out, "^file1.txt~2:line10$", flags=TestGrep._reflags)
1408 self.assertContainsRe(out, "^file0.txt~1.1.1:line10$", flags=TestGrep._reflags)
1409 self.assertContainsRe(out, "^file1.txt~1.1.1:line10$", flags=TestGrep._reflags)
1410 self.assertEqual(len(out.splitlines()), 8)
1411
1412 out, err = self.run_bzr(['grep', '-r', '-1..', '-n', '--levels=0', '.ine1'])
1413 self.assertContainsRe(out, "file0.txt~2:1:line1", flags=TestGrep._reflags)
1414 self.assertContainsRe(out, "file1.txt~2:1:line1", flags=TestGrep._reflags)
1415 self.assertContainsRe(out, "file0.txt~1.1.1:1:line1", flags=TestGrep._reflags)
1416 self.assertContainsRe(out, "file1.txt~1.1.1:1:line1", flags=TestGrep._reflags)
1417
1418 def test_dotted_rev_grep(self):
1419 """Grep in dotted revs
1420 """
1421 wd0 = 'foobar0'
1422 wd1 = 'foobar1'
1423
1424 self.make_branch_and_tree(wd0)
1425 os.chdir(wd0)
1426 self._mk_versioned_file('file0.txt')
1427 os.chdir('..')
1428
1429 out, err = self.run_bzr(['branch', wd0, wd1])
1430 os.chdir(wd1)
1431 self._mk_versioned_file('file1.txt') # revno 1.1.1
1432 self._update_file('file1.txt', "text 0\n") # revno 1.1.2
1433 self._update_file('file1.txt', "text 1\n") # revno 1.1.3
1434 self._update_file('file1.txt', "text 2\n") # revno 1.1.4
1435 os.chdir(osutils.pathjoin('..', wd0))
1436
1437 out, err = self.run_bzr(['merge', osutils.pathjoin('..', wd1)])
1438 out, err = self.run_bzr(['ci', '-m', 'merged'])
1439
1440 out, err = self.run_bzr(['grep', '-r', '1.1.1..1.1.4', 'text'])
1441 self.assertContainsRe(out, "file1.txt~1.1.2:text 0", flags=TestGrep._reflags)
1442 self.assertContainsRe(out, "file1.txt~1.1.3:text 1", flags=TestGrep._reflags)
1443 self.assertContainsRe(out, "file1.txt~1.1.3:text 1", flags=TestGrep._reflags)
1444 self.assertContainsRe(out, "file1.txt~1.1.4:text 0", flags=TestGrep._reflags)
1445 self.assertContainsRe(out, "file1.txt~1.1.4:text 1", flags=TestGrep._reflags)
1446 self.assertContainsRe(out, "file1.txt~1.1.4:text 2", flags=TestGrep._reflags)
1447 self.assertEqual(len(out.splitlines()), 6)
1448
1449 def test_versioned_binary_file_grep(self):
1450 """(versioned) Grep for pattern in binary file.
1451 """
1452 wd = 'foobar0'
1453 self.make_branch_and_tree(wd)
1454 os.chdir(wd)
1455 self._mk_versioned_file('file.txt')
1456 self._mk_versioned_file('file0.bin')
1457 self._update_file('file0.bin', "\x00lineNN\x00\n")
1458
1459 # note: set --verbose/-v flag to get the skip message.
1460 out, err = self.run_bzr(['grep', '-v', '-r', 'last:1',
1461 'lineNN', 'file0.bin'])
1462 self.assertNotContainsRe(out, "file0.bin", flags=TestGrep._reflags)
1463 self.assertContainsRe(err, "Binary file.*file0.bin.*skipped", flags=TestGrep._reflags)
1464 self.assertEqual(len(out.splitlines()), 0)
1465 self.assertEqual(len(err.splitlines()), 1)
1466
1467 out, err = self.run_bzr(['grep', '-v', '-r', 'last:1',
1468 'line.N', 'file0.bin'])
1469 self.assertNotContainsRe(out, "file0.bin", flags=TestGrep._reflags)
1470 self.assertContainsRe(err, "Binary file.*file0.bin.*skipped", flags=TestGrep._reflags)
1471 self.assertEqual(len(out.splitlines()), 0)
1472 self.assertEqual(len(err.splitlines()), 1)
1473
1474 def test_wtree_binary_file_grep(self):
1475 """(wtree) Grep for pattern in binary file.
1476 """
1477 wd = 'foobar0'
1478 self.make_branch_and_tree(wd)
1479 os.chdir(wd)
1480 self._mk_versioned_file('file0.bin')
1481 self._update_file('file0.bin', "\x00lineNN\x00\n")
1482
1483 # note: set --verbose/-v flag to get the skip message.
1484 out, err = self.run_bzr(['grep', '-v', 'lineNN', 'file0.bin'])
1485 self.assertNotContainsRe(out, "file0.bin:line1", flags=TestGrep._reflags)
1486 self.assertContainsRe(err, "Binary file.*file0.bin.*skipped", flags=TestGrep._reflags)
1487
1488 # binary warning should not be shown without --verbose
1489 out, err = self.run_bzr(['grep', 'lineNN', 'file0.bin'])
1490 self.assertNotContainsRe(out, "file0.bin:line1", flags=TestGrep._reflags)
1491 self.assertNotContainsRe(err, "Binary file", flags=TestGrep._reflags)
1492
1493 def test_revspec(self):
1494 """Ensure various revspecs work
1495 """
1496 wd = 'foobar0'
1497 self.make_branch_and_tree(wd)
1498 os.chdir(wd)
1499 self._mk_versioned_dir('dir0') # rev1
1500 self._mk_versioned_file('dir0/file0.txt') # rev2
1501 self._update_file('dir0/file0.txt', "v3 text\n") # rev3
1502 self._update_file('dir0/file0.txt', "v4 text\n") # rev4
1503 self._update_file('dir0/file0.txt', "v5 text\n") # rev5
1504
1505 out, err = self.run_bzr(['grep', '-r', 'revno:1..2', 'v3'])
1506 self.assertNotContainsRe(out, "file0", flags=TestGrep._reflags)
1507 self.assertEqual(len(out.splitlines()), 0)
1508
1509 out, err = self.run_bzr(['grep', '-r', 'revno:4..', 'v4'])
1510 self.assertContainsRe(out, "^dir0/file0.txt", flags=TestGrep._reflags)
1511 self.assertEqual(len(out.splitlines()), 2) # find v4 in rev4 and rev5
1512
1513 out, err = self.run_bzr(['grep', '-r', '..revno:3', 'v4'])
1514 self.assertNotContainsRe(out, "file0", flags=TestGrep._reflags)
1515 self.assertEqual(len(out.splitlines()), 0)
1516
1517 out, err = self.run_bzr(['grep', '-r', '..revno:3', 'v3'])
1518 self.assertContainsRe(out, "^dir0/file0.txt", flags=TestGrep._reflags)
1519 self.assertEqual(len(out.splitlines()), 1)
1520
1521 def test_wtree_files_with_matches(self):
1522 """(wtree) Ensure --files-with-matches, -l works
1523 """
1524 wd = 'foobar0'
1525 self.make_branch_and_tree(wd)
1526 os.chdir(wd)
1527
1528 self._mk_versioned_file('file0.txt', total_lines=2)
1529 self._mk_versioned_file('file1.txt', total_lines=2)
1530 self._mk_versioned_dir('dir0')
1531 self._mk_versioned_file('dir0/file00.txt', total_lines=2)
1532 self._mk_versioned_file('dir0/file01.txt', total_lines=2)
1533
1534 self._update_file('file0.txt', 'HELLO\n', checkin=False)
1535 self._update_file('dir0/file00.txt', 'HELLO\n', checkin=False)
1536
1537 # fixed-string
1538 out, err = self.run_bzr(['grep', '--files-with-matches', 'HELLO'])
1539
1540 self.assertContainsRe(out, "^file0.txt$", flags=TestGrep._reflags)
1541 self.assertContainsRe(out, "^dir0/file00.txt$", flags=TestGrep._reflags)
1542 self.assertEqual(len(out.splitlines()), 2)
1543
1544 # regex
1545 out, err = self.run_bzr(['grep', '--files-with-matches', 'HE.LO'])
1546
1547 self.assertContainsRe(out, "^file0.txt$", flags=TestGrep._reflags)
1548 self.assertContainsRe(out, "^dir0/file00.txt$", flags=TestGrep._reflags)
1549 self.assertEqual(len(out.splitlines()), 2)
1550
1551 # fixed-string
1552 out, err = self.run_bzr(['grep', '-l', 'HELLO'])
1553
1554 self.assertContainsRe(out, "^file0.txt$", flags=TestGrep._reflags)
1555 self.assertContainsRe(out, "^dir0/file00.txt$", flags=TestGrep._reflags)
1556 self.assertEqual(len(out.splitlines()), 2)
1557
1558 # regex
1559 out, err = self.run_bzr(['grep', '-l', 'HE.LO'])
1560
1561 self.assertContainsRe(out, "^file0.txt$", flags=TestGrep._reflags)
1562 self.assertContainsRe(out, "^dir0/file00.txt$", flags=TestGrep._reflags)
1563 self.assertEqual(len(out.splitlines()), 2)
1564
1565 # fixed-string
1566 out, err = self.run_bzr(['grep', '-l', 'HELLO', 'dir0', 'file1.txt'])
1567
1568 self.assertContainsRe(out, "^dir0/file00.txt$", flags=TestGrep._reflags)
1569 self.assertEqual(len(out.splitlines()), 1)
1570
1571 # regex
1572 out, err = self.run_bzr(['grep', '-l', '.ELLO', 'dir0', 'file1.txt'])
1573
1574 self.assertContainsRe(out, "^dir0/file00.txt$", flags=TestGrep._reflags)
1575 self.assertEqual(len(out.splitlines()), 1)
1576
1577 # fixed-string
1578 out, err = self.run_bzr(['grep', '-l', 'HELLO', 'file0.txt'])
1579
1580 self.assertContainsRe(out, "^file0.txt$", flags=TestGrep._reflags)
1581 self.assertEqual(len(out.splitlines()), 1)
1582
1583 # regex
1584 out, err = self.run_bzr(['grep', '-l', '.ELLO', 'file0.txt'])
1585
1586 self.assertContainsRe(out, "^file0.txt$", flags=TestGrep._reflags)
1587 self.assertEqual(len(out.splitlines()), 1)
1588
1589 # fixed-string
1590 out, err = self.run_bzr(['grep', '--no-recursive', '-l', 'HELLO'])
1591
1592 self.assertContainsRe(out, "^file0.txt$", flags=TestGrep._reflags)
1593 self.assertEqual(len(out.splitlines()), 1)
1594
1595 # regex
1596 out, err = self.run_bzr(['grep', '--no-recursive', '-l', '.ELLO'])
1597
1598 self.assertContainsRe(out, "^file0.txt$", flags=TestGrep._reflags)
1599 self.assertEqual(len(out.splitlines()), 1)
1600
1601 def test_ver_files_with_matches(self):
1602 """(ver) Ensure --files-with-matches, -l works
1603 """
1604 wd = 'foobar0'
1605 self.make_branch_and_tree(wd)
1606 os.chdir(wd)
1607
1608 self._mk_versioned_file('file0.txt', total_lines=2) # rev 1
1609 self._mk_versioned_file('file1.txt', total_lines=2) # rev 2
1610 self._mk_versioned_dir('dir0') # rev 3
1611 self._mk_versioned_file('dir0/file00.txt', total_lines=2) # rev 4
1612 self._mk_versioned_file('dir0/file01.txt', total_lines=2) # rev 5
1613
1614 self._update_file('file0.txt', 'HELLO\n') # rev 6
1615 self._update_file('dir0/file00.txt', 'HELLO\n') # rev 7
1616
1617 # fixed-string
1618 out, err = self.run_bzr(['grep', '-r', '-1', '--files-with-matches',
1619 'HELLO'])
1620
1621 self.assertContainsRe(out, "^file0.txt~7$", flags=TestGrep._reflags)
1622 self.assertContainsRe(out, "^dir0/file00.txt~7$", flags=TestGrep._reflags)
1623 self.assertEqual(len(out.splitlines()), 2)
1624
1625 # regex
1626 out, err = self.run_bzr(['grep', '-r', '-1', '--files-with-matches',
1627 'H.LLO'])
1628
1629 self.assertContainsRe(out, "^file0.txt~7$", flags=TestGrep._reflags)
1630 self.assertContainsRe(out, "^dir0/file00.txt~7$", flags=TestGrep._reflags)
1631 self.assertEqual(len(out.splitlines()), 2)
1632
1633 # fixed-string
1634 out, err = self.run_bzr(['grep', '-r', '6..7', '--files-with-matches',
1635 'HELLO'])
1636
1637 self.assertContainsRe(out, "^file0.txt~6$", flags=TestGrep._reflags)
1638 self.assertContainsRe(out, "^file0.txt~7$", flags=TestGrep._reflags)
1639 self.assertContainsRe(out, "^dir0/file00.txt~7$", flags=TestGrep._reflags)
1640 self.assertEqual(len(out.splitlines()), 3)
1641
1642 # regex
1643 out, err = self.run_bzr(['grep', '-r', '6..7', '--files-with-matches',
1644 'H.LLO'])
1645
1646 self.assertContainsRe(out, "^file0.txt~6$", flags=TestGrep._reflags)
1647 self.assertContainsRe(out, "^file0.txt~7$", flags=TestGrep._reflags)
1648 self.assertContainsRe(out, "^dir0/file00.txt~7$", flags=TestGrep._reflags)
1649 self.assertEqual(len(out.splitlines()), 3)
1650
1651 # fixed-string
1652 out, err = self.run_bzr(['grep', '-r', '-1', '-l', 'HELLO'])
1653
1654 self.assertContainsRe(out, "^file0.txt~7$", flags=TestGrep._reflags)
1655 self.assertContainsRe(out, "^dir0/file00.txt~7$", flags=TestGrep._reflags)
1656 self.assertEqual(len(out.splitlines()), 2)
1657
1658 # regex
1659 out, err = self.run_bzr(['grep', '-r', '-1', '-l', 'H.LLO'])
1660
1661 self.assertContainsRe(out, "^file0.txt~7$", flags=TestGrep._reflags)
1662 self.assertContainsRe(out, "^dir0/file00.txt~7$", flags=TestGrep._reflags)
1663 self.assertEqual(len(out.splitlines()), 2)
1664
1665 # fixed-string
1666 out, err = self.run_bzr(['grep', '-l', 'HELLO', '-r', '-1',
1667 'dir0', 'file1.txt'])
1668
1669 self.assertContainsRe(out, "^dir0/file00.txt~7$", flags=TestGrep._reflags)
1670 self.assertEqual(len(out.splitlines()), 1)
1671
1672 # regex
1673 out, err = self.run_bzr(['grep', '-l', 'H.LLO', '-r', '-1',
1674 'dir0', 'file1.txt'])
1675
1676 self.assertContainsRe(out, "^dir0/file00.txt~7$", flags=TestGrep._reflags)
1677 self.assertEqual(len(out.splitlines()), 1)
1678
1679 # fixed-string
1680 out, err = self.run_bzr(['grep', '-l', 'HELLO',
1681 '-r', '-2', 'file0.txt'])
1682
1683 self.assertContainsRe(out, "^file0.txt~6$", flags=TestGrep._reflags)
1684 self.assertEqual(len(out.splitlines()), 1)
1685
1686 # regex
1687 out, err = self.run_bzr(['grep', '-l', 'HE.LO',
1688 '-r', '-2', 'file0.txt'])
1689
1690 self.assertContainsRe(out, "^file0.txt~6$", flags=TestGrep._reflags)
1691 self.assertEqual(len(out.splitlines()), 1)
1692
1693 # fixed-string
1694 out, err = self.run_bzr(['grep', '--no-recursive', '-r', '-1',
1695 '-l', 'HELLO'])
1696
1697 self.assertContainsRe(out, "^file0.txt~7$", flags=TestGrep._reflags)
1698 self.assertEqual(len(out.splitlines()), 1)
1699
1700 # regex
1701 out, err = self.run_bzr(['grep', '--no-recursive', '-r', '-1',
1702 '-l', '.ELLO'])
1703
1704 self.assertContainsRe(out, "^file0.txt~7$", flags=TestGrep._reflags)
1705 self.assertEqual(len(out.splitlines()), 1)
1706
1707 def test_wtree_files_without_matches(self):
1708 """(wtree) Ensure --files-without-match, -L works
1709 """
1710 wd = 'foobar0'
1711 self.make_branch_and_tree(wd)
1712 os.chdir(wd)
1713
1714 self._mk_versioned_file('file0.txt', total_lines=2)
1715 self._mk_versioned_file('file1.txt', total_lines=2)
1716 self._mk_versioned_dir('dir0')
1717 self._mk_versioned_file('dir0/file00.txt', total_lines=2)
1718 self._mk_versioned_file('dir0/file01.txt', total_lines=2)
1719
1720 self._update_file('file0.txt', 'HELLO\n', checkin=False)
1721 self._update_file('dir0/file00.txt', 'HELLO\n', checkin=False)
1722
1723 # fixed-string
1724 out, err = self.run_bzr(['grep', '--files-without-match', 'HELLO'])
1725
1726 self.assertContainsRe(out, "^file1.txt$", flags=TestGrep._reflags)
1727 self.assertContainsRe(out, "^dir0/file01.txt$", flags=TestGrep._reflags)
1728 self.assertEqual(len(out.splitlines()), 2)
1729
1730 # regex
1731 out, err = self.run_bzr(['grep', '--files-without-match', 'HE.LO'])
1732
1733 self.assertContainsRe(out, "^file1.txt$", flags=TestGrep._reflags)
1734 self.assertContainsRe(out, "^dir0/file01.txt$", flags=TestGrep._reflags)
1735 self.assertEqual(len(out.splitlines()), 2)
1736
1737 # fixed-string
1738 out, err = self.run_bzr(['grep', '-L', 'HELLO'])
1739
1740 self.assertContainsRe(out, "^file1.txt$", flags=TestGrep._reflags)
1741 self.assertContainsRe(out, "^dir0/file01.txt$", flags=TestGrep._reflags)
1742 self.assertEqual(len(out.splitlines()), 2)
1743
1744 # regex
1745 out, err = self.run_bzr(['grep', '-L', 'HE.LO'])
1746
1747 self.assertContainsRe(out, "^file1.txt$", flags=TestGrep._reflags)
1748 self.assertContainsRe(out, "^dir0/file01.txt$", flags=TestGrep._reflags)
1749 self.assertEqual(len(out.splitlines()), 2)
1750
1751 # fixed-string
1752 out, err = self.run_bzr(['grep', '-L', 'HELLO', 'dir0', 'file1.txt'])
1753
1754 self.assertContainsRe(out, "^file1.txt$", flags=TestGrep._reflags)
1755 self.assertContainsRe(out, "^dir0/file01.txt$", flags=TestGrep._reflags)
1756 self.assertEqual(len(out.splitlines()), 2)
1757
1758 # regex
1759 out, err = self.run_bzr(['grep', '-L', '.ELLO', 'dir0', 'file1.txt'])
1760
1761 self.assertContainsRe(out, "^file1.txt$", flags=TestGrep._reflags)
1762 self.assertContainsRe(out, "^dir0/file01.txt$", flags=TestGrep._reflags)
1763 self.assertEqual(len(out.splitlines()), 2)
1764
1765 # fixed-string
1766 out, err = self.run_bzr(['grep', '-L', 'HELLO', 'file1.txt'])
1767
1768 self.assertContainsRe(out, "^file1.txt$", flags=TestGrep._reflags)
1769 self.assertEqual(len(out.splitlines()), 1)
1770
1771 # regex
1772 out, err = self.run_bzr(['grep', '-L', '.ELLO', 'file1.txt'])
1773
1774 self.assertContainsRe(out, "^file1.txt$", flags=TestGrep._reflags)
1775 self.assertEqual(len(out.splitlines()), 1)
1776
1777 # fixed-string
1778 out, err = self.run_bzr(['grep', '--no-recursive', '-L', 'HELLO'])
1779
1780 self.assertContainsRe(out, "^file1.txt$", flags=TestGrep._reflags)
1781 self.assertEqual(len(out.splitlines()), 1)
1782
1783 # regex
1784 out, err = self.run_bzr(['grep', '--no-recursive', '-L', '.ELLO'])
1785
1786 self.assertContainsRe(out, "^file1.txt$", flags=TestGrep._reflags)
1787 self.assertEqual(len(out.splitlines()), 1)
1788
1789 def test_ver_files_without_matches(self):
1790 """(ver) Ensure --files-without-match, -L works
1791 """
1792 wd = 'foobar0'
1793 self.make_branch_and_tree(wd)
1794 os.chdir(wd)
1795
1796 self._mk_versioned_file('file0.txt', total_lines=2) # rev 1
1797 self._mk_versioned_file('file1.txt', total_lines=2) # rev 2
1798 self._mk_versioned_dir('dir0') # rev 3
1799 self._mk_versioned_file('dir0/file00.txt', total_lines=2) # rev 4
1800 self._mk_versioned_file('dir0/file01.txt', total_lines=2) # rev 5
1801
1802 self._update_file('file0.txt', 'HELLO\n') # rev 6
1803 self._update_file('dir0/file00.txt', 'HELLO\n') # rev 7
1804
1805 # fixed-string
1806 out, err = self.run_bzr(['grep', '-r', '-1', '--files-without-match',
1807 'HELLO'])
1808
1809 self.assertContainsRe(out, "^file1.txt~7$", flags=TestGrep._reflags)
1810 self.assertContainsRe(out, "^dir0/file01.txt~7$", flags=TestGrep._reflags)
1811 self.assertEqual(len(out.splitlines()), 2)
1812
1813 # regex
1814 out, err = self.run_bzr(['grep', '-r', '-1', '--files-without-match',
1815 'H.LLO'])
1816
1817 self.assertContainsRe(out, "^file1.txt~7$", flags=TestGrep._reflags)
1818 self.assertContainsRe(out, "^dir0/file01.txt~7$", flags=TestGrep._reflags)
1819 self.assertEqual(len(out.splitlines()), 2)
1820
1821 # fixed-string
1822 out, err = self.run_bzr(['grep', '-r', '6..7', '--files-without-match',
1823 'HELLO'])
1824
1825 self.assertContainsRe(out, "^file1.txt~6$", flags=TestGrep._reflags)
1826 self.assertContainsRe(out, "^dir0/file00.txt~6$", flags=TestGrep._reflags)
1827 self.assertContainsRe(out, "^dir0/file01.txt~6$", flags=TestGrep._reflags)
1828 self.assertContainsRe(out, "^file1.txt~7$", flags=TestGrep._reflags)
1829 self.assertContainsRe(out, "^dir0/file01.txt~7$", flags=TestGrep._reflags)
1830 self.assertEqual(len(out.splitlines()), 5)
1831
1832 # regex
1833 out, err = self.run_bzr(['grep', '-r', '6..7', '--files-without-match',
1834 'H.LLO'])
1835
1836 self.assertContainsRe(out, "^file1.txt~6$", flags=TestGrep._reflags)
1837 self.assertContainsRe(out, "^dir0/file00.txt~6$", flags=TestGrep._reflags)
1838 self.assertContainsRe(out, "^dir0/file01.txt~6$", flags=TestGrep._reflags)
1839 self.assertContainsRe(out, "^file1.txt~7$", flags=TestGrep._reflags)
1840 self.assertContainsRe(out, "^dir0/file01.txt~7$", flags=TestGrep._reflags)
1841 self.assertEqual(len(out.splitlines()), 5)
1842
1843 # fixed-string
1844 out, err = self.run_bzr(['grep', '-r', '-1', '-L', 'HELLO'])
1845
1846 self.assertContainsRe(out, "^file1.txt~7$", flags=TestGrep._reflags)
1847 self.assertContainsRe(out, "^dir0/file01.txt~7$", flags=TestGrep._reflags)
1848 self.assertEqual(len(out.splitlines()), 2)
1849
1850 # regex
1851 out, err = self.run_bzr(['grep', '-r', '-1', '-L', 'H.LLO'])
1852
1853 self.assertContainsRe(out, "^file1.txt~7$", flags=TestGrep._reflags)
1854 self.assertContainsRe(out, "^dir0/file01.txt~7$", flags=TestGrep._reflags)
1855 self.assertEqual(len(out.splitlines()), 2)
1856
1857 # fixed-string
1858 out, err = self.run_bzr(['grep', '-L', 'HELLO', '-r', '-1',
1859 'dir0', 'file1.txt'])
1860
1861 self.assertContainsRe(out, "^file1.txt~7$", flags=TestGrep._reflags)
1862 self.assertContainsRe(out, "^dir0/file01.txt~7$", flags=TestGrep._reflags)
1863 self.assertEqual(len(out.splitlines()), 2)
1864
1865 # regex
1866 out, err = self.run_bzr(['grep', '-L', 'H.LLO', '-r', '-1',
1867 'dir0', 'file1.txt'])
1868
1869 self.assertContainsRe(out, "^file1.txt~7$", flags=TestGrep._reflags)
1870 self.assertContainsRe(out, "^dir0/file01.txt~7$", flags=TestGrep._reflags)
1871 self.assertEqual(len(out.splitlines()), 2)
1872
1873 # fixed-string
1874 out, err = self.run_bzr(['grep', '-L', 'HELLO',
1875 '-r', '-2', 'file1.txt'])
1876
1877 self.assertContainsRe(out, "^file1.txt~6$", flags=TestGrep._reflags)
1878 self.assertEqual(len(out.splitlines()), 1)
1879
1880 # regex
1881 out, err = self.run_bzr(['grep', '-L', 'HE.LO',
1882 '-r', '-2', 'file1.txt'])
1883
1884 self.assertContainsRe(out, "^file1.txt~6$", flags=TestGrep._reflags)
1885 self.assertEqual(len(out.splitlines()), 1)
1886
1887 # fixed-string
1888 out, err = self.run_bzr(['grep', '--no-recursive', '-r', '-1',
1889 '-L', 'HELLO'])
1890
1891 self.assertContainsRe(out, "^file1.txt~7$", flags=TestGrep._reflags)
1892 self.assertEqual(len(out.splitlines()), 1)
1893
1894 # regex
1895 out, err = self.run_bzr(['grep', '--no-recursive', '-r', '-1',
1896 '-L', '.ELLO'])
1897
1898 self.assertContainsRe(out, "^file1.txt~7$", flags=TestGrep._reflags)
1899 self.assertEqual(len(out.splitlines()), 1)
1900
1901 def test_no_tree(self):
1902 """Ensure grep works without working tree.
1903 """
1904 wd0 = 'foobar0'
1905 wd1 = 'foobar1'
1906 self.make_branch_and_tree(wd0)
1907 os.chdir(wd0)
1908 self._mk_versioned_file('file0.txt')
1909 os.chdir('..')
1910 out, err = self.run_bzr(['branch', '--no-tree', wd0, wd1])
1911 os.chdir(wd1)
1912
1913 out, err = self.run_bzr(['grep', 'line1'], 3)
1914 self.assertContainsRe(err, "Cannot search working tree", flags=TestGrep._reflags)
1915 self.assertEqual(out, '')
1916
1917 out, err = self.run_bzr(['grep', '-r', '1', 'line1'])
1918 self.assertContainsRe(out, "file0.txt~1:line1", flags=TestGrep._reflags)
1919 self.assertEqual(len(out.splitlines()), 2) # finds line1 and line10
1920
1921
1922class TestNonAscii(GrepTestBase):
1923 """Tests for non-ascii filenames and file contents"""
1924
1925 _test_needs_features = [UnicodeFilenameFeature]
1926
1927 def test_unicode_only_file(self):
1928 """Test filename and contents that requires a unicode encoding"""
1929 tree = self.make_branch_and_tree(".")
1930 contents = [u"\u1234"]
1931 self.build_tree(contents)
1932 tree.add(contents)
1933 tree.commit("Initial commit")
1934 as_utf8 = u"\u1234".encode("UTF-8")
1935
1936 # GZ 2010-06-07: Note we can't actually grep for \u1234 as the pattern
1937 # is mangled according to the user encoding.
1938 streams = self.run_bzr(["grep", "--files-with-matches",
1939 u"contents"], encoding="UTF-8")
1940 self.assertEqual(streams, (as_utf8 + "\n", ""))
1941
1942 streams = self.run_bzr(["grep", "-r", "1", "--files-with-matches",
1943 u"contents"], encoding="UTF-8")
1944 self.assertEqual(streams, (as_utf8 + "~1\n", ""))
1945
1946 fileencoding = osutils.get_user_encoding()
1947 as_mangled = as_utf8.decode(fileencoding, "replace").encode("UTF-8")
1948
1949 streams = self.run_bzr(["grep", "-n",
1950 u"contents"], encoding="UTF-8")
1951 self.assertEqual(streams, ("%s:1:contents of %s\n" %
1952 (as_utf8, as_mangled), ""))
1953
1954 streams = self.run_bzr(["grep", "-n", "-r", "1",
1955 u"contents"], encoding="UTF-8")
1956 self.assertEqual(streams, ("%s~1:1:contents of %s\n" %
1957 (as_utf8, as_mangled), ""))
1958
1959
1960class TestColorGrep(GrepTestBase):
1961 """Tests for the --color option."""
1962
1963 # GZ 2010-06-05: Does this really require the feature? Nothing prints.
1964 _test_needs_features = [ColorFeature]
1965
1966 _rev_sep = color_string('~', fg=FG.BOLD_YELLOW)
1967 _sep = color_string(':', fg=FG.BOLD_CYAN)
1968
1969 def test_color_option(self):
1970 """Ensure options for color are valid.
1971 """
1972 out, err = self.run_bzr(['grep', '--color', 'foo', 'bar'], 3)
1973 self.assertEqual(out, '')
1974 self.assertContainsRe(err, 'Valid values for --color are', flags=TestGrep._reflags)
1975
1976 def test_ver_matching_files(self):
1977 """(versioned) Search for matches or no matches only"""
1978 tree = self.make_branch_and_tree(".")
1979 contents = ["d/", "d/aaa", "bbb"]
1980 self.build_tree(contents)
1981 tree.add(contents)
1982 tree.commit("Initial commit")
1983
1984 # GZ 2010-06-05: Maybe modify the working tree here
1985
1986 streams = self.run_bzr(["grep", "--color", "always", "-r", "1",
1987 "--files-with-matches", "aaa"])
1988 self.assertEqual(streams, ("".join([
1989 FG.MAGENTA, "d/aaa", self._rev_sep, "1", "\n"
1990 ]), ""))
1991
1992 streams = self.run_bzr(["grep", "--color", "always", "-r", "1",
1993 "--files-without-match", "aaa"])
1994 self.assertEqual(streams, ("".join([
1995 FG.MAGENTA, "bbb", self._rev_sep, "1", "\n"
1996 ]), ""))
1997
1998 def test_wtree_matching_files(self):
1999 """(wtree) Search for matches or no matches only"""
2000 tree = self.make_branch_and_tree(".")
2001 contents = ["d/", "d/aaa", "bbb"]
2002 self.build_tree(contents)
2003 tree.add(contents)
2004 tree.commit("Initial commit")
2005
2006 # GZ 2010-06-05: Maybe modify the working tree here
2007
2008 streams = self.run_bzr(["grep", "--color", "always",
2009 "--files-with-matches", "aaa"])
2010 self.assertEqual(streams, ("".join([
2011 FG.MAGENTA, "d/aaa", FG.NONE, "\n"
2012 ]), ""))
2013
2014 streams = self.run_bzr(["grep", "--color", "always",
2015 "--files-without-match", "aaa"])
2016 self.assertEqual(streams, ("".join([
2017 FG.MAGENTA, "bbb", FG.NONE, "\n"
2018 ]), ""))
2019
2020 def test_ver_basic_file(self):
2021 """(versioned) Search for pattern in specfic file.
2022 """
2023 wd = 'foobar0'
2024 self.make_branch_and_tree(wd)
2025 os.chdir(wd)
2026 lp = 'foo is foobar'
2027 self._mk_versioned_file('file0.txt', line_prefix=lp, total_lines=1)
2028
2029 # prepare colored result
2030 foo = color_string('foo', fg=FG.BOLD_RED)
2031 res = (FG.MAGENTA + 'file0.txt'
2032 + self._rev_sep + '1' + self._sep
2033 + foo + ' is ' + foo + 'bar1' + '\n')
2034 txt_res = 'file0.txt~1:foo is foobar1\n'
2035
2036 nres = (FG.MAGENTA + 'file0.txt'
2037 + self._rev_sep + '1' + self._sep + '1' + self._sep
2038 + foo + ' is ' + foo + 'bar1' + '\n')
2039
2040 out, err = self.run_bzr(['grep', '--color',
2041 'always', '-r', '1', 'foo'])
2042 self.assertEqual(out, res)
2043 self.assertEqual(len(out.splitlines()), 1)
2044
2045 # auto should produce plain text result
2046 # as stdout is redireched here.
2047 out, err = self.run_bzr(['grep', '--color',
2048 'auto', '-r', '1', 'foo'])
2049 self.assertEqual(out, txt_res)
2050 self.assertEqual(len(out.splitlines()), 1)
2051
2052 out, err = self.run_bzr(['grep', '-i', '--color',
2053 'always', '-r', '1', 'FOO'])
2054 self.assertEqual(out, res)
2055 self.assertEqual(len(out.splitlines()), 1)
2056
2057 out, err = self.run_bzr(['grep', '--color',
2058 'always', '-r', '1', 'f.o'])
2059 self.assertEqual(out, res)
2060 self.assertEqual(len(out.splitlines()), 1)
2061
2062 out, err = self.run_bzr(['grep', '-i', '--color',
2063 'always', '-r', '1', 'F.O'])
2064 self.assertEqual(out, res)
2065 self.assertEqual(len(out.splitlines()), 1)
2066
2067 out, err = self.run_bzr(['grep', '-n', '--color',
2068 'always', '-r', '1', 'foo'])
2069 self.assertEqual(out, nres)
2070 self.assertEqual(len(out.splitlines()), 1)
2071
2072 out, err = self.run_bzr(['grep', '-n', '-i', '--color',
2073 'always', '-r', '1', 'FOO'])
2074 self.assertEqual(out, nres)
2075 self.assertEqual(len(out.splitlines()), 1)
2076
2077 out, err = self.run_bzr(['grep', '-n', '--color',
2078 'always', '-r', '1', 'f.o'])
2079 self.assertEqual(out, nres)
2080 self.assertEqual(len(out.splitlines()), 1)
2081
2082 out, err = self.run_bzr(['grep', '-n', '-i', '--color',
2083 'always', '-r', '1', 'F.O'])
2084 self.assertEqual(out, nres)
2085 self.assertEqual(len(out.splitlines()), 1)
2086
2087 def test_wtree_basic_file(self):
2088 """(wtree) Search for pattern in specfic file.
2089 """
2090 wd = 'foobar0'
2091 self.make_branch_and_tree(wd)
2092 os.chdir(wd)
2093 lp = 'foo is foobar'
2094 self._mk_versioned_file('file0.txt', line_prefix=lp, total_lines=1)
2095
2096 # prepare colored result
2097 foo = color_string('foo', fg=FG.BOLD_RED)
2098 res = (FG.MAGENTA + 'file0.txt'
2099 + self._sep + foo + ' is ' + foo + 'bar1' + '\n')
2100
2101 nres = (FG.MAGENTA + 'file0.txt'
2102 + self._sep + '1' + self._sep
2103 + foo + ' is ' + foo + 'bar1' + '\n')
2104
2105 out, err = self.run_bzr(['grep', '--color',
2106 'always', 'foo'])
2107 self.assertEqual(out, res)
2108 self.assertEqual(len(out.splitlines()), 1)
2109
2110 out, err = self.run_bzr(['grep', '-i', '--color',
2111 'always', 'FOO'])
2112 self.assertEqual(out, res)
2113 self.assertEqual(len(out.splitlines()), 1)
2114
2115 out, err = self.run_bzr(['grep', '--color',
2116 'always', 'f.o'])
2117 self.assertEqual(out, res)
2118 self.assertEqual(len(out.splitlines()), 1)
2119
2120 out, err = self.run_bzr(['grep', '-i', '--color',
2121 'always', 'F.O'])
2122 self.assertEqual(out, res)
2123 self.assertEqual(len(out.splitlines()), 1)
2124
2125 out, err = self.run_bzr(['grep', '-n', '--color',
2126 'always', 'foo'])
2127 self.assertEqual(out, nres)
2128 self.assertEqual(len(out.splitlines()), 1)
2129
2130 out, err = self.run_bzr(['grep', '-n', '-i', '--color',
2131 'always', 'FOO'])
2132 self.assertEqual(out, nres)
2133 self.assertEqual(len(out.splitlines()), 1)
2134
2135 out, err = self.run_bzr(['grep', '-n', '--color',
2136 'always', 'f.o'])
2137 self.assertEqual(out, nres)
2138 self.assertEqual(len(out.splitlines()), 1)
2139
2140 out, err = self.run_bzr(['grep', '-n', '-i', '--color',
2141 'always', 'F.O'])
2142 self.assertEqual(out, nres)
2143 self.assertEqual(len(out.splitlines()), 1)
2144
2145
2146# copied from bzrlib.tests.blackbox.test_diff
2147def subst_dates(string):
2148 """Replace date strings with constant values."""
2149 return re.sub(r'\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-\+]\d{4}',
2150 'YYYY-MM-DD HH:MM:SS +ZZZZ', string)
2151
2152
2153class TestGrepDiff(tests.TestCaseWithTransport):
2154
2155 def make_example_branch(self):
2156 tree = self.make_branch_and_tree('.')
2157 self.build_tree_contents([
2158 ('hello', 'foo\n'),
2159 ('goodbye', 'baz\n')])
2160 tree.add(['hello'])
2161 tree.commit('setup')
2162 tree.add(['goodbye'])
2163 tree.commit('setup')
2164 return tree
2165
2166 def test_grep_diff_basic(self):
2167 """grep -p basic test."""
2168 tree = self.make_example_branch()
2169 self.build_tree_contents([('hello', 'hello world!\n')])
2170 tree.commit('updated hello')
2171 out, err = self.run_bzr(['grep', '-p', 'hello'])
2172 self.assertEquals(err, '')
2173 self.assertEqualDiff(subst_dates(out), '''\
2174=== revno:3 ===
2175 === modified file 'hello'
2176 --- hello YYYY-MM-DD HH:MM:SS +ZZZZ
2177 +++ hello YYYY-MM-DD HH:MM:SS +ZZZZ
2178 +hello world!
2179=== revno:1 ===
2180 === added file 'hello'
2181 --- hello YYYY-MM-DD HH:MM:SS +ZZZZ
2182 +++ hello YYYY-MM-DD HH:MM:SS +ZZZZ
2183''')
2184
2185 def test_grep_diff_revision(self):
2186 """grep -p specific revision."""
2187 tree = self.make_example_branch()
2188 self.build_tree_contents([('hello', 'hello world!\n')])
2189 tree.commit('updated hello')
2190 out, err = self.run_bzr(['grep', '-p', '-r', '3', 'hello'])
2191 self.assertEquals(err, '')
2192 self.assertEqualDiff(subst_dates(out), '''\
2193=== revno:3 ===
2194 === modified file 'hello'
2195 --- hello YYYY-MM-DD HH:MM:SS +ZZZZ
2196 +++ hello YYYY-MM-DD HH:MM:SS +ZZZZ
2197 +hello world!
2198''')
2199
2200 def test_grep_diff_revision_range(self):
2201 """grep -p revision range."""
2202 tree = self.make_example_branch()
2203 self.build_tree_contents([('hello', 'hello world!1\n')]) # rev 3
2204 tree.commit('rev3')
2205 self.build_tree_contents([('blah', 'hello world!2\n')]) # rev 4
2206 tree.add('blah')
2207 tree.commit('rev4')
2208 open('hello', 'a').write('hello world!3\n')
2209 #self.build_tree_contents([('hello', 'hello world!3\n')]) # rev 5
2210 tree.commit('rev5')
2211 out, err = self.run_bzr(['grep', '-p', '-r', '2..5', 'hello'])
2212 self.assertEquals(err, '')
2213 self.assertEqualDiff(subst_dates(out), '''\
2214=== revno:5 ===
2215 === modified file 'hello'
2216 --- hello YYYY-MM-DD HH:MM:SS +ZZZZ
2217 +++ hello YYYY-MM-DD HH:MM:SS +ZZZZ
2218 +hello world!3
2219=== revno:4 ===
2220 === added file 'blah'
2221 +hello world!2
2222=== revno:3 ===
2223 === modified file 'hello'
2224 --- hello YYYY-MM-DD HH:MM:SS +ZZZZ
2225 +++ hello YYYY-MM-DD HH:MM:SS +ZZZZ
2226 +hello world!1
2227''')
2228
2229 def test_grep_diff_color(self):
2230 """grep -p color test."""
2231 tree = self.make_example_branch()
2232 self.build_tree_contents([('hello', 'hello world!\n')])
2233 tree.commit('updated hello')
2234 out, err = self.run_bzr(['grep', '--diff', '-r', '3',
2235 '--color', 'always', 'hello'])
2236 self.assertEquals(err, '')
2237 revno = color_string('=== revno:3 ===', fg=FG.BOLD_BLUE) + '\n'
2238 filename = color_string(" === modified file 'hello'", fg=FG.BOLD_MAGENTA) + '\n'
2239 redhello = color_string('hello', fg=FG.BOLD_RED)
2240 diffstr = '''\
2241 --- hello YYYY-MM-DD HH:MM:SS +ZZZZ
2242 +++ hello YYYY-MM-DD HH:MM:SS +ZZZZ
2243 +hello world!
2244'''
2245 diffstr = diffstr.replace('hello', redhello)
2246 self.assertEqualDiff(subst_dates(out), revno + filename + diffstr)
2247
2248 def test_grep_norevs(self):
2249 """grep -p with zero revisions."""
2250 out, err = self.run_bzr(['init'])
2251 out, err = self.run_bzr(['grep', '--diff', 'foo'], 3)
2252 self.assertEquals(out, '')
2253 self.assertContainsRe(err, "ERROR:.*revision.* does not exist in branch")
2254
02255
=== modified file 'bzrlib/tests/features.py'
--- bzrlib/tests/features.py 2012-03-09 16:48:55 +0000
+++ bzrlib/tests/features.py 2012-08-23 15:07:23 +0000
@@ -492,3 +492,15 @@
492492
493493
494win32_feature = Win32Feature()494win32_feature = Win32Feature()
495
496
497class _ColorFeature(Feature):
498
499 def _probe(self):
500 from bzrlib._termcolor import allow_color
501 return allow_color()
502
503 def feature_name(self):
504 return "Terminal supports color."
505
506ColorFeature = _ColorFeature()
495507
=== modified file 'doc/en/release-notes/bzr-2.6.txt'
--- doc/en/release-notes/bzr-2.6.txt 2012-08-03 12:22:25 +0000
+++ doc/en/release-notes/bzr-2.6.txt 2012-08-23 15:07:23 +0000
@@ -106,6 +106,8 @@
106* New option ``--overwrite-tags`` for ``bzr pull`` and ``bzr push``.106* New option ``--overwrite-tags`` for ``bzr pull`` and ``bzr push``.
107 (Jelmer Vernooij, #681792)107 (Jelmer Vernooij, #681792)
108108
109* The 'grep' plugin is now shipped with bzr. (Jelmer Vernooij)
110
109Improvements111Improvements
110************112************
111113