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
1=== modified file '__init__.py'
2--- __init__.py 2010-06-26 02:34:08 +0000
3+++ __init__.py 2011-02-20 00:38:52 +0000
4@@ -13,249 +13,16 @@
5 # You should have received a copy of the GNU General Public License
6 # along with this program; if not, write to the Free Software
7 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
8+
9 """Print lines matching PATTERN for specified files and revisions."""
10
11-import os
12-import sys
13-
14-from bzrlib import errors
15-from bzrlib.commands import Command, register_command, display_command
16-from bzrlib.option import Option, ListOption
17-
18-from bzrlib.lazy_import import lazy_import
19-lazy_import(globals(), """
20-import re
21-
22-from termcolor import allow_color
23-import grep
24-
25-import bzrlib
26-from bzrlib.revisionspec import RevisionSpec
27-from bzrlib import (
28- osutils,
29- bzrdir,
30- trace,
31- )
32-""")
33+from bzrlib.commands import plugin_cmds
34+
35 import version
36
37 version_info = version.version_info
38
39-# FIXME: _parse_levels should be shared with bzrlib.builtins. this is a copy
40-# to avoid the error
41-# "IllegalUseOfScopeReplacer: ScopeReplacer object '_parse_levels' was used
42-# incorrectly: Object already cleaned up, did you assign it to another
43-# variable?: _factory
44-# with lazy import
45-def _parse_levels(s):
46- try:
47- return int(s)
48- except ValueError:
49- msg = "The levels argument must be an integer."
50- raise errors.BzrCommandError(msg)
51-
52-
53-class GrepOptions(object):
54- """Container to pass around grep options.
55-
56- This class is used as a container to pass around user option and
57- some other params (like outf) to processing functions. This makes
58- it easier to add more options as grep evolves.
59- """
60- verbose = False
61- ignore_case = False
62- no_recursive = False
63- from_root = False
64- null = False
65- levels = None
66- line_number = False
67- path_list = None
68- revision = None
69- pattern = None
70- include = None
71- exclude = None
72- fixed_string = False
73- files_with_matches = False
74- files_without_match = False
75- color = None
76- diff = False
77-
78- # derived options
79- recursive = None
80- eol_marker = None
81- patternc = None
82- sub_patternc = None
83- print_revno = None
84- fixed_string = None
85- outf = None
86- show_color = False
87-
88-
89-class cmd_grep(Command):
90- """Print lines matching PATTERN for specified files and revisions.
91-
92- This command searches the specified files and revisions for a given
93- pattern. The pattern is specified as a Python regular expressions[1].
94-
95- If the file name is not specified, the revisions starting with the
96- current directory are searched recursively. If the revision number is
97- not specified, the working copy is searched. To search the last committed
98- revision, use the '-r -1' or '-r last:1' option.
99-
100- Unversioned files are not searched unless explicitly specified on the
101- command line. Unversioned directores are not searched.
102-
103- When searching a pattern, the output is shown in the 'filepath:string'
104- format. If a revision is explicitly searched, the output is shown as
105- 'filepath~N:string', where N is the revision number.
106-
107- --include and --exclude options can be used to search only (or exclude
108- from search) files with base name matches the specified Unix style GLOB
109- pattern. The GLOB pattern an use *, ?, and [...] as wildcards, and \\
110- to quote wildcard or backslash character literally. Note that the glob
111- pattern is not a regular expression.
112-
113- [1] http://docs.python.org/library/re.html#regular-expression-syntax
114- """
115-
116- encoding_type = 'replace'
117- takes_args = ['pattern', 'path*']
118- takes_options = [
119- 'verbose',
120- 'revision',
121- Option('color', type=str, argname='when',
122- help='Show match in color. WHEN is never, always or auto.'),
123- Option('diff', short_name='p',
124- help='Grep for pattern in changeset for each revision.'),
125- ListOption('exclude', type=str, argname='glob', short_name='X',
126- help="Skip files whose base name matches GLOB."),
127- ListOption('include', type=str, argname='glob', short_name='I',
128- help="Search only files whose base name matches GLOB."),
129- Option('files-with-matches', short_name='l',
130- help='Print only the name of each input file in '
131- 'which PATTERN is found.'),
132- Option('files-without-match', short_name='L',
133- help='Print only the name of each input file in '
134- 'which PATTERN is not found.'),
135- Option('fixed-string', short_name='F',
136- help='Interpret PATTERN is a single fixed string (not regex).'),
137- Option('from-root',
138- help='Search for pattern starting from the root of the branch. '
139- '(implies --recursive)'),
140- Option('ignore-case', short_name='i',
141- help='ignore case distinctions while matching.'),
142- Option('levels',
143- help='Number of levels to display - 0 for all, 1 for collapsed '
144- '(1 is default).',
145- argname='N',
146- type=_parse_levels),
147- Option('line-number', short_name='n',
148- help='show 1-based line number.'),
149- Option('no-recursive',
150- help="Don't recurse into subdirectories. (default is --recursive)"),
151- Option('null', short_name='Z',
152- help='Write an ASCII NUL (\\0) separator '
153- 'between output lines rather than a newline.'),
154- ]
155-
156-
157- @display_command
158- def run(self, verbose=False, ignore_case=False, no_recursive=False,
159- from_root=False, null=False, levels=None, line_number=False,
160- path_list=None, revision=None, pattern=None, include=None,
161- exclude=None, fixed_string=False, files_with_matches=False,
162- files_without_match=False, color='never', diff=False):
163-
164- if path_list == None:
165- path_list = ['.']
166- else:
167- if from_root:
168- raise errors.BzrCommandError('cannot specify both --from-root and PATH.')
169-
170- if files_with_matches and files_without_match:
171- raise errors.BzrCommandError('cannot specify both '
172- '-l/--files-with-matches and -L/--files-without-matches.')
173-
174- if color not in ['always', 'never', 'auto']:
175- raise errors.BzrCommandError('Valid values for --color are '
176- '"always", "never" or "auto".')
177-
178- if levels==None:
179- levels=1
180-
181- print_revno = False
182- if revision != None or levels == 0:
183- # print revision numbers as we may be showing multiple revisions
184- print_revno = True
185-
186- eol_marker = '\n'
187- if null:
188- eol_marker = '\0'
189-
190- if not ignore_case and grep.is_fixed_string(pattern):
191- # if the pattern isalnum, implicitly use to -F for faster grep
192- fixed_string = True
193- elif ignore_case and fixed_string:
194- # GZ 2010-06-02: Fall back to regexp rather than lowercasing
195- # pattern and text which will cause pain later
196- fixed_string = False
197- pattern = re.escape(pattern)
198-
199- patternc = None
200- re_flags = re.MULTILINE
201- if ignore_case:
202- re_flags |= re.IGNORECASE
203-
204- if not fixed_string:
205- patternc = grep.compile_pattern(pattern, re_flags)
206-
207- if color == 'always':
208- show_color = True
209- elif color == 'never':
210- show_color = False
211- elif color == 'auto':
212- show_color = allow_color()
213-
214- GrepOptions.verbose = verbose
215- GrepOptions.ignore_case = ignore_case
216- GrepOptions.no_recursive = no_recursive
217- GrepOptions.from_root = from_root
218- GrepOptions.null = null
219- GrepOptions.levels = levels
220- GrepOptions.line_number = line_number
221- GrepOptions.path_list = path_list
222- GrepOptions.revision = revision
223- GrepOptions.pattern = pattern
224- GrepOptions.include = include
225- GrepOptions.exclude = exclude
226- GrepOptions.fixed_string = fixed_string
227- GrepOptions.files_with_matches = files_with_matches
228- GrepOptions.files_without_match = files_without_match
229- GrepOptions.color = color
230- GrepOptions.diff = False
231-
232- GrepOptions.eol_marker = eol_marker
233- GrepOptions.print_revno = print_revno
234- GrepOptions.patternc = patternc
235- GrepOptions.recursive = not no_recursive
236- GrepOptions.fixed_string = fixed_string
237- GrepOptions.outf = self.outf
238- GrepOptions.show_color = show_color
239-
240- if diff == True:
241- # options not used:
242- # files_with_matches, files_without_match
243- # levels(?), line_number, from_root
244- # include, exclude
245- # These are silently ignored.
246- grep.grep_diff(GrepOptions)
247- elif revision == None:
248- grep.workingtree_grep(GrepOptions)
249- else:
250- grep.versioned_grep(GrepOptions)
251-
252-
253-register_command(cmd_grep)
254+plugin_cmds.register_lazy("cmd_grep", [], "bzrlib.plugins.grep.cmds")
255
256 def test_suite():
257 from bzrlib.tests import TestUtil
258
259=== added file 'cmds.py'
260--- cmds.py 1970-01-01 00:00:00 +0000
261+++ cmds.py 2011-02-20 00:38:52 +0000
262@@ -0,0 +1,238 @@
263+# Copyright (C) 2010 Canonical Ltd
264+#
265+# This program is free software; you can redistribute it and/or modify
266+# it under the terms of the GNU General Public License as published by
267+# the Free Software Foundation; either version 2 of the License, or
268+# (at your option) any later version.
269+#
270+# This program is distributed in the hope that it will be useful,
271+# but WITHOUT ANY WARRANTY; without even the implied warranty of
272+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
273+# GNU General Public License for more details.
274+#
275+# You should have received a copy of the GNU General Public License
276+# along with this program; if not, write to the Free Software
277+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
278+
279+"""Print lines matching PATTERN for specified files and revisions."""
280+
281+from bzrlib import errors
282+from bzrlib.commands import Command, display_command
283+from bzrlib.option import Option, ListOption
284+
285+# FIXME: _parse_levels should be shared with bzrlib.builtins. this is a copy
286+# to avoid the error
287+# "IllegalUseOfScopeReplacer: ScopeReplacer object '_parse_levels' was used
288+# incorrectly: Object already cleaned up, did you assign it to another
289+# variable?: _factory
290+# with lazy import
291+def _parse_levels(s):
292+ try:
293+ return int(s)
294+ except ValueError:
295+ msg = "The levels argument must be an integer."
296+ raise errors.BzrCommandError(msg)
297+
298+
299+class GrepOptions(object):
300+ """Container to pass around grep options.
301+
302+ This class is used as a container to pass around user option and
303+ some other params (like outf) to processing functions. This makes
304+ it easier to add more options as grep evolves.
305+ """
306+ verbose = False
307+ ignore_case = False
308+ no_recursive = False
309+ from_root = False
310+ null = False
311+ levels = None
312+ line_number = False
313+ path_list = None
314+ revision = None
315+ pattern = None
316+ include = None
317+ exclude = None
318+ fixed_string = False
319+ files_with_matches = False
320+ files_without_match = False
321+ color = None
322+ diff = False
323+
324+ # derived options
325+ recursive = None
326+ eol_marker = None
327+ patternc = None
328+ sub_patternc = None
329+ print_revno = None
330+ fixed_string = None
331+ outf = None
332+ show_color = False
333+
334+
335+class cmd_grep(Command):
336+ """Print lines matching PATTERN for specified files and revisions.
337+
338+ This command searches the specified files and revisions for a given
339+ pattern. The pattern is specified as a Python regular expressions[1].
340+
341+ If the file name is not specified, the revisions starting with the
342+ current directory are searched recursively. If the revision number is
343+ not specified, the working copy is searched. To search the last committed
344+ revision, use the '-r -1' or '-r last:1' option.
345+
346+ Unversioned files are not searched unless explicitly specified on the
347+ command line. Unversioned directores are not searched.
348+
349+ When searching a pattern, the output is shown in the 'filepath:string'
350+ format. If a revision is explicitly searched, the output is shown as
351+ 'filepath~N:string', where N is the revision number.
352+
353+ --include and --exclude options can be used to search only (or exclude
354+ from search) files with base name matches the specified Unix style GLOB
355+ pattern. The GLOB pattern an use *, ?, and [...] as wildcards, and \\
356+ to quote wildcard or backslash character literally. Note that the glob
357+ pattern is not a regular expression.
358+
359+ [1] http://docs.python.org/library/re.html#regular-expression-syntax
360+ """
361+
362+ encoding_type = 'replace'
363+ takes_args = ['pattern', 'path*']
364+ takes_options = [
365+ 'verbose',
366+ 'revision',
367+ Option('color', type=str, argname='when',
368+ help='Show match in color. WHEN is never, always or auto.'),
369+ Option('diff', short_name='p',
370+ help='Grep for pattern in changeset for each revision.'),
371+ ListOption('exclude', type=str, argname='glob', short_name='X',
372+ help="Skip files whose base name matches GLOB."),
373+ ListOption('include', type=str, argname='glob', short_name='I',
374+ help="Search only files whose base name matches GLOB."),
375+ Option('files-with-matches', short_name='l',
376+ help='Print only the name of each input file in '
377+ 'which PATTERN is found.'),
378+ Option('files-without-match', short_name='L',
379+ help='Print only the name of each input file in '
380+ 'which PATTERN is not found.'),
381+ Option('fixed-string', short_name='F',
382+ help='Interpret PATTERN is a single fixed string (not regex).'),
383+ Option('from-root',
384+ help='Search for pattern starting from the root of the branch. '
385+ '(implies --recursive)'),
386+ Option('ignore-case', short_name='i',
387+ help='ignore case distinctions while matching.'),
388+ Option('levels',
389+ help='Number of levels to display - 0 for all, 1 for collapsed '
390+ '(1 is default).',
391+ argname='N',
392+ type=_parse_levels),
393+ Option('line-number', short_name='n',
394+ help='show 1-based line number.'),
395+ Option('no-recursive',
396+ help="Don't recurse into subdirectories. (default is --recursive)"),
397+ Option('null', short_name='Z',
398+ help='Write an ASCII NUL (\\0) separator '
399+ 'between output lines rather than a newline.'),
400+ ]
401+
402+
403+ @display_command
404+ def run(self, verbose=False, ignore_case=False, no_recursive=False,
405+ from_root=False, null=False, levels=None, line_number=False,
406+ path_list=None, revision=None, pattern=None, include=None,
407+ exclude=None, fixed_string=False, files_with_matches=False,
408+ files_without_match=False, color='never', diff=False):
409+ from bzrlib.plugins.grep import (
410+ grep,
411+ termcolor,
412+ )
413+ import re
414+ if path_list == None:
415+ path_list = ['.']
416+ else:
417+ if from_root:
418+ raise errors.BzrCommandError('cannot specify both --from-root and PATH.')
419+
420+ if files_with_matches and files_without_match:
421+ raise errors.BzrCommandError('cannot specify both '
422+ '-l/--files-with-matches and -L/--files-without-matches.')
423+
424+ if color not in ['always', 'never', 'auto']:
425+ raise errors.BzrCommandError('Valid values for --color are '
426+ '"always", "never" or "auto".')
427+
428+ if levels==None:
429+ levels=1
430+
431+ print_revno = False
432+ if revision != None or levels == 0:
433+ # print revision numbers as we may be showing multiple revisions
434+ print_revno = True
435+
436+ eol_marker = '\n'
437+ if null:
438+ eol_marker = '\0'
439+
440+ if not ignore_case and grep.is_fixed_string(pattern):
441+ # if the pattern isalnum, implicitly use to -F for faster grep
442+ fixed_string = True
443+ elif ignore_case and fixed_string:
444+ # GZ 2010-06-02: Fall back to regexp rather than lowercasing
445+ # pattern and text which will cause pain later
446+ fixed_string = False
447+ pattern = re.escape(pattern)
448+
449+ patternc = None
450+ re_flags = re.MULTILINE
451+ if ignore_case:
452+ re_flags |= re.IGNORECASE
453+
454+ if not fixed_string:
455+ patternc = grep.compile_pattern(pattern, re_flags)
456+
457+ if color == 'always':
458+ show_color = True
459+ elif color == 'never':
460+ show_color = False
461+ elif color == 'auto':
462+ show_color = termcolor.allow_color()
463+
464+ GrepOptions.verbose = verbose
465+ GrepOptions.ignore_case = ignore_case
466+ GrepOptions.no_recursive = no_recursive
467+ GrepOptions.from_root = from_root
468+ GrepOptions.null = null
469+ GrepOptions.levels = levels
470+ GrepOptions.line_number = line_number
471+ GrepOptions.path_list = path_list
472+ GrepOptions.revision = revision
473+ GrepOptions.pattern = pattern
474+ GrepOptions.include = include
475+ GrepOptions.exclude = exclude
476+ GrepOptions.fixed_string = fixed_string
477+ GrepOptions.files_with_matches = files_with_matches
478+ GrepOptions.files_without_match = files_without_match
479+ GrepOptions.color = color
480+ GrepOptions.diff = False
481+
482+ GrepOptions.eol_marker = eol_marker
483+ GrepOptions.print_revno = print_revno
484+ GrepOptions.patternc = patternc
485+ GrepOptions.recursive = not no_recursive
486+ GrepOptions.fixed_string = fixed_string
487+ GrepOptions.outf = self.outf
488+ GrepOptions.show_color = show_color
489+
490+ if diff == True:
491+ # options not used:
492+ # files_with_matches, files_without_match
493+ # levels(?), line_number, from_root
494+ # include, exclude
495+ # These are silently ignored.
496+ grep.grep_diff(GrepOptions)
497+ elif revision == None:
498+ grep.workingtree_grep(GrepOptions)
499+ else:
500+ grep.versioned_grep(GrepOptions)

Subscribers

People subscribed via source and target branches