13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
17
"""builtin bzr commands"""
84
82
tree = WorkingTree.open_containing(file_list[0])[0]
85
83
if tree.supports_views():
86
84
view_files = tree.views.lookup_view()
88
for filename in file_list:
89
if not osutils.is_inside_any(view_files, filename):
90
raise errors.FileOutsideView(filename, view_files)
85
for filename in file_list:
86
if not osutils.is_inside_any(view_files, filename):
87
raise errors.FileOutsideView(filename, view_files)
92
89
tree = WorkingTree.open_containing(u'.')[0]
93
90
if tree.supports_views():
152
149
file_list = view_files
153
150
view_str = views.view_display_str(view_files)
154
note("Ignoring files outside view. View is %s" % view_str)
151
note("ignoring files outside view: %s" % view_str)
155
152
return tree, file_list
156
153
tree = WorkingTree.open_containing(osutils.realpath(file_list[0]))[0]
157
154
return tree, safe_relpath_files(tree, file_list, canonicalize,
722
719
takes_args = ['names*']
723
720
takes_options = [Option("after", help="Move only the bzr identifier"
724
721
" of the file, because the file has already been moved."),
725
Option('auto', help='Automatically guess renames.'),
726
Option('dry-run', help='Avoid making changes when guessing renames.'),
728
723
aliases = ['move', 'rename']
729
724
encoding_type = 'replace'
731
def run(self, names_list, after=False, auto=False, dry_run=False):
733
return self.run_auto(names_list, after, dry_run)
735
raise errors.BzrCommandError('--dry-run requires --auto.')
726
def run(self, names_list, after=False):
736
727
if names_list is None:
738
730
if len(names_list) < 2:
739
731
raise errors.BzrCommandError("missing file argument")
740
732
tree, rel_names = tree_files(names_list, canonicalize=False)
747
def run_auto(self, names_list, after, dry_run):
748
if names_list is not None and len(names_list) > 1:
749
raise errors.BzrCommandError('Only one path may be specified to'
752
raise errors.BzrCommandError('--after cannot be specified with'
754
work_tree, file_list = tree_files(names_list, default_branch='.')
755
work_tree.lock_write()
757
rename_map.RenameMap.guess_renames(work_tree, dry_run)
761
739
def _run(self, tree, names_list, rel_names, after):
762
740
into_existing = osutils.isdir(names_list[-1])
763
741
if into_existing and len(names_list) == 2:
864
_see_also = ['push', 'update', 'status-flags', 'send']
842
_see_also = ['push', 'update', 'status-flags']
865
843
takes_options = ['remember', 'overwrite', 'revision',
866
844
custom_help('verbose',
867
845
help='Show logs of pulled revisions.'),
1952
1930
--show-ids display revision-ids (and file-ids), not just revnos
1954
1932
Note that the default number of levels to display is a function of the
1955
log format. If the -n option is not used, the standard log formats show
1956
just the top level (mainline).
1933
log format. If the -n option is not used, ``short`` and ``line`` show
1934
just the top level (mainline) while ``long`` shows all levels of merged
1958
1937
Status summaries are shown using status flags like A, M, etc. To see
1959
1938
the changes explained using words like ``added`` and ``modified``
1996
1975
:Path filtering:
1998
If parameters are given and the first one is not a branch, the log
1999
will be filtered to show only those revisions that changed the
2000
nominated files or directories.
1977
If a parameter is given and it's not a branch, the log will be filtered
1978
to show only those revisions that changed the nominated file or
2002
1981
Filenames are interpreted within their historical context. To log a
2003
1982
deleted file, specify a revision range so that the file existed at
2026
2005
explicitly ask for this (and no way to stop logging a file back
2027
2006
until it was last renamed).
2008
Note: If the path is a directory, only revisions that directly changed
2009
that directory object are currently shown. This is considered a bug.
2010
(Support for filtering against multiple files and for files within a
2011
directory is under development.)
2029
2013
:Other filtering:
2031
2015
The --message option can be used for finding revisions that match a
2045
2029
You may find it useful to add the aliases below to ``bazaar.conf``::
2049
top = log -l10 --line
2033
top = log -r-10.. --short --forward
2034
show = log -v -p -n1 --long
2052
2036
``bzr tip`` will then show the latest revision while ``bzr top``
2053
2037
will show the last 10 mainline revisions. To see the details of a
2054
2038
particular revision X, ``bzr show -rX``.
2056
If you are interested in looking deeper into a particular merge X,
2057
use ``bzr log -n0 -rX``.
2040
As many GUI tools and Web interfaces do, you may prefer viewing
2041
history collapsed initially. If you are interested in looking deeper
2042
into a particular merge X, use ``bzr log -n0 -rX``. If you like
2043
working this way, you may wish to either:
2045
* change your default log format to short (or line)
2046
* add this alias: log = log -n1
2059
2048
``bzr log -v`` on a branch with lots of history is currently
2060
2049
very slow. A fix for this issue is currently under development.
2137
2122
revision = change
2140
filter_by_dir = False
2142
# find the file ids to log and check for directory filtering
2143
b, file_info_list, rev1, rev2 = _get_info_for_log_files(revision,
2145
for relpath, file_id, kind in file_info_list:
2127
# find the file id to log:
2129
tree, b, fp = bzrdir.BzrDir.open_containing_tree_or_branch(
2132
file_id = _get_fileid_to_log(revision, tree, b, fp)
2146
2133
if file_id is None:
2147
2134
raise errors.BzrCommandError(
2148
2135
"Path unknown at end or start of revision range: %s" %
2150
# If the relpath is the top of the tree, we log everything
2155
file_ids.append(file_id)
2156
filter_by_dir = filter_by_dir or (
2157
kind in ['directory', 'tree-reference'])
2160
2139
# FIXME ? log the current subdir only RBC 20060203
2161
2140
if revision is not None \
2162
2141
and len(revision) > 0 and revision[0].get_branch():
2166
2145
dir, relpath = bzrdir.BzrDir.open_containing(location)
2167
2146
b = dir.open_branch()
2168
2150
rev1, rev2 = _get_revision_range(revision, b, self.name())
2170
# Decide on the type of delta & diff filtering to use
2171
# TODO: add an --all-files option to make this configurable & consistent
2179
diff_type = 'partial'
2185
# Build the log formatter
2186
2151
if log_format is None:
2187
2152
log_format = log.log_formatter_registry.get_default(b)
2188
2154
lf = log_format(show_ids=show_ids, to_file=self.outf,
2189
2155
show_timezone=timezone,
2190
2156
delta_format=get_verbosity_level(),
2193
# Choose the algorithm for doing the logging. It's annoying
2194
# having multiple code paths like this but necessary until
2195
# the underlying repository format is faster at generating
2196
# deltas or can provide everything we need from the indices.
2197
# The default algorithm - match-using-deltas - works for
2198
# multiple files and directories and is faster for small
2199
# amounts of history (200 revisions say). However, it's too
2200
# slow for logging a single file in a repository with deep
2201
# history, i.e. > 10K revisions. In the spirit of "do no
2202
# evil when adding features", we continue to use the
2203
# original algorithm - per-file-graph - for the "single
2204
# file that isn't a directory without showing a delta" case.
2205
partial_history = revision and b.repository._format.supports_chks
2206
match_using_deltas = (len(file_ids) != 1 or filter_by_dir
2207
or delta_type or partial_history)
2209
# Build the LogRequest and execute it
2210
if len(file_ids) == 0:
2212
rqst = make_log_request_dict(
2213
direction=direction, specific_fileids=file_ids,
2214
start_revision=rev1, end_revision=rev2, limit=limit,
2215
message_search=message, delta_type=delta_type,
2216
diff_type=diff_type, _match_using_deltas=match_using_deltas)
2217
Logger(b, rqst).show(lf)
2163
direction=direction,
2164
start_revision=rev1,
2168
show_diff=show_diff)
2489
2440
if len(matches) > 0:
2490
2441
print "Warning: the following files are version controlled and" \
2491
" match your ignore pattern:\n%s" \
2492
"\nThese files will continue to be version controlled" \
2493
" unless you 'bzr remove' them." % ("\n".join(matches),)
2442
" match your ignore pattern:\n%s" % ("\n".join(matches),)
2496
2445
class cmd_ignored(Command):
2575
2524
help="Type of file to export to.",
2578
Option('filters', help='Apply content filters to export the '
2579
'convenient form.'),
2582
2529
help="Name of the root directory inside the exported file."),
2584
2531
def run(self, dest, branch_or_subdir=None, revision=None, format=None,
2585
root=None, filters=False):
2586
2533
from bzrlib.export import export
2588
2535
if branch_or_subdir is None:
2596
2543
rev_tree = _get_one_revision_tree('export', revision, branch=b, tree=tree)
2598
export(rev_tree, dest, format, root, subdir, filtered=filters)
2545
export(rev_tree, dest, format, root, subdir)
2599
2546
except errors.NoSuchExportFormat, e:
2600
2547
raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
2612
2559
_see_also = ['ls']
2613
2560
takes_options = [
2614
2561
Option('name-from-revision', help='The path name in the old tree.'),
2615
Option('filters', help='Apply content filters to display the '
2616
'convenience form.'),
2619
2564
takes_args = ['filename']
2620
2565
encoding_type = 'exact'
2622
2567
@display_command
2623
def run(self, filename, revision=None, name_from_revision=False,
2568
def run(self, filename, revision=None, name_from_revision=False):
2625
2569
if revision is not None and len(revision) != 1:
2626
2570
raise errors.BzrCommandError("bzr cat --revision takes exactly"
2627
2571
" one revision specifier")
2630
2574
branch.lock_read()
2632
2576
return self._run(tree, branch, relpath, filename, revision,
2633
name_from_revision, filters)
2635
2579
branch.unlock()
2637
def _run(self, tree, b, relpath, filename, revision, name_from_revision,
2581
def _run(self, tree, b, relpath, filename, revision, name_from_revision):
2639
2582
if tree is None:
2640
2583
tree = b.basis_tree()
2641
2584
rev_tree = _get_one_revision_tree('cat', revision, branch=b)
2586
cur_file_id = tree.path2id(relpath)
2643
2587
old_file_id = rev_tree.path2id(relpath)
2645
2589
if name_from_revision:
2646
# Try in revision if requested
2647
2590
if old_file_id is None:
2648
2591
raise errors.BzrCommandError(
2649
2592
"%r is not present in revision %s" % (
2650
2593
filename, rev_tree.get_revision_id()))
2652
2595
content = rev_tree.get_file_text(old_file_id)
2654
cur_file_id = tree.path2id(relpath)
2656
if cur_file_id is not None:
2657
# Then try with the actual file id
2659
content = rev_tree.get_file_text(cur_file_id)
2661
except errors.NoSuchId:
2662
# The actual file id didn't exist at that time
2664
if not found and old_file_id is not None:
2665
# Finally try with the old file id
2666
content = rev_tree.get_file_text(old_file_id)
2669
# Can't be found anywhere
2670
raise errors.BzrCommandError(
2671
"%r is not present in revision %s" % (
2672
filename, rev_tree.get_revision_id()))
2674
from bzrlib.filters import (
2675
ContentFilterContext,
2676
filtered_output_bytes,
2678
filters = rev_tree._content_filter_stack(relpath)
2679
chunks = content.splitlines(True)
2680
content = filtered_output_bytes(chunks, filters,
2681
ContentFilterContext(relpath, rev_tree))
2682
self.outf.writelines(content)
2684
self.outf.write(content)
2596
elif cur_file_id is not None:
2597
content = rev_tree.get_file_text(cur_file_id)
2598
elif old_file_id is not None:
2599
content = rev_tree.get_file_text(old_file_id)
2601
raise errors.BzrCommandError(
2602
"%r is not present in revision %s" % (
2603
filename, rev_tree.get_revision_id()))
2604
self.outf.write(content)
2687
2607
class cmd_local_time_offset(Command):
2761
2681
help="Refuse to commit if there are unknown "
2762
2682
"files in the working tree."),
2763
2683
ListOption('fixes', type=str,
2764
help="Mark a bug as being fixed by this revision "
2765
"(see \"bzr help bugs\")."),
2684
help="Mark a bug as being fixed by this revision."),
2766
2685
ListOption('author', type=unicode,
2767
2686
help="Set the author's name, if it's different "
2768
2687
"from the committer."),
2779
2698
aliases = ['ci', 'checkin']
2781
def _iter_bug_fix_urls(self, fixes, branch):
2700
def _get_bug_fix_properties(self, fixes, branch):
2782
2702
# Configure the properties for bug fixing attributes.
2783
2703
for fixed_bug in fixes:
2784
2704
tokens = fixed_bug.split(':')
2785
2705
if len(tokens) != 2:
2786
2706
raise errors.BzrCommandError(
2787
"Invalid bug %s. Must be in the form of 'tracker:id'. "
2788
"See \"bzr help bugs\" for more information on this "
2789
"feature.\nCommit refused." % fixed_bug)
2707
"Invalid bug %s. Must be in the form of 'tag:id'. "
2708
"Commit refused." % fixed_bug)
2790
2709
tag, bug_id = tokens
2792
yield bugtracker.get_bug_url(tag, branch, bug_id)
2711
bug_url = bugtracker.get_bug_url(tag, branch, bug_id)
2793
2712
except errors.UnknownBugTrackerAbbreviation:
2794
2713
raise errors.BzrCommandError(
2795
2714
'Unrecognized bug %s. Commit refused.' % fixed_bug)
2796
except errors.MalformedBugIdentifier, e:
2715
except errors.MalformedBugIdentifier:
2797
2716
raise errors.BzrCommandError(
2798
"%s\nCommit refused." % (str(e),))
2717
"Invalid bug identifier for %s. Commit refused."
2719
properties.append('%s fixed' % bug_url)
2720
return '\n'.join(properties)
2800
2722
def run(self, message=None, file=None, verbose=False, selected_list=None,
2801
2723
unchanged=False, strict=False, local=False, fixes=None,
3200
3123
Option('list-only',
3201
3124
help='List the tests instead of running them.'),
3202
RegistryOption('parallel',
3203
help="Run the test suite in parallel.",
3204
lazy_registry=('bzrlib.tests', 'parallel_registry'),
3205
value_switches=False,
3207
3125
Option('randomize', type=str, argname="SEED",
3208
3126
help='Randomize the order of tests using the given'
3209
3127
' seed or "now" for the current time.'),
3235
3151
lsprof_timed=None, cache_dir=None,
3236
3152
first=False, list_only=False,
3237
3153
randomize=None, exclude=None, strict=False,
3238
load_list=None, debugflag=None, starting_with=None, subunit=False,
3154
load_list=None, debugflag=None, starting_with=None):
3240
3155
from bzrlib.tests import selftest
3241
3156
import bzrlib.benchmarks as benchmarks
3242
3157
from bzrlib.benchmarks import tree_creator
3258
3173
pattern = '|'.join(testspecs_list)
3263
from bzrlib.tests import SubUnitBzrRunner
3265
raise errors.BzrCommandError("subunit not available. subunit "
3266
"needs to be installed to use --subunit.")
3267
self.additional_selftest_args['runner_class'] = SubUnitBzrRunner
3269
self.additional_selftest_args.setdefault(
3270
'suite_decorators', []).append(parallel)
3272
3177
test_suite_factory = benchmarks.test_suite
3273
3178
# Unless user explicitly asks for quiet, be verbose in benchmarks
3415
3320
bzr merge -r 81..82 ../bzr.dev
3417
To apply a merge directive contained in /tmp/merge:
3322
To apply a merge directive contained in in /tmp/merge:
3419
3324
bzr merge /tmp/merge
3422
3327
encoding_type = 'exact'
3423
_see_also = ['update', 'remerge', 'status-flags', 'send']
3328
_see_also = ['update', 'remerge', 'status-flags']
3424
3329
takes_args = ['location?']
3425
3330
takes_options = [
3462
3367
allow_pending = True
3463
3368
verified = 'inapplicable'
3464
3369
tree = WorkingTree.open_containing(directory)[0]
3466
# die as quickly as possible if there are uncommitted changes
3468
basis_tree = tree.revision_tree(tree.last_revision())
3469
except errors.NoSuchRevision:
3470
basis_tree = tree.basis_tree()
3472
changes = tree.changes_from(basis_tree)
3473
if changes.has_changed():
3474
raise errors.UncommittedChanges(tree)
3476
3370
view_info = _get_view_info_for_change_reporter(tree)
3477
3371
change_reporter = delta._ChangeReporter(
3478
3372
unversioned_filter=tree.is_ignored, view_info=view_info)
3936
3830
type=_parse_revision_str,
3937
3831
help='Filter on local branch revisions (inclusive). '
3938
3832
'See "help revisionspec" for details.'),
3939
Option('include-merges',
3940
'Show all revisions in addition to the mainline ones.'),
3833
Option('include-merges', 'Show merged revisions.'),
3942
3835
encoding_type = 'replace'
4842
Option('body', help='Body for the email.', type=unicode),
4843
4734
RegistryOption.from_kwargs('format',
4844
4735
'Use the specified output format.',
4845
4736
**{'4': 'Bundle format 4, Merge Directive 2 (default)',
4849
4740
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
4850
4741
no_patch=False, revision=None, remember=False, output=None,
4851
format='4', mail_to=None, message=None, body=None, **kwargs):
4742
format='4', mail_to=None, message=None, **kwargs):
4852
4743
return self._run(submit_branch, revision, public_branch, remember,
4853
4744
format, no_bundle, no_patch, output,
4854
kwargs.get('from', '.'), mail_to, message, body)
4745
kwargs.get('from', '.'), mail_to, message)
4856
4747
def _run(self, submit_branch, revision, public_branch, remember, format,
4857
no_bundle, no_patch, output, from_, mail_to, message, body):
4748
no_bundle, no_patch, output, from_, mail_to, message):
4858
4749
from bzrlib.revision import NULL_REVISION
4859
4750
branch = Branch.open_containing(from_)[0]
4860
4751
if output is None:
4872
4763
if mail_to is None:
4873
4764
mail_to = config.get_user_option('submit_to')
4874
4765
mail_client = config.get_mail_client()
4875
if (not getattr(mail_client, 'supports_body', False)
4876
and body is not None):
4877
raise errors.BzrCommandError(
4878
'Mail client "%s" does not support specifying body' %
4879
mail_client.__class__.__name__)
4880
4766
if remember and submit_branch is None:
4881
4767
raise errors.BzrCommandError(
4882
4768
'--remember requires a branch to be specified.')
5035
4920
return self._run(submit_branch, revision, public_branch, remember,
5036
4921
format, no_bundle, no_patch, output,
5037
kwargs.get('from', '.'), None, None, None)
4922
kwargs.get('from', '.'), None, None)
5040
4925
class cmd_tag(Command):
5445
5330
class cmd_hooks(Command):
5331
"""Show a branch's currently registered hooks.
5335
takes_args = ['path?']
5451
for hook_key in sorted(hooks.known_hooks.keys()):
5452
some_hooks = hooks.known_hooks_key_to_object(hook_key)
5453
self.outf.write("%s:\n" % type(some_hooks).__name__)
5454
for hook_name, hook_point in sorted(some_hooks.items()):
5455
self.outf.write(" %s:\n" % (hook_name,))
5456
found_hooks = list(hook_point)
5458
for hook in found_hooks:
5459
self.outf.write(" %s\n" %
5460
(some_hooks.get_hook_name(hook),))
5462
self.outf.write(" <no hooks installed>\n")
5337
def run(self, path=None):
5340
branch_hooks = Branch.open(path).hooks
5341
for hook_type in branch_hooks:
5342
hooks = branch_hooks[hook_type]
5343
self.outf.write("%s:\n" % (hook_type,))
5346
self.outf.write(" %s\n" %
5347
(branch_hooks.get_hook_name(hook),))
5349
self.outf.write(" <no hooks installed>\n")
5465
5352
class cmd_shelve(Command):
5498
5385
value_switches=True, enum_switch=False),
5500
5387
Option('list', help='List shelved changes.'),
5502
help='Destroy removed changes instead of shelving them.'),
5504
5389
_see_also = ['unshelve']
5506
5391
def run(self, revision=None, all=False, file_list=None, message=None,
5507
writer=None, list=False, destroy=False):
5392
writer=None, list=False):
5509
5394
return self.run_for_list()
5510
5395
from bzrlib.shelf_ui import Shelver
5560
5445
Unshelver.from_args(shelf_id, action).run()
5563
class cmd_clean_tree(Command):
5564
"""Remove unwanted files from working tree.
5566
By default, only unknown files, not ignored files, are deleted. Versioned
5567
files are never deleted.
5569
Another class is 'detritus', which includes files emitted by bzr during
5570
normal operations and selftests. (The value of these files decreases with
5573
If no options are specified, unknown files are deleted. Otherwise, option
5574
flags are respected, and may be combined.
5576
To check what clean-tree will do, use --dry-run.
5578
takes_options = [Option('ignored', help='Delete all ignored files.'),
5579
Option('detritus', help='Delete conflict files, merge'
5580
' backups, and failed selftest dirs.'),
5582
help='Delete files unknown to bzr (default).'),
5583
Option('dry-run', help='Show files to delete instead of'
5585
Option('force', help='Do not prompt before deleting.')]
5586
def run(self, unknown=False, ignored=False, detritus=False, dry_run=False,
5588
from bzrlib.clean_tree import clean_tree
5589
if not (unknown or ignored or detritus):
5593
clean_tree('.', unknown=unknown, ignored=ignored, detritus=detritus,
5594
dry_run=dry_run, no_prompt=force)
5597
5448
def _create_prefix(cur_transport):
5598
5449
needed = [cur_transport]
5599
5450
# Recurse upwards until we can create a directory successfully