1922
1923
force=(file_deletion_strategy == 'no-backup'))
1925
class cmd_file_id(Command):
1926
__doc__ = """Print file_id of a particular file or directory.
1928
The file_id is assigned when the file is first added and remains the
1929
same through all revisions where the file exists, even when it is
1934
_see_also = ['inventory', 'ls']
1935
takes_args = ['filename']
1938
def run(self, filename):
1939
tree, relpath = WorkingTree.open_containing(filename)
1940
file_id = tree.path2id(relpath)
1942
raise errors.NotVersionedError(filename)
1944
self.outf.write(file_id.decode('utf-8') + '\n')
1947
class cmd_file_path(Command):
1948
__doc__ = """Print path of file_ids to a file or directory.
1950
This prints one line for each directory down to the target,
1951
starting at the branch root.
1955
takes_args = ['filename']
1958
def run(self, filename):
1959
tree, relpath = WorkingTree.open_containing(filename)
1960
fid = tree.path2id(relpath)
1962
raise errors.NotVersionedError(filename)
1963
segments = osutils.splitpath(relpath)
1964
for pos in range(1, len(segments) + 1):
1965
path = osutils.joinpath(segments[:pos])
1966
self.outf.write("%s\n" % tree.path2id(path))
1969
1926
class cmd_reconcile(Command):
1970
1927
__doc__ = """Reconcile brz metadata in a branch.
3432
3388
rev_tree = _get_one_revision_tree('cat', revision, branch=b)
3433
3389
self.add_cleanup(rev_tree.lock_read().unlock)
3435
old_file_id = rev_tree.path2id(relpath)
3437
# TODO: Split out this code to something that generically finds the
3438
# best id for a path across one or more trees; it's like
3439
# find_ids_across_trees but restricted to find just one. -- mbp
3441
3391
if name_from_revision:
3442
3392
# Try in revision if requested
3443
if old_file_id is None:
3393
if not rev_tree.is_versioned(relpath):
3444
3394
raise errors.BzrCommandError(gettext(
3445
3395
"{0!r} is not present in revision {1}").format(
3446
3396
filename, rev_tree.get_revision_id()))
3448
actual_file_id = old_file_id
3397
rev_tree_path = relpath
3450
cur_file_id = tree.path2id(relpath)
3451
if cur_file_id is not None and rev_tree.has_id(cur_file_id):
3452
actual_file_id = cur_file_id
3453
elif old_file_id is not None:
3454
actual_file_id = old_file_id
3456
raise errors.BzrCommandError(gettext(
3457
"{0!r} is not present in revision {1}").format(
3458
filename, rev_tree.get_revision_id()))
3459
relpath = rev_tree.id2path(actual_file_id)
3400
rev_tree_path = _mod_tree.find_previous_path(
3401
tree, rev_tree, relpath)
3402
except errors.NoSuchFile:
3403
rev_tree_path = None
3405
if rev_tree_path is None:
3406
# Path didn't exist in working tree
3407
if not rev_tree.is_versioned(relpath):
3408
raise errors.BzrCommandError(gettext(
3409
"{0!r} is not present in revision {1}").format(
3410
filename, rev_tree.get_revision_id()))
3412
# Fall back to the same path in the basis tree, if present.
3413
rev_tree_path = relpath
3461
3416
from .filter_tree import ContentFilterTree
3462
3417
filter_tree = ContentFilterTree(
3463
3418
rev_tree, rev_tree._content_filter_stack)
3464
fileobj = filter_tree.get_file(relpath)
3419
fileobj = filter_tree.get_file(rev_tree_path)
3466
fileobj = rev_tree.get_file(relpath)
3421
fileobj = rev_tree.get_file(rev_tree_path)
3467
3422
shutil.copyfileobj(fileobj, self.outf)
3468
3423
self.cleanup_now()
6871
6831
cmd_reconcile().run(".")
6834
class cmd_grep(Command):
6835
"""Print lines matching PATTERN for specified files and revisions.
6837
This command searches the specified files and revisions for a given
6838
pattern. The pattern is specified as a Python regular expressions[1].
6840
If the file name is not specified, the revisions starting with the
6841
current directory are searched recursively. If the revision number is
6842
not specified, the working copy is searched. To search the last committed
6843
revision, use the '-r -1' or '-r last:1' option.
6845
Unversioned files are not searched unless explicitly specified on the
6846
command line. Unversioned directores are not searched.
6848
When searching a pattern, the output is shown in the 'filepath:string'
6849
format. If a revision is explicitly searched, the output is shown as
6850
'filepath~N:string', where N is the revision number.
6852
--include and --exclude options can be used to search only (or exclude
6853
from search) files with base name matches the specified Unix style GLOB
6854
pattern. The GLOB pattern an use *, ?, and [...] as wildcards, and \\
6855
to quote wildcard or backslash character literally. Note that the glob
6856
pattern is not a regular expression.
6858
[1] http://docs.python.org/library/re.html#regular-expression-syntax
6861
encoding_type = 'replace'
6862
takes_args = ['pattern', 'path*']
6866
Option('color', type=text_type, argname='when',
6867
help='Show match in color. WHEN is never, always or auto.'),
6868
Option('diff', short_name='p',
6869
help='Grep for pattern in changeset for each revision.'),
6870
ListOption('exclude', type=text_type, argname='glob', short_name='X',
6871
help="Skip files whose base name matches GLOB."),
6872
ListOption('include', type=text_type, argname='glob', short_name='I',
6873
help="Search only files whose base name matches GLOB."),
6874
Option('files-with-matches', short_name='l',
6875
help='Print only the name of each input file in '
6876
'which PATTERN is found.'),
6877
Option('files-without-match', short_name='L',
6878
help='Print only the name of each input file in '
6879
'which PATTERN is not found.'),
6880
Option('fixed-string', short_name='F',
6881
help='Interpret PATTERN is a single fixed string (not regex).'),
6883
help='Search for pattern starting from the root of the branch. '
6884
'(implies --recursive)'),
6885
Option('ignore-case', short_name='i',
6886
help='Ignore case distinctions while matching.'),
6888
help='Number of levels to display - 0 for all, 1 for collapsed '
6891
type=_parse_levels),
6892
Option('line-number', short_name='n',
6893
help='Show 1-based line number.'),
6894
Option('no-recursive',
6895
help="Don't recurse into subdirectories. (default is --recursive)"),
6896
Option('null', short_name='Z',
6897
help='Write an ASCII NUL (\\0) separator '
6898
'between output lines rather than a newline.'),
6902
def run(self, verbose=False, ignore_case=False, no_recursive=False,
6903
from_root=False, null=False, levels=None, line_number=False,
6904
path_list=None, revision=None, pattern=None, include=None,
6905
exclude=None, fixed_string=False, files_with_matches=False,
6906
files_without_match=False, color=None, diff=False):
6907
from breezy import _termcolor
6910
if path_list is None:
6914
raise errors.BzrCommandError(
6915
'cannot specify both --from-root and PATH.')
6917
if files_with_matches and files_without_match:
6918
raise errors.BzrCommandError(
6919
'cannot specify both '
6920
'-l/--files-with-matches and -L/--files-without-matches.')
6922
global_config = _mod_config.GlobalConfig()
6925
color = global_config.get_user_option('grep_color')
6930
if color not in ['always', 'never', 'auto']:
6931
raise errors.BzrCommandError('Valid values for --color are '
6932
'"always", "never" or "auto".')
6938
if revision is not None or levels == 0:
6939
# print revision numbers as we may be showing multiple revisions
6946
if not ignore_case and grep.is_fixed_string(pattern):
6947
# if the pattern isalnum, implicitly use to -F for faster grep
6949
elif ignore_case and fixed_string:
6950
# GZ 2010-06-02: Fall back to regexp rather than lowercasing
6951
# pattern and text which will cause pain later
6952
fixed_string = False
6953
pattern = re.escape(pattern)
6956
re_flags = re.MULTILINE
6958
re_flags |= re.IGNORECASE
6960
if not fixed_string:
6961
patternc = grep.compile_pattern(
6962
pattern.encode(grep._user_encoding), re_flags)
6964
if color == 'always':
6966
elif color == 'never':
6968
elif color == 'auto':
6969
show_color = _termcolor.allow_color()
6971
opts = grep.GrepOptions()
6973
opts.verbose = verbose
6974
opts.ignore_case = ignore_case
6975
opts.no_recursive = no_recursive
6976
opts.from_root = from_root
6978
opts.levels = levels
6979
opts.line_number = line_number
6980
opts.path_list = path_list
6981
opts.revision = revision
6982
opts.pattern = pattern
6983
opts.include = include
6984
opts.exclude = exclude
6985
opts.fixed_string = fixed_string
6986
opts.files_with_matches = files_with_matches
6987
opts.files_without_match = files_without_match
6991
opts.eol_marker = eol_marker
6992
opts.print_revno = print_revno
6993
opts.patternc = patternc
6994
opts.recursive = not no_recursive
6995
opts.fixed_string = fixed_string
6996
opts.outf = self.outf
6997
opts.show_color = show_color
7001
# files_with_matches, files_without_match
7002
# levels(?), line_number, from_root
7004
# These are silently ignored.
7005
grep.grep_diff(opts)
7006
elif revision is None:
7007
grep.workingtree_grep(opts)
7009
grep.versioned_grep(opts)
6874
7012
def _register_lazy_builtins():
6875
7013
# register lazy builtins from other modules; called at startup and should
6876
7014
# be only called once.