Merge lp:~jelmer/bzr/merge-grep into lp:bzr
- merge-grep
- Merge into bzr.dev
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 |
Related bugs: |
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.
To post a comment you must log in.
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
1 | === added file 'bzrlib/_termcolor.py' |
2 | --- bzrlib/_termcolor.py 1970-01-01 00:00:00 +0000 |
3 | +++ bzrlib/_termcolor.py 2012-08-23 15:07:23 +0000 |
4 | @@ -0,0 +1,78 @@ |
5 | +# Copyright (C) 2010 Canonical Ltd |
6 | +# |
7 | +# This program is free software; you can redistribute it and/or modify |
8 | +# it under the terms of the GNU General Public License as published by |
9 | +# the Free Software Foundation; either version 2 of the License, or |
10 | +# (at your option) any later version. |
11 | +# |
12 | +# This program is distributed in the hope that it will be useful, |
13 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | +# GNU General Public License for more details. |
16 | +# |
17 | +# You should have received a copy of the GNU General Public License |
18 | +# along with this program; if not, write to the Free Software |
19 | +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | + |
21 | +from __future__ import absolute_import |
22 | + |
23 | +import os |
24 | +import sys |
25 | + |
26 | + |
27 | +class FG(object): |
28 | + """Unix terminal foreground color codes (16-color).""" |
29 | + RED = '\033[31m' |
30 | + GREEN = '\033[32m' |
31 | + YELLOW = '\033[33m' |
32 | + BLUE = '\033[34m' |
33 | + MAGENTA = '\033[35m' |
34 | + CYAN = '\033[36m' |
35 | + WHITE = '\033[37m' |
36 | + |
37 | + # Bold Foreground |
38 | + BOLD_RED = '\033[1;31m' |
39 | + BOLD_GREEN = '\033[1;32m' |
40 | + BOLD_YELLOW = '\033[1;33m' |
41 | + BOLD_BLUE = '\033[1;34m' |
42 | + BOLD_MAGENTA = '\033[1;35m' |
43 | + BOLD_CYAN = '\033[1;36m' |
44 | + BOLD_WHITE = '\033[1;37m' |
45 | + |
46 | + NONE = '\033[0m' |
47 | + |
48 | + |
49 | +class BG(object): |
50 | + """Unix terminal background color codes (16-color).""" |
51 | + BLACK = '\033[40m' |
52 | + RED = '\033[41m' |
53 | + GREEN = '\033[42m' |
54 | + YELLOW = '\033[43m' |
55 | + BLUE = '\033[44m' |
56 | + MAGENTA = '\033[45m' |
57 | + CYAN = '\033[46m' |
58 | + WHITE = '\033[47m' |
59 | + |
60 | + NONE = '\033[0m' |
61 | + |
62 | + |
63 | +def color_string(s, fg, bg=''): |
64 | + return fg + bg + s + FG.NONE |
65 | + |
66 | + |
67 | +def re_color_string(compiled_pattern, s, fg): |
68 | + return compiled_pattern.sub(fg + r'\1' + FG.NONE, s) |
69 | + |
70 | + |
71 | +def allow_color(): |
72 | + if os.name != 'posix': |
73 | + return False |
74 | + if not sys.stdout.isatty(): |
75 | + return False |
76 | + try: |
77 | + import curses |
78 | + curses.setupterm() |
79 | + return curses.tigetnum('colors') > 2 |
80 | + except curses.error: |
81 | + return False |
82 | + |
83 | |
84 | === added directory 'bzrlib/plugins/grep' |
85 | === added file 'bzrlib/plugins/grep/.bzrignore' |
86 | --- bzrlib/plugins/grep/.bzrignore 1970-01-01 00:00:00 +0000 |
87 | +++ bzrlib/plugins/grep/.bzrignore 2012-08-23 15:07:23 +0000 |
88 | @@ -0,0 +1,1 @@ |
89 | +./build |
90 | |
91 | === added file 'bzrlib/plugins/grep/NEWS' |
92 | --- bzrlib/plugins/grep/NEWS 1970-01-01 00:00:00 +0000 |
93 | +++ bzrlib/plugins/grep/NEWS 2012-08-23 15:07:23 +0000 |
94 | @@ -0,0 +1,73 @@ |
95 | +This is the NEWS file from bzr-grep from before it was merged into bzr core. |
96 | +For changes before then, please refer to the main bzr log file. |
97 | + |
98 | +bzr-grep 0.5.0-final - Unreleased |
99 | +================================== |
100 | +* ``bzr grep`` now supports ``--diff|-p`` option to search through |
101 | + changesets. (Parth Malwankar, #540705) |
102 | + |
103 | +* Option ``grep_color`` can be set in ``bazaar.conf`` instead of using |
104 | + the option ``--color`` from the command line. (Johan Dahlin) |
105 | + |
106 | +bzr-grep 0.4.0-final - 08-Jun-2010 |
107 | +================================== |
108 | +* Add seperate output formatter to reduce duplication of search loops, |
109 | + additionally make -Fi use regexp rather than lowercasing pattern and |
110 | + entirety of text for the same reason. This also fixes bug #590589 |
111 | + - UnicodeDecodeError with options -Fi. (Martin [gz]) |
112 | + |
113 | +* Added fast path for no match that avoids splitting the file text into |
114 | + seperate lines and testing each one, by checking the entire text for a |
115 | + possible match initially. (Martin [gz]) |
116 | + |
117 | +* Added Makefile. (Parth Malwankar) |
118 | + |
119 | +* Fixed setup.py to work correctly. (Martin [gz]) |
120 | + |
121 | +bzr-grep 0.3.0-final - 23-May-2010 |
122 | +================================== |
123 | +* Support for --color option (POSIX only). (Parth Malwankar, #571694) |
124 | + |
125 | +* Revisions in branches without trees can now be searched with |
126 | + -r option. (Parth Malwankar, #584240) |
127 | + |
128 | +* Trying to search working tree for a treeless branch no longer |
129 | + produces a stack trace but gives an error message suggesting use of |
130 | + -r option. (Parth Malwankar, #572658) |
131 | + |
132 | +bzr-grep 0.2.0-final - 30-Mar-2010 |
133 | +================================== |
134 | +* 'binary file skipped' warning is not shows without --verbose flag |
135 | + (Parth Malwankar, #539031) |
136 | + |
137 | +* Added support for -F/--fixed-string for faster search. |
138 | + Simple patterns [a-zA-Z0-9 _] are now implicitly -F and searched faster. |
139 | + (Parth Malwankar, #539263) |
140 | + |
141 | +* Better unicode handling. bzr-grep no longer crashes with UnicodeDecode |
142 | + error for some outputs. (Parth Malwankar, #539258) |
143 | + |
144 | +* Faster grep for revision range. bzr-grep now caches results for |
145 | + files that have not changed between revisions. |
146 | + (Parth Malwankar, #542375) |
147 | + |
148 | +* Faster grep for specific revision. (Parth Malwankar, #539429) |
149 | + |
150 | +* Significant performance improvement. Working tree grep for bzr.dev |
151 | + has gone from ~7.5s to ~1s. (Parth Malwankar, #539028) |
152 | + |
153 | +* Support for -L/--files-without-match and -l/files-with-matches |
154 | + (Parth Malwankar, #540097) |
155 | + |
156 | +bzr-grep 0.1.0-final - 14-Mar-2010 |
157 | +================================== |
158 | +* --recursive is now default. (Parth Malwankar, #536688) |
159 | + |
160 | +* ``bzr grep`` searches working copy by default. (Parth Malwankar, #537072) |
161 | + |
162 | +* --include/exclude=GLOB is now supported. (Parth Malwankar, #529889) |
163 | + |
164 | +bzr-grep 0.0.1-final - 10-Mar-2010 |
165 | +================================== |
166 | +* Initial release (Parth Malwankar) |
167 | + |
168 | |
169 | === added file 'bzrlib/plugins/grep/__init__.py' |
170 | --- bzrlib/plugins/grep/__init__.py 1970-01-01 00:00:00 +0000 |
171 | +++ bzrlib/plugins/grep/__init__.py 2012-08-23 15:07:23 +0000 |
172 | @@ -0,0 +1,38 @@ |
173 | +# Copyright (C) 2010 Canonical Ltd |
174 | +# |
175 | +# This program is free software; you can redistribute it and/or modify |
176 | +# it under the terms of the GNU General Public License as published by |
177 | +# the Free Software Foundation; either version 2 of the License, or |
178 | +# (at your option) any later version. |
179 | +# |
180 | +# This program is distributed in the hope that it will be useful, |
181 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
182 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
183 | +# GNU General Public License for more details. |
184 | +# |
185 | +# You should have received a copy of the GNU General Public License |
186 | +# along with this program; if not, write to the Free Software |
187 | +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
188 | + |
189 | +"""Print lines matching PATTERN for specified files and revisions.""" |
190 | + |
191 | +from __future__ import absolute_import |
192 | + |
193 | +from bzrlib import version_info |
194 | +from bzrlib.commands import plugin_cmds |
195 | + |
196 | +plugin_cmds.register_lazy("cmd_grep", [], "bzrlib.plugins.grep.cmds") |
197 | + |
198 | +def test_suite(): |
199 | + from bzrlib.tests import TestUtil |
200 | + |
201 | + suite = TestUtil.TestSuite() |
202 | + loader = TestUtil.TestLoader() |
203 | + testmod_names = [ |
204 | + 'test_grep', |
205 | + ] |
206 | + |
207 | + suite.addTest(loader.loadTestsFromModuleNames( |
208 | + ["%s.%s" % (__name__, tmn) for tmn in testmod_names])) |
209 | + return suite |
210 | + |
211 | |
212 | === added file 'bzrlib/plugins/grep/cmds.py' |
213 | --- bzrlib/plugins/grep/cmds.py 1970-01-01 00:00:00 +0000 |
214 | +++ bzrlib/plugins/grep/cmds.py 2012-08-23 15:07:23 +0000 |
215 | @@ -0,0 +1,249 @@ |
216 | +# Copyright (C) 2010 Canonical Ltd |
217 | +# |
218 | +# This program is free software; you can redistribute it and/or modify |
219 | +# it under the terms of the GNU General Public License as published by |
220 | +# the Free Software Foundation; either version 2 of the License, or |
221 | +# (at your option) any later version. |
222 | +# |
223 | +# This program is distributed in the hope that it will be useful, |
224 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
225 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
226 | +# GNU General Public License for more details. |
227 | +# |
228 | +# You should have received a copy of the GNU General Public License |
229 | +# along with this program; if not, write to the Free Software |
230 | +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
231 | + |
232 | +"""Print lines matching PATTERN for specified files and revisions.""" |
233 | + |
234 | +from __future__ import absolute_import |
235 | + |
236 | +from bzrlib import errors |
237 | +from bzrlib.commands import Command, display_command |
238 | +from bzrlib.option import Option, ListOption |
239 | +from bzrlib.config import GlobalConfig |
240 | + |
241 | +# FIXME: _parse_levels should be shared with bzrlib.builtins. this is a copy |
242 | +# to avoid the error |
243 | +# "IllegalUseOfScopeReplacer: ScopeReplacer object '_parse_levels' was used |
244 | +# incorrectly: Object already cleaned up, did you assign it to another |
245 | +# variable?: _factory |
246 | +# with lazy import |
247 | +def _parse_levels(s): |
248 | + try: |
249 | + return int(s) |
250 | + except ValueError: |
251 | + msg = "The levels argument must be an integer." |
252 | + raise errors.BzrCommandError(msg) |
253 | + |
254 | + |
255 | +class GrepOptions(object): |
256 | + """Container to pass around grep options. |
257 | + |
258 | + This class is used as a container to pass around user option and |
259 | + some other params (like outf) to processing functions. This makes |
260 | + it easier to add more options as grep evolves. |
261 | + """ |
262 | + verbose = False |
263 | + ignore_case = False |
264 | + no_recursive = False |
265 | + from_root = False |
266 | + null = False |
267 | + levels = None |
268 | + line_number = False |
269 | + path_list = None |
270 | + revision = None |
271 | + pattern = None |
272 | + include = None |
273 | + exclude = None |
274 | + fixed_string = False |
275 | + files_with_matches = False |
276 | + files_without_match = False |
277 | + color = None |
278 | + diff = False |
279 | + |
280 | + # derived options |
281 | + recursive = None |
282 | + eol_marker = None |
283 | + patternc = None |
284 | + sub_patternc = None |
285 | + print_revno = None |
286 | + fixed_string = None |
287 | + outf = None |
288 | + show_color = False |
289 | + |
290 | + |
291 | +class cmd_grep(Command): |
292 | + """Print lines matching PATTERN for specified files and revisions. |
293 | + |
294 | + This command searches the specified files and revisions for a given |
295 | + pattern. The pattern is specified as a Python regular expressions[1]. |
296 | + |
297 | + If the file name is not specified, the revisions starting with the |
298 | + current directory are searched recursively. If the revision number is |
299 | + not specified, the working copy is searched. To search the last committed |
300 | + revision, use the '-r -1' or '-r last:1' option. |
301 | + |
302 | + Unversioned files are not searched unless explicitly specified on the |
303 | + command line. Unversioned directores are not searched. |
304 | + |
305 | + When searching a pattern, the output is shown in the 'filepath:string' |
306 | + format. If a revision is explicitly searched, the output is shown as |
307 | + 'filepath~N:string', where N is the revision number. |
308 | + |
309 | + --include and --exclude options can be used to search only (or exclude |
310 | + from search) files with base name matches the specified Unix style GLOB |
311 | + pattern. The GLOB pattern an use *, ?, and [...] as wildcards, and \\ |
312 | + to quote wildcard or backslash character literally. Note that the glob |
313 | + pattern is not a regular expression. |
314 | + |
315 | + [1] http://docs.python.org/library/re.html#regular-expression-syntax |
316 | + """ |
317 | + |
318 | + encoding_type = 'replace' |
319 | + takes_args = ['pattern', 'path*'] |
320 | + takes_options = [ |
321 | + 'verbose', |
322 | + 'revision', |
323 | + Option('color', type=str, argname='when', |
324 | + help='Show match in color. WHEN is never, always or auto.'), |
325 | + Option('diff', short_name='p', |
326 | + help='Grep for pattern in changeset for each revision.'), |
327 | + ListOption('exclude', type=str, argname='glob', short_name='X', |
328 | + help="Skip files whose base name matches GLOB."), |
329 | + ListOption('include', type=str, argname='glob', short_name='I', |
330 | + help="Search only files whose base name matches GLOB."), |
331 | + Option('files-with-matches', short_name='l', |
332 | + help='Print only the name of each input file in ' |
333 | + 'which PATTERN is found.'), |
334 | + Option('files-without-match', short_name='L', |
335 | + help='Print only the name of each input file in ' |
336 | + 'which PATTERN is not found.'), |
337 | + Option('fixed-string', short_name='F', |
338 | + help='Interpret PATTERN is a single fixed string (not regex).'), |
339 | + Option('from-root', |
340 | + help='Search for pattern starting from the root of the branch. ' |
341 | + '(implies --recursive)'), |
342 | + Option('ignore-case', short_name='i', |
343 | + help='ignore case distinctions while matching.'), |
344 | + Option('levels', |
345 | + help='Number of levels to display - 0 for all, 1 for collapsed ' |
346 | + '(1 is default).', |
347 | + argname='N', |
348 | + type=_parse_levels), |
349 | + Option('line-number', short_name='n', |
350 | + help='show 1-based line number.'), |
351 | + Option('no-recursive', |
352 | + help="Don't recurse into subdirectories. (default is --recursive)"), |
353 | + Option('null', short_name='Z', |
354 | + help='Write an ASCII NUL (\\0) separator ' |
355 | + 'between output lines rather than a newline.'), |
356 | + ] |
357 | + |
358 | + |
359 | + @display_command |
360 | + def run(self, verbose=False, ignore_case=False, no_recursive=False, |
361 | + from_root=False, null=False, levels=None, line_number=False, |
362 | + path_list=None, revision=None, pattern=None, include=None, |
363 | + exclude=None, fixed_string=False, files_with_matches=False, |
364 | + files_without_match=False, color=None, diff=False): |
365 | + from bzrlib import _termcolor |
366 | + from bzrlib.plugins.grep import ( |
367 | + grep, |
368 | + ) |
369 | + import re |
370 | + if path_list is None: |
371 | + path_list = ['.'] |
372 | + else: |
373 | + if from_root: |
374 | + raise errors.BzrCommandError('cannot specify both --from-root and PATH.') |
375 | + |
376 | + if files_with_matches and files_without_match: |
377 | + raise errors.BzrCommandError('cannot specify both ' |
378 | + '-l/--files-with-matches and -L/--files-without-matches.') |
379 | + |
380 | + global_config = GlobalConfig() |
381 | + |
382 | + if color is None: |
383 | + color = global_config.get_user_option('grep_color') |
384 | + |
385 | + if color is None: |
386 | + color = 'never' |
387 | + |
388 | + if color not in ['always', 'never', 'auto']: |
389 | + raise errors.BzrCommandError('Valid values for --color are ' |
390 | + '"always", "never" or "auto".') |
391 | + |
392 | + if levels==None: |
393 | + levels=1 |
394 | + |
395 | + print_revno = False |
396 | + if revision != None or levels == 0: |
397 | + # print revision numbers as we may be showing multiple revisions |
398 | + print_revno = True |
399 | + |
400 | + eol_marker = '\n' |
401 | + if null: |
402 | + eol_marker = '\0' |
403 | + |
404 | + if not ignore_case and grep.is_fixed_string(pattern): |
405 | + # if the pattern isalnum, implicitly use to -F for faster grep |
406 | + fixed_string = True |
407 | + elif ignore_case and fixed_string: |
408 | + # GZ 2010-06-02: Fall back to regexp rather than lowercasing |
409 | + # pattern and text which will cause pain later |
410 | + fixed_string = False |
411 | + pattern = re.escape(pattern) |
412 | + |
413 | + patternc = None |
414 | + re_flags = re.MULTILINE |
415 | + if ignore_case: |
416 | + re_flags |= re.IGNORECASE |
417 | + |
418 | + if not fixed_string: |
419 | + patternc = grep.compile_pattern(pattern, re_flags) |
420 | + |
421 | + if color == 'always': |
422 | + show_color = True |
423 | + elif color == 'never': |
424 | + show_color = False |
425 | + elif color == 'auto': |
426 | + show_color = _termcolor.allow_color() |
427 | + |
428 | + GrepOptions.verbose = verbose |
429 | + GrepOptions.ignore_case = ignore_case |
430 | + GrepOptions.no_recursive = no_recursive |
431 | + GrepOptions.from_root = from_root |
432 | + GrepOptions.null = null |
433 | + GrepOptions.levels = levels |
434 | + GrepOptions.line_number = line_number |
435 | + GrepOptions.path_list = path_list |
436 | + GrepOptions.revision = revision |
437 | + GrepOptions.pattern = pattern |
438 | + GrepOptions.include = include |
439 | + GrepOptions.exclude = exclude |
440 | + GrepOptions.fixed_string = fixed_string |
441 | + GrepOptions.files_with_matches = files_with_matches |
442 | + GrepOptions.files_without_match = files_without_match |
443 | + GrepOptions.color = color |
444 | + GrepOptions.diff = False |
445 | + |
446 | + GrepOptions.eol_marker = eol_marker |
447 | + GrepOptions.print_revno = print_revno |
448 | + GrepOptions.patternc = patternc |
449 | + GrepOptions.recursive = not no_recursive |
450 | + GrepOptions.fixed_string = fixed_string |
451 | + GrepOptions.outf = self.outf |
452 | + GrepOptions.show_color = show_color |
453 | + |
454 | + if diff: |
455 | + # options not used: |
456 | + # files_with_matches, files_without_match |
457 | + # levels(?), line_number, from_root |
458 | + # include, exclude |
459 | + # These are silently ignored. |
460 | + grep.grep_diff(GrepOptions) |
461 | + elif revision is None: |
462 | + grep.workingtree_grep(GrepOptions) |
463 | + else: |
464 | + grep.versioned_grep(GrepOptions) |
465 | |
466 | === added file 'bzrlib/plugins/grep/grep.py' |
467 | --- bzrlib/plugins/grep/grep.py 1970-01-01 00:00:00 +0000 |
468 | +++ bzrlib/plugins/grep/grep.py 2012-08-23 15:07:23 +0000 |
469 | @@ -0,0 +1,728 @@ |
470 | +# Copyright (C) 2010 Canonical Ltd |
471 | +# |
472 | +# This program is free software; you can redistribute it and/or modify |
473 | +# it under the terms of the GNU General Public License as published by |
474 | +# the Free Software Foundation; either version 2 of the License, or |
475 | +# (at your option) any later version. |
476 | +# |
477 | +# This program is distributed in the hope that it will be useful, |
478 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
479 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
480 | +# GNU General Public License for more details. |
481 | +# |
482 | +# You should have received a copy of the GNU General Public License |
483 | +# along with this program; if not, write to the Free Software |
484 | +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
485 | + |
486 | +from __future__ import absolute_import |
487 | + |
488 | +import sys |
489 | + |
490 | +from bzrlib.lazy_import import lazy_import |
491 | +lazy_import(globals(), """ |
492 | +from fnmatch import fnmatch |
493 | +import re |
494 | +from cStringIO import StringIO |
495 | + |
496 | +from bzrlib._termcolor import color_string, re_color_string, FG |
497 | + |
498 | +from bzrlib.revisionspec import ( |
499 | + RevisionSpec, |
500 | + RevisionSpec_revid, |
501 | + RevisionSpec_revno, |
502 | + ) |
503 | +from bzrlib import ( |
504 | + bzrdir, |
505 | + diff, |
506 | + errors, |
507 | + lazy_regex, |
508 | + osutils, |
509 | + revision as _mod_revision, |
510 | + trace, |
511 | + ) |
512 | +""") |
513 | + |
514 | +_user_encoding = osutils.get_user_encoding() |
515 | + |
516 | + |
517 | +class _RevisionNotLinear(Exception): |
518 | + """Raised when a revision is not on left-hand history.""" |
519 | + |
520 | + |
521 | +def _rev_on_mainline(rev_tuple): |
522 | + """returns True is rev tuple is on mainline""" |
523 | + if len(rev_tuple) == 1: |
524 | + return True |
525 | + return rev_tuple[1] == 0 and rev_tuple[2] == 0 |
526 | + |
527 | + |
528 | +# NOTE: _linear_view_revisions is basided on |
529 | +# bzrlib.log._linear_view_revisions. |
530 | +# This should probably be a common public API |
531 | +def _linear_view_revisions(branch, start_rev_id, end_rev_id): |
532 | + # requires that start is older than end |
533 | + repo = branch.repository |
534 | + graph = repo.get_graph() |
535 | + for revision_id in graph.iter_lefthand_ancestry( |
536 | + end_rev_id, (_mod_revision.NULL_REVISION, )): |
537 | + revno = branch.revision_id_to_dotted_revno(revision_id) |
538 | + revno_str = '.'.join(str(n) for n in revno) |
539 | + if revision_id == start_rev_id: |
540 | + yield revision_id, revno_str, 0 |
541 | + break |
542 | + yield revision_id, revno_str, 0 |
543 | + |
544 | + |
545 | +# NOTE: _graph_view_revisions is copied from |
546 | +# bzrlib.log._graph_view_revisions. |
547 | +# This should probably be a common public API |
548 | +def _graph_view_revisions(branch, start_rev_id, end_rev_id, |
549 | + rebase_initial_depths=True): |
550 | + """Calculate revisions to view including merges, newest to oldest. |
551 | + |
552 | + :param branch: the branch |
553 | + :param start_rev_id: the lower revision-id |
554 | + :param end_rev_id: the upper revision-id |
555 | + :param rebase_initial_depth: should depths be rebased until a mainline |
556 | + revision is found? |
557 | + :return: An iterator of (revision_id, dotted_revno, merge_depth) tuples. |
558 | + """ |
559 | + # requires that start is older than end |
560 | + view_revisions = branch.iter_merge_sorted_revisions( |
561 | + start_revision_id=end_rev_id, stop_revision_id=start_rev_id, |
562 | + stop_rule="with-merges") |
563 | + if not rebase_initial_depths: |
564 | + for (rev_id, merge_depth, revno, end_of_merge |
565 | + ) in view_revisions: |
566 | + yield rev_id, '.'.join(map(str, revno)), merge_depth |
567 | + else: |
568 | + # We're following a development line starting at a merged revision. |
569 | + # We need to adjust depths down by the initial depth until we find |
570 | + # a depth less than it. Then we use that depth as the adjustment. |
571 | + # If and when we reach the mainline, depth adjustment ends. |
572 | + depth_adjustment = None |
573 | + for (rev_id, merge_depth, revno, end_of_merge |
574 | + ) in view_revisions: |
575 | + if depth_adjustment is None: |
576 | + depth_adjustment = merge_depth |
577 | + if depth_adjustment: |
578 | + if merge_depth < depth_adjustment: |
579 | + # From now on we reduce the depth adjustement, this can be |
580 | + # surprising for users. The alternative requires two passes |
581 | + # which breaks the fast display of the first revision |
582 | + # though. |
583 | + depth_adjustment = merge_depth |
584 | + merge_depth -= depth_adjustment |
585 | + yield rev_id, '.'.join(map(str, revno)), merge_depth |
586 | + |
587 | + |
588 | +def compile_pattern(pattern, flags=0): |
589 | + patternc = None |
590 | + try: |
591 | + # use python's re.compile as we need to catch re.error in case of bad pattern |
592 | + lazy_regex.reset_compile() |
593 | + patternc = re.compile(pattern, flags) |
594 | + except re.error, e: |
595 | + raise errors.BzrError("Invalid pattern: '%s'" % pattern) |
596 | + return patternc |
597 | + |
598 | + |
599 | +def is_fixed_string(s): |
600 | + if re.match("^([A-Za-z0-9_]|\s)*$", s): |
601 | + return True |
602 | + return False |
603 | + |
604 | + |
605 | +class _GrepDiffOutputter(object): |
606 | + """Precalculate formatting based on options given for diff grep. |
607 | + """ |
608 | + |
609 | + def __init__(self, opts): |
610 | + self.opts = opts |
611 | + self.outf = opts.outf |
612 | + if opts.show_color: |
613 | + pat = opts.pattern.encode(_user_encoding, 'replace') |
614 | + if opts.fixed_string: |
615 | + self._old = pat |
616 | + self._new = color_string(pat, FG.BOLD_RED) |
617 | + self.get_writer = self._get_writer_fixed_highlighted |
618 | + else: |
619 | + flags = opts.patternc.flags |
620 | + self._sub = re.compile(pat.join(("((?:",")+)")), flags).sub |
621 | + self._highlight = color_string("\\1", FG.BOLD_RED) |
622 | + self.get_writer = self._get_writer_regexp_highlighted |
623 | + else: |
624 | + self.get_writer = self._get_writer_plain |
625 | + |
626 | + def get_file_header_writer(self): |
627 | + """Get function for writing file headers""" |
628 | + write = self.outf.write |
629 | + eol_marker = self.opts.eol_marker |
630 | + def _line_writer(line): |
631 | + write(line + eol_marker) |
632 | + def _line_writer_color(line): |
633 | + write(FG.BOLD_MAGENTA + line + FG.NONE + eol_marker) |
634 | + if self.opts.show_color: |
635 | + return _line_writer_color |
636 | + else: |
637 | + return _line_writer |
638 | + return _line_writer |
639 | + |
640 | + def get_revision_header_writer(self): |
641 | + """Get function for writing revno lines""" |
642 | + write = self.outf.write |
643 | + eol_marker = self.opts.eol_marker |
644 | + def _line_writer(line): |
645 | + write(line + eol_marker) |
646 | + def _line_writer_color(line): |
647 | + write(FG.BOLD_BLUE + line + FG.NONE + eol_marker) |
648 | + if self.opts.show_color: |
649 | + return _line_writer_color |
650 | + else: |
651 | + return _line_writer |
652 | + return _line_writer |
653 | + |
654 | + def _get_writer_plain(self): |
655 | + """Get function for writing uncoloured output""" |
656 | + write = self.outf.write |
657 | + eol_marker = self.opts.eol_marker |
658 | + def _line_writer(line): |
659 | + write(line + eol_marker) |
660 | + return _line_writer |
661 | + |
662 | + def _get_writer_regexp_highlighted(self): |
663 | + """Get function for writing output with regexp match highlighted""" |
664 | + _line_writer = self._get_writer_plain() |
665 | + sub, highlight = self._sub, self._highlight |
666 | + def _line_writer_regexp_highlighted(line): |
667 | + """Write formatted line with matched pattern highlighted""" |
668 | + return _line_writer(line=sub(highlight, line)) |
669 | + return _line_writer_regexp_highlighted |
670 | + |
671 | + def _get_writer_fixed_highlighted(self): |
672 | + """Get function for writing output with search string highlighted""" |
673 | + _line_writer = self._get_writer_plain() |
674 | + old, new = self._old, self._new |
675 | + def _line_writer_fixed_highlighted(line): |
676 | + """Write formatted line with string searched for highlighted""" |
677 | + return _line_writer(line=line.replace(old, new)) |
678 | + return _line_writer_fixed_highlighted |
679 | + |
680 | + |
681 | +def grep_diff(opts): |
682 | + wt, branch, relpath = \ |
683 | + bzrdir.BzrDir.open_containing_tree_or_branch('.') |
684 | + branch.lock_read() |
685 | + try: |
686 | + if opts.revision: |
687 | + start_rev = opts.revision[0] |
688 | + else: |
689 | + # if no revision is sepcified for diff grep we grep all changesets. |
690 | + opts.revision = [RevisionSpec.from_string('revno:1'), |
691 | + RevisionSpec.from_string('last:1')] |
692 | + start_rev = opts.revision[0] |
693 | + start_revid = start_rev.as_revision_id(branch) |
694 | + if start_revid == 'null:': |
695 | + return |
696 | + srevno_tuple = branch.revision_id_to_dotted_revno(start_revid) |
697 | + if len(opts.revision) == 2: |
698 | + end_rev = opts.revision[1] |
699 | + end_revid = end_rev.as_revision_id(branch) |
700 | + if end_revid is None: |
701 | + end_revno, end_revid = branch.last_revision_info() |
702 | + erevno_tuple = branch.revision_id_to_dotted_revno(end_revid) |
703 | + |
704 | + grep_mainline = (_rev_on_mainline(srevno_tuple) and |
705 | + _rev_on_mainline(erevno_tuple)) |
706 | + |
707 | + # ensure that we go in reverse order |
708 | + if srevno_tuple > erevno_tuple: |
709 | + srevno_tuple, erevno_tuple = erevno_tuple, srevno_tuple |
710 | + start_revid, end_revid = end_revid, start_revid |
711 | + |
712 | + # Optimization: Traversing the mainline in reverse order is much |
713 | + # faster when we don't want to look at merged revs. We try this |
714 | + # with _linear_view_revisions. If all revs are to be grepped we |
715 | + # use the slower _graph_view_revisions |
716 | + if opts.levels==1 and grep_mainline: |
717 | + given_revs = _linear_view_revisions(branch, start_revid, end_revid) |
718 | + else: |
719 | + given_revs = _graph_view_revisions(branch, start_revid, end_revid) |
720 | + else: |
721 | + # We do an optimization below. For grepping a specific revison |
722 | + # We don't need to call _graph_view_revisions which is slow. |
723 | + # We create the start_rev_tuple for only that specific revision. |
724 | + # _graph_view_revisions is used only for revision range. |
725 | + start_revno = '.'.join(map(str, srevno_tuple)) |
726 | + start_rev_tuple = (start_revid, start_revno, 0) |
727 | + given_revs = [start_rev_tuple] |
728 | + repo = branch.repository |
729 | + diff_pattern = re.compile("^[+\-].*(" + opts.pattern + ")") |
730 | + file_pattern = re.compile("=== (modified|added|removed) file '.*'", re.UNICODE) |
731 | + outputter = _GrepDiffOutputter(opts) |
732 | + writeline = outputter.get_writer() |
733 | + writerevno = outputter.get_revision_header_writer() |
734 | + writefileheader = outputter.get_file_header_writer() |
735 | + file_encoding = _user_encoding |
736 | + for revid, revno, merge_depth in given_revs: |
737 | + if opts.levels == 1 and merge_depth != 0: |
738 | + # with level=1 show only top level |
739 | + continue |
740 | + |
741 | + rev_spec = RevisionSpec_revid.from_string("revid:"+revid) |
742 | + new_rev = repo.get_revision(revid) |
743 | + new_tree = rev_spec.as_tree(branch) |
744 | + if len(new_rev.parent_ids) == 0: |
745 | + ancestor_id = _mod_revision.NULL_REVISION |
746 | + else: |
747 | + ancestor_id = new_rev.parent_ids[0] |
748 | + old_tree = repo.revision_tree(ancestor_id) |
749 | + s = StringIO() |
750 | + diff.show_diff_trees(old_tree, new_tree, s, |
751 | + old_label='', new_label='') |
752 | + display_revno = True |
753 | + display_file = False |
754 | + file_header = None |
755 | + text = s.getvalue() |
756 | + for line in text.splitlines(): |
757 | + if file_pattern.search(line): |
758 | + file_header = line |
759 | + display_file = True |
760 | + elif diff_pattern.search(line): |
761 | + if display_revno: |
762 | + writerevno("=== revno:%s ===" % (revno,)) |
763 | + display_revno = False |
764 | + if display_file: |
765 | + writefileheader(" %s" % (file_header,)) |
766 | + display_file = False |
767 | + line = line.decode(file_encoding, 'replace') |
768 | + writeline(" %s" % (line,)) |
769 | + finally: |
770 | + branch.unlock() |
771 | + |
772 | + |
773 | +def versioned_grep(opts): |
774 | + wt, branch, relpath = \ |
775 | + bzrdir.BzrDir.open_containing_tree_or_branch('.') |
776 | + branch.lock_read() |
777 | + try: |
778 | + start_rev = opts.revision[0] |
779 | + start_revid = start_rev.as_revision_id(branch) |
780 | + if start_revid is None: |
781 | + start_rev = RevisionSpec_revno.from_string("revno:1") |
782 | + start_revid = start_rev.as_revision_id(branch) |
783 | + srevno_tuple = branch.revision_id_to_dotted_revno(start_revid) |
784 | + |
785 | + if len(opts.revision) == 2: |
786 | + end_rev = opts.revision[1] |
787 | + end_revid = end_rev.as_revision_id(branch) |
788 | + if end_revid is None: |
789 | + end_revno, end_revid = branch.last_revision_info() |
790 | + erevno_tuple = branch.revision_id_to_dotted_revno(end_revid) |
791 | + |
792 | + grep_mainline = (_rev_on_mainline(srevno_tuple) and |
793 | + _rev_on_mainline(erevno_tuple)) |
794 | + |
795 | + # ensure that we go in reverse order |
796 | + if srevno_tuple > erevno_tuple: |
797 | + srevno_tuple, erevno_tuple = erevno_tuple, srevno_tuple |
798 | + start_revid, end_revid = end_revid, start_revid |
799 | + |
800 | + # Optimization: Traversing the mainline in reverse order is much |
801 | + # faster when we don't want to look at merged revs. We try this |
802 | + # with _linear_view_revisions. If all revs are to be grepped we |
803 | + # use the slower _graph_view_revisions |
804 | + if opts.levels == 1 and grep_mainline: |
805 | + given_revs = _linear_view_revisions(branch, start_revid, end_revid) |
806 | + else: |
807 | + given_revs = _graph_view_revisions(branch, start_revid, end_revid) |
808 | + else: |
809 | + # We do an optimization below. For grepping a specific revison |
810 | + # We don't need to call _graph_view_revisions which is slow. |
811 | + # We create the start_rev_tuple for only that specific revision. |
812 | + # _graph_view_revisions is used only for revision range. |
813 | + start_revno = '.'.join(map(str, srevno_tuple)) |
814 | + start_rev_tuple = (start_revid, start_revno, 0) |
815 | + given_revs = [start_rev_tuple] |
816 | + |
817 | + # GZ 2010-06-02: Shouldn't be smuggling this on opts, but easy for now |
818 | + opts.outputter = _Outputter(opts, use_cache=True) |
819 | + |
820 | + for revid, revno, merge_depth in given_revs: |
821 | + if opts.levels == 1 and merge_depth != 0: |
822 | + # with level=1 show only top level |
823 | + continue |
824 | + |
825 | + rev = RevisionSpec_revid.from_string("revid:"+revid) |
826 | + tree = rev.as_tree(branch) |
827 | + for path in opts.path_list: |
828 | + path_for_id = osutils.pathjoin(relpath, path) |
829 | + id = tree.path2id(path_for_id) |
830 | + if not id: |
831 | + trace.warning("Skipped unknown file '%s'." % path) |
832 | + continue |
833 | + |
834 | + if osutils.isdir(path): |
835 | + path_prefix = path |
836 | + dir_grep(tree, path, relpath, opts, revno, path_prefix) |
837 | + else: |
838 | + versioned_file_grep(tree, id, '.', path, opts, revno) |
839 | + finally: |
840 | + branch.unlock() |
841 | + |
842 | + |
843 | +def workingtree_grep(opts): |
844 | + revno = opts.print_revno = None # for working tree set revno to None |
845 | + |
846 | + tree, branch, relpath = \ |
847 | + bzrdir.BzrDir.open_containing_tree_or_branch('.') |
848 | + if not tree: |
849 | + msg = ('Cannot search working tree. Working tree not found.\n' |
850 | + 'To search for specific revision in history use the -r option.') |
851 | + raise errors.BzrCommandError(msg) |
852 | + |
853 | + # GZ 2010-06-02: Shouldn't be smuggling this on opts, but easy for now |
854 | + opts.outputter = _Outputter(opts) |
855 | + |
856 | + tree.lock_read() |
857 | + try: |
858 | + for path in opts.path_list: |
859 | + if osutils.isdir(path): |
860 | + path_prefix = path |
861 | + dir_grep(tree, path, relpath, opts, revno, path_prefix) |
862 | + else: |
863 | + _file_grep(open(path).read(), path, opts, revno) |
864 | + finally: |
865 | + tree.unlock() |
866 | + |
867 | + |
868 | +def _skip_file(include, exclude, path): |
869 | + if include and not _path_in_glob_list(path, include): |
870 | + return True |
871 | + if exclude and _path_in_glob_list(path, exclude): |
872 | + return True |
873 | + return False |
874 | + |
875 | + |
876 | +def dir_grep(tree, path, relpath, opts, revno, path_prefix): |
877 | + # setup relpath to open files relative to cwd |
878 | + rpath = relpath |
879 | + if relpath: |
880 | + rpath = osutils.pathjoin('..',relpath) |
881 | + |
882 | + from_dir = osutils.pathjoin(relpath, path) |
883 | + if opts.from_root: |
884 | + # start searching recursively from root |
885 | + from_dir=None |
886 | + recursive=True |
887 | + |
888 | + to_grep = [] |
889 | + to_grep_append = to_grep.append |
890 | + # GZ 2010-06-05: The cache dict used to be recycled every call to dir_grep |
891 | + # and hits manually refilled. Could do this again if it was |
892 | + # for a good reason, otherwise cache might want purging. |
893 | + outputter = opts.outputter |
894 | + for fp, fc, fkind, fid, entry in tree.list_files(include_root=False, |
895 | + from_dir=from_dir, recursive=opts.recursive): |
896 | + |
897 | + if _skip_file(opts.include, opts.exclude, fp): |
898 | + continue |
899 | + |
900 | + if fc == 'V' and fkind == 'file': |
901 | + if revno != None: |
902 | + # If old result is valid, print results immediately. |
903 | + # Otherwise, add file info to to_grep so that the |
904 | + # loop later will get chunks and grep them |
905 | + cache_id = tree.get_file_revision(fid) |
906 | + if cache_id in outputter.cache: |
907 | + # GZ 2010-06-05: Not really sure caching and re-outputting |
908 | + # the old path is really the right thing, |
909 | + # but it's what the old code seemed to do |
910 | + outputter.write_cached_lines(cache_id, revno) |
911 | + else: |
912 | + to_grep_append((fid, (fp, fid))) |
913 | + else: |
914 | + # we are grepping working tree. |
915 | + if from_dir is None: |
916 | + from_dir = '.' |
917 | + |
918 | + path_for_file = osutils.pathjoin(tree.basedir, from_dir, fp) |
919 | + if opts.files_with_matches or opts.files_without_match: |
920 | + # Optimize for wtree list-only as we don't need to read the |
921 | + # entire file |
922 | + file = open(path_for_file, 'r', buffering=4096) |
923 | + _file_grep_list_only_wtree(file, fp, opts, path_prefix) |
924 | + else: |
925 | + file_text = open(path_for_file, 'r').read() |
926 | + _file_grep(file_text, fp, opts, revno, path_prefix) |
927 | + |
928 | + if revno != None: # grep versioned files |
929 | + for (path, fid), chunks in tree.iter_files_bytes(to_grep): |
930 | + path = _make_display_path(relpath, path) |
931 | + _file_grep(chunks[0], path, opts, revno, path_prefix, |
932 | + tree.get_file_revision(fid, path)) |
933 | + |
934 | + |
935 | +def _make_display_path(relpath, path): |
936 | + """Return path string relative to user cwd. |
937 | + |
938 | + Take tree's 'relpath' and user supplied 'path', and return path |
939 | + that can be displayed to the user. |
940 | + """ |
941 | + if relpath: |
942 | + # update path so to display it w.r.t cwd |
943 | + # handle windows slash separator |
944 | + path = osutils.normpath(osutils.pathjoin(relpath, path)) |
945 | + path = path.replace('\\', '/') |
946 | + path = path.replace(relpath + '/', '', 1) |
947 | + return path |
948 | + |
949 | + |
950 | +def versioned_file_grep(tree, id, relpath, path, opts, revno, path_prefix = None): |
951 | + """Create a file object for the specified id and pass it on to _file_grep. |
952 | + """ |
953 | + |
954 | + path = _make_display_path(relpath, path) |
955 | + file_text = tree.get_file_text(id) |
956 | + _file_grep(file_text, path, opts, revno, path_prefix) |
957 | + |
958 | + |
959 | +def _path_in_glob_list(path, glob_list): |
960 | + for glob in glob_list: |
961 | + if fnmatch(path, glob): |
962 | + return True |
963 | + return False |
964 | + |
965 | + |
966 | +def _file_grep_list_only_wtree(file, path, opts, path_prefix=None): |
967 | + # test and skip binary files |
968 | + if '\x00' in file.read(1024): |
969 | + if opts.verbose: |
970 | + trace.warning("Binary file '%s' skipped." % path) |
971 | + return |
972 | + |
973 | + file.seek(0) # search from beginning |
974 | + |
975 | + found = False |
976 | + if opts.fixed_string: |
977 | + pattern = opts.pattern.encode(_user_encoding, 'replace') |
978 | + for line in file: |
979 | + if pattern in line: |
980 | + found = True |
981 | + break |
982 | + else: # not fixed_string |
983 | + for line in file: |
984 | + if opts.patternc.search(line): |
985 | + found = True |
986 | + break |
987 | + |
988 | + if (opts.files_with_matches and found) or \ |
989 | + (opts.files_without_match and not found): |
990 | + if path_prefix and path_prefix != '.': |
991 | + # user has passed a dir arg, show that as result prefix |
992 | + path = osutils.pathjoin(path_prefix, path) |
993 | + opts.outputter.get_writer(path, None, None)() |
994 | + |
995 | + |
996 | +class _Outputter(object): |
997 | + """Precalculate formatting based on options given |
998 | + |
999 | + The idea here is to do this work only once per run, and finally return a |
1000 | + function that will do the minimum amount possible for each match. |
1001 | + """ |
1002 | + def __init__(self, opts, use_cache=False): |
1003 | + self.outf = opts.outf |
1004 | + if use_cache: |
1005 | + # self.cache is used to cache results for dir grep based on fid. |
1006 | + # If the fid is does not change between results, it means that |
1007 | + # the result will be the same apart from revno. In such a case |
1008 | + # we avoid getting file chunks from repo and grepping. The result |
1009 | + # is just printed by replacing old revno with new one. |
1010 | + self.cache = {} |
1011 | + else: |
1012 | + self.cache = None |
1013 | + no_line = opts.files_with_matches or opts.files_without_match |
1014 | + |
1015 | + if opts.show_color: |
1016 | + pat = opts.pattern.encode(_user_encoding, 'replace') |
1017 | + if no_line: |
1018 | + self.get_writer = self._get_writer_plain |
1019 | + elif opts.fixed_string: |
1020 | + self._old = pat |
1021 | + self._new = color_string(pat, FG.BOLD_RED) |
1022 | + self.get_writer = self._get_writer_fixed_highlighted |
1023 | + else: |
1024 | + flags = opts.patternc.flags |
1025 | + self._sub = re.compile(pat.join(("((?:",")+)")), flags).sub |
1026 | + self._highlight = color_string("\\1", FG.BOLD_RED) |
1027 | + self.get_writer = self._get_writer_regexp_highlighted |
1028 | + path_start = FG.MAGENTA |
1029 | + path_end = FG.NONE |
1030 | + sep = color_string(':', FG.BOLD_CYAN) |
1031 | + rev_sep = color_string('~', FG.BOLD_YELLOW) |
1032 | + else: |
1033 | + self.get_writer = self._get_writer_plain |
1034 | + path_start = path_end = "" |
1035 | + sep = ":" |
1036 | + rev_sep = "~" |
1037 | + |
1038 | + parts = [path_start, "%(path)s"] |
1039 | + if opts.print_revno: |
1040 | + parts.extend([rev_sep, "%(revno)s"]) |
1041 | + self._format_initial = "".join(parts) |
1042 | + parts = [] |
1043 | + if no_line: |
1044 | + if not opts.print_revno: |
1045 | + parts.append(path_end) |
1046 | + else: |
1047 | + if opts.line_number: |
1048 | + parts.extend([sep, "%(lineno)s"]) |
1049 | + parts.extend([sep, "%(line)s"]) |
1050 | + parts.append(opts.eol_marker) |
1051 | + self._format_perline = "".join(parts) |
1052 | + |
1053 | + def _get_writer_plain(self, path, revno, cache_id): |
1054 | + """Get function for writing uncoloured output""" |
1055 | + per_line = self._format_perline |
1056 | + start = self._format_initial % {"path":path, "revno":revno} |
1057 | + write = self.outf.write |
1058 | + if self.cache is not None and cache_id is not None: |
1059 | + result_list = [] |
1060 | + self.cache[cache_id] = path, result_list |
1061 | + add_to_cache = result_list.append |
1062 | + def _line_cache_and_writer(**kwargs): |
1063 | + """Write formatted line and cache arguments""" |
1064 | + end = per_line % kwargs |
1065 | + add_to_cache(end) |
1066 | + write(start + end) |
1067 | + return _line_cache_and_writer |
1068 | + def _line_writer(**kwargs): |
1069 | + """Write formatted line from arguments given by underlying opts""" |
1070 | + write(start + per_line % kwargs) |
1071 | + return _line_writer |
1072 | + |
1073 | + def write_cached_lines(self, cache_id, revno): |
1074 | + """Write cached results out again for new revision""" |
1075 | + cached_path, cached_matches = self.cache[cache_id] |
1076 | + start = self._format_initial % {"path":cached_path, "revno":revno} |
1077 | + write = self.outf.write |
1078 | + for end in cached_matches: |
1079 | + write(start + end) |
1080 | + |
1081 | + def _get_writer_regexp_highlighted(self, path, revno, cache_id): |
1082 | + """Get function for writing output with regexp match highlighted""" |
1083 | + _line_writer = self._get_writer_plain(path, revno, cache_id) |
1084 | + sub, highlight = self._sub, self._highlight |
1085 | + def _line_writer_regexp_highlighted(line, **kwargs): |
1086 | + """Write formatted line with matched pattern highlighted""" |
1087 | + return _line_writer(line=sub(highlight, line), **kwargs) |
1088 | + return _line_writer_regexp_highlighted |
1089 | + |
1090 | + def _get_writer_fixed_highlighted(self, path, revno, cache_id): |
1091 | + """Get function for writing output with search string highlighted""" |
1092 | + _line_writer = self._get_writer_plain(path, revno, cache_id) |
1093 | + old, new = self._old, self._new |
1094 | + def _line_writer_fixed_highlighted(line, **kwargs): |
1095 | + """Write formatted line with string searched for highlighted""" |
1096 | + return _line_writer(line=line.replace(old, new), **kwargs) |
1097 | + return _line_writer_fixed_highlighted |
1098 | + |
1099 | + |
1100 | +def _file_grep(file_text, path, opts, revno, path_prefix=None, cache_id=None): |
1101 | + # test and skip binary files |
1102 | + if '\x00' in file_text[:1024]: |
1103 | + if opts.verbose: |
1104 | + trace.warning("Binary file '%s' skipped." % path) |
1105 | + return |
1106 | + |
1107 | + if path_prefix and path_prefix != '.': |
1108 | + # user has passed a dir arg, show that as result prefix |
1109 | + path = osutils.pathjoin(path_prefix, path) |
1110 | + |
1111 | + # GZ 2010-06-07: There's no actual guarentee the file contents will be in |
1112 | + # the user encoding, but we have to guess something and it |
1113 | + # is a reasonable default without a better mechanism. |
1114 | + file_encoding = _user_encoding |
1115 | + pattern = opts.pattern.encode(_user_encoding, 'replace') |
1116 | + |
1117 | + writeline = opts.outputter.get_writer(path, revno, cache_id) |
1118 | + |
1119 | + if opts.files_with_matches or opts.files_without_match: |
1120 | + if opts.fixed_string: |
1121 | + if sys.platform > (2, 5): |
1122 | + found = pattern in file_text |
1123 | + else: |
1124 | + for line in file_text.splitlines(): |
1125 | + if pattern in line: |
1126 | + found = True |
1127 | + break |
1128 | + else: |
1129 | + found = False |
1130 | + else: |
1131 | + search = opts.patternc.search |
1132 | + if "$" not in pattern: |
1133 | + found = search(file_text) is not None |
1134 | + else: |
1135 | + for line in file_text.splitlines(): |
1136 | + if search(line): |
1137 | + found = True |
1138 | + break |
1139 | + else: |
1140 | + found = False |
1141 | + if (opts.files_with_matches and found) or \ |
1142 | + (opts.files_without_match and not found): |
1143 | + writeline() |
1144 | + elif opts.fixed_string: |
1145 | + # Fast path for no match, search through the entire file at once rather |
1146 | + # than a line at a time. However, we don't want this without Python 2.5 |
1147 | + # as the quick string search algorithm wasn't implemented till then: |
1148 | + # <http://effbot.org/zone/stringlib.htm> |
1149 | + if sys.version_info > (2, 5): |
1150 | + i = file_text.find(pattern) |
1151 | + if i == -1: |
1152 | + return |
1153 | + b = file_text.rfind("\n", 0, i) + 1 |
1154 | + if opts.line_number: |
1155 | + start = file_text.count("\n", 0, b) + 1 |
1156 | + file_text = file_text[b:] |
1157 | + else: |
1158 | + start = 1 |
1159 | + if opts.line_number: |
1160 | + for index, line in enumerate(file_text.splitlines()): |
1161 | + if pattern in line: |
1162 | + line = line.decode(file_encoding, 'replace') |
1163 | + writeline(lineno=index+start, line=line) |
1164 | + else: |
1165 | + for line in file_text.splitlines(): |
1166 | + if pattern in line: |
1167 | + line = line.decode(file_encoding, 'replace') |
1168 | + writeline(line=line) |
1169 | + else: |
1170 | + # Fast path on no match, the re module avoids bad behaviour in most |
1171 | + # standard cases, but perhaps could try and detect backtracking |
1172 | + # patterns here and avoid whole text search in those cases |
1173 | + search = opts.patternc.search |
1174 | + if "$" not in pattern: |
1175 | + # GZ 2010-06-05: Grr, re.MULTILINE can't save us when searching |
1176 | + # through revisions as bazaar returns binary mode |
1177 | + # and trailing \r breaks $ as line ending match |
1178 | + m = search(file_text) |
1179 | + if m is None: |
1180 | + return |
1181 | + b = file_text.rfind("\n", 0, m.start()) + 1 |
1182 | + if opts.line_number: |
1183 | + start = file_text.count("\n", 0, b) + 1 |
1184 | + file_text = file_text[b:] |
1185 | + else: |
1186 | + start = 1 |
1187 | + if opts.line_number: |
1188 | + for index, line in enumerate(file_text.splitlines()): |
1189 | + if search(line): |
1190 | + line = line.decode(file_encoding, 'replace') |
1191 | + writeline(lineno=index+start, line=line) |
1192 | + else: |
1193 | + for line in file_text.splitlines(): |
1194 | + if search(line): |
1195 | + line = line.decode(file_encoding, 'replace') |
1196 | + writeline(line=line) |
1197 | + |
1198 | |
1199 | === added file 'bzrlib/plugins/grep/test_grep.py' |
1200 | --- bzrlib/plugins/grep/test_grep.py 1970-01-01 00:00:00 +0000 |
1201 | +++ bzrlib/plugins/grep/test_grep.py 2012-08-23 15:07:23 +0000 |
1202 | @@ -0,0 +1,2254 @@ |
1203 | +# Copyright (C) 2010 Canonical Ltd |
1204 | +# |
1205 | +# This program is free software; you can redistribute it and/or modify |
1206 | +# it under the terms of the GNU General Public License as published by |
1207 | +# the Free Software Foundation; either version 2 of the License, or |
1208 | +# (at your option) any later version. |
1209 | +# |
1210 | +# This program is distributed in the hope that it will be useful, |
1211 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1212 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1213 | +# GNU General Public License for more details. |
1214 | +# |
1215 | +# You should have received a copy of the GNU General Public License |
1216 | +# along with this program; if not, write to the Free Software |
1217 | +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
1218 | + |
1219 | +from __future__ import absolute_import |
1220 | + |
1221 | +import os |
1222 | +import re |
1223 | +import unicodedata as ud |
1224 | + |
1225 | +from bzrlib import tests, osutils |
1226 | +from bzrlib._termcolor import color_string, FG |
1227 | + |
1228 | +from bzrlib.tests.features import ( |
1229 | + ColorFeature, |
1230 | + UnicodeFilenameFeature, |
1231 | + ) |
1232 | + |
1233 | +# NOTE: As bzr-grep optimizes PATTERN search to -F/--fixed-string |
1234 | +# for patterns that are not alphanumeric+whitespace, we test grep |
1235 | +# specfically with patterns that have special characters so that |
1236 | +# regex path is tested. alphanumeric patterns test the -F path. |
1237 | + |
1238 | +class GrepTestBase(tests.TestCaseWithTransport): |
1239 | + """Base class for testing grep. |
1240 | + |
1241 | + Provides support methods for creating directory and file revisions. |
1242 | + """ |
1243 | + _reflags = re.MULTILINE|re.DOTALL |
1244 | + |
1245 | + def _mk_file(self, path, line_prefix, total_lines, versioned): |
1246 | + text='' |
1247 | + for i in range(total_lines): |
1248 | + text += line_prefix + str(i+1) + "\n" |
1249 | + |
1250 | + open(path, 'w').write(text) |
1251 | + if versioned: |
1252 | + self.run_bzr(['add', path]) |
1253 | + self.run_bzr(['ci', '-m', '"' + path + '"']) |
1254 | + |
1255 | + def _update_file(self, path, text, checkin=True): |
1256 | + """append text to file 'path' and check it in""" |
1257 | + open(path, 'a').write(text) |
1258 | + if checkin: |
1259 | + self.run_bzr(['ci', path, '-m', '"' + path + '"']) |
1260 | + |
1261 | + def _mk_unknown_file(self, path, line_prefix='line', total_lines=10): |
1262 | + self._mk_file(path, line_prefix, total_lines, versioned=False) |
1263 | + |
1264 | + def _mk_versioned_file(self, path, line_prefix='line', total_lines=10): |
1265 | + self._mk_file(path, line_prefix, total_lines, versioned=True) |
1266 | + |
1267 | + def _mk_dir(self, path, versioned): |
1268 | + os.mkdir(path) |
1269 | + if versioned: |
1270 | + self.run_bzr(['add', path]) |
1271 | + self.run_bzr(['ci', '-m', '"' + path + '"']) |
1272 | + |
1273 | + def _mk_unknown_dir(self, path): |
1274 | + self._mk_dir(path, versioned=False) |
1275 | + |
1276 | + def _mk_versioned_dir(self, path): |
1277 | + self._mk_dir(path, versioned=True) |
1278 | + |
1279 | + |
1280 | +class TestGrep(GrepTestBase): |
1281 | + """Core functional tests for grep.""" |
1282 | + |
1283 | + def test_basic_unknown_file(self): |
1284 | + """Search for pattern in specfic file. |
1285 | + |
1286 | + If specified file is unknown, grep it anyway.""" |
1287 | + wd = 'foobar0' |
1288 | + self.make_branch_and_tree(wd) |
1289 | + os.chdir(wd) |
1290 | + self._mk_unknown_file('file0.txt') |
1291 | + |
1292 | + out, err = self.run_bzr(['grep', 'line1', 'file0.txt']) |
1293 | + self.assertContainsRe(out, "file0.txt:line1", flags=TestGrep._reflags) |
1294 | + self.assertEqual(len(out.splitlines()), 2) # finds line1 and line10 |
1295 | + |
1296 | + out, err = self.run_bzr(['grep', 'line\d+', 'file0.txt']) |
1297 | + self.assertContainsRe(out, "file0.txt:line1", flags=TestGrep._reflags) |
1298 | + self.assertEqual(len(out.splitlines()), 10) |
1299 | + |
1300 | + # unknown file is not grepped unless explicitely specified |
1301 | + out, err = self.run_bzr(['grep', 'line1']) |
1302 | + self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags) |
1303 | + self.assertEqual(len(out.splitlines()), 0) |
1304 | + |
1305 | + # unknown file is not grepped unless explicitely specified |
1306 | + out, err = self.run_bzr(['grep', 'line1$']) |
1307 | + self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags) |
1308 | + self.assertEqual(len(out.splitlines()), 0) |
1309 | + |
1310 | + def test_ver_basic_file(self): |
1311 | + """(versioned) Search for pattern in specfic file. |
1312 | + """ |
1313 | + wd = 'foobar0' |
1314 | + self.make_branch_and_tree(wd) |
1315 | + os.chdir(wd) |
1316 | + self._mk_versioned_file('file0.txt') |
1317 | + |
1318 | + out, err = self.run_bzr(['grep', '-r', '1', 'line1', 'file0.txt']) |
1319 | + self.assertContainsRe(out, "file0.txt~1:line1", flags=TestGrep._reflags) |
1320 | + self.assertEqual(len(out.splitlines()), 2) # finds line1 and line10 |
1321 | + |
1322 | + out, err = self.run_bzr(['grep', '-r', '1', 'line[0-9]$', 'file0.txt']) |
1323 | + self.assertContainsRe(out, "file0.txt~1:line1", flags=TestGrep._reflags) |
1324 | + self.assertEqual(len(out.splitlines()), 9) |
1325 | + |
1326 | + # finds all the lines |
1327 | + out, err = self.run_bzr(['grep', '-r', '1', 'line[0-9]', 'file0.txt']) |
1328 | + self.assertContainsRe(out, "file0.txt~1:line1", flags=TestGrep._reflags) |
1329 | + self.assertEqual(len(out.splitlines()), 10) |
1330 | + |
1331 | + def test_wtree_basic_file(self): |
1332 | + """(wtree) Search for pattern in specfic file. |
1333 | + """ |
1334 | + wd = 'foobar0' |
1335 | + self.make_branch_and_tree(wd) |
1336 | + os.chdir(wd) |
1337 | + self._mk_versioned_file('file0.txt') |
1338 | + self._update_file('file0.txt', 'ABC\n', checkin=False) |
1339 | + |
1340 | + out, err = self.run_bzr(['grep', 'ABC', 'file0.txt']) |
1341 | + self.assertContainsRe(out, "file0.txt:ABC", flags=TestGrep._reflags) |
1342 | + self.assertEqual(len(out.splitlines()), 1) |
1343 | + |
1344 | + out, err = self.run_bzr(['grep', '[A-Z]{3}', 'file0.txt']) |
1345 | + self.assertContainsRe(out, "file0.txt:ABC", flags=TestGrep._reflags) |
1346 | + self.assertEqual(len(out.splitlines()), 1) |
1347 | + |
1348 | + out, err = self.run_bzr(['grep', '-r', 'last:1', 'ABC', 'file0.txt']) |
1349 | + self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags) |
1350 | + self.assertEqual(len(out.splitlines()), 0) |
1351 | + |
1352 | + out, err = self.run_bzr(['grep', '-r', 'last:1', '[A-Z]{3}', 'file0.txt']) |
1353 | + self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags) |
1354 | + self.assertEqual(len(out.splitlines()), 0) |
1355 | + |
1356 | + def test_ver_basic_include(self): |
1357 | + """(versioned) Ensure that -I flag is respected. |
1358 | + """ |
1359 | + wd = 'foobar0' |
1360 | + self.make_branch_and_tree(wd) |
1361 | + os.chdir(wd) |
1362 | + self._mk_versioned_file('file0.aa') |
1363 | + self._mk_versioned_file('file0.bb') |
1364 | + self._mk_versioned_file('file0.cc') |
1365 | + |
1366 | + out, err = self.run_bzr(['grep', '-r', 'last:1', |
1367 | + '--include', '*.aa', '--include', '*.bb', 'line1']) |
1368 | + self.assertContainsRe(out, "file0.aa~.:line1", flags=TestGrep._reflags) |
1369 | + self.assertContainsRe(out, "file0.bb~.:line1", flags=TestGrep._reflags) |
1370 | + self.assertNotContainsRe(out, "file0.cc", flags=TestGrep._reflags) |
1371 | + # two lines each (line1, line10) from file0.aa and file0.bb |
1372 | + self.assertEqual(len(out.splitlines()), 4) |
1373 | + |
1374 | + out, err = self.run_bzr(['grep', '-r', 'last:1', |
1375 | + '--include', '*.aa', '--include', '*.bb', 'line1$']) |
1376 | + self.assertContainsRe(out, "file0.aa~.:line1", flags=TestGrep._reflags) |
1377 | + self.assertContainsRe(out, "file0.bb~.:line1", flags=TestGrep._reflags) |
1378 | + self.assertNotContainsRe(out, "file0.cc", flags=TestGrep._reflags) |
1379 | + # one lines each (line1) from file0.aa and file0.bb |
1380 | + self.assertEqual(len(out.splitlines()), 2) |
1381 | + |
1382 | + out, err = self.run_bzr(['grep', '-r', 'last:1', |
1383 | + '-I', '*.aa', '-I', '*.bb', 'line1']) |
1384 | + self.assertContainsRe(out, "file0.aa~.:line1", flags=TestGrep._reflags) |
1385 | + self.assertContainsRe(out, "file0.bb~.:line1", flags=TestGrep._reflags) |
1386 | + self.assertNotContainsRe(out, "file0.cc", flags=TestGrep._reflags) |
1387 | + # two lines each (line1, line10) from file0.aa and file0.bb |
1388 | + self.assertEqual(len(out.splitlines()), 4) |
1389 | + |
1390 | + out, err = self.run_bzr(['grep', '-r', 'last:1', |
1391 | + '-I', '*.aa', '-I', '*.bb', 'line1$']) |
1392 | + self.assertContainsRe(out, "file0.aa~.:line1", flags=TestGrep._reflags) |
1393 | + self.assertContainsRe(out, "file0.bb~.:line1", flags=TestGrep._reflags) |
1394 | + self.assertNotContainsRe(out, "file0.cc", flags=TestGrep._reflags) |
1395 | + # one lines each (line1) from file0.aa and file0.bb |
1396 | + self.assertEqual(len(out.splitlines()), 2) |
1397 | + |
1398 | + def test_wtree_basic_include(self): |
1399 | + """(wtree) Ensure that --include flag is respected. |
1400 | + """ |
1401 | + wd = 'foobar0' |
1402 | + self.make_branch_and_tree(wd) |
1403 | + os.chdir(wd) |
1404 | + self._mk_versioned_file('file0.aa') |
1405 | + self._mk_versioned_file('file0.bb') |
1406 | + self._mk_versioned_file('file0.cc') |
1407 | + |
1408 | + out, err = self.run_bzr(['grep', '--include', '*.aa', |
1409 | + '--include', '*.bb', 'line1']) |
1410 | + self.assertContainsRe(out, "file0.aa:line1", flags=TestGrep._reflags) |
1411 | + self.assertContainsRe(out, "file0.bb:line1", flags=TestGrep._reflags) |
1412 | + self.assertNotContainsRe(out, "file0.cc", flags=TestGrep._reflags) |
1413 | + # two lines each (line1, line10) from file0.aa and file0.bb |
1414 | + self.assertEqual(len(out.splitlines()), 4) |
1415 | + |
1416 | + out, err = self.run_bzr(['grep', '--include', '*.aa', |
1417 | + '--include', '*.bb', 'line1$']) |
1418 | + self.assertContainsRe(out, "file0.aa:line1", flags=TestGrep._reflags) |
1419 | + self.assertContainsRe(out, "file0.bb:line1", flags=TestGrep._reflags) |
1420 | + self.assertNotContainsRe(out, "file0.cc", flags=TestGrep._reflags) |
1421 | + # one line each (line1) from file0.aa and file0.bb |
1422 | + self.assertEqual(len(out.splitlines()), 2) |
1423 | + |
1424 | + def test_ver_basic_exclude(self): |
1425 | + """(versioned) Ensure that --exclude flag is respected. |
1426 | + """ |
1427 | + wd = 'foobar0' |
1428 | + self.make_branch_and_tree(wd) |
1429 | + os.chdir(wd) |
1430 | + self._mk_versioned_file('file0.aa') |
1431 | + self._mk_versioned_file('file0.bb') |
1432 | + self._mk_versioned_file('file0.cc') |
1433 | + |
1434 | + out, err = self.run_bzr(['grep', '-r', 'last:1', |
1435 | + '--exclude', '*.cc', 'line1']) |
1436 | + self.assertContainsRe(out, "file0.aa~.:line1$", flags=TestGrep._reflags) |
1437 | + self.assertContainsRe(out, "file0.bb~.:line1$", flags=TestGrep._reflags) |
1438 | + self.assertContainsRe(out, "file0.aa~.:line10", flags=TestGrep._reflags) |
1439 | + self.assertContainsRe(out, "file0.bb~.:line10", flags=TestGrep._reflags) |
1440 | + self.assertNotContainsRe(out, "file0.cc", flags=TestGrep._reflags) |
1441 | + # two lines each (line1, line10) from file0.aa and file0.bb |
1442 | + self.assertEqual(len(out.splitlines()), 4) |
1443 | + |
1444 | + out, err = self.run_bzr(['grep', '-r', 'last:1', |
1445 | + '--exclude', '*.cc', 'line1$']) |
1446 | + self.assertContainsRe(out, "file0.aa~.:line1", flags=TestGrep._reflags) |
1447 | + self.assertContainsRe(out, "file0.bb~.:line1", flags=TestGrep._reflags) |
1448 | + self.assertNotContainsRe(out, "file0.cc", flags=TestGrep._reflags) |
1449 | + # one line each (line1) from file0.aa and file0.bb |
1450 | + self.assertEqual(len(out.splitlines()), 2) |
1451 | + |
1452 | + out, err = self.run_bzr(['grep', '-r', 'last:1', |
1453 | + '-X', '*.cc', 'line1']) |
1454 | + self.assertContainsRe(out, "file0.aa~.:line1", flags=TestGrep._reflags) |
1455 | + self.assertContainsRe(out, "file0.bb~.:line1", flags=TestGrep._reflags) |
1456 | + self.assertNotContainsRe(out, "file0.cc", flags=TestGrep._reflags) |
1457 | + # two lines each (line1, line10) from file0.aa and file0.bb |
1458 | + self.assertEqual(len(out.splitlines()), 4) |
1459 | + |
1460 | + def test_wtree_basic_exclude(self): |
1461 | + """(wtree) Ensure that --exclude flag is respected. |
1462 | + """ |
1463 | + wd = 'foobar0' |
1464 | + self.make_branch_and_tree(wd) |
1465 | + os.chdir(wd) |
1466 | + self._mk_versioned_file('file0.aa') |
1467 | + self._mk_versioned_file('file0.bb') |
1468 | + self._mk_versioned_file('file0.cc') |
1469 | + |
1470 | + out, err = self.run_bzr(['grep', '--exclude', '*.cc', 'line1']) |
1471 | + self.assertContainsRe(out, "file0.aa:line1", flags=TestGrep._reflags) |
1472 | + self.assertContainsRe(out, "file0.bb:line1", flags=TestGrep._reflags) |
1473 | + self.assertNotContainsRe(out, "file0.cc", flags=TestGrep._reflags) |
1474 | + # two lines each (line1, line10) from file0.aa and file0.bb |
1475 | + self.assertEqual(len(out.splitlines()), 4) |
1476 | + |
1477 | + out, err = self.run_bzr(['grep', '--exclude', '*.cc', 'lin.1$']) |
1478 | + self.assertContainsRe(out, "file0.aa:line1", flags=TestGrep._reflags) |
1479 | + self.assertContainsRe(out, "file0.bb:line1", flags=TestGrep._reflags) |
1480 | + self.assertNotContainsRe(out, "file0.cc", flags=TestGrep._reflags) |
1481 | + # one line each (line1) from file0.aa and file0.bb |
1482 | + self.assertEqual(len(out.splitlines()), 2) |
1483 | + |
1484 | + def test_ver_multiple_files(self): |
1485 | + """(versioned) Search for pattern in multiple files. |
1486 | + """ |
1487 | + wd = 'foobar0' |
1488 | + self.make_branch_and_tree(wd) |
1489 | + os.chdir(wd) |
1490 | + self._mk_versioned_file('file0.txt', total_lines=2) |
1491 | + self._mk_versioned_file('file1.txt', total_lines=2) |
1492 | + self._mk_versioned_file('file2.txt', total_lines=2) |
1493 | + |
1494 | + out, err = self.run_bzr(['grep', '-r', 'last:1', 'line[1-2]$']) |
1495 | + self.assertContainsRe(out, "file0.txt~.:line1", flags=TestGrep._reflags) |
1496 | + self.assertContainsRe(out, "file0.txt~.:line2", flags=TestGrep._reflags) |
1497 | + self.assertContainsRe(out, "file1.txt~.:line1", flags=TestGrep._reflags) |
1498 | + self.assertContainsRe(out, "file1.txt~.:line2", flags=TestGrep._reflags) |
1499 | + self.assertContainsRe(out, "file2.txt~.:line1", flags=TestGrep._reflags) |
1500 | + self.assertContainsRe(out, "file2.txt~.:line2", flags=TestGrep._reflags) |
1501 | + self.assertEqual(len(out.splitlines()), 6) |
1502 | + |
1503 | + out, err = self.run_bzr(['grep', '-r', 'last:1', 'line']) |
1504 | + self.assertContainsRe(out, "file0.txt~.:line1", flags=TestGrep._reflags) |
1505 | + self.assertContainsRe(out, "file0.txt~.:line2", flags=TestGrep._reflags) |
1506 | + self.assertContainsRe(out, "file1.txt~.:line1", flags=TestGrep._reflags) |
1507 | + self.assertContainsRe(out, "file1.txt~.:line2", flags=TestGrep._reflags) |
1508 | + self.assertContainsRe(out, "file2.txt~.:line1", flags=TestGrep._reflags) |
1509 | + self.assertContainsRe(out, "file2.txt~.:line2", flags=TestGrep._reflags) |
1510 | + self.assertEqual(len(out.splitlines()), 6) |
1511 | + |
1512 | + def test_multiple_wtree_files(self): |
1513 | + """(wtree) Search for pattern in multiple files in working tree. |
1514 | + """ |
1515 | + wd = 'foobar0' |
1516 | + self.make_branch_and_tree(wd) |
1517 | + os.chdir(wd) |
1518 | + self._mk_versioned_file('file0.txt', total_lines=2) |
1519 | + self._mk_versioned_file('file1.txt', total_lines=2) |
1520 | + self._mk_versioned_file('file2.txt', total_lines=2) |
1521 | + self._update_file('file0.txt', 'HELLO\n', checkin=False) |
1522 | + self._update_file('file1.txt', 'HELLO\n', checkin=True) |
1523 | + self._update_file('file2.txt', 'HELLO\n', checkin=False) |
1524 | + |
1525 | + out, err = self.run_bzr(['grep', 'HELLO', |
1526 | + 'file0.txt', 'file1.txt', 'file2.txt']) |
1527 | + |
1528 | + self.assertContainsRe(out, "file0.txt:HELLO", flags=TestGrep._reflags) |
1529 | + self.assertContainsRe(out, "file1.txt:HELLO", flags=TestGrep._reflags) |
1530 | + self.assertContainsRe(out, "file2.txt:HELLO", flags=TestGrep._reflags) |
1531 | + self.assertEqual(len(out.splitlines()), 3) |
1532 | + |
1533 | + out, err = self.run_bzr(['grep', 'HELLO', '-r', 'last:1', |
1534 | + 'file0.txt', 'file1.txt', 'file2.txt']) |
1535 | + |
1536 | + self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags) |
1537 | + self.assertContainsRe(out, "file1.txt~.:HELLO", flags=TestGrep._reflags) |
1538 | + self.assertNotContainsRe(out, "file2.txt", flags=TestGrep._reflags) |
1539 | + self.assertEqual(len(out.splitlines()), 1) |
1540 | + |
1541 | + out, err = self.run_bzr(['grep', 'HE..O', |
1542 | + 'file0.txt', 'file1.txt', 'file2.txt']) |
1543 | + |
1544 | + self.assertContainsRe(out, "file0.txt:HELLO", flags=TestGrep._reflags) |
1545 | + self.assertContainsRe(out, "file1.txt:HELLO", flags=TestGrep._reflags) |
1546 | + self.assertContainsRe(out, "file2.txt:HELLO", flags=TestGrep._reflags) |
1547 | + self.assertEqual(len(out.splitlines()), 3) |
1548 | + |
1549 | + out, err = self.run_bzr(['grep', 'HE..O', '-r', 'last:1', |
1550 | + 'file0.txt', 'file1.txt', 'file2.txt']) |
1551 | + |
1552 | + self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags) |
1553 | + self.assertContainsRe(out, "file1.txt~.:HELLO", flags=TestGrep._reflags) |
1554 | + self.assertNotContainsRe(out, "file2.txt", flags=TestGrep._reflags) |
1555 | + self.assertEqual(len(out.splitlines()), 1) |
1556 | + |
1557 | + def test_ver_null_option(self): |
1558 | + """(versioned) --null option should use NUL instead of newline. |
1559 | + """ |
1560 | + wd = 'foobar0' |
1561 | + self.make_branch_and_tree(wd) |
1562 | + os.chdir(wd) |
1563 | + self._mk_versioned_file('file0.txt', total_lines=3) |
1564 | + |
1565 | + nref = ud.normalize(u'NFC', u"file0.txt~1:line1\0file0.txt~1:line2\0file0.txt~1:line3\0") |
1566 | + |
1567 | + out, err = self.run_bzr(['grep', '-r', 'last:1', '--null', 'line[1-3]']) |
1568 | + nout = ud.normalize(u'NFC', out.decode('utf-8', 'ignore')) |
1569 | + self.assertEqual(nout, nref) |
1570 | + self.assertEqual(len(out.splitlines()), 1) |
1571 | + |
1572 | + out, err = self.run_bzr(['grep', '-r', 'last:1', '-Z', 'line[1-3]']) |
1573 | + nout = ud.normalize(u'NFC', out.decode('utf-8', 'ignore')) |
1574 | + self.assertEqual(nout, nref) |
1575 | + self.assertEqual(len(out.splitlines()), 1) |
1576 | + |
1577 | + out, err = self.run_bzr(['grep', '-r', 'last:1', '--null', 'line']) |
1578 | + nout = ud.normalize(u'NFC', out.decode('utf-8', 'ignore')) |
1579 | + self.assertEqual(nout, nref) |
1580 | + self.assertEqual(len(out.splitlines()), 1) |
1581 | + |
1582 | + def test_wtree_null_option(self): |
1583 | + """(wtree) --null option should use NUL instead of newline. |
1584 | + """ |
1585 | + wd = 'foobar0' |
1586 | + self.make_branch_and_tree(wd) |
1587 | + os.chdir(wd) |
1588 | + self._mk_versioned_file('file0.txt', total_lines=3) |
1589 | + |
1590 | + out, err = self.run_bzr(['grep', '--null', 'line[1-3]']) |
1591 | + self.assertEqual(out, "file0.txt:line1\0file0.txt:line2\0file0.txt:line3\0") |
1592 | + self.assertEqual(len(out.splitlines()), 1) |
1593 | + |
1594 | + out, err = self.run_bzr(['grep', '-Z', 'line[1-3]']) |
1595 | + self.assertEqual(out, "file0.txt:line1\0file0.txt:line2\0file0.txt:line3\0") |
1596 | + self.assertEqual(len(out.splitlines()), 1) |
1597 | + |
1598 | + out, err = self.run_bzr(['grep', '-Z', 'line']) |
1599 | + self.assertEqual(out, "file0.txt:line1\0file0.txt:line2\0file0.txt:line3\0") |
1600 | + self.assertEqual(len(out.splitlines()), 1) |
1601 | + |
1602 | + def test_versioned_file_in_dir_no_recursive(self): |
1603 | + """(versioned) Should not recurse with --no-recursive""" |
1604 | + wd = 'foobar0' |
1605 | + self.make_branch_and_tree(wd) |
1606 | + os.chdir(wd) |
1607 | + self._mk_versioned_file('fileX.txt', line_prefix='lin') |
1608 | + self._mk_versioned_dir('dir0') |
1609 | + self._mk_versioned_file('dir0/file0.txt') |
1610 | + |
1611 | + out, err = self.run_bzr(['grep', '-r', 'last:1', '--no-recursive', 'line1']) |
1612 | + self.assertNotContainsRe(out, "file0.txt~.:line1", flags=TestGrep._reflags) |
1613 | + self.assertEqual(len(out.splitlines()), 0) |
1614 | + |
1615 | + out, err = self.run_bzr(['grep', '-r', 'last:1', '--no-recursive', 'line1$']) |
1616 | + self.assertNotContainsRe(out, "file0.txt~.:line1", flags=TestGrep._reflags) |
1617 | + self.assertEqual(len(out.splitlines()), 0) |
1618 | + |
1619 | + def test_wtree_file_in_dir_no_recursive(self): |
1620 | + """(wtree) Should not recurse with --no-recursive""" |
1621 | + wd = 'foobar0' |
1622 | + self.make_branch_and_tree(wd) |
1623 | + os.chdir(wd) |
1624 | + self._mk_versioned_file('fileX.txt', line_prefix='lin') |
1625 | + self._mk_versioned_dir('dir0') |
1626 | + self._mk_versioned_file('dir0/file0.txt') |
1627 | + |
1628 | + out, err = self.run_bzr(['grep', '--no-recursive', 'line1']) |
1629 | + self.assertNotContainsRe(out, "file0.txt:line1", flags=TestGrep._reflags) |
1630 | + self.assertEqual(len(out.splitlines()), 0) |
1631 | + |
1632 | + out, err = self.run_bzr(['grep', '--no-recursive', 'lin.1']) |
1633 | + self.assertNotContainsRe(out, "file0.txt:line1", flags=TestGrep._reflags) |
1634 | + self.assertEqual(len(out.splitlines()), 0) |
1635 | + |
1636 | + def test_versioned_file_in_dir_recurse(self): |
1637 | + """(versioned) Should recurse by default. |
1638 | + """ |
1639 | + wd = 'foobar0' |
1640 | + self.make_branch_and_tree(wd) |
1641 | + os.chdir(wd) |
1642 | + self._mk_versioned_dir('dir0') |
1643 | + self._mk_versioned_file('dir0/file0.txt') |
1644 | + |
1645 | + out, err = self.run_bzr(['grep', '-r', '-1', '.i.e1']) |
1646 | + self.assertContainsRe(out, "^dir0/file0.txt~.:line1", flags=TestGrep._reflags) |
1647 | + # find line1 and line10 |
1648 | + self.assertEqual(len(out.splitlines()), 2) |
1649 | + |
1650 | + out, err = self.run_bzr(['grep', '-r', '-1', 'line1']) |
1651 | + self.assertContainsRe(out, "^dir0/file0.txt~.:line1", flags=TestGrep._reflags) |
1652 | + # find line1 and line10 |
1653 | + self.assertEqual(len(out.splitlines()), 2) |
1654 | + |
1655 | + def test_wtree_file_in_dir_recurse(self): |
1656 | + """(wtree) Should recurse by default. |
1657 | + """ |
1658 | + wd = 'foobar0' |
1659 | + self.make_branch_and_tree(wd) |
1660 | + os.chdir(wd) |
1661 | + self._mk_versioned_dir('dir0') |
1662 | + self._mk_versioned_file('dir0/file0.txt') |
1663 | + |
1664 | + out, err = self.run_bzr(['grep', 'line1']) |
1665 | + self.assertContainsRe(out, "^dir0/file0.txt:line1", flags=TestGrep._reflags) |
1666 | + # find line1 and line10 |
1667 | + self.assertEqual(len(out.splitlines()), 2) |
1668 | + |
1669 | + out, err = self.run_bzr(['grep', 'lin.1']) |
1670 | + self.assertContainsRe(out, "^dir0/file0.txt:line1", flags=TestGrep._reflags) |
1671 | + # find line1 and line10 |
1672 | + self.assertEqual(len(out.splitlines()), 2) |
1673 | + |
1674 | + def test_versioned_file_within_dir(self): |
1675 | + """(versioned) Search for pattern while in nested dir. |
1676 | + """ |
1677 | + wd = 'foobar0' |
1678 | + self.make_branch_and_tree(wd) |
1679 | + os.chdir(wd) |
1680 | + self._mk_versioned_dir('dir0') |
1681 | + self._mk_versioned_file('dir0/file0.txt') |
1682 | + os.chdir('dir0') |
1683 | + |
1684 | + out, err = self.run_bzr(['grep', '-r', 'last:1', 'line1']) |
1685 | + self.assertContainsRe(out, "^file0.txt~.:line1", flags=TestGrep._reflags) |
1686 | + # finds line1 and line10 |
1687 | + self.assertEqual(len(out.splitlines()), 2) |
1688 | + |
1689 | + out, err = self.run_bzr(['grep', '-r', 'last:1', '.i.e1']) |
1690 | + self.assertContainsRe(out, "^file0.txt~.:line1", flags=TestGrep._reflags) |
1691 | + # finds line1 and line10 |
1692 | + self.assertEqual(len(out.splitlines()), 2) |
1693 | + |
1694 | + def test_versioned_include_file_within_dir(self): |
1695 | + """(versioned) Ensure --include is respected with file within dir. |
1696 | + """ |
1697 | + wd = 'foobar0' |
1698 | + self.make_branch_and_tree(wd) |
1699 | + os.chdir(wd) |
1700 | + self._mk_versioned_dir('dir0') # revno 1 |
1701 | + self._mk_versioned_file('dir0/file0.txt') # revno 2 |
1702 | + self._mk_versioned_file('dir0/file1.aa') # revno 3 |
1703 | + self._update_file('dir0/file1.aa', 'hello\n') # revno 4 |
1704 | + self._update_file('dir0/file0.txt', 'hello\n') # revno 5 |
1705 | + os.chdir('dir0') |
1706 | + |
1707 | + out, err = self.run_bzr(['grep', '-r', 'last:1', |
1708 | + '--include', '*.aa', 'line1']) |
1709 | + self.assertContainsRe(out, "^file1.aa~5:line1$", flags=TestGrep._reflags) |
1710 | + self.assertContainsRe(out, "^file1.aa~5:line10$", flags=TestGrep._reflags) |
1711 | + self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags) |
1712 | + # finds line1 and line10 |
1713 | + self.assertEqual(len(out.splitlines()), 2) |
1714 | + |
1715 | + out, err = self.run_bzr(['grep', '-r', 'last:2..last:1', |
1716 | + '--include', '*.aa', 'line1']) |
1717 | + self.assertContainsRe(out, "^file1.aa~4:line1$", flags=TestGrep._reflags) |
1718 | + self.assertContainsRe(out, "^file1.aa~4:line10$", flags=TestGrep._reflags) |
1719 | + self.assertContainsRe(out, "^file1.aa~5:line1$", flags=TestGrep._reflags) |
1720 | + self.assertContainsRe(out, "^file1.aa~5:line10$", flags=TestGrep._reflags) |
1721 | + self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags) |
1722 | + # finds line1 and line10 over two revisions |
1723 | + self.assertEqual(len(out.splitlines()), 4) |
1724 | + |
1725 | + out, err = self.run_bzr(['grep', '-r', 'last:1', |
1726 | + '--include', '*.aa', 'lin.1']) |
1727 | + self.assertContainsRe(out, "^file1.aa~5:line1$", flags=TestGrep._reflags) |
1728 | + self.assertContainsRe(out, "^file1.aa~5:line10$", flags=TestGrep._reflags) |
1729 | + self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags) |
1730 | + # finds line1 and line10 |
1731 | + self.assertEqual(len(out.splitlines()), 2) |
1732 | + |
1733 | + out, err = self.run_bzr(['grep', '-r', 'last:3..last:1', |
1734 | + '--include', '*.aa', 'lin.1']) |
1735 | + self.assertContainsRe(out, "^file1.aa~3:line1$", flags=TestGrep._reflags) |
1736 | + self.assertContainsRe(out, "^file1.aa~4:line1$", flags=TestGrep._reflags) |
1737 | + self.assertContainsRe(out, "^file1.aa~5:line1$", flags=TestGrep._reflags) |
1738 | + self.assertContainsRe(out, "^file1.aa~3:line10$", flags=TestGrep._reflags) |
1739 | + self.assertContainsRe(out, "^file1.aa~4:line10$", flags=TestGrep._reflags) |
1740 | + self.assertContainsRe(out, "^file1.aa~5:line10$", flags=TestGrep._reflags) |
1741 | + self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags) |
1742 | + # finds line1 and line10 over 3 revisions |
1743 | + self.assertEqual(len(out.splitlines()), 6) |
1744 | + |
1745 | + def test_versioned_exclude_file_within_dir(self): |
1746 | + """(versioned) Ensure --exclude is respected with file within dir. |
1747 | + """ |
1748 | + wd = 'foobar0' |
1749 | + self.make_branch_and_tree(wd) |
1750 | + os.chdir(wd) |
1751 | + self._mk_versioned_dir('dir0') |
1752 | + self._mk_versioned_file('dir0/file0.txt') |
1753 | + self._mk_versioned_file('dir0/file1.aa') |
1754 | + os.chdir('dir0') |
1755 | + |
1756 | + out, err = self.run_bzr(['grep', '-r', 'last:1', |
1757 | + '--exclude', '*.txt', 'line1']) |
1758 | + self.assertContainsRe(out, "^file1.aa~.:line1", flags=TestGrep._reflags) |
1759 | + self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags) |
1760 | + # finds line1 and line10 |
1761 | + self.assertEqual(len(out.splitlines()), 2) |
1762 | + |
1763 | + out, err = self.run_bzr(['grep', '-r', 'last:1', |
1764 | + '--exclude', '*.txt', 'l[a-z]ne1']) |
1765 | + self.assertContainsRe(out, "^file1.aa~.:line1", flags=TestGrep._reflags) |
1766 | + self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags) |
1767 | + # finds line1 and line10 |
1768 | + self.assertEqual(len(out.splitlines()), 2) |
1769 | + |
1770 | + def test_wtree_file_within_dir(self): |
1771 | + """(wtree) Search for pattern while in nested dir. |
1772 | + """ |
1773 | + wd = 'foobar0' |
1774 | + self.make_branch_and_tree(wd) |
1775 | + os.chdir(wd) |
1776 | + self._mk_versioned_dir('dir0') |
1777 | + self._mk_versioned_file('dir0/file0.txt') |
1778 | + os.chdir('dir0') |
1779 | + |
1780 | + out, err = self.run_bzr(['grep', 'line1']) |
1781 | + self.assertContainsRe(out, "^file0.txt:line1", flags=TestGrep._reflags) |
1782 | + # finds line1 and line10 |
1783 | + self.assertEqual(len(out.splitlines()), 2) |
1784 | + |
1785 | + out, err = self.run_bzr(['grep', 'l[aeiou]ne1']) |
1786 | + self.assertContainsRe(out, "^file0.txt:line1", flags=TestGrep._reflags) |
1787 | + # finds line1 and line10 |
1788 | + self.assertEqual(len(out.splitlines()), 2) |
1789 | + |
1790 | + def test_wtree_include_file_within_dir(self): |
1791 | + """(wtree) Ensure --include is respected with file within dir. |
1792 | + """ |
1793 | + wd = 'foobar0' |
1794 | + self.make_branch_and_tree(wd) |
1795 | + os.chdir(wd) |
1796 | + self._mk_versioned_dir('dir0') |
1797 | + self._mk_versioned_file('dir0/file0.txt') |
1798 | + self._mk_versioned_file('dir0/file1.aa') |
1799 | + os.chdir('dir0') |
1800 | + |
1801 | + out, err = self.run_bzr(['grep', '--include', '*.aa', 'line1']) |
1802 | + self.assertContainsRe(out, "^file1.aa:line1", flags=TestGrep._reflags) |
1803 | + # finds line1 and line10 |
1804 | + self.assertEqual(len(out.splitlines()), 2) |
1805 | + |
1806 | + out, err = self.run_bzr(['grep', '--include', '*.aa', 'l[ixn]ne1']) |
1807 | + self.assertContainsRe(out, "^file1.aa:line1", flags=TestGrep._reflags) |
1808 | + self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags) |
1809 | + # finds line1 and line10 |
1810 | + self.assertEqual(len(out.splitlines()), 2) |
1811 | + |
1812 | + def test_wtree_exclude_file_within_dir(self): |
1813 | + """(wtree) Ensure --exclude is respected with file within dir. |
1814 | + """ |
1815 | + wd = 'foobar0' |
1816 | + self.make_branch_and_tree(wd) |
1817 | + os.chdir(wd) |
1818 | + self._mk_versioned_dir('dir0') |
1819 | + self._mk_versioned_file('dir0/file0.txt') |
1820 | + self._mk_versioned_file('dir0/file1.aa') |
1821 | + os.chdir('dir0') |
1822 | + |
1823 | + out, err = self.run_bzr(['grep', '--exclude', '*.txt', 'li.e1']) |
1824 | + self.assertContainsRe(out, "^file1.aa:line1$", flags=TestGrep._reflags) |
1825 | + self.assertContainsRe(out, "^file1.aa:line10$", flags=TestGrep._reflags) |
1826 | + self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags) |
1827 | + # finds line1 and line10 |
1828 | + self.assertEqual(len(out.splitlines()), 2) |
1829 | + |
1830 | + out, err = self.run_bzr(['grep', '--exclude', '*.txt', 'line1']) |
1831 | + self.assertContainsRe(out, "^file1.aa:line1$", flags=TestGrep._reflags) |
1832 | + self.assertContainsRe(out, "^file1.aa:line10$", flags=TestGrep._reflags) |
1833 | + self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags) |
1834 | + # finds line1 and line10 |
1835 | + self.assertEqual(len(out.splitlines()), 2) |
1836 | + |
1837 | + def test_versioned_include_from_outside_dir(self): |
1838 | + """(versioned) Ensure --include is respected during recursive search. |
1839 | + """ |
1840 | + wd = 'foobar0' |
1841 | + self.make_branch_and_tree(wd) |
1842 | + os.chdir(wd) |
1843 | + |
1844 | + self._mk_versioned_dir('dir0') |
1845 | + self._mk_versioned_file('dir0/file0.aa') |
1846 | + |
1847 | + self._mk_versioned_dir('dir1') |
1848 | + self._mk_versioned_file('dir1/file1.bb') |
1849 | + |
1850 | + self._mk_versioned_dir('dir2') |
1851 | + self._mk_versioned_file('dir2/file2.cc') |
1852 | + |
1853 | + out, err = self.run_bzr(['grep', '-r', 'last:1', |
1854 | + '--include', '*.aa', '--include', '*.bb', 'l..e1']) |
1855 | + self.assertContainsRe(out, "^dir0/file0.aa~.:line1$", flags=TestGrep._reflags) |
1856 | + self.assertContainsRe(out, "^dir1/file1.bb~.:line1$", flags=TestGrep._reflags) |
1857 | + self.assertContainsRe(out, "^dir0/file0.aa~.:line10$", flags=TestGrep._reflags) |
1858 | + self.assertContainsRe(out, "^dir1/file1.bb~.:line10$", flags=TestGrep._reflags) |
1859 | + self.assertNotContainsRe(out, "file1.cc", flags=TestGrep._reflags) |
1860 | + # finds line1 and line10 |
1861 | + self.assertEqual(len(out.splitlines()), 4) |
1862 | + |
1863 | + out, err = self.run_bzr(['grep', '-r', 'last:1', |
1864 | + '--include', '*.aa', '--include', '*.bb', 'line1']) |
1865 | + self.assertContainsRe(out, "^dir0/file0.aa~.:line1$", flags=TestGrep._reflags) |
1866 | + self.assertContainsRe(out, "^dir1/file1.bb~.:line1$", flags=TestGrep._reflags) |
1867 | + self.assertContainsRe(out, "^dir0/file0.aa~.:line10$", flags=TestGrep._reflags) |
1868 | + self.assertContainsRe(out, "^dir1/file1.bb~.:line10$", flags=TestGrep._reflags) |
1869 | + self.assertNotContainsRe(out, "file1.cc", flags=TestGrep._reflags) |
1870 | + # finds line1 and line10 |
1871 | + self.assertEqual(len(out.splitlines()), 4) |
1872 | + |
1873 | + def test_wtree_include_from_outside_dir(self): |
1874 | + """(wtree) Ensure --include is respected during recursive search. |
1875 | + """ |
1876 | + wd = 'foobar0' |
1877 | + self.make_branch_and_tree(wd) |
1878 | + os.chdir(wd) |
1879 | + |
1880 | + self._mk_versioned_dir('dir0') |
1881 | + self._mk_versioned_file('dir0/file0.aa') |
1882 | + |
1883 | + self._mk_versioned_dir('dir1') |
1884 | + self._mk_versioned_file('dir1/file1.bb') |
1885 | + |
1886 | + self._mk_versioned_dir('dir2') |
1887 | + self._mk_versioned_file('dir2/file2.cc') |
1888 | + |
1889 | + out, err = self.run_bzr(['grep', '--include', '*.aa', |
1890 | + '--include', '*.bb', 'l.n.1']) |
1891 | + self.assertContainsRe(out, "^dir0/file0.aa:line1$", flags=TestGrep._reflags) |
1892 | + self.assertContainsRe(out, "^dir1/file1.bb:line1$", flags=TestGrep._reflags) |
1893 | + self.assertContainsRe(out, "^dir0/file0.aa:line10$", flags=TestGrep._reflags) |
1894 | + self.assertContainsRe(out, "^dir1/file1.bb:line10$", flags=TestGrep._reflags) |
1895 | + self.assertNotContainsRe(out, "file1.cc", flags=TestGrep._reflags) |
1896 | + # finds line1 and line10 |
1897 | + self.assertEqual(len(out.splitlines()), 4) |
1898 | + |
1899 | + out, err = self.run_bzr(['grep', '--include', '*.aa', |
1900 | + '--include', '*.bb', 'line1']) |
1901 | + self.assertContainsRe(out, "^dir0/file0.aa:line1$", flags=TestGrep._reflags) |
1902 | + self.assertContainsRe(out, "^dir1/file1.bb:line1$", flags=TestGrep._reflags) |
1903 | + self.assertContainsRe(out, "^dir0/file0.aa:line10$", flags=TestGrep._reflags) |
1904 | + self.assertContainsRe(out, "^dir1/file1.bb:line10$", flags=TestGrep._reflags) |
1905 | + self.assertNotContainsRe(out, "file1.cc", flags=TestGrep._reflags) |
1906 | + # finds line1 and line10 |
1907 | + self.assertEqual(len(out.splitlines()), 4) |
1908 | + |
1909 | + def test_versioned_exclude_from_outside_dir(self): |
1910 | + """(versioned) Ensure --exclude is respected during recursive search. |
1911 | + """ |
1912 | + wd = 'foobar0' |
1913 | + self.make_branch_and_tree(wd) |
1914 | + os.chdir(wd) |
1915 | + |
1916 | + self._mk_versioned_dir('dir0') |
1917 | + self._mk_versioned_file('dir0/file0.aa') |
1918 | + |
1919 | + self._mk_versioned_dir('dir1') |
1920 | + self._mk_versioned_file('dir1/file1.bb') |
1921 | + |
1922 | + self._mk_versioned_dir('dir2') |
1923 | + self._mk_versioned_file('dir2/file2.cc') |
1924 | + |
1925 | + out, err = self.run_bzr(['grep', '-r', 'last:1', |
1926 | + '--exclude', '*.cc', 'l..e1']) |
1927 | + self.assertContainsRe(out, "^dir0/file0.aa~.:line1", flags=TestGrep._reflags) |
1928 | + self.assertContainsRe(out, "^dir1/file1.bb~.:line1", flags=TestGrep._reflags) |
1929 | + self.assertNotContainsRe(out, "file1.cc", flags=TestGrep._reflags) |
1930 | + |
1931 | + out, err = self.run_bzr(['grep', '-r', 'last:1', |
1932 | + '--exclude', '*.cc', 'line1']) |
1933 | + self.assertContainsRe(out, "^dir0/file0.aa~.:line1", flags=TestGrep._reflags) |
1934 | + self.assertContainsRe(out, "^dir1/file1.bb~.:line1", flags=TestGrep._reflags) |
1935 | + self.assertNotContainsRe(out, "file1.cc", flags=TestGrep._reflags) |
1936 | + |
1937 | + def test_wtree_exclude_from_outside_dir(self): |
1938 | + """(wtree) Ensure --exclude is respected during recursive search. |
1939 | + """ |
1940 | + wd = 'foobar0' |
1941 | + self.make_branch_and_tree(wd) |
1942 | + os.chdir(wd) |
1943 | + |
1944 | + self._mk_versioned_dir('dir0') |
1945 | + self._mk_versioned_file('dir0/file0.aa') |
1946 | + |
1947 | + self._mk_versioned_dir('dir1') |
1948 | + self._mk_versioned_file('dir1/file1.bb') |
1949 | + |
1950 | + self._mk_versioned_dir('dir2') |
1951 | + self._mk_versioned_file('dir2/file2.cc') |
1952 | + |
1953 | + out, err = self.run_bzr(['grep', '--exclude', '*.cc', 'l[hijk]ne1']) |
1954 | + self.assertContainsRe(out, "^dir0/file0.aa:line1", flags=TestGrep._reflags) |
1955 | + self.assertContainsRe(out, "^dir1/file1.bb:line1", flags=TestGrep._reflags) |
1956 | + self.assertNotContainsRe(out, "file1.cc", flags=TestGrep._reflags) |
1957 | + |
1958 | + out, err = self.run_bzr(['grep', '--exclude', '*.cc', 'line1']) |
1959 | + self.assertContainsRe(out, "^dir0/file0.aa:line1", flags=TestGrep._reflags) |
1960 | + self.assertContainsRe(out, "^dir1/file1.bb:line1", flags=TestGrep._reflags) |
1961 | + self.assertNotContainsRe(out, "file1.cc", flags=TestGrep._reflags) |
1962 | + |
1963 | + def test_workingtree_files_from_outside_dir(self): |
1964 | + """(wtree) Grep for pattern with dirs passed as argument. |
1965 | + """ |
1966 | + wd = 'foobar0' |
1967 | + self.make_branch_and_tree(wd) |
1968 | + os.chdir(wd) |
1969 | + |
1970 | + self._mk_versioned_dir('dir0') |
1971 | + self._mk_versioned_file('dir0/file0.txt') |
1972 | + |
1973 | + self._mk_versioned_dir('dir1') |
1974 | + self._mk_versioned_file('dir1/file1.txt') |
1975 | + |
1976 | + out, err = self.run_bzr(['grep', 'l[aeiou]ne1', 'dir0', 'dir1']) |
1977 | + self.assertContainsRe(out, "^dir0/file0.txt:line1", flags=TestGrep._reflags) |
1978 | + self.assertContainsRe(out, "^dir1/file1.txt:line1", flags=TestGrep._reflags) |
1979 | + |
1980 | + out, err = self.run_bzr(['grep', 'line1', 'dir0', 'dir1']) |
1981 | + self.assertContainsRe(out, "^dir0/file0.txt:line1", flags=TestGrep._reflags) |
1982 | + self.assertContainsRe(out, "^dir1/file1.txt:line1", flags=TestGrep._reflags) |
1983 | + |
1984 | + def test_versioned_files_from_outside_dir(self): |
1985 | + """(versioned) Grep for pattern with dirs passed as argument. |
1986 | + """ |
1987 | + wd = 'foobar0' |
1988 | + self.make_branch_and_tree(wd) |
1989 | + os.chdir(wd) |
1990 | + |
1991 | + self._mk_versioned_dir('dir0') |
1992 | + self._mk_versioned_file('dir0/file0.txt') |
1993 | + |
1994 | + self._mk_versioned_dir('dir1') |
1995 | + self._mk_versioned_file('dir1/file1.txt') |
1996 | + |
1997 | + out, err = self.run_bzr(['grep', '-r', 'last:1', '.ine1', 'dir0', 'dir1']) |
1998 | + self.assertContainsRe(out, "^dir0/file0.txt~.:line1", flags=TestGrep._reflags) |
1999 | + self.assertContainsRe(out, "^dir1/file1.txt~.:line1", flags=TestGrep._reflags) |
2000 | + |
2001 | + out, err = self.run_bzr(['grep', '-r', 'last:1', 'line1', 'dir0', 'dir1']) |
2002 | + self.assertContainsRe(out, "^dir0/file0.txt~.:line1", flags=TestGrep._reflags) |
2003 | + self.assertContainsRe(out, "^dir1/file1.txt~.:line1", flags=TestGrep._reflags) |
2004 | + |
2005 | + def test_wtree_files_from_outside_dir(self): |
2006 | + """(wtree) Grep for pattern with dirs passed as argument. |
2007 | + """ |
2008 | + wd = 'foobar0' |
2009 | + self.make_branch_and_tree(wd) |
2010 | + os.chdir(wd) |
2011 | + |
2012 | + self._mk_versioned_dir('dir0') |
2013 | + self._mk_versioned_file('dir0/file0.txt') |
2014 | + |
2015 | + self._mk_versioned_dir('dir1') |
2016 | + self._mk_versioned_file('dir1/file1.txt') |
2017 | + |
2018 | + out, err = self.run_bzr(['grep', 'li.e1', 'dir0', 'dir1']) |
2019 | + self.assertContainsRe(out, "^dir0/file0.txt:line1", flags=TestGrep._reflags) |
2020 | + self.assertContainsRe(out, "^dir1/file1.txt:line1", flags=TestGrep._reflags) |
2021 | + |
2022 | + out, err = self.run_bzr(['grep', 'line1', 'dir0', 'dir1']) |
2023 | + self.assertContainsRe(out, "^dir0/file0.txt:line1", flags=TestGrep._reflags) |
2024 | + self.assertContainsRe(out, "^dir1/file1.txt:line1", flags=TestGrep._reflags) |
2025 | + |
2026 | + def test_versioned_files_from_outside_two_dirs(self): |
2027 | + """(versioned) Grep for pattern with two levels of nested dir. |
2028 | + """ |
2029 | + wd = 'foobar0' |
2030 | + self.make_branch_and_tree(wd) |
2031 | + os.chdir(wd) |
2032 | + |
2033 | + self._mk_versioned_dir('dir0') |
2034 | + self._mk_versioned_file('dir0/file0.txt') |
2035 | + |
2036 | + self._mk_versioned_dir('dir1') |
2037 | + self._mk_versioned_file('dir1/file1.txt') |
2038 | + |
2039 | + self._mk_versioned_dir('dir0/dir00') |
2040 | + self._mk_versioned_file('dir0/dir00/file0.txt') |
2041 | + |
2042 | + out, err = self.run_bzr(['grep', '-r', 'last:1', 'l.ne1', 'dir0/dir00']) |
2043 | + self.assertContainsRe(out, "^dir0/dir00/file0.txt~.:line1", flags=TestGrep._reflags) |
2044 | + |
2045 | + out, err = self.run_bzr(['grep', '-r', 'last:1', 'l.ne1']) |
2046 | + self.assertContainsRe(out, "^dir0/dir00/file0.txt~.:line1", flags=TestGrep._reflags) |
2047 | + |
2048 | + out, err = self.run_bzr(['grep', '-r', 'last:1', 'line1', 'dir0/dir00']) |
2049 | + self.assertContainsRe(out, "^dir0/dir00/file0.txt~.:line1", flags=TestGrep._reflags) |
2050 | + |
2051 | + out, err = self.run_bzr(['grep', '-r', 'last:1', 'line1']) |
2052 | + self.assertContainsRe(out, "^dir0/dir00/file0.txt~.:line1", flags=TestGrep._reflags) |
2053 | + |
2054 | + def test_wtree_files_from_outside_two_dirs(self): |
2055 | + """(wtree) Grep for pattern with two levels of nested dir. |
2056 | + """ |
2057 | + wd = 'foobar0' |
2058 | + self.make_branch_and_tree(wd) |
2059 | + os.chdir(wd) |
2060 | + |
2061 | + self._mk_versioned_dir('dir0') |
2062 | + self._mk_versioned_file('dir0/file0.txt') |
2063 | + |
2064 | + self._mk_versioned_dir('dir1') |
2065 | + self._mk_versioned_file('dir1/file1.txt') |
2066 | + |
2067 | + self._mk_versioned_dir('dir0/dir00') |
2068 | + self._mk_versioned_file('dir0/dir00/file0.txt') |
2069 | + |
2070 | + out, err = self.run_bzr(['grep', 'lin.1', 'dir0/dir00']) |
2071 | + self.assertContainsRe(out, "^dir0/dir00/file0.txt:line1", flags=TestGrep._reflags) |
2072 | + |
2073 | + out, err = self.run_bzr(['grep', 'li.e1']) |
2074 | + self.assertContainsRe(out, "^dir0/dir00/file0.txt:line1", flags=TestGrep._reflags) |
2075 | + |
2076 | + out, err = self.run_bzr(['grep', 'line1', 'dir0/dir00']) |
2077 | + self.assertContainsRe(out, "^dir0/dir00/file0.txt:line1", flags=TestGrep._reflags) |
2078 | + |
2079 | + out, err = self.run_bzr(['grep', 'line1']) |
2080 | + self.assertContainsRe(out, "^dir0/dir00/file0.txt:line1", flags=TestGrep._reflags) |
2081 | + |
2082 | + def test_versioned_file_within_dir_two_levels(self): |
2083 | + """(versioned) Search for pattern while in nested dir (two levels). |
2084 | + """ |
2085 | + wd = 'foobar0' |
2086 | + self.make_branch_and_tree(wd) |
2087 | + os.chdir(wd) |
2088 | + self._mk_versioned_dir('dir0') |
2089 | + self._mk_versioned_dir('dir0/dir1') |
2090 | + self._mk_versioned_file('dir0/dir1/file0.txt') |
2091 | + os.chdir('dir0') |
2092 | + |
2093 | + out, err = self.run_bzr(['grep', '-r', 'last:1', '.ine1']) |
2094 | + self.assertContainsRe(out, "^dir1/file0.txt~.:line1", flags=TestGrep._reflags) |
2095 | + |
2096 | + out, err = self.run_bzr(['grep', '-r', 'last:1', '--from-root', 'l.ne1']) |
2097 | + self.assertContainsRe(out, "^dir0/dir1/file0.txt~.:line1", flags=TestGrep._reflags) |
2098 | + |
2099 | + out, err = self.run_bzr(['grep', '-r', 'last:1', '--no-recursive', 'line1']) |
2100 | + self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags) |
2101 | + |
2102 | + out, err = self.run_bzr(['grep', '-r', 'last:1', 'lin.1']) |
2103 | + self.assertContainsRe(out, "^dir1/file0.txt~.:line1", flags=TestGrep._reflags) |
2104 | + |
2105 | + out, err = self.run_bzr(['grep', '-r', 'last:1', '--from-root', 'line1']) |
2106 | + self.assertContainsRe(out, "^dir0/dir1/file0.txt~.:line1", flags=TestGrep._reflags) |
2107 | + |
2108 | + out, err = self.run_bzr(['grep', '-r', 'last:1', '--no-recursive', 'line1']) |
2109 | + self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags) |
2110 | + self.assertEqual(len(out.splitlines()), 0) |
2111 | + |
2112 | + def test_wtree_file_within_dir_two_levels(self): |
2113 | + """(wtree) Search for pattern while in nested dir (two levels). |
2114 | + """ |
2115 | + wd = 'foobar0' |
2116 | + self.make_branch_and_tree(wd) |
2117 | + os.chdir(wd) |
2118 | + self._mk_versioned_dir('dir0') |
2119 | + self._mk_versioned_dir('dir0/dir1') |
2120 | + self._mk_versioned_file('dir0/dir1/file0.txt') |
2121 | + os.chdir('dir0') |
2122 | + |
2123 | + out, err = self.run_bzr(['grep', 'l[hij]ne1']) |
2124 | + self.assertContainsRe(out, "^dir1/file0.txt:line1", flags=TestGrep._reflags) |
2125 | + |
2126 | + out, err = self.run_bzr(['grep', '--from-root', 'l.ne1']) |
2127 | + self.assertContainsRe(out, "^dir0/dir1/file0.txt:line1", flags=TestGrep._reflags) |
2128 | + |
2129 | + out, err = self.run_bzr(['grep', '--no-recursive', 'lin.1']) |
2130 | + self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags) |
2131 | + |
2132 | + out, err = self.run_bzr(['grep', 'line1']) |
2133 | + self.assertContainsRe(out, "^dir1/file0.txt:line1", flags=TestGrep._reflags) |
2134 | + |
2135 | + out, err = self.run_bzr(['grep', '--from-root', 'line1']) |
2136 | + self.assertContainsRe(out, "^dir0/dir1/file0.txt:line1", flags=TestGrep._reflags) |
2137 | + |
2138 | + out, err = self.run_bzr(['grep', '--no-recursive', 'line1']) |
2139 | + self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags) |
2140 | + |
2141 | + def test_versioned_ignore_case_no_match(self): |
2142 | + """(versioned) Match fails without --ignore-case. |
2143 | + """ |
2144 | + wd = 'foobar0' |
2145 | + self.make_branch_and_tree(wd) |
2146 | + os.chdir(wd) |
2147 | + self._mk_versioned_file('file0.txt') |
2148 | + |
2149 | + out, err = self.run_bzr(['grep', '-r', 'last:1', 'LinE1', 'file0.txt']) |
2150 | + self.assertNotContainsRe(out, "file0.txt~.:line1", flags=TestGrep._reflags) |
2151 | + |
2152 | + out, err = self.run_bzr(['grep', '-r', 'last:1', 'Li.E1', 'file0.txt']) |
2153 | + self.assertNotContainsRe(out, "file0.txt~.:line1", flags=TestGrep._reflags) |
2154 | + |
2155 | + def test_wtree_ignore_case_no_match(self): |
2156 | + """(wtree) Match fails without --ignore-case. |
2157 | + """ |
2158 | + wd = 'foobar0' |
2159 | + self.make_branch_and_tree(wd) |
2160 | + os.chdir(wd) |
2161 | + self._mk_versioned_file('file0.txt') |
2162 | + |
2163 | + out, err = self.run_bzr(['grep', 'LinE1', 'file0.txt']) |
2164 | + self.assertNotContainsRe(out, "file0.txt:line1", flags=TestGrep._reflags) |
2165 | + |
2166 | + out, err = self.run_bzr(['grep', '.inE1', 'file0.txt']) |
2167 | + self.assertNotContainsRe(out, "file0.txt:line1", flags=TestGrep._reflags) |
2168 | + |
2169 | + def test_versioned_ignore_case_match(self): |
2170 | + """(versioned) Match fails without --ignore-case. |
2171 | + """ |
2172 | + wd = 'foobar0' |
2173 | + self.make_branch_and_tree(wd) |
2174 | + os.chdir(wd) |
2175 | + self._mk_versioned_file('file0.txt') |
2176 | + |
2177 | + out, err = self.run_bzr(['grep', '-r', 'last:1', |
2178 | + '-i', 'Li.E1', 'file0.txt']) |
2179 | + self.assertContainsRe(out, "file0.txt~.:line1", flags=TestGrep._reflags) |
2180 | + |
2181 | + out, err = self.run_bzr(['grep', '-r', 'last:1', |
2182 | + '-i', 'LinE1', 'file0.txt']) |
2183 | + self.assertContainsRe(out, "file0.txt~.:line1", flags=TestGrep._reflags) |
2184 | + |
2185 | + out, err = self.run_bzr(['grep', '-r', 'last:1', |
2186 | + '--ignore-case', 'LinE1', 'file0.txt']) |
2187 | + self.assertContainsRe(out, "^file0.txt~.:line1", flags=TestGrep._reflags) |
2188 | + |
2189 | + def test_wtree_ignore_case_match(self): |
2190 | + """(wtree) Match fails without --ignore-case. |
2191 | + """ |
2192 | + wd = 'foobar0' |
2193 | + self.make_branch_and_tree(wd) |
2194 | + os.chdir(wd) |
2195 | + self._mk_versioned_file('file0.txt') |
2196 | + |
2197 | + out, err = self.run_bzr(['grep', '-i', 'LinE1', 'file0.txt']) |
2198 | + self.assertContainsRe(out, "file0.txt:line1", flags=TestGrep._reflags) |
2199 | + |
2200 | + out, err = self.run_bzr(['grep', '--ignore-case', 'LinE1', 'file0.txt']) |
2201 | + self.assertContainsRe(out, "^file0.txt:line1", flags=TestGrep._reflags) |
2202 | + |
2203 | + out, err = self.run_bzr(['grep', '--ignore-case', 'Li.E1', 'file0.txt']) |
2204 | + self.assertContainsRe(out, "^file0.txt:line1", flags=TestGrep._reflags) |
2205 | + |
2206 | + def test_versioned_from_root_fail(self): |
2207 | + """(versioned) Match should fail without --from-root. |
2208 | + """ |
2209 | + wd = 'foobar0' |
2210 | + self.make_branch_and_tree(wd) |
2211 | + os.chdir(wd) |
2212 | + self._mk_versioned_file('file0.txt') |
2213 | + self._mk_versioned_dir('dir0') |
2214 | + os.chdir('dir0') |
2215 | + |
2216 | + out, err = self.run_bzr(['grep', '-r', 'last:1', 'li.e1']) |
2217 | + self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags) |
2218 | + |
2219 | + out, err = self.run_bzr(['grep', '-r', 'last:1', 'line1']) |
2220 | + self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags) |
2221 | + |
2222 | + def test_wtree_from_root_fail(self): |
2223 | + """(wtree) Match should fail without --from-root. |
2224 | + """ |
2225 | + wd = 'foobar0' |
2226 | + self.make_branch_and_tree(wd) |
2227 | + os.chdir(wd) |
2228 | + self._mk_versioned_file('file0.txt') |
2229 | + self._mk_versioned_dir('dir0') |
2230 | + os.chdir('dir0') |
2231 | + |
2232 | + out, err = self.run_bzr(['grep', 'line1']) |
2233 | + self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags) |
2234 | + |
2235 | + out, err = self.run_bzr(['grep', 'li.e1']) |
2236 | + self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags) |
2237 | + |
2238 | + def test_versioned_from_root_pass(self): |
2239 | + """(versioned) Match pass with --from-root. |
2240 | + """ |
2241 | + wd = 'foobar0' |
2242 | + self.make_branch_and_tree(wd) |
2243 | + os.chdir(wd) |
2244 | + self._mk_versioned_file('file0.txt') |
2245 | + self._mk_versioned_dir('dir0') |
2246 | + os.chdir('dir0') |
2247 | + |
2248 | + out, err = self.run_bzr(['grep', '-r', 'last:1', |
2249 | + '--from-root', 'l.ne1']) |
2250 | + self.assertContainsRe(out, "file0.txt~.:line1", flags=TestGrep._reflags) |
2251 | + |
2252 | + out, err = self.run_bzr(['grep', '-r', 'last:1', |
2253 | + '--from-root', 'line1']) |
2254 | + self.assertContainsRe(out, "file0.txt~.:line1", flags=TestGrep._reflags) |
2255 | + |
2256 | + def test_wtree_from_root_pass(self): |
2257 | + """(wtree) Match pass with --from-root. |
2258 | + """ |
2259 | + wd = 'foobar0' |
2260 | + self.make_branch_and_tree(wd) |
2261 | + os.chdir(wd) |
2262 | + self._mk_versioned_file('file0.txt') |
2263 | + self._mk_versioned_dir('dir0') |
2264 | + os.chdir('dir0') |
2265 | + |
2266 | + out, err = self.run_bzr(['grep', '--from-root', 'lin.1']) |
2267 | + self.assertContainsRe(out, "file0.txt:line1", flags=TestGrep._reflags) |
2268 | + |
2269 | + out, err = self.run_bzr(['grep', '--from-root', 'line1']) |
2270 | + self.assertContainsRe(out, "file0.txt:line1", flags=TestGrep._reflags) |
2271 | + |
2272 | + def test_versioned_with_line_number(self): |
2273 | + """(versioned) Search for pattern with --line-number. |
2274 | + """ |
2275 | + wd = 'foobar0' |
2276 | + self.make_branch_and_tree(wd) |
2277 | + os.chdir(wd) |
2278 | + self._mk_versioned_file('file0.txt') |
2279 | + |
2280 | + out, err = self.run_bzr(['grep', '-r', 'last:1', |
2281 | + '--line-number', 'li.e3', 'file0.txt']) |
2282 | + self.assertContainsRe(out, "file0.txt~.:3:line3", flags=TestGrep._reflags) |
2283 | + |
2284 | + out, err = self.run_bzr(['grep', '-r', 'last:1', |
2285 | + '--line-number', 'line3', 'file0.txt']) |
2286 | + self.assertContainsRe(out, "file0.txt~.:3:line3", flags=TestGrep._reflags) |
2287 | + |
2288 | + out, err = self.run_bzr(['grep', '-r', 'last:1', |
2289 | + '-n', 'line1', 'file0.txt']) |
2290 | + self.assertContainsRe(out, "file0.txt~.:1:line1", flags=TestGrep._reflags) |
2291 | + |
2292 | + out, err = self.run_bzr(['grep', '-n', 'line[0-9]', 'file0.txt']) |
2293 | + self.assertContainsRe(out, "file0.txt:3:line3", flags=TestGrep._reflags) |
2294 | + |
2295 | + def test_wtree_with_line_number(self): |
2296 | + """(wtree) Search for pattern with --line-number. |
2297 | + """ |
2298 | + wd = 'foobar0' |
2299 | + self.make_branch_and_tree(wd) |
2300 | + os.chdir(wd) |
2301 | + self._mk_versioned_file('file0.txt') |
2302 | + |
2303 | + out, err = self.run_bzr(['grep', '--line-number', 'line3', 'file0.txt']) |
2304 | + self.assertContainsRe(out, "file0.txt:3:line3", flags=TestGrep._reflags) |
2305 | + |
2306 | + out, err = self.run_bzr(['grep', '-n', 'line1', 'file0.txt']) |
2307 | + self.assertContainsRe(out, "file0.txt:1:line1", flags=TestGrep._reflags) |
2308 | + |
2309 | + out, err = self.run_bzr(['grep', '-n', '[hjkl]ine1', 'file0.txt']) |
2310 | + self.assertContainsRe(out, "file0.txt:1:line1", flags=TestGrep._reflags) |
2311 | + |
2312 | + out, err = self.run_bzr(['grep', '-n', 'line[0-9]', 'file0.txt']) |
2313 | + self.assertContainsRe(out, "file0.txt:3:line3", flags=TestGrep._reflags) |
2314 | + |
2315 | + def test_revno_basic_history_grep_file(self): |
2316 | + """Search for pattern in specific revision number in a file. |
2317 | + """ |
2318 | + wd = 'foobar0' |
2319 | + fname = 'file0.txt' |
2320 | + self.make_branch_and_tree(wd) |
2321 | + os.chdir(wd) |
2322 | + self._mk_versioned_file(fname, total_lines=0) |
2323 | + self._update_file(fname, text="v2 text\n") |
2324 | + self._update_file(fname, text="v3 text\n") |
2325 | + self._update_file(fname, text="v4 text\n") |
2326 | + |
2327 | + # rev 2 should not have text 'v3' |
2328 | + out, err = self.run_bzr(['grep', '-r', '2', 'v3', fname]) |
2329 | + self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags) |
2330 | + |
2331 | + # rev 3 should not have text 'v3' |
2332 | + out, err = self.run_bzr(['grep', '-r', '3', 'v3', fname]) |
2333 | + self.assertContainsRe(out, "file0.txt~3:v3.*", flags=TestGrep._reflags) |
2334 | + |
2335 | + # rev 3 should not have text 'v3' with line number |
2336 | + out, err = self.run_bzr(['grep', '-r', '3', '-n', 'v3', fname]) |
2337 | + self.assertContainsRe(out, "file0.txt~3:2:v3.*", flags=TestGrep._reflags) |
2338 | + |
2339 | + # rev 2 should not have text 'v3' |
2340 | + out, err = self.run_bzr(['grep', '-r', '2', '[tuv]3', fname]) |
2341 | + self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags) |
2342 | + |
2343 | + # rev 3 should not have text 'v3' |
2344 | + out, err = self.run_bzr(['grep', '-r', '3', '[tuv]3', fname]) |
2345 | + self.assertContainsRe(out, "file0.txt~3:v3.*", flags=TestGrep._reflags) |
2346 | + |
2347 | + # rev 3 should not have text 'v3' with line number |
2348 | + out, err = self.run_bzr(['grep', '-r', '3', '-n', '[tuv]3', fname]) |
2349 | + self.assertContainsRe(out, "file0.txt~3:2:v3.*", flags=TestGrep._reflags) |
2350 | + |
2351 | + def test_revno_basic_history_grep_full(self): |
2352 | + """Search for pattern in specific revision number in a file. |
2353 | + """ |
2354 | + wd = 'foobar0' |
2355 | + fname = 'file0.txt' |
2356 | + self.make_branch_and_tree(wd) |
2357 | + os.chdir(wd) |
2358 | + self._mk_versioned_file(fname, total_lines=0) # rev1 |
2359 | + self._mk_versioned_file('file1.txt') # rev2 |
2360 | + self._update_file(fname, text="v3 text\n") # rev3 |
2361 | + self._update_file(fname, text="v4 text\n") # rev4 |
2362 | + self._update_file(fname, text="v5 text\n") # rev5 |
2363 | + |
2364 | + # rev 2 should not have text 'v3' |
2365 | + out, err = self.run_bzr(['grep', '-r', '2', 'v3']) |
2366 | + self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags) |
2367 | + |
2368 | + # rev 3 should not have text 'v3' |
2369 | + out, err = self.run_bzr(['grep', '-r', '3', 'v3']) |
2370 | + self.assertContainsRe(out, "file0.txt~3:v3", flags=TestGrep._reflags) |
2371 | + |
2372 | + # rev 3 should not have text 'v3' with line number |
2373 | + out, err = self.run_bzr(['grep', '-r', '3', '-n', 'v3']) |
2374 | + self.assertContainsRe(out, "file0.txt~3:1:v3", flags=TestGrep._reflags) |
2375 | + |
2376 | + # rev 2 should not have text 'v3' |
2377 | + out, err = self.run_bzr(['grep', '-r', '2', '[tuv]3']) |
2378 | + self.assertNotContainsRe(out, "file0.txt", flags=TestGrep._reflags) |
2379 | + |
2380 | + # rev 3 should not have text 'v3' |
2381 | + out, err = self.run_bzr(['grep', '-r', '3', '[tuv]3']) |
2382 | + self.assertContainsRe(out, "file0.txt~3:v3", flags=TestGrep._reflags) |
2383 | + |
2384 | + # rev 3 should not have text 'v3' with line number |
2385 | + out, err = self.run_bzr(['grep', '-r', '3', '-n', '[tuv]3']) |
2386 | + self.assertContainsRe(out, "file0.txt~3:1:v3", flags=TestGrep._reflags) |
2387 | + |
2388 | + def test_revno_versioned_file_in_dir(self): |
2389 | + """Grep specific version of file withing dir. |
2390 | + """ |
2391 | + wd = 'foobar0' |
2392 | + self.make_branch_and_tree(wd) |
2393 | + os.chdir(wd) |
2394 | + self._mk_versioned_dir('dir0') # rev1 |
2395 | + self._mk_versioned_file('dir0/file0.txt') # rev2 |
2396 | + self._update_file('dir0/file0.txt', "v3 text\n") # rev3 |
2397 | + self._update_file('dir0/file0.txt', "v4 text\n") # rev4 |
2398 | + self._update_file('dir0/file0.txt', "v5 text\n") # rev5 |
2399 | + |
2400 | + # v4 should not be present in revno 3 |
2401 | + out, err = self.run_bzr(['grep', '-r', 'last:3', 'v4']) |
2402 | + self.assertNotContainsRe(out, "^dir0/file0.txt", flags=TestGrep._reflags) |
2403 | + |
2404 | + # v4 should be present in revno 4 |
2405 | + out, err = self.run_bzr(['grep', '-r', 'last:2', 'v4']) |
2406 | + self.assertContainsRe(out, "^dir0/file0.txt~4:v4", flags=TestGrep._reflags) |
2407 | + |
2408 | + # v4 should not be present in revno 3 |
2409 | + out, err = self.run_bzr(['grep', '-r', 'last:3', '[tuv]4']) |
2410 | + self.assertNotContainsRe(out, "^dir0/file0.txt", flags=TestGrep._reflags) |
2411 | + |
2412 | + # v4 should be present in revno 4 |
2413 | + out, err = self.run_bzr(['grep', '-r', 'last:2', '[tuv]4']) |
2414 | + self.assertContainsRe(out, "^dir0/file0.txt~4:v4", flags=TestGrep._reflags) |
2415 | + |
2416 | + def test_revno_range_basic_history_grep(self): |
2417 | + """Search for pattern in revision range for file. |
2418 | + """ |
2419 | + wd = 'foobar0' |
2420 | + fname = 'file0.txt' |
2421 | + self.make_branch_and_tree(wd) |
2422 | + os.chdir(wd) |
2423 | + self._mk_versioned_file(fname, total_lines=0) # rev1 |
2424 | + self._mk_versioned_file('file1.txt') # rev2 |
2425 | + self._update_file(fname, text="v3 text\n") # rev3 |
2426 | + self._update_file(fname, text="v4 text\n") # rev4 |
2427 | + self._update_file(fname, text="v5 text\n") # rev5 |
2428 | + self._update_file(fname, text="v6 text\n") # rev6 |
2429 | + |
2430 | + out, err = self.run_bzr(['grep', '-r', '1..', 'v3']) |
2431 | + self.assertContainsRe(out, "file0.txt~3:v3", flags=TestGrep._reflags) |
2432 | + self.assertContainsRe(out, "file0.txt~4:v3", flags=TestGrep._reflags) |
2433 | + self.assertContainsRe(out, "file0.txt~5:v3", flags=TestGrep._reflags) |
2434 | + self.assertContainsRe(out, "file0.txt~6:v3", flags=TestGrep._reflags) |
2435 | + self.assertEqual(len(out.splitlines()), 4) |
2436 | + |
2437 | + out, err = self.run_bzr(['grep', '-r', '..1', 'v3']) |
2438 | + # searching only rev1 gives nothing |
2439 | + self.assertEqual(len(out.splitlines()), 0) |
2440 | + |
2441 | + out, err = self.run_bzr(['grep', '-r', '..6', 'v3']) |
2442 | + self.assertContainsRe(out, "file0.txt~3:v3", flags=TestGrep._reflags) |
2443 | + self.assertContainsRe(out, "file0.txt~4:v3", flags=TestGrep._reflags) |
2444 | + self.assertContainsRe(out, "file0.txt~5:v3", flags=TestGrep._reflags) |
2445 | + self.assertContainsRe(out, "file0.txt~6:v3", flags=TestGrep._reflags) |
2446 | + self.assertEqual(len(out.splitlines()), 4) |
2447 | + |
2448 | + out, err = self.run_bzr(['grep', '-r', '..', 'v3']) |
2449 | + self.assertContainsRe(out, "file0.txt~3:v3", flags=TestGrep._reflags) |
2450 | + self.assertContainsRe(out, "file0.txt~4:v3", flags=TestGrep._reflags) |
2451 | + self.assertContainsRe(out, "file0.txt~5:v3", flags=TestGrep._reflags) |
2452 | + self.assertContainsRe(out, "file0.txt~6:v3", flags=TestGrep._reflags) |
2453 | + self.assertEqual(len(out.splitlines()), 4) |
2454 | + |
2455 | + out, err = self.run_bzr(['grep', '-r', '1..5', 'v3']) |
2456 | + self.assertContainsRe(out, "file0.txt~3:v3", flags=TestGrep._reflags) |
2457 | + self.assertContainsRe(out, "file0.txt~4:v3", flags=TestGrep._reflags) |
2458 | + self.assertContainsRe(out, "file0.txt~5:v3", flags=TestGrep._reflags) |
2459 | + self.assertNotContainsRe(out, "file0.txt~6:v3", flags=TestGrep._reflags) |
2460 | + self.assertEqual(len(out.splitlines()), 3) |
2461 | + |
2462 | + out, err = self.run_bzr(['grep', '-r', '5..1', 'v3']) |
2463 | + self.assertContainsRe(out, "file0.txt~3:v3", flags=TestGrep._reflags) |
2464 | + self.assertContainsRe(out, "file0.txt~4:v3", flags=TestGrep._reflags) |
2465 | + self.assertContainsRe(out, "file0.txt~5:v3", flags=TestGrep._reflags) |
2466 | + self.assertNotContainsRe(out, "file0.txt~6:v3", flags=TestGrep._reflags) |
2467 | + self.assertEqual(len(out.splitlines()), 3) |
2468 | + |
2469 | + out, err = self.run_bzr(['grep', '-r', '1..', '[tuv]3']) |
2470 | + self.assertContainsRe(out, "file0.txt~3:v3", flags=TestGrep._reflags) |
2471 | + self.assertContainsRe(out, "file0.txt~4:v3", flags=TestGrep._reflags) |
2472 | + self.assertContainsRe(out, "file0.txt~5:v3", flags=TestGrep._reflags) |
2473 | + self.assertContainsRe(out, "file0.txt~6:v3", flags=TestGrep._reflags) |
2474 | + self.assertEqual(len(out.splitlines()), 4) |
2475 | + |
2476 | + out, err = self.run_bzr(['grep', '-r', '1..5', '[tuv]3']) |
2477 | + self.assertContainsRe(out, "file0.txt~3:v3", flags=TestGrep._reflags) |
2478 | + self.assertContainsRe(out, "file0.txt~4:v3", flags=TestGrep._reflags) |
2479 | + self.assertContainsRe(out, "file0.txt~5:v3", flags=TestGrep._reflags) |
2480 | + self.assertNotContainsRe(out, "file0.txt~6:v3", flags=TestGrep._reflags) |
2481 | + self.assertEqual(len(out.splitlines()), 3) |
2482 | + |
2483 | + out, err = self.run_bzr(['grep', '-r', '5..1', '[tuv]3']) |
2484 | + self.assertContainsRe(out, "file0.txt~3:v3", flags=TestGrep._reflags) |
2485 | + self.assertContainsRe(out, "file0.txt~4:v3", flags=TestGrep._reflags) |
2486 | + self.assertContainsRe(out, "file0.txt~5:v3", flags=TestGrep._reflags) |
2487 | + self.assertNotContainsRe(out, "file0.txt~6:v3", flags=TestGrep._reflags) |
2488 | + self.assertEqual(len(out.splitlines()), 3) |
2489 | + |
2490 | + def test_revno_range_versioned_file_in_dir(self): |
2491 | + """Grep rev-range for pattern for file withing a dir. |
2492 | + """ |
2493 | + wd = 'foobar0' |
2494 | + self.make_branch_and_tree(wd) |
2495 | + os.chdir(wd) |
2496 | + self._mk_versioned_dir('dir0') # rev1 |
2497 | + self._mk_versioned_file('dir0/file0.txt') # rev2 |
2498 | + self._update_file('dir0/file0.txt', "v3 text\n") # rev3 |
2499 | + self._update_file('dir0/file0.txt', "v4 text\n") # rev4 |
2500 | + self._update_file('dir0/file0.txt', "v5 text\n") # rev5 |
2501 | + self._update_file('dir0/file0.txt', "v6 text\n") # rev6 |
2502 | + |
2503 | + out, err = self.run_bzr(['grep', '-r', '2..5', 'v3']) |
2504 | + self.assertContainsRe(out, "^dir0/file0.txt~3:v3", flags=TestGrep._reflags) |
2505 | + self.assertContainsRe(out, "^dir0/file0.txt~4:v3", flags=TestGrep._reflags) |
2506 | + self.assertContainsRe(out, "^dir0/file0.txt~5:v3", flags=TestGrep._reflags) |
2507 | + self.assertNotContainsRe(out, "^dir0/file0.txt~6:v3", flags=TestGrep._reflags) |
2508 | + self.assertEqual(len(out.splitlines()), 3) |
2509 | + |
2510 | + out, err = self.run_bzr(['grep', '-r', '2..5', '[tuv]3']) |
2511 | + self.assertContainsRe(out, "^dir0/file0.txt~3:v3", flags=TestGrep._reflags) |
2512 | + self.assertContainsRe(out, "^dir0/file0.txt~4:v3", flags=TestGrep._reflags) |
2513 | + self.assertContainsRe(out, "^dir0/file0.txt~5:v3", flags=TestGrep._reflags) |
2514 | + self.assertNotContainsRe(out, "^dir0/file0.txt~6:v3", flags=TestGrep._reflags) |
2515 | + self.assertEqual(len(out.splitlines()), 3) |
2516 | + |
2517 | + def test_revno_range_versioned_file_from_outside_dir(self): |
2518 | + """Grep rev-range for pattern from outside dir. |
2519 | + """ |
2520 | + wd = 'foobar0' |
2521 | + self.make_branch_and_tree(wd) |
2522 | + os.chdir(wd) |
2523 | + self._mk_versioned_dir('dir0') # rev1 |
2524 | + self._mk_versioned_file('dir0/file0.txt') # rev2 |
2525 | + self._update_file('dir0/file0.txt', "v3 text\n") # rev3 |
2526 | + self._update_file('dir0/file0.txt', "v4 text\n") # rev4 |
2527 | + self._update_file('dir0/file0.txt', "v5 text\n") # rev5 |
2528 | + self._update_file('dir0/file0.txt', "v6 text\n") # rev6 |
2529 | + |
2530 | + out, err = self.run_bzr(['grep', '-r', '2..5', 'v3', 'dir0']) |
2531 | + self.assertContainsRe(out, "^dir0/file0.txt~3:v3", flags=TestGrep._reflags) |
2532 | + self.assertContainsRe(out, "^dir0/file0.txt~4:v3", flags=TestGrep._reflags) |
2533 | + self.assertContainsRe(out, "^dir0/file0.txt~5:v3", flags=TestGrep._reflags) |
2534 | + self.assertNotContainsRe(out, "^dir0/file0.txt~6:v3", flags=TestGrep._reflags) |
2535 | + |
2536 | + out, err = self.run_bzr(['grep', '-r', '2..5', '[tuv]3', 'dir0']) |
2537 | + self.assertContainsRe(out, "^dir0/file0.txt~3:v3", flags=TestGrep._reflags) |
2538 | + self.assertContainsRe(out, "^dir0/file0.txt~4:v3", flags=TestGrep._reflags) |
2539 | + self.assertContainsRe(out, "^dir0/file0.txt~5:v3", flags=TestGrep._reflags) |
2540 | + self.assertNotContainsRe(out, "^dir0/file0.txt~6:v3", flags=TestGrep._reflags) |
2541 | + |
2542 | + def test_levels(self): |
2543 | + """--levels=0 should show findings from merged revision. |
2544 | + """ |
2545 | + wd0 = 'foobar0' |
2546 | + wd1 = 'foobar1' |
2547 | + |
2548 | + self.make_branch_and_tree(wd0) |
2549 | + os.chdir(wd0) |
2550 | + self._mk_versioned_file('file0.txt') |
2551 | + os.chdir('..') |
2552 | + |
2553 | + out, err = self.run_bzr(['branch', wd0, wd1]) |
2554 | + os.chdir(wd1) |
2555 | + self._mk_versioned_file('file1.txt') |
2556 | + os.chdir(osutils.pathjoin('..', wd0)) |
2557 | + |
2558 | + out, err = self.run_bzr(['merge', osutils.pathjoin('..', wd1)]) |
2559 | + out, err = self.run_bzr(['ci', '-m', 'merged']) |
2560 | + |
2561 | + out, err = self.run_bzr(['grep', 'line1']) |
2562 | + self.assertContainsRe(out, "file0.txt:line1", flags=TestGrep._reflags) |
2563 | + self.assertContainsRe(out, "file1.txt:line1", flags=TestGrep._reflags) |
2564 | + |
2565 | + # levels should be ignored by wtree grep |
2566 | + out, err = self.run_bzr(['grep', '--levels=0', 'line1']) |
2567 | + self.assertContainsRe(out, "^file0.txt:line1$", flags=TestGrep._reflags) |
2568 | + self.assertContainsRe(out, "^file1.txt:line1$", flags=TestGrep._reflags) |
2569 | + self.assertContainsRe(out, "^file0.txt:line10$", flags=TestGrep._reflags) |
2570 | + self.assertContainsRe(out, "^file1.txt:line10$", flags=TestGrep._reflags) |
2571 | + self.assertEqual(len(out.splitlines()), 4) |
2572 | + |
2573 | + out, err = self.run_bzr(['grep', '-r', 'last:1..', '--levels=0', 'line1']) |
2574 | + self.assertContainsRe(out, "^file0.txt~2:line1$", flags=TestGrep._reflags) |
2575 | + self.assertContainsRe(out, "^file1.txt~2:line1$", flags=TestGrep._reflags) |
2576 | + self.assertContainsRe(out, "^file0.txt~1.1.1:line1$", flags=TestGrep._reflags) |
2577 | + self.assertContainsRe(out, "^file1.txt~1.1.1:line1$", flags=TestGrep._reflags) |
2578 | + self.assertContainsRe(out, "^file0.txt~2:line10$", flags=TestGrep._reflags) |
2579 | + self.assertContainsRe(out, "^file1.txt~2:line10$", flags=TestGrep._reflags) |
2580 | + self.assertContainsRe(out, "^file0.txt~1.1.1:line10$", flags=TestGrep._reflags) |
2581 | + self.assertContainsRe(out, "^file1.txt~1.1.1:line10$", flags=TestGrep._reflags) |
2582 | + self.assertEqual(len(out.splitlines()), 8) |
2583 | + |
2584 | + out, err = self.run_bzr(['grep', '-r', '-1..', '-n', '--levels=0', 'line1']) |
2585 | + self.assertContainsRe(out, "^file0.txt~2:1:line1$", flags=TestGrep._reflags) |
2586 | + self.assertContainsRe(out, "^file1.txt~2:1:line1$", flags=TestGrep._reflags) |
2587 | + self.assertContainsRe(out, "^file0.txt~1.1.1:1:line1$", flags=TestGrep._reflags) |
2588 | + self.assertContainsRe(out, "^file1.txt~1.1.1:1:line1$", flags=TestGrep._reflags) |
2589 | + self.assertContainsRe(out, "^file0.txt~2:10:line10$", flags=TestGrep._reflags) |
2590 | + self.assertContainsRe(out, "^file1.txt~2:10:line10$", flags=TestGrep._reflags) |
2591 | + self.assertContainsRe(out, "^file0.txt~1.1.1:10:line10$", flags=TestGrep._reflags) |
2592 | + self.assertContainsRe(out, "^file1.txt~1.1.1:10:line10$", flags=TestGrep._reflags) |
2593 | + self.assertEqual(len(out.splitlines()), 8) |
2594 | + |
2595 | + # levels should be ignored by wtree grep |
2596 | + out, err = self.run_bzr(['grep', '--levels=0', 'l.ne1']) |
2597 | + self.assertContainsRe(out, "^file0.txt:line1$", flags=TestGrep._reflags) |
2598 | + self.assertContainsRe(out, "^file1.txt:line1$", flags=TestGrep._reflags) |
2599 | + self.assertContainsRe(out, "^file0.txt:line10$", flags=TestGrep._reflags) |
2600 | + self.assertContainsRe(out, "^file1.txt:line10$", flags=TestGrep._reflags) |
2601 | + self.assertEqual(len(out.splitlines()), 4) |
2602 | + |
2603 | + out, err = self.run_bzr(['grep', '-r', 'last:1..', '--levels=0', 'lin.1']) |
2604 | + self.assertContainsRe(out, "^file0.txt~2:line1$", flags=TestGrep._reflags) |
2605 | + self.assertContainsRe(out, "^file1.txt~2:line1$", flags=TestGrep._reflags) |
2606 | + self.assertContainsRe(out, "^file0.txt~1.1.1:line1$", flags=TestGrep._reflags) |
2607 | + self.assertContainsRe(out, "^file1.txt~1.1.1:line1$", flags=TestGrep._reflags) |
2608 | + self.assertContainsRe(out, "^file0.txt~2:line10$", flags=TestGrep._reflags) |
2609 | + self.assertContainsRe(out, "^file1.txt~2:line10$", flags=TestGrep._reflags) |
2610 | + self.assertContainsRe(out, "^file0.txt~1.1.1:line10$", flags=TestGrep._reflags) |
2611 | + self.assertContainsRe(out, "^file1.txt~1.1.1:line10$", flags=TestGrep._reflags) |
2612 | + self.assertEqual(len(out.splitlines()), 8) |
2613 | + |
2614 | + out, err = self.run_bzr(['grep', '-r', '-1..', '-n', '--levels=0', '.ine1']) |
2615 | + self.assertContainsRe(out, "file0.txt~2:1:line1", flags=TestGrep._reflags) |
2616 | + self.assertContainsRe(out, "file1.txt~2:1:line1", flags=TestGrep._reflags) |
2617 | + self.assertContainsRe(out, "file0.txt~1.1.1:1:line1", flags=TestGrep._reflags) |
2618 | + self.assertContainsRe(out, "file1.txt~1.1.1:1:line1", flags=TestGrep._reflags) |
2619 | + |
2620 | + def test_dotted_rev_grep(self): |
2621 | + """Grep in dotted revs |
2622 | + """ |
2623 | + wd0 = 'foobar0' |
2624 | + wd1 = 'foobar1' |
2625 | + |
2626 | + self.make_branch_and_tree(wd0) |
2627 | + os.chdir(wd0) |
2628 | + self._mk_versioned_file('file0.txt') |
2629 | + os.chdir('..') |
2630 | + |
2631 | + out, err = self.run_bzr(['branch', wd0, wd1]) |
2632 | + os.chdir(wd1) |
2633 | + self._mk_versioned_file('file1.txt') # revno 1.1.1 |
2634 | + self._update_file('file1.txt', "text 0\n") # revno 1.1.2 |
2635 | + self._update_file('file1.txt', "text 1\n") # revno 1.1.3 |
2636 | + self._update_file('file1.txt', "text 2\n") # revno 1.1.4 |
2637 | + os.chdir(osutils.pathjoin('..', wd0)) |
2638 | + |
2639 | + out, err = self.run_bzr(['merge', osutils.pathjoin('..', wd1)]) |
2640 | + out, err = self.run_bzr(['ci', '-m', 'merged']) |
2641 | + |
2642 | + out, err = self.run_bzr(['grep', '-r', '1.1.1..1.1.4', 'text']) |
2643 | + self.assertContainsRe(out, "file1.txt~1.1.2:text 0", flags=TestGrep._reflags) |
2644 | + self.assertContainsRe(out, "file1.txt~1.1.3:text 1", flags=TestGrep._reflags) |
2645 | + self.assertContainsRe(out, "file1.txt~1.1.3:text 1", flags=TestGrep._reflags) |
2646 | + self.assertContainsRe(out, "file1.txt~1.1.4:text 0", flags=TestGrep._reflags) |
2647 | + self.assertContainsRe(out, "file1.txt~1.1.4:text 1", flags=TestGrep._reflags) |
2648 | + self.assertContainsRe(out, "file1.txt~1.1.4:text 2", flags=TestGrep._reflags) |
2649 | + self.assertEqual(len(out.splitlines()), 6) |
2650 | + |
2651 | + def test_versioned_binary_file_grep(self): |
2652 | + """(versioned) Grep for pattern in binary file. |
2653 | + """ |
2654 | + wd = 'foobar0' |
2655 | + self.make_branch_and_tree(wd) |
2656 | + os.chdir(wd) |
2657 | + self._mk_versioned_file('file.txt') |
2658 | + self._mk_versioned_file('file0.bin') |
2659 | + self._update_file('file0.bin', "\x00lineNN\x00\n") |
2660 | + |
2661 | + # note: set --verbose/-v flag to get the skip message. |
2662 | + out, err = self.run_bzr(['grep', '-v', '-r', 'last:1', |
2663 | + 'lineNN', 'file0.bin']) |
2664 | + self.assertNotContainsRe(out, "file0.bin", flags=TestGrep._reflags) |
2665 | + self.assertContainsRe(err, "Binary file.*file0.bin.*skipped", flags=TestGrep._reflags) |
2666 | + self.assertEqual(len(out.splitlines()), 0) |
2667 | + self.assertEqual(len(err.splitlines()), 1) |
2668 | + |
2669 | + out, err = self.run_bzr(['grep', '-v', '-r', 'last:1', |
2670 | + 'line.N', 'file0.bin']) |
2671 | + self.assertNotContainsRe(out, "file0.bin", flags=TestGrep._reflags) |
2672 | + self.assertContainsRe(err, "Binary file.*file0.bin.*skipped", flags=TestGrep._reflags) |
2673 | + self.assertEqual(len(out.splitlines()), 0) |
2674 | + self.assertEqual(len(err.splitlines()), 1) |
2675 | + |
2676 | + def test_wtree_binary_file_grep(self): |
2677 | + """(wtree) Grep for pattern in binary file. |
2678 | + """ |
2679 | + wd = 'foobar0' |
2680 | + self.make_branch_and_tree(wd) |
2681 | + os.chdir(wd) |
2682 | + self._mk_versioned_file('file0.bin') |
2683 | + self._update_file('file0.bin', "\x00lineNN\x00\n") |
2684 | + |
2685 | + # note: set --verbose/-v flag to get the skip message. |
2686 | + out, err = self.run_bzr(['grep', '-v', 'lineNN', 'file0.bin']) |
2687 | + self.assertNotContainsRe(out, "file0.bin:line1", flags=TestGrep._reflags) |
2688 | + self.assertContainsRe(err, "Binary file.*file0.bin.*skipped", flags=TestGrep._reflags) |
2689 | + |
2690 | + # binary warning should not be shown without --verbose |
2691 | + out, err = self.run_bzr(['grep', 'lineNN', 'file0.bin']) |
2692 | + self.assertNotContainsRe(out, "file0.bin:line1", flags=TestGrep._reflags) |
2693 | + self.assertNotContainsRe(err, "Binary file", flags=TestGrep._reflags) |
2694 | + |
2695 | + def test_revspec(self): |
2696 | + """Ensure various revspecs work |
2697 | + """ |
2698 | + wd = 'foobar0' |
2699 | + self.make_branch_and_tree(wd) |
2700 | + os.chdir(wd) |
2701 | + self._mk_versioned_dir('dir0') # rev1 |
2702 | + self._mk_versioned_file('dir0/file0.txt') # rev2 |
2703 | + self._update_file('dir0/file0.txt', "v3 text\n") # rev3 |
2704 | + self._update_file('dir0/file0.txt', "v4 text\n") # rev4 |
2705 | + self._update_file('dir0/file0.txt', "v5 text\n") # rev5 |
2706 | + |
2707 | + out, err = self.run_bzr(['grep', '-r', 'revno:1..2', 'v3']) |
2708 | + self.assertNotContainsRe(out, "file0", flags=TestGrep._reflags) |
2709 | + self.assertEqual(len(out.splitlines()), 0) |
2710 | + |
2711 | + out, err = self.run_bzr(['grep', '-r', 'revno:4..', 'v4']) |
2712 | + self.assertContainsRe(out, "^dir0/file0.txt", flags=TestGrep._reflags) |
2713 | + self.assertEqual(len(out.splitlines()), 2) # find v4 in rev4 and rev5 |
2714 | + |
2715 | + out, err = self.run_bzr(['grep', '-r', '..revno:3', 'v4']) |
2716 | + self.assertNotContainsRe(out, "file0", flags=TestGrep._reflags) |
2717 | + self.assertEqual(len(out.splitlines()), 0) |
2718 | + |
2719 | + out, err = self.run_bzr(['grep', '-r', '..revno:3', 'v3']) |
2720 | + self.assertContainsRe(out, "^dir0/file0.txt", flags=TestGrep._reflags) |
2721 | + self.assertEqual(len(out.splitlines()), 1) |
2722 | + |
2723 | + def test_wtree_files_with_matches(self): |
2724 | + """(wtree) Ensure --files-with-matches, -l works |
2725 | + """ |
2726 | + wd = 'foobar0' |
2727 | + self.make_branch_and_tree(wd) |
2728 | + os.chdir(wd) |
2729 | + |
2730 | + self._mk_versioned_file('file0.txt', total_lines=2) |
2731 | + self._mk_versioned_file('file1.txt', total_lines=2) |
2732 | + self._mk_versioned_dir('dir0') |
2733 | + self._mk_versioned_file('dir0/file00.txt', total_lines=2) |
2734 | + self._mk_versioned_file('dir0/file01.txt', total_lines=2) |
2735 | + |
2736 | + self._update_file('file0.txt', 'HELLO\n', checkin=False) |
2737 | + self._update_file('dir0/file00.txt', 'HELLO\n', checkin=False) |
2738 | + |
2739 | + # fixed-string |
2740 | + out, err = self.run_bzr(['grep', '--files-with-matches', 'HELLO']) |
2741 | + |
2742 | + self.assertContainsRe(out, "^file0.txt$", flags=TestGrep._reflags) |
2743 | + self.assertContainsRe(out, "^dir0/file00.txt$", flags=TestGrep._reflags) |
2744 | + self.assertEqual(len(out.splitlines()), 2) |
2745 | + |
2746 | + # regex |
2747 | + out, err = self.run_bzr(['grep', '--files-with-matches', 'HE.LO']) |
2748 | + |
2749 | + self.assertContainsRe(out, "^file0.txt$", flags=TestGrep._reflags) |
2750 | + self.assertContainsRe(out, "^dir0/file00.txt$", flags=TestGrep._reflags) |
2751 | + self.assertEqual(len(out.splitlines()), 2) |
2752 | + |
2753 | + # fixed-string |
2754 | + out, err = self.run_bzr(['grep', '-l', 'HELLO']) |
2755 | + |
2756 | + self.assertContainsRe(out, "^file0.txt$", flags=TestGrep._reflags) |
2757 | + self.assertContainsRe(out, "^dir0/file00.txt$", flags=TestGrep._reflags) |
2758 | + self.assertEqual(len(out.splitlines()), 2) |
2759 | + |
2760 | + # regex |
2761 | + out, err = self.run_bzr(['grep', '-l', 'HE.LO']) |
2762 | + |
2763 | + self.assertContainsRe(out, "^file0.txt$", flags=TestGrep._reflags) |
2764 | + self.assertContainsRe(out, "^dir0/file00.txt$", flags=TestGrep._reflags) |
2765 | + self.assertEqual(len(out.splitlines()), 2) |
2766 | + |
2767 | + # fixed-string |
2768 | + out, err = self.run_bzr(['grep', '-l', 'HELLO', 'dir0', 'file1.txt']) |
2769 | + |
2770 | + self.assertContainsRe(out, "^dir0/file00.txt$", flags=TestGrep._reflags) |
2771 | + self.assertEqual(len(out.splitlines()), 1) |
2772 | + |
2773 | + # regex |
2774 | + out, err = self.run_bzr(['grep', '-l', '.ELLO', 'dir0', 'file1.txt']) |
2775 | + |
2776 | + self.assertContainsRe(out, "^dir0/file00.txt$", flags=TestGrep._reflags) |
2777 | + self.assertEqual(len(out.splitlines()), 1) |
2778 | + |
2779 | + # fixed-string |
2780 | + out, err = self.run_bzr(['grep', '-l', 'HELLO', 'file0.txt']) |
2781 | + |
2782 | + self.assertContainsRe(out, "^file0.txt$", flags=TestGrep._reflags) |
2783 | + self.assertEqual(len(out.splitlines()), 1) |
2784 | + |
2785 | + # regex |
2786 | + out, err = self.run_bzr(['grep', '-l', '.ELLO', 'file0.txt']) |
2787 | + |
2788 | + self.assertContainsRe(out, "^file0.txt$", flags=TestGrep._reflags) |
2789 | + self.assertEqual(len(out.splitlines()), 1) |
2790 | + |
2791 | + # fixed-string |
2792 | + out, err = self.run_bzr(['grep', '--no-recursive', '-l', 'HELLO']) |
2793 | + |
2794 | + self.assertContainsRe(out, "^file0.txt$", flags=TestGrep._reflags) |
2795 | + self.assertEqual(len(out.splitlines()), 1) |
2796 | + |
2797 | + # regex |
2798 | + out, err = self.run_bzr(['grep', '--no-recursive', '-l', '.ELLO']) |
2799 | + |
2800 | + self.assertContainsRe(out, "^file0.txt$", flags=TestGrep._reflags) |
2801 | + self.assertEqual(len(out.splitlines()), 1) |
2802 | + |
2803 | + def test_ver_files_with_matches(self): |
2804 | + """(ver) Ensure --files-with-matches, -l works |
2805 | + """ |
2806 | + wd = 'foobar0' |
2807 | + self.make_branch_and_tree(wd) |
2808 | + os.chdir(wd) |
2809 | + |
2810 | + self._mk_versioned_file('file0.txt', total_lines=2) # rev 1 |
2811 | + self._mk_versioned_file('file1.txt', total_lines=2) # rev 2 |
2812 | + self._mk_versioned_dir('dir0') # rev 3 |
2813 | + self._mk_versioned_file('dir0/file00.txt', total_lines=2) # rev 4 |
2814 | + self._mk_versioned_file('dir0/file01.txt', total_lines=2) # rev 5 |
2815 | + |
2816 | + self._update_file('file0.txt', 'HELLO\n') # rev 6 |
2817 | + self._update_file('dir0/file00.txt', 'HELLO\n') # rev 7 |
2818 | + |
2819 | + # fixed-string |
2820 | + out, err = self.run_bzr(['grep', '-r', '-1', '--files-with-matches', |
2821 | + 'HELLO']) |
2822 | + |
2823 | + self.assertContainsRe(out, "^file0.txt~7$", flags=TestGrep._reflags) |
2824 | + self.assertContainsRe(out, "^dir0/file00.txt~7$", flags=TestGrep._reflags) |
2825 | + self.assertEqual(len(out.splitlines()), 2) |
2826 | + |
2827 | + # regex |
2828 | + out, err = self.run_bzr(['grep', '-r', '-1', '--files-with-matches', |
2829 | + 'H.LLO']) |
2830 | + |
2831 | + self.assertContainsRe(out, "^file0.txt~7$", flags=TestGrep._reflags) |
2832 | + self.assertContainsRe(out, "^dir0/file00.txt~7$", flags=TestGrep._reflags) |
2833 | + self.assertEqual(len(out.splitlines()), 2) |
2834 | + |
2835 | + # fixed-string |
2836 | + out, err = self.run_bzr(['grep', '-r', '6..7', '--files-with-matches', |
2837 | + 'HELLO']) |
2838 | + |
2839 | + self.assertContainsRe(out, "^file0.txt~6$", flags=TestGrep._reflags) |
2840 | + self.assertContainsRe(out, "^file0.txt~7$", flags=TestGrep._reflags) |
2841 | + self.assertContainsRe(out, "^dir0/file00.txt~7$", flags=TestGrep._reflags) |
2842 | + self.assertEqual(len(out.splitlines()), 3) |
2843 | + |
2844 | + # regex |
2845 | + out, err = self.run_bzr(['grep', '-r', '6..7', '--files-with-matches', |
2846 | + 'H.LLO']) |
2847 | + |
2848 | + self.assertContainsRe(out, "^file0.txt~6$", flags=TestGrep._reflags) |
2849 | + self.assertContainsRe(out, "^file0.txt~7$", flags=TestGrep._reflags) |
2850 | + self.assertContainsRe(out, "^dir0/file00.txt~7$", flags=TestGrep._reflags) |
2851 | + self.assertEqual(len(out.splitlines()), 3) |
2852 | + |
2853 | + # fixed-string |
2854 | + out, err = self.run_bzr(['grep', '-r', '-1', '-l', 'HELLO']) |
2855 | + |
2856 | + self.assertContainsRe(out, "^file0.txt~7$", flags=TestGrep._reflags) |
2857 | + self.assertContainsRe(out, "^dir0/file00.txt~7$", flags=TestGrep._reflags) |
2858 | + self.assertEqual(len(out.splitlines()), 2) |
2859 | + |
2860 | + # regex |
2861 | + out, err = self.run_bzr(['grep', '-r', '-1', '-l', 'H.LLO']) |
2862 | + |
2863 | + self.assertContainsRe(out, "^file0.txt~7$", flags=TestGrep._reflags) |
2864 | + self.assertContainsRe(out, "^dir0/file00.txt~7$", flags=TestGrep._reflags) |
2865 | + self.assertEqual(len(out.splitlines()), 2) |
2866 | + |
2867 | + # fixed-string |
2868 | + out, err = self.run_bzr(['grep', '-l', 'HELLO', '-r', '-1', |
2869 | + 'dir0', 'file1.txt']) |
2870 | + |
2871 | + self.assertContainsRe(out, "^dir0/file00.txt~7$", flags=TestGrep._reflags) |
2872 | + self.assertEqual(len(out.splitlines()), 1) |
2873 | + |
2874 | + # regex |
2875 | + out, err = self.run_bzr(['grep', '-l', 'H.LLO', '-r', '-1', |
2876 | + 'dir0', 'file1.txt']) |
2877 | + |
2878 | + self.assertContainsRe(out, "^dir0/file00.txt~7$", flags=TestGrep._reflags) |
2879 | + self.assertEqual(len(out.splitlines()), 1) |
2880 | + |
2881 | + # fixed-string |
2882 | + out, err = self.run_bzr(['grep', '-l', 'HELLO', |
2883 | + '-r', '-2', 'file0.txt']) |
2884 | + |
2885 | + self.assertContainsRe(out, "^file0.txt~6$", flags=TestGrep._reflags) |
2886 | + self.assertEqual(len(out.splitlines()), 1) |
2887 | + |
2888 | + # regex |
2889 | + out, err = self.run_bzr(['grep', '-l', 'HE.LO', |
2890 | + '-r', '-2', 'file0.txt']) |
2891 | + |
2892 | + self.assertContainsRe(out, "^file0.txt~6$", flags=TestGrep._reflags) |
2893 | + self.assertEqual(len(out.splitlines()), 1) |
2894 | + |
2895 | + # fixed-string |
2896 | + out, err = self.run_bzr(['grep', '--no-recursive', '-r', '-1', |
2897 | + '-l', 'HELLO']) |
2898 | + |
2899 | + self.assertContainsRe(out, "^file0.txt~7$", flags=TestGrep._reflags) |
2900 | + self.assertEqual(len(out.splitlines()), 1) |
2901 | + |
2902 | + # regex |
2903 | + out, err = self.run_bzr(['grep', '--no-recursive', '-r', '-1', |
2904 | + '-l', '.ELLO']) |
2905 | + |
2906 | + self.assertContainsRe(out, "^file0.txt~7$", flags=TestGrep._reflags) |
2907 | + self.assertEqual(len(out.splitlines()), 1) |
2908 | + |
2909 | + def test_wtree_files_without_matches(self): |
2910 | + """(wtree) Ensure --files-without-match, -L works |
2911 | + """ |
2912 | + wd = 'foobar0' |
2913 | + self.make_branch_and_tree(wd) |
2914 | + os.chdir(wd) |
2915 | + |
2916 | + self._mk_versioned_file('file0.txt', total_lines=2) |
2917 | + self._mk_versioned_file('file1.txt', total_lines=2) |
2918 | + self._mk_versioned_dir('dir0') |
2919 | + self._mk_versioned_file('dir0/file00.txt', total_lines=2) |
2920 | + self._mk_versioned_file('dir0/file01.txt', total_lines=2) |
2921 | + |
2922 | + self._update_file('file0.txt', 'HELLO\n', checkin=False) |
2923 | + self._update_file('dir0/file00.txt', 'HELLO\n', checkin=False) |
2924 | + |
2925 | + # fixed-string |
2926 | + out, err = self.run_bzr(['grep', '--files-without-match', 'HELLO']) |
2927 | + |
2928 | + self.assertContainsRe(out, "^file1.txt$", flags=TestGrep._reflags) |
2929 | + self.assertContainsRe(out, "^dir0/file01.txt$", flags=TestGrep._reflags) |
2930 | + self.assertEqual(len(out.splitlines()), 2) |
2931 | + |
2932 | + # regex |
2933 | + out, err = self.run_bzr(['grep', '--files-without-match', 'HE.LO']) |
2934 | + |
2935 | + self.assertContainsRe(out, "^file1.txt$", flags=TestGrep._reflags) |
2936 | + self.assertContainsRe(out, "^dir0/file01.txt$", flags=TestGrep._reflags) |
2937 | + self.assertEqual(len(out.splitlines()), 2) |
2938 | + |
2939 | + # fixed-string |
2940 | + out, err = self.run_bzr(['grep', '-L', 'HELLO']) |
2941 | + |
2942 | + self.assertContainsRe(out, "^file1.txt$", flags=TestGrep._reflags) |
2943 | + self.assertContainsRe(out, "^dir0/file01.txt$", flags=TestGrep._reflags) |
2944 | + self.assertEqual(len(out.splitlines()), 2) |
2945 | + |
2946 | + # regex |
2947 | + out, err = self.run_bzr(['grep', '-L', 'HE.LO']) |
2948 | + |
2949 | + self.assertContainsRe(out, "^file1.txt$", flags=TestGrep._reflags) |
2950 | + self.assertContainsRe(out, "^dir0/file01.txt$", flags=TestGrep._reflags) |
2951 | + self.assertEqual(len(out.splitlines()), 2) |
2952 | + |
2953 | + # fixed-string |
2954 | + out, err = self.run_bzr(['grep', '-L', 'HELLO', 'dir0', 'file1.txt']) |
2955 | + |
2956 | + self.assertContainsRe(out, "^file1.txt$", flags=TestGrep._reflags) |
2957 | + self.assertContainsRe(out, "^dir0/file01.txt$", flags=TestGrep._reflags) |
2958 | + self.assertEqual(len(out.splitlines()), 2) |
2959 | + |
2960 | + # regex |
2961 | + out, err = self.run_bzr(['grep', '-L', '.ELLO', 'dir0', 'file1.txt']) |
2962 | + |
2963 | + self.assertContainsRe(out, "^file1.txt$", flags=TestGrep._reflags) |
2964 | + self.assertContainsRe(out, "^dir0/file01.txt$", flags=TestGrep._reflags) |
2965 | + self.assertEqual(len(out.splitlines()), 2) |
2966 | + |
2967 | + # fixed-string |
2968 | + out, err = self.run_bzr(['grep', '-L', 'HELLO', 'file1.txt']) |
2969 | + |
2970 | + self.assertContainsRe(out, "^file1.txt$", flags=TestGrep._reflags) |
2971 | + self.assertEqual(len(out.splitlines()), 1) |
2972 | + |
2973 | + # regex |
2974 | + out, err = self.run_bzr(['grep', '-L', '.ELLO', 'file1.txt']) |
2975 | + |
2976 | + self.assertContainsRe(out, "^file1.txt$", flags=TestGrep._reflags) |
2977 | + self.assertEqual(len(out.splitlines()), 1) |
2978 | + |
2979 | + # fixed-string |
2980 | + out, err = self.run_bzr(['grep', '--no-recursive', '-L', 'HELLO']) |
2981 | + |
2982 | + self.assertContainsRe(out, "^file1.txt$", flags=TestGrep._reflags) |
2983 | + self.assertEqual(len(out.splitlines()), 1) |
2984 | + |
2985 | + # regex |
2986 | + out, err = self.run_bzr(['grep', '--no-recursive', '-L', '.ELLO']) |
2987 | + |
2988 | + self.assertContainsRe(out, "^file1.txt$", flags=TestGrep._reflags) |
2989 | + self.assertEqual(len(out.splitlines()), 1) |
2990 | + |
2991 | + def test_ver_files_without_matches(self): |
2992 | + """(ver) Ensure --files-without-match, -L works |
2993 | + """ |
2994 | + wd = 'foobar0' |
2995 | + self.make_branch_and_tree(wd) |
2996 | + os.chdir(wd) |
2997 | + |
2998 | + self._mk_versioned_file('file0.txt', total_lines=2) # rev 1 |
2999 | + self._mk_versioned_file('file1.txt', total_lines=2) # rev 2 |
3000 | + self._mk_versioned_dir('dir0') # rev 3 |
3001 | + self._mk_versioned_file('dir0/file00.txt', total_lines=2) # rev 4 |
3002 | + self._mk_versioned_file('dir0/file01.txt', total_lines=2) # rev 5 |
3003 | + |
3004 | + self._update_file('file0.txt', 'HELLO\n') # rev 6 |
3005 | + self._update_file('dir0/file00.txt', 'HELLO\n') # rev 7 |
3006 | + |
3007 | + # fixed-string |
3008 | + out, err = self.run_bzr(['grep', '-r', '-1', '--files-without-match', |
3009 | + 'HELLO']) |
3010 | + |
3011 | + self.assertContainsRe(out, "^file1.txt~7$", flags=TestGrep._reflags) |
3012 | + self.assertContainsRe(out, "^dir0/file01.txt~7$", flags=TestGrep._reflags) |
3013 | + self.assertEqual(len(out.splitlines()), 2) |
3014 | + |
3015 | + # regex |
3016 | + out, err = self.run_bzr(['grep', '-r', '-1', '--files-without-match', |
3017 | + 'H.LLO']) |
3018 | + |
3019 | + self.assertContainsRe(out, "^file1.txt~7$", flags=TestGrep._reflags) |
3020 | + self.assertContainsRe(out, "^dir0/file01.txt~7$", flags=TestGrep._reflags) |
3021 | + self.assertEqual(len(out.splitlines()), 2) |
3022 | + |
3023 | + # fixed-string |
3024 | + out, err = self.run_bzr(['grep', '-r', '6..7', '--files-without-match', |
3025 | + 'HELLO']) |
3026 | + |
3027 | + self.assertContainsRe(out, "^file1.txt~6$", flags=TestGrep._reflags) |
3028 | + self.assertContainsRe(out, "^dir0/file00.txt~6$", flags=TestGrep._reflags) |
3029 | + self.assertContainsRe(out, "^dir0/file01.txt~6$", flags=TestGrep._reflags) |
3030 | + self.assertContainsRe(out, "^file1.txt~7$", flags=TestGrep._reflags) |
3031 | + self.assertContainsRe(out, "^dir0/file01.txt~7$", flags=TestGrep._reflags) |
3032 | + self.assertEqual(len(out.splitlines()), 5) |
3033 | + |
3034 | + # regex |
3035 | + out, err = self.run_bzr(['grep', '-r', '6..7', '--files-without-match', |
3036 | + 'H.LLO']) |
3037 | + |
3038 | + self.assertContainsRe(out, "^file1.txt~6$", flags=TestGrep._reflags) |
3039 | + self.assertContainsRe(out, "^dir0/file00.txt~6$", flags=TestGrep._reflags) |
3040 | + self.assertContainsRe(out, "^dir0/file01.txt~6$", flags=TestGrep._reflags) |
3041 | + self.assertContainsRe(out, "^file1.txt~7$", flags=TestGrep._reflags) |
3042 | + self.assertContainsRe(out, "^dir0/file01.txt~7$", flags=TestGrep._reflags) |
3043 | + self.assertEqual(len(out.splitlines()), 5) |
3044 | + |
3045 | + # fixed-string |
3046 | + out, err = self.run_bzr(['grep', '-r', '-1', '-L', 'HELLO']) |
3047 | + |
3048 | + self.assertContainsRe(out, "^file1.txt~7$", flags=TestGrep._reflags) |
3049 | + self.assertContainsRe(out, "^dir0/file01.txt~7$", flags=TestGrep._reflags) |
3050 | + self.assertEqual(len(out.splitlines()), 2) |
3051 | + |
3052 | + # regex |
3053 | + out, err = self.run_bzr(['grep', '-r', '-1', '-L', 'H.LLO']) |
3054 | + |
3055 | + self.assertContainsRe(out, "^file1.txt~7$", flags=TestGrep._reflags) |
3056 | + self.assertContainsRe(out, "^dir0/file01.txt~7$", flags=TestGrep._reflags) |
3057 | + self.assertEqual(len(out.splitlines()), 2) |
3058 | + |
3059 | + # fixed-string |
3060 | + out, err = self.run_bzr(['grep', '-L', 'HELLO', '-r', '-1', |
3061 | + 'dir0', 'file1.txt']) |
3062 | + |
3063 | + self.assertContainsRe(out, "^file1.txt~7$", flags=TestGrep._reflags) |
3064 | + self.assertContainsRe(out, "^dir0/file01.txt~7$", flags=TestGrep._reflags) |
3065 | + self.assertEqual(len(out.splitlines()), 2) |
3066 | + |
3067 | + # regex |
3068 | + out, err = self.run_bzr(['grep', '-L', 'H.LLO', '-r', '-1', |
3069 | + 'dir0', 'file1.txt']) |
3070 | + |
3071 | + self.assertContainsRe(out, "^file1.txt~7$", flags=TestGrep._reflags) |
3072 | + self.assertContainsRe(out, "^dir0/file01.txt~7$", flags=TestGrep._reflags) |
3073 | + self.assertEqual(len(out.splitlines()), 2) |
3074 | + |
3075 | + # fixed-string |
3076 | + out, err = self.run_bzr(['grep', '-L', 'HELLO', |
3077 | + '-r', '-2', 'file1.txt']) |
3078 | + |
3079 | + self.assertContainsRe(out, "^file1.txt~6$", flags=TestGrep._reflags) |
3080 | + self.assertEqual(len(out.splitlines()), 1) |
3081 | + |
3082 | + # regex |
3083 | + out, err = self.run_bzr(['grep', '-L', 'HE.LO', |
3084 | + '-r', '-2', 'file1.txt']) |
3085 | + |
3086 | + self.assertContainsRe(out, "^file1.txt~6$", flags=TestGrep._reflags) |
3087 | + self.assertEqual(len(out.splitlines()), 1) |
3088 | + |
3089 | + # fixed-string |
3090 | + out, err = self.run_bzr(['grep', '--no-recursive', '-r', '-1', |
3091 | + '-L', 'HELLO']) |
3092 | + |
3093 | + self.assertContainsRe(out, "^file1.txt~7$", flags=TestGrep._reflags) |
3094 | + self.assertEqual(len(out.splitlines()), 1) |
3095 | + |
3096 | + # regex |
3097 | + out, err = self.run_bzr(['grep', '--no-recursive', '-r', '-1', |
3098 | + '-L', '.ELLO']) |
3099 | + |
3100 | + self.assertContainsRe(out, "^file1.txt~7$", flags=TestGrep._reflags) |
3101 | + self.assertEqual(len(out.splitlines()), 1) |
3102 | + |
3103 | + def test_no_tree(self): |
3104 | + """Ensure grep works without working tree. |
3105 | + """ |
3106 | + wd0 = 'foobar0' |
3107 | + wd1 = 'foobar1' |
3108 | + self.make_branch_and_tree(wd0) |
3109 | + os.chdir(wd0) |
3110 | + self._mk_versioned_file('file0.txt') |
3111 | + os.chdir('..') |
3112 | + out, err = self.run_bzr(['branch', '--no-tree', wd0, wd1]) |
3113 | + os.chdir(wd1) |
3114 | + |
3115 | + out, err = self.run_bzr(['grep', 'line1'], 3) |
3116 | + self.assertContainsRe(err, "Cannot search working tree", flags=TestGrep._reflags) |
3117 | + self.assertEqual(out, '') |
3118 | + |
3119 | + out, err = self.run_bzr(['grep', '-r', '1', 'line1']) |
3120 | + self.assertContainsRe(out, "file0.txt~1:line1", flags=TestGrep._reflags) |
3121 | + self.assertEqual(len(out.splitlines()), 2) # finds line1 and line10 |
3122 | + |
3123 | + |
3124 | +class TestNonAscii(GrepTestBase): |
3125 | + """Tests for non-ascii filenames and file contents""" |
3126 | + |
3127 | + _test_needs_features = [UnicodeFilenameFeature] |
3128 | + |
3129 | + def test_unicode_only_file(self): |
3130 | + """Test filename and contents that requires a unicode encoding""" |
3131 | + tree = self.make_branch_and_tree(".") |
3132 | + contents = [u"\u1234"] |
3133 | + self.build_tree(contents) |
3134 | + tree.add(contents) |
3135 | + tree.commit("Initial commit") |
3136 | + as_utf8 = u"\u1234".encode("UTF-8") |
3137 | + |
3138 | + # GZ 2010-06-07: Note we can't actually grep for \u1234 as the pattern |
3139 | + # is mangled according to the user encoding. |
3140 | + streams = self.run_bzr(["grep", "--files-with-matches", |
3141 | + u"contents"], encoding="UTF-8") |
3142 | + self.assertEqual(streams, (as_utf8 + "\n", "")) |
3143 | + |
3144 | + streams = self.run_bzr(["grep", "-r", "1", "--files-with-matches", |
3145 | + u"contents"], encoding="UTF-8") |
3146 | + self.assertEqual(streams, (as_utf8 + "~1\n", "")) |
3147 | + |
3148 | + fileencoding = osutils.get_user_encoding() |
3149 | + as_mangled = as_utf8.decode(fileencoding, "replace").encode("UTF-8") |
3150 | + |
3151 | + streams = self.run_bzr(["grep", "-n", |
3152 | + u"contents"], encoding="UTF-8") |
3153 | + self.assertEqual(streams, ("%s:1:contents of %s\n" % |
3154 | + (as_utf8, as_mangled), "")) |
3155 | + |
3156 | + streams = self.run_bzr(["grep", "-n", "-r", "1", |
3157 | + u"contents"], encoding="UTF-8") |
3158 | + self.assertEqual(streams, ("%s~1:1:contents of %s\n" % |
3159 | + (as_utf8, as_mangled), "")) |
3160 | + |
3161 | + |
3162 | +class TestColorGrep(GrepTestBase): |
3163 | + """Tests for the --color option.""" |
3164 | + |
3165 | + # GZ 2010-06-05: Does this really require the feature? Nothing prints. |
3166 | + _test_needs_features = [ColorFeature] |
3167 | + |
3168 | + _rev_sep = color_string('~', fg=FG.BOLD_YELLOW) |
3169 | + _sep = color_string(':', fg=FG.BOLD_CYAN) |
3170 | + |
3171 | + def test_color_option(self): |
3172 | + """Ensure options for color are valid. |
3173 | + """ |
3174 | + out, err = self.run_bzr(['grep', '--color', 'foo', 'bar'], 3) |
3175 | + self.assertEqual(out, '') |
3176 | + self.assertContainsRe(err, 'Valid values for --color are', flags=TestGrep._reflags) |
3177 | + |
3178 | + def test_ver_matching_files(self): |
3179 | + """(versioned) Search for matches or no matches only""" |
3180 | + tree = self.make_branch_and_tree(".") |
3181 | + contents = ["d/", "d/aaa", "bbb"] |
3182 | + self.build_tree(contents) |
3183 | + tree.add(contents) |
3184 | + tree.commit("Initial commit") |
3185 | + |
3186 | + # GZ 2010-06-05: Maybe modify the working tree here |
3187 | + |
3188 | + streams = self.run_bzr(["grep", "--color", "always", "-r", "1", |
3189 | + "--files-with-matches", "aaa"]) |
3190 | + self.assertEqual(streams, ("".join([ |
3191 | + FG.MAGENTA, "d/aaa", self._rev_sep, "1", "\n" |
3192 | + ]), "")) |
3193 | + |
3194 | + streams = self.run_bzr(["grep", "--color", "always", "-r", "1", |
3195 | + "--files-without-match", "aaa"]) |
3196 | + self.assertEqual(streams, ("".join([ |
3197 | + FG.MAGENTA, "bbb", self._rev_sep, "1", "\n" |
3198 | + ]), "")) |
3199 | + |
3200 | + def test_wtree_matching_files(self): |
3201 | + """(wtree) Search for matches or no matches only""" |
3202 | + tree = self.make_branch_and_tree(".") |
3203 | + contents = ["d/", "d/aaa", "bbb"] |
3204 | + self.build_tree(contents) |
3205 | + tree.add(contents) |
3206 | + tree.commit("Initial commit") |
3207 | + |
3208 | + # GZ 2010-06-05: Maybe modify the working tree here |
3209 | + |
3210 | + streams = self.run_bzr(["grep", "--color", "always", |
3211 | + "--files-with-matches", "aaa"]) |
3212 | + self.assertEqual(streams, ("".join([ |
3213 | + FG.MAGENTA, "d/aaa", FG.NONE, "\n" |
3214 | + ]), "")) |
3215 | + |
3216 | + streams = self.run_bzr(["grep", "--color", "always", |
3217 | + "--files-without-match", "aaa"]) |
3218 | + self.assertEqual(streams, ("".join([ |
3219 | + FG.MAGENTA, "bbb", FG.NONE, "\n" |
3220 | + ]), "")) |
3221 | + |
3222 | + def test_ver_basic_file(self): |
3223 | + """(versioned) Search for pattern in specfic file. |
3224 | + """ |
3225 | + wd = 'foobar0' |
3226 | + self.make_branch_and_tree(wd) |
3227 | + os.chdir(wd) |
3228 | + lp = 'foo is foobar' |
3229 | + self._mk_versioned_file('file0.txt', line_prefix=lp, total_lines=1) |
3230 | + |
3231 | + # prepare colored result |
3232 | + foo = color_string('foo', fg=FG.BOLD_RED) |
3233 | + res = (FG.MAGENTA + 'file0.txt' |
3234 | + + self._rev_sep + '1' + self._sep |
3235 | + + foo + ' is ' + foo + 'bar1' + '\n') |
3236 | + txt_res = 'file0.txt~1:foo is foobar1\n' |
3237 | + |
3238 | + nres = (FG.MAGENTA + 'file0.txt' |
3239 | + + self._rev_sep + '1' + self._sep + '1' + self._sep |
3240 | + + foo + ' is ' + foo + 'bar1' + '\n') |
3241 | + |
3242 | + out, err = self.run_bzr(['grep', '--color', |
3243 | + 'always', '-r', '1', 'foo']) |
3244 | + self.assertEqual(out, res) |
3245 | + self.assertEqual(len(out.splitlines()), 1) |
3246 | + |
3247 | + # auto should produce plain text result |
3248 | + # as stdout is redireched here. |
3249 | + out, err = self.run_bzr(['grep', '--color', |
3250 | + 'auto', '-r', '1', 'foo']) |
3251 | + self.assertEqual(out, txt_res) |
3252 | + self.assertEqual(len(out.splitlines()), 1) |
3253 | + |
3254 | + out, err = self.run_bzr(['grep', '-i', '--color', |
3255 | + 'always', '-r', '1', 'FOO']) |
3256 | + self.assertEqual(out, res) |
3257 | + self.assertEqual(len(out.splitlines()), 1) |
3258 | + |
3259 | + out, err = self.run_bzr(['grep', '--color', |
3260 | + 'always', '-r', '1', 'f.o']) |
3261 | + self.assertEqual(out, res) |
3262 | + self.assertEqual(len(out.splitlines()), 1) |
3263 | + |
3264 | + out, err = self.run_bzr(['grep', '-i', '--color', |
3265 | + 'always', '-r', '1', 'F.O']) |
3266 | + self.assertEqual(out, res) |
3267 | + self.assertEqual(len(out.splitlines()), 1) |
3268 | + |
3269 | + out, err = self.run_bzr(['grep', '-n', '--color', |
3270 | + 'always', '-r', '1', 'foo']) |
3271 | + self.assertEqual(out, nres) |
3272 | + self.assertEqual(len(out.splitlines()), 1) |
3273 | + |
3274 | + out, err = self.run_bzr(['grep', '-n', '-i', '--color', |
3275 | + 'always', '-r', '1', 'FOO']) |
3276 | + self.assertEqual(out, nres) |
3277 | + self.assertEqual(len(out.splitlines()), 1) |
3278 | + |
3279 | + out, err = self.run_bzr(['grep', '-n', '--color', |
3280 | + 'always', '-r', '1', 'f.o']) |
3281 | + self.assertEqual(out, nres) |
3282 | + self.assertEqual(len(out.splitlines()), 1) |
3283 | + |
3284 | + out, err = self.run_bzr(['grep', '-n', '-i', '--color', |
3285 | + 'always', '-r', '1', 'F.O']) |
3286 | + self.assertEqual(out, nres) |
3287 | + self.assertEqual(len(out.splitlines()), 1) |
3288 | + |
3289 | + def test_wtree_basic_file(self): |
3290 | + """(wtree) Search for pattern in specfic file. |
3291 | + """ |
3292 | + wd = 'foobar0' |
3293 | + self.make_branch_and_tree(wd) |
3294 | + os.chdir(wd) |
3295 | + lp = 'foo is foobar' |
3296 | + self._mk_versioned_file('file0.txt', line_prefix=lp, total_lines=1) |
3297 | + |
3298 | + # prepare colored result |
3299 | + foo = color_string('foo', fg=FG.BOLD_RED) |
3300 | + res = (FG.MAGENTA + 'file0.txt' |
3301 | + + self._sep + foo + ' is ' + foo + 'bar1' + '\n') |
3302 | + |
3303 | + nres = (FG.MAGENTA + 'file0.txt' |
3304 | + + self._sep + '1' + self._sep |
3305 | + + foo + ' is ' + foo + 'bar1' + '\n') |
3306 | + |
3307 | + out, err = self.run_bzr(['grep', '--color', |
3308 | + 'always', 'foo']) |
3309 | + self.assertEqual(out, res) |
3310 | + self.assertEqual(len(out.splitlines()), 1) |
3311 | + |
3312 | + out, err = self.run_bzr(['grep', '-i', '--color', |
3313 | + 'always', 'FOO']) |
3314 | + self.assertEqual(out, res) |
3315 | + self.assertEqual(len(out.splitlines()), 1) |
3316 | + |
3317 | + out, err = self.run_bzr(['grep', '--color', |
3318 | + 'always', 'f.o']) |
3319 | + self.assertEqual(out, res) |
3320 | + self.assertEqual(len(out.splitlines()), 1) |
3321 | + |
3322 | + out, err = self.run_bzr(['grep', '-i', '--color', |
3323 | + 'always', 'F.O']) |
3324 | + self.assertEqual(out, res) |
3325 | + self.assertEqual(len(out.splitlines()), 1) |
3326 | + |
3327 | + out, err = self.run_bzr(['grep', '-n', '--color', |
3328 | + 'always', 'foo']) |
3329 | + self.assertEqual(out, nres) |
3330 | + self.assertEqual(len(out.splitlines()), 1) |
3331 | + |
3332 | + out, err = self.run_bzr(['grep', '-n', '-i', '--color', |
3333 | + 'always', 'FOO']) |
3334 | + self.assertEqual(out, nres) |
3335 | + self.assertEqual(len(out.splitlines()), 1) |
3336 | + |
3337 | + out, err = self.run_bzr(['grep', '-n', '--color', |
3338 | + 'always', 'f.o']) |
3339 | + self.assertEqual(out, nres) |
3340 | + self.assertEqual(len(out.splitlines()), 1) |
3341 | + |
3342 | + out, err = self.run_bzr(['grep', '-n', '-i', '--color', |
3343 | + 'always', 'F.O']) |
3344 | + self.assertEqual(out, nres) |
3345 | + self.assertEqual(len(out.splitlines()), 1) |
3346 | + |
3347 | + |
3348 | +# copied from bzrlib.tests.blackbox.test_diff |
3349 | +def subst_dates(string): |
3350 | + """Replace date strings with constant values.""" |
3351 | + return re.sub(r'\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-\+]\d{4}', |
3352 | + 'YYYY-MM-DD HH:MM:SS +ZZZZ', string) |
3353 | + |
3354 | + |
3355 | +class TestGrepDiff(tests.TestCaseWithTransport): |
3356 | + |
3357 | + def make_example_branch(self): |
3358 | + tree = self.make_branch_and_tree('.') |
3359 | + self.build_tree_contents([ |
3360 | + ('hello', 'foo\n'), |
3361 | + ('goodbye', 'baz\n')]) |
3362 | + tree.add(['hello']) |
3363 | + tree.commit('setup') |
3364 | + tree.add(['goodbye']) |
3365 | + tree.commit('setup') |
3366 | + return tree |
3367 | + |
3368 | + def test_grep_diff_basic(self): |
3369 | + """grep -p basic test.""" |
3370 | + tree = self.make_example_branch() |
3371 | + self.build_tree_contents([('hello', 'hello world!\n')]) |
3372 | + tree.commit('updated hello') |
3373 | + out, err = self.run_bzr(['grep', '-p', 'hello']) |
3374 | + self.assertEquals(err, '') |
3375 | + self.assertEqualDiff(subst_dates(out), '''\ |
3376 | +=== revno:3 === |
3377 | + === modified file 'hello' |
3378 | + --- hello YYYY-MM-DD HH:MM:SS +ZZZZ |
3379 | + +++ hello YYYY-MM-DD HH:MM:SS +ZZZZ |
3380 | + +hello world! |
3381 | +=== revno:1 === |
3382 | + === added file 'hello' |
3383 | + --- hello YYYY-MM-DD HH:MM:SS +ZZZZ |
3384 | + +++ hello YYYY-MM-DD HH:MM:SS +ZZZZ |
3385 | +''') |
3386 | + |
3387 | + def test_grep_diff_revision(self): |
3388 | + """grep -p specific revision.""" |
3389 | + tree = self.make_example_branch() |
3390 | + self.build_tree_contents([('hello', 'hello world!\n')]) |
3391 | + tree.commit('updated hello') |
3392 | + out, err = self.run_bzr(['grep', '-p', '-r', '3', 'hello']) |
3393 | + self.assertEquals(err, '') |
3394 | + self.assertEqualDiff(subst_dates(out), '''\ |
3395 | +=== revno:3 === |
3396 | + === modified file 'hello' |
3397 | + --- hello YYYY-MM-DD HH:MM:SS +ZZZZ |
3398 | + +++ hello YYYY-MM-DD HH:MM:SS +ZZZZ |
3399 | + +hello world! |
3400 | +''') |
3401 | + |
3402 | + def test_grep_diff_revision_range(self): |
3403 | + """grep -p revision range.""" |
3404 | + tree = self.make_example_branch() |
3405 | + self.build_tree_contents([('hello', 'hello world!1\n')]) # rev 3 |
3406 | + tree.commit('rev3') |
3407 | + self.build_tree_contents([('blah', 'hello world!2\n')]) # rev 4 |
3408 | + tree.add('blah') |
3409 | + tree.commit('rev4') |
3410 | + open('hello', 'a').write('hello world!3\n') |
3411 | + #self.build_tree_contents([('hello', 'hello world!3\n')]) # rev 5 |
3412 | + tree.commit('rev5') |
3413 | + out, err = self.run_bzr(['grep', '-p', '-r', '2..5', 'hello']) |
3414 | + self.assertEquals(err, '') |
3415 | + self.assertEqualDiff(subst_dates(out), '''\ |
3416 | +=== revno:5 === |
3417 | + === modified file 'hello' |
3418 | + --- hello YYYY-MM-DD HH:MM:SS +ZZZZ |
3419 | + +++ hello YYYY-MM-DD HH:MM:SS +ZZZZ |
3420 | + +hello world!3 |
3421 | +=== revno:4 === |
3422 | + === added file 'blah' |
3423 | + +hello world!2 |
3424 | +=== revno:3 === |
3425 | + === modified file 'hello' |
3426 | + --- hello YYYY-MM-DD HH:MM:SS +ZZZZ |
3427 | + +++ hello YYYY-MM-DD HH:MM:SS +ZZZZ |
3428 | + +hello world!1 |
3429 | +''') |
3430 | + |
3431 | + def test_grep_diff_color(self): |
3432 | + """grep -p color test.""" |
3433 | + tree = self.make_example_branch() |
3434 | + self.build_tree_contents([('hello', 'hello world!\n')]) |
3435 | + tree.commit('updated hello') |
3436 | + out, err = self.run_bzr(['grep', '--diff', '-r', '3', |
3437 | + '--color', 'always', 'hello']) |
3438 | + self.assertEquals(err, '') |
3439 | + revno = color_string('=== revno:3 ===', fg=FG.BOLD_BLUE) + '\n' |
3440 | + filename = color_string(" === modified file 'hello'", fg=FG.BOLD_MAGENTA) + '\n' |
3441 | + redhello = color_string('hello', fg=FG.BOLD_RED) |
3442 | + diffstr = '''\ |
3443 | + --- hello YYYY-MM-DD HH:MM:SS +ZZZZ |
3444 | + +++ hello YYYY-MM-DD HH:MM:SS +ZZZZ |
3445 | + +hello world! |
3446 | +''' |
3447 | + diffstr = diffstr.replace('hello', redhello) |
3448 | + self.assertEqualDiff(subst_dates(out), revno + filename + diffstr) |
3449 | + |
3450 | + def test_grep_norevs(self): |
3451 | + """grep -p with zero revisions.""" |
3452 | + out, err = self.run_bzr(['init']) |
3453 | + out, err = self.run_bzr(['grep', '--diff', 'foo'], 3) |
3454 | + self.assertEquals(out, '') |
3455 | + self.assertContainsRe(err, "ERROR:.*revision.* does not exist in branch") |
3456 | + |
3457 | |
3458 | === modified file 'bzrlib/tests/features.py' |
3459 | --- bzrlib/tests/features.py 2012-03-09 16:48:55 +0000 |
3460 | +++ bzrlib/tests/features.py 2012-08-23 15:07:23 +0000 |
3461 | @@ -492,3 +492,15 @@ |
3462 | |
3463 | |
3464 | win32_feature = Win32Feature() |
3465 | + |
3466 | + |
3467 | +class _ColorFeature(Feature): |
3468 | + |
3469 | + def _probe(self): |
3470 | + from bzrlib._termcolor import allow_color |
3471 | + return allow_color() |
3472 | + |
3473 | + def feature_name(self): |
3474 | + return "Terminal supports color." |
3475 | + |
3476 | +ColorFeature = _ColorFeature() |
3477 | |
3478 | === modified file 'doc/en/release-notes/bzr-2.6.txt' |
3479 | --- doc/en/release-notes/bzr-2.6.txt 2012-08-03 12:22:25 +0000 |
3480 | +++ doc/en/release-notes/bzr-2.6.txt 2012-08-23 15:07:23 +0000 |
3481 | @@ -106,6 +106,8 @@ |
3482 | * New option ``--overwrite-tags`` for ``bzr pull`` and ``bzr push``. |
3483 | (Jelmer Vernooij, #681792) |
3484 | |
3485 | +* The 'grep' plugin is now shipped with bzr. (Jelmer Vernooij) |
3486 | + |
3487 | Improvements |
3488 | ************ |
3489 |
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.