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

Proposed by Jelmer Vernooij
Status: Merged
Approved by: John A Meinel
Approved revision: no longer in the source branch.
Merged at revision: 143
Proposed branch: lp:~jelmer/bzr-grep/lazy
Merge into: lp:bzr-grep
Diff against target: 500 lines (+242/-237)
2 files modified
__init__.py (+4/-237)
cmds.py (+238/-0)
To merge this branch: bzr merge lp:~jelmer/bzr-grep/lazy
Reviewer Review Type Date Requested Status
John A Meinel Approve
Review via email: mp+50489@code.launchpad.net

Description of the change

This moves the actual command implementation to a separate file.

It shaves some (limited) time off the bzr startup time.

To post a comment you must log in.
Revision history for this message
John A Meinel (jameinel) wrote :

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 2/19/2011 6:39 PM, Jelmer Vernooij wrote:
> Jelmer Vernooij has proposed merging lp:~jelmer/bzr-grep/lazy into lp:bzr-grep.
>
> Requested reviews:
> Bazaar Developers (bzr)
>
> For more details, see:
> https://code.launchpad.net/~jelmer/bzr-grep/lazy/+merge/50489
>
> This moves the actual command implementation to a separate file.
>
> It shaves some (limited) time off the bzr startup time.

 merge: approve

John
=:->
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk1mlmAACgkQJdeBCYSNAANz3wCeJ9WBF1fIA4FO6F6XiS2MR8qm
QRcAn3zX/97+dZE/VOC0F3nj0AGSOiIn
=rohz
-----END PGP SIGNATURE-----

review: Approve
lp:~jelmer/bzr-grep/lazy updated
143. By Jelmer Vernooij

Merge lazy loading of command implementation.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file '__init__.py'
--- __init__.py 2010-06-26 02:34:08 +0000
+++ __init__.py 2011-02-20 00:38:52 +0000
@@ -13,249 +13,16 @@
13# You should have received a copy of the GNU General Public License13# You should have received a copy of the GNU General Public License
14# along with this program; if not, write to the Free Software14# along with this program; if not, write to the Free Software
15# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA15# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16
16"""Print lines matching PATTERN for specified files and revisions."""17"""Print lines matching PATTERN for specified files and revisions."""
1718
18import os19from bzrlib.commands import plugin_cmds
19import sys20
20
21from bzrlib import errors
22from bzrlib.commands import Command, register_command, display_command
23from bzrlib.option import Option, ListOption
24
25from bzrlib.lazy_import import lazy_import
26lazy_import(globals(), """
27import re
28
29from termcolor import allow_color
30import grep
31
32import bzrlib
33from bzrlib.revisionspec import RevisionSpec
34from bzrlib import (
35 osutils,
36 bzrdir,
37 trace,
38 )
39""")
40import version21import version
4122
42version_info = version.version_info23version_info = version.version_info
4324
44# FIXME: _parse_levels should be shared with bzrlib.builtins. this is a copy25plugin_cmds.register_lazy("cmd_grep", [], "bzrlib.plugins.grep.cmds")
45# to avoid the error
46# "IllegalUseOfScopeReplacer: ScopeReplacer object '_parse_levels' was used
47# incorrectly: Object already cleaned up, did you assign it to another
48# variable?: _factory
49# with lazy import
50def _parse_levels(s):
51 try:
52 return int(s)
53 except ValueError:
54 msg = "The levels argument must be an integer."
55 raise errors.BzrCommandError(msg)
56
57
58class GrepOptions(object):
59 """Container to pass around grep options.
60
61 This class is used as a container to pass around user option and
62 some other params (like outf) to processing functions. This makes
63 it easier to add more options as grep evolves.
64 """
65 verbose = False
66 ignore_case = False
67 no_recursive = False
68 from_root = False
69 null = False
70 levels = None
71 line_number = False
72 path_list = None
73 revision = None
74 pattern = None
75 include = None
76 exclude = None
77 fixed_string = False
78 files_with_matches = False
79 files_without_match = False
80 color = None
81 diff = False
82
83 # derived options
84 recursive = None
85 eol_marker = None
86 patternc = None
87 sub_patternc = None
88 print_revno = None
89 fixed_string = None
90 outf = None
91 show_color = False
92
93
94class cmd_grep(Command):
95 """Print lines matching PATTERN for specified files and revisions.
96
97 This command searches the specified files and revisions for a given
98 pattern. The pattern is specified as a Python regular expressions[1].
99
100 If the file name is not specified, the revisions starting with the
101 current directory are searched recursively. If the revision number is
102 not specified, the working copy is searched. To search the last committed
103 revision, use the '-r -1' or '-r last:1' option.
104
105 Unversioned files are not searched unless explicitly specified on the
106 command line. Unversioned directores are not searched.
107
108 When searching a pattern, the output is shown in the 'filepath:string'
109 format. If a revision is explicitly searched, the output is shown as
110 'filepath~N:string', where N is the revision number.
111
112 --include and --exclude options can be used to search only (or exclude
113 from search) files with base name matches the specified Unix style GLOB
114 pattern. The GLOB pattern an use *, ?, and [...] as wildcards, and \\
115 to quote wildcard or backslash character literally. Note that the glob
116 pattern is not a regular expression.
117
118 [1] http://docs.python.org/library/re.html#regular-expression-syntax
119 """
120
121 encoding_type = 'replace'
122 takes_args = ['pattern', 'path*']
123 takes_options = [
124 'verbose',
125 'revision',
126 Option('color', type=str, argname='when',
127 help='Show match in color. WHEN is never, always or auto.'),
128 Option('diff', short_name='p',
129 help='Grep for pattern in changeset for each revision.'),
130 ListOption('exclude', type=str, argname='glob', short_name='X',
131 help="Skip files whose base name matches GLOB."),
132 ListOption('include', type=str, argname='glob', short_name='I',
133 help="Search only files whose base name matches GLOB."),
134 Option('files-with-matches', short_name='l',
135 help='Print only the name of each input file in '
136 'which PATTERN is found.'),
137 Option('files-without-match', short_name='L',
138 help='Print only the name of each input file in '
139 'which PATTERN is not found.'),
140 Option('fixed-string', short_name='F',
141 help='Interpret PATTERN is a single fixed string (not regex).'),
142 Option('from-root',
143 help='Search for pattern starting from the root of the branch. '
144 '(implies --recursive)'),
145 Option('ignore-case', short_name='i',
146 help='ignore case distinctions while matching.'),
147 Option('levels',
148 help='Number of levels to display - 0 for all, 1 for collapsed '
149 '(1 is default).',
150 argname='N',
151 type=_parse_levels),
152 Option('line-number', short_name='n',
153 help='show 1-based line number.'),
154 Option('no-recursive',
155 help="Don't recurse into subdirectories. (default is --recursive)"),
156 Option('null', short_name='Z',
157 help='Write an ASCII NUL (\\0) separator '
158 'between output lines rather than a newline.'),
159 ]
160
161
162 @display_command
163 def run(self, verbose=False, ignore_case=False, no_recursive=False,
164 from_root=False, null=False, levels=None, line_number=False,
165 path_list=None, revision=None, pattern=None, include=None,
166 exclude=None, fixed_string=False, files_with_matches=False,
167 files_without_match=False, color='never', diff=False):
168
169 if path_list == None:
170 path_list = ['.']
171 else:
172 if from_root:
173 raise errors.BzrCommandError('cannot specify both --from-root and PATH.')
174
175 if files_with_matches and files_without_match:
176 raise errors.BzrCommandError('cannot specify both '
177 '-l/--files-with-matches and -L/--files-without-matches.')
178
179 if color not in ['always', 'never', 'auto']:
180 raise errors.BzrCommandError('Valid values for --color are '
181 '"always", "never" or "auto".')
182
183 if levels==None:
184 levels=1
185
186 print_revno = False
187 if revision != None or levels == 0:
188 # print revision numbers as we may be showing multiple revisions
189 print_revno = True
190
191 eol_marker = '\n'
192 if null:
193 eol_marker = '\0'
194
195 if not ignore_case and grep.is_fixed_string(pattern):
196 # if the pattern isalnum, implicitly use to -F for faster grep
197 fixed_string = True
198 elif ignore_case and fixed_string:
199 # GZ 2010-06-02: Fall back to regexp rather than lowercasing
200 # pattern and text which will cause pain later
201 fixed_string = False
202 pattern = re.escape(pattern)
203
204 patternc = None
205 re_flags = re.MULTILINE
206 if ignore_case:
207 re_flags |= re.IGNORECASE
208
209 if not fixed_string:
210 patternc = grep.compile_pattern(pattern, re_flags)
211
212 if color == 'always':
213 show_color = True
214 elif color == 'never':
215 show_color = False
216 elif color == 'auto':
217 show_color = allow_color()
218
219 GrepOptions.verbose = verbose
220 GrepOptions.ignore_case = ignore_case
221 GrepOptions.no_recursive = no_recursive
222 GrepOptions.from_root = from_root
223 GrepOptions.null = null
224 GrepOptions.levels = levels
225 GrepOptions.line_number = line_number
226 GrepOptions.path_list = path_list
227 GrepOptions.revision = revision
228 GrepOptions.pattern = pattern
229 GrepOptions.include = include
230 GrepOptions.exclude = exclude
231 GrepOptions.fixed_string = fixed_string
232 GrepOptions.files_with_matches = files_with_matches
233 GrepOptions.files_without_match = files_without_match
234 GrepOptions.color = color
235 GrepOptions.diff = False
236
237 GrepOptions.eol_marker = eol_marker
238 GrepOptions.print_revno = print_revno
239 GrepOptions.patternc = patternc
240 GrepOptions.recursive = not no_recursive
241 GrepOptions.fixed_string = fixed_string
242 GrepOptions.outf = self.outf
243 GrepOptions.show_color = show_color
244
245 if diff == True:
246 # options not used:
247 # files_with_matches, files_without_match
248 # levels(?), line_number, from_root
249 # include, exclude
250 # These are silently ignored.
251 grep.grep_diff(GrepOptions)
252 elif revision == None:
253 grep.workingtree_grep(GrepOptions)
254 else:
255 grep.versioned_grep(GrepOptions)
256
257
258register_command(cmd_grep)
25926
260def test_suite():27def test_suite():
261 from bzrlib.tests import TestUtil28 from bzrlib.tests import TestUtil
26229
=== added file 'cmds.py'
--- cmds.py 1970-01-01 00:00:00 +0000
+++ cmds.py 2011-02-20 00:38:52 +0000
@@ -0,0 +1,238 @@
1# Copyright (C) 2010 Canonical Ltd
2#
3# This program is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation; either version 2 of the License, or
6# (at your option) any later version.
7#
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11# GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License
14# along with this program; if not, write to the Free Software
15# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16
17"""Print lines matching PATTERN for specified files and revisions."""
18
19from bzrlib import errors
20from bzrlib.commands import Command, display_command
21from bzrlib.option import Option, ListOption
22
23# FIXME: _parse_levels should be shared with bzrlib.builtins. this is a copy
24# to avoid the error
25# "IllegalUseOfScopeReplacer: ScopeReplacer object '_parse_levels' was used
26# incorrectly: Object already cleaned up, did you assign it to another
27# variable?: _factory
28# with lazy import
29def _parse_levels(s):
30 try:
31 return int(s)
32 except ValueError:
33 msg = "The levels argument must be an integer."
34 raise errors.BzrCommandError(msg)
35
36
37class GrepOptions(object):
38 """Container to pass around grep options.
39
40 This class is used as a container to pass around user option and
41 some other params (like outf) to processing functions. This makes
42 it easier to add more options as grep evolves.
43 """
44 verbose = False
45 ignore_case = False
46 no_recursive = False
47 from_root = False
48 null = False
49 levels = None
50 line_number = False
51 path_list = None
52 revision = None
53 pattern = None
54 include = None
55 exclude = None
56 fixed_string = False
57 files_with_matches = False
58 files_without_match = False
59 color = None
60 diff = False
61
62 # derived options
63 recursive = None
64 eol_marker = None
65 patternc = None
66 sub_patternc = None
67 print_revno = None
68 fixed_string = None
69 outf = None
70 show_color = False
71
72
73class cmd_grep(Command):
74 """Print lines matching PATTERN for specified files and revisions.
75
76 This command searches the specified files and revisions for a given
77 pattern. The pattern is specified as a Python regular expressions[1].
78
79 If the file name is not specified, the revisions starting with the
80 current directory are searched recursively. If the revision number is
81 not specified, the working copy is searched. To search the last committed
82 revision, use the '-r -1' or '-r last:1' option.
83
84 Unversioned files are not searched unless explicitly specified on the
85 command line. Unversioned directores are not searched.
86
87 When searching a pattern, the output is shown in the 'filepath:string'
88 format. If a revision is explicitly searched, the output is shown as
89 'filepath~N:string', where N is the revision number.
90
91 --include and --exclude options can be used to search only (or exclude
92 from search) files with base name matches the specified Unix style GLOB
93 pattern. The GLOB pattern an use *, ?, and [...] as wildcards, and \\
94 to quote wildcard or backslash character literally. Note that the glob
95 pattern is not a regular expression.
96
97 [1] http://docs.python.org/library/re.html#regular-expression-syntax
98 """
99
100 encoding_type = 'replace'
101 takes_args = ['pattern', 'path*']
102 takes_options = [
103 'verbose',
104 'revision',
105 Option('color', type=str, argname='when',
106 help='Show match in color. WHEN is never, always or auto.'),
107 Option('diff', short_name='p',
108 help='Grep for pattern in changeset for each revision.'),
109 ListOption('exclude', type=str, argname='glob', short_name='X',
110 help="Skip files whose base name matches GLOB."),
111 ListOption('include', type=str, argname='glob', short_name='I',
112 help="Search only files whose base name matches GLOB."),
113 Option('files-with-matches', short_name='l',
114 help='Print only the name of each input file in '
115 'which PATTERN is found.'),
116 Option('files-without-match', short_name='L',
117 help='Print only the name of each input file in '
118 'which PATTERN is not found.'),
119 Option('fixed-string', short_name='F',
120 help='Interpret PATTERN is a single fixed string (not regex).'),
121 Option('from-root',
122 help='Search for pattern starting from the root of the branch. '
123 '(implies --recursive)'),
124 Option('ignore-case', short_name='i',
125 help='ignore case distinctions while matching.'),
126 Option('levels',
127 help='Number of levels to display - 0 for all, 1 for collapsed '
128 '(1 is default).',
129 argname='N',
130 type=_parse_levels),
131 Option('line-number', short_name='n',
132 help='show 1-based line number.'),
133 Option('no-recursive',
134 help="Don't recurse into subdirectories. (default is --recursive)"),
135 Option('null', short_name='Z',
136 help='Write an ASCII NUL (\\0) separator '
137 'between output lines rather than a newline.'),
138 ]
139
140
141 @display_command
142 def run(self, verbose=False, ignore_case=False, no_recursive=False,
143 from_root=False, null=False, levels=None, line_number=False,
144 path_list=None, revision=None, pattern=None, include=None,
145 exclude=None, fixed_string=False, files_with_matches=False,
146 files_without_match=False, color='never', diff=False):
147 from bzrlib.plugins.grep import (
148 grep,
149 termcolor,
150 )
151 import re
152 if path_list == None:
153 path_list = ['.']
154 else:
155 if from_root:
156 raise errors.BzrCommandError('cannot specify both --from-root and PATH.')
157
158 if files_with_matches and files_without_match:
159 raise errors.BzrCommandError('cannot specify both '
160 '-l/--files-with-matches and -L/--files-without-matches.')
161
162 if color not in ['always', 'never', 'auto']:
163 raise errors.BzrCommandError('Valid values for --color are '
164 '"always", "never" or "auto".')
165
166 if levels==None:
167 levels=1
168
169 print_revno = False
170 if revision != None or levels == 0:
171 # print revision numbers as we may be showing multiple revisions
172 print_revno = True
173
174 eol_marker = '\n'
175 if null:
176 eol_marker = '\0'
177
178 if not ignore_case and grep.is_fixed_string(pattern):
179 # if the pattern isalnum, implicitly use to -F for faster grep
180 fixed_string = True
181 elif ignore_case and fixed_string:
182 # GZ 2010-06-02: Fall back to regexp rather than lowercasing
183 # pattern and text which will cause pain later
184 fixed_string = False
185 pattern = re.escape(pattern)
186
187 patternc = None
188 re_flags = re.MULTILINE
189 if ignore_case:
190 re_flags |= re.IGNORECASE
191
192 if not fixed_string:
193 patternc = grep.compile_pattern(pattern, re_flags)
194
195 if color == 'always':
196 show_color = True
197 elif color == 'never':
198 show_color = False
199 elif color == 'auto':
200 show_color = termcolor.allow_color()
201
202 GrepOptions.verbose = verbose
203 GrepOptions.ignore_case = ignore_case
204 GrepOptions.no_recursive = no_recursive
205 GrepOptions.from_root = from_root
206 GrepOptions.null = null
207 GrepOptions.levels = levels
208 GrepOptions.line_number = line_number
209 GrepOptions.path_list = path_list
210 GrepOptions.revision = revision
211 GrepOptions.pattern = pattern
212 GrepOptions.include = include
213 GrepOptions.exclude = exclude
214 GrepOptions.fixed_string = fixed_string
215 GrepOptions.files_with_matches = files_with_matches
216 GrepOptions.files_without_match = files_without_match
217 GrepOptions.color = color
218 GrepOptions.diff = False
219
220 GrepOptions.eol_marker = eol_marker
221 GrepOptions.print_revno = print_revno
222 GrepOptions.patternc = patternc
223 GrepOptions.recursive = not no_recursive
224 GrepOptions.fixed_string = fixed_string
225 GrepOptions.outf = self.outf
226 GrepOptions.show_color = show_color
227
228 if diff == True:
229 # options not used:
230 # files_with_matches, files_without_match
231 # levels(?), line_number, from_root
232 # include, exclude
233 # These are silently ignored.
234 grep.grep_diff(GrepOptions)
235 elif revision == None:
236 grep.workingtree_grep(GrepOptions)
237 else:
238 grep.versioned_grep(GrepOptions)

Subscribers

People subscribed via source and target branches