79
80
def tree_files_for_add(file_list):
80
"""Add handles files a bit differently so it a custom implementation."""
82
Return a tree and list of absolute paths from a file list.
84
Similar to tree_files, but add handles files a bit differently, so it a
85
custom implementation. In particular, MutableTreeTree.smart_add expects
86
absolute paths, which it immediately converts to relative paths.
88
# FIXME Would be nice to just return the relative paths like
89
# internal_tree_files does, but there are a large number of unit tests
90
# that assume the current interface to mutabletree.smart_add
82
tree = WorkingTree.open_containing(file_list[0])[0]
92
tree, relpath = WorkingTree.open_containing(file_list[0])
83
93
if tree.supports_views():
84
94
view_files = tree.views.lookup_view()
85
for filename in file_list:
86
if not osutils.is_inside_any(view_files, filename):
87
raise errors.FileOutsideView(filename, view_files)
96
for filename in file_list:
97
if not osutils.is_inside_any(view_files, filename):
98
raise errors.FileOutsideView(filename, view_files)
99
file_list = file_list[:]
100
file_list[0] = tree.abspath(relpath)
89
102
tree = WorkingTree.open_containing(u'.')[0]
90
103
if tree.supports_views():
521
Option('tree', help='Show revno of working tree'),
486
def run(self, revision=None, directory=u'.', revision_info_list=[]):
489
if revision is not None:
490
revs.extend(revision)
491
if revision_info_list is not None:
492
for rev in revision_info_list:
493
revs.append(RevisionSpec.from_string(rev))
495
b = Branch.open_containing(directory)[0]
498
revs.append(RevisionSpec.from_string('-1'))
501
revision_id = rev.as_revision_id(b)
503
revno = '%4d' % (b.revision_id_to_revno(revision_id))
504
except errors.NoSuchRevision:
505
dotted_map = b.get_revision_id_to_revno_map()
506
revno = '.'.join(str(i) for i in dotted_map[revision_id])
507
print '%s %s' % (revno, revision_id)
525
def run(self, revision=None, directory=u'.', tree=False,
526
revision_info_list=[]):
529
wt = WorkingTree.open_containing(directory)[0]
532
except (errors.NoWorkingTree, errors.NotLocalUrl):
534
b = Branch.open_containing(directory)[0]
538
if revision is not None:
539
revision_ids.extend(rev.as_revision_id(b) for rev in revision)
540
if revision_info_list is not None:
541
for rev_str in revision_info_list:
542
rev_spec = RevisionSpec.from_string(rev_str)
543
revision_ids.append(rev_spec.as_revision_id(b))
544
# No arguments supplied, default to the last revision
545
if len(revision_ids) == 0:
548
raise errors.NoWorkingTree(directory)
549
revision_ids.append(wt.last_revision())
551
revision_ids.append(b.last_revision())
555
for revision_id in revision_ids:
557
dotted_revno = b.revision_id_to_dotted_revno(revision_id)
558
revno = '.'.join(str(i) for i in dotted_revno)
559
except errors.NoSuchRevision:
561
maxlen = max(maxlen, len(revno))
562
revinfos.append([revno, revision_id])
570
self.outf.write('%*s %s\n' % (maxlen, ri[0], ri[1]))
510
573
class cmd_add(Command):
721
783
takes_args = ['names*']
722
784
takes_options = [Option("after", help="Move only the bzr identifier"
723
785
" of the file, because the file has already been moved."),
786
Option('auto', help='Automatically guess renames.'),
787
Option('dry-run', help='Avoid making changes when guessing renames.'),
725
789
aliases = ['move', 'rename']
726
790
encoding_type = 'replace'
728
def run(self, names_list, after=False):
792
def run(self, names_list, after=False, auto=False, dry_run=False):
794
return self.run_auto(names_list, after, dry_run)
796
raise errors.BzrCommandError('--dry-run requires --auto.')
729
797
if names_list is None:
732
799
if len(names_list) < 2:
733
800
raise errors.BzrCommandError("missing file argument")
734
801
tree, rel_names = tree_files(names_list, canonicalize=False)
802
tree.lock_tree_write()
737
804
self._run(tree, names_list, rel_names, after)
808
def run_auto(self, names_list, after, dry_run):
809
if names_list is not None and len(names_list) > 1:
810
raise errors.BzrCommandError('Only one path may be specified to'
813
raise errors.BzrCommandError('--after cannot be specified with'
815
work_tree, file_list = tree_files(names_list, default_branch='.')
816
work_tree.lock_tree_write()
818
rename_map.RenameMap.guess_renames(work_tree, dry_run)
741
822
def _run(self, tree, names_list, rel_names, after):
742
823
into_existing = osutils.isdir(names_list[-1])
743
824
if into_existing and len(names_list) == 2:
906
995
if branch_to.get_parent() is None or remember:
907
996
branch_to.set_parent(branch_from.base)
909
if revision is not None:
910
revision_id = revision.as_revision_id(branch_from)
912
branch_to.lock_write()
998
if branch_from is not branch_to:
999
branch_from.lock_read()
914
if tree_to is not None:
915
view_info = _get_view_info_for_change_reporter(tree_to)
916
change_reporter = delta._ChangeReporter(
917
unversioned_filter=tree_to.is_ignored, view_info=view_info)
918
result = tree_to.pull(branch_from, overwrite, revision_id,
920
possible_transports=possible_transports)
922
result = branch_to.pull(branch_from, overwrite, revision_id)
924
result.report(self.outf)
925
if verbose and result.old_revid != result.new_revid:
926
log.show_branch_change(branch_to, self.outf, result.old_revno,
1001
if revision is not None:
1002
revision_id = revision.as_revision_id(branch_from)
1004
branch_to.lock_write()
1006
if tree_to is not None:
1007
view_info = _get_view_info_for_change_reporter(tree_to)
1008
change_reporter = delta._ChangeReporter(
1009
unversioned_filter=tree_to.is_ignored,
1010
view_info=view_info)
1011
result = tree_to.pull(
1012
branch_from, overwrite, revision_id, change_reporter,
1013
possible_transports=possible_transports, local=local)
1015
result = branch_to.pull(
1016
branch_from, overwrite, revision_id, local=local)
1018
result.report(self.outf)
1019
if verbose and result.old_revid != result.new_revid:
1020
log.show_branch_change(
1021
branch_to, self.outf, result.old_revno,
1026
if branch_from is not branch_to:
1027
branch_from.unlock()
932
1030
class cmd_push(Command):
986
1087
def run(self, location=None, remember=False, overwrite=False,
987
1088
create_prefix=False, verbose=False, revision=None,
988
1089
use_existing_dir=False, directory=None, stacked_on=None,
1090
stacked=False, strict=None):
990
1091
from bzrlib.push import _show_push_branch
992
# Get the source branch and revision_id
993
1093
if directory is None:
995
br_from = Branch.open_containing(directory)[0]
1095
# Get the source branch
1097
_unused) = bzrdir.BzrDir.open_containing_tree_or_branch(directory)
1099
strict = br_from.get_config().get_user_option_as_bool('push_strict')
1100
if strict is None: strict = True # default value
1101
# Get the tip's revision_id
996
1102
revision = _get_one_revision('push', revision)
997
1103
if revision is not None:
998
1104
revision_id = revision.in_history(br_from).rev_id
1000
revision_id = br_from.last_revision()
1107
if strict and tree is not None and revision_id is None:
1108
if (tree.has_changes(tree.basis_tree())
1109
or len(tree.get_parent_ids()) > 1):
1110
raise errors.UncommittedChanges(
1111
tree, more='Use --no-strict to force the push.')
1112
if tree.last_revision() != tree.branch.last_revision():
1113
# The tree has lost sync with its branch, there is little
1114
# chance that the user is aware of it but he can still force
1115
# the push with --no-strict
1116
raise errors.OutOfDateTree(
1117
tree, more='Use --no-strict to force the push.')
1002
1119
# Get the stacked_on branch, if any
1003
1120
if stacked_on is not None:
1061
1178
'branch for all operations.'),
1062
1179
Option('standalone',
1063
1180
help='Do not use a shared repository, even if available.'),
1181
Option('use-existing-dir',
1182
help='By default branch will fail if the target'
1183
' directory exists, but does not already'
1184
' have a control directory. This flag will'
1185
' allow branch to proceed.'),
1065
1187
aliases = ['get', 'clone']
1067
1189
def run(self, from_location, to_location=None, revision=None,
1068
hardlink=False, stacked=False, standalone=False, no_tree=False):
1190
hardlink=False, stacked=False, standalone=False, no_tree=False,
1191
use_existing_dir=False):
1069
1192
from bzrlib.tag import _merge_tags_if_possible
1071
1194
accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
1196
if (accelerator_tree is not None and
1197
accelerator_tree.supports_content_filtering()):
1198
accelerator_tree = None
1073
1199
revision = _get_one_revision('branch', revision)
1074
1200
br_from.lock_read()
2147
2289
dir, relpath = bzrdir.BzrDir.open_containing(location)
2148
2290
b = dir.open_branch()
2152
2291
rev1, rev2 = _get_revision_range(revision, b, self.name())
2293
# Decide on the type of delta & diff filtering to use
2294
# TODO: add an --all-files option to make this configurable & consistent
2302
diff_type = 'partial'
2308
# Build the log formatter
2153
2309
if log_format is None:
2154
2310
log_format = log.log_formatter_registry.get_default(b)
2156
2311
lf = log_format(show_ids=show_ids, to_file=self.outf,
2157
2312
show_timezone=timezone,
2158
2313
delta_format=get_verbosity_level(),
2165
direction=direction,
2166
start_revision=rev1,
2170
show_diff=show_diff)
2315
show_advice=levels is None)
2317
# Choose the algorithm for doing the logging. It's annoying
2318
# having multiple code paths like this but necessary until
2319
# the underlying repository format is faster at generating
2320
# deltas or can provide everything we need from the indices.
2321
# The default algorithm - match-using-deltas - works for
2322
# multiple files and directories and is faster for small
2323
# amounts of history (200 revisions say). However, it's too
2324
# slow for logging a single file in a repository with deep
2325
# history, i.e. > 10K revisions. In the spirit of "do no
2326
# evil when adding features", we continue to use the
2327
# original algorithm - per-file-graph - for the "single
2328
# file that isn't a directory without showing a delta" case.
2329
partial_history = revision and b.repository._format.supports_chks
2330
match_using_deltas = (len(file_ids) != 1 or filter_by_dir
2331
or delta_type or partial_history)
2333
# Build the LogRequest and execute it
2334
if len(file_ids) == 0:
2336
rqst = make_log_request_dict(
2337
direction=direction, specific_fileids=file_ids,
2338
start_revision=rev1, end_revision=rev2, limit=limit,
2339
message_search=message, delta_type=delta_type,
2340
diff_type=diff_type, _match_using_deltas=match_using_deltas)
2341
Logger(b, rqst).show(lf)
2311
2484
apply_view = True
2312
2485
view_str = views.view_display_str(view_files)
2313
note("ignoring files outside view: %s" % view_str)
2486
note("Ignoring files outside view. View is %s" % view_str)
2315
2488
tree.lock_read()
2317
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False):
2318
if fp.startswith(relpath):
2319
fp = osutils.pathjoin(prefix, fp[len(relpath):])
2320
if non_recursive and '/' in fp:
2322
if not all and not selection[fc]:
2324
if kind is not None and fkind != kind:
2328
views.check_path_in_view(tree, fp)
2329
except errors.FileOutsideView:
2331
kindch = entry.kind_character()
2332
outstring = fp + kindch
2334
outstring = '%-8s %s' % (fc, outstring)
2335
if show_ids and fid is not None:
2336
outstring = "%-50s %s" % (outstring, fid)
2337
self.outf.write(outstring + '\n')
2339
self.outf.write(fp + '\0')
2342
self.outf.write(fid)
2343
self.outf.write('\0')
2490
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False,
2491
from_dir=relpath, recursive=recursive):
2492
# Apply additional masking
2493
if not all and not selection[fc]:
2495
if kind is not None and fkind != kind:
2500
fullpath = osutils.pathjoin(relpath, fp)
2503
views.check_path_in_view(tree, fullpath)
2504
except errors.FileOutsideView:
2509
fp = osutils.pathjoin(prefix, fp)
2510
kindch = entry.kind_character()
2511
outstring = fp + kindch
2512
ui.ui_factory.clear_term()
2514
outstring = '%-8s %s' % (fc, outstring)
2515
if show_ids and fid is not None:
2516
outstring = "%-50s %s" % (outstring, fid)
2517
self.outf.write(outstring + '\n')
2519
self.outf.write(fp + '\0')
2522
self.outf.write(fid)
2523
self.outf.write('\0')
2346
2527
if fid is not None:
2351
self.outf.write('%-50s %s\n' % (outstring, my_id))
2353
self.outf.write(outstring + '\n')
2531
self.outf.write('%-50s %s\n' % (outstring, my_id))
2533
self.outf.write(outstring + '\n')
2576
2763
branch.lock_read()
2578
2765
return self._run(tree, branch, relpath, filename, revision,
2766
name_from_revision, filters)
2581
2768
branch.unlock()
2583
def _run(self, tree, b, relpath, filename, revision, name_from_revision):
2770
def _run(self, tree, b, relpath, filename, revision, name_from_revision,
2584
2772
if tree is None:
2585
2773
tree = b.basis_tree()
2586
2774
rev_tree = _get_one_revision_tree('cat', revision, branch=b)
2588
cur_file_id = tree.path2id(relpath)
2589
2776
old_file_id = rev_tree.path2id(relpath)
2591
2778
if name_from_revision:
2779
# Try in revision if requested
2592
2780
if old_file_id is None:
2593
2781
raise errors.BzrCommandError(
2594
2782
"%r is not present in revision %s" % (
2595
2783
filename, rev_tree.get_revision_id()))
2597
2785
content = rev_tree.get_file_text(old_file_id)
2598
elif cur_file_id is not None:
2599
content = rev_tree.get_file_text(cur_file_id)
2600
elif old_file_id is not None:
2601
content = rev_tree.get_file_text(old_file_id)
2603
raise errors.BzrCommandError(
2604
"%r is not present in revision %s" % (
2605
filename, rev_tree.get_revision_id()))
2606
self.outf.write(content)
2787
cur_file_id = tree.path2id(relpath)
2789
if cur_file_id is not None:
2790
# Then try with the actual file id
2792
content = rev_tree.get_file_text(cur_file_id)
2794
except errors.NoSuchId:
2795
# The actual file id didn't exist at that time
2797
if not found and old_file_id is not None:
2798
# Finally try with the old file id
2799
content = rev_tree.get_file_text(old_file_id)
2802
# Can't be found anywhere
2803
raise errors.BzrCommandError(
2804
"%r is not present in revision %s" % (
2805
filename, rev_tree.get_revision_id()))
2807
from bzrlib.filters import (
2808
ContentFilterContext,
2809
filtered_output_bytes,
2811
filters = rev_tree._content_filter_stack(relpath)
2812
chunks = content.splitlines(True)
2813
content = filtered_output_bytes(chunks, filters,
2814
ContentFilterContext(relpath, rev_tree))
2815
self.outf.writelines(content)
2817
self.outf.write(content)
2609
2820
class cmd_local_time_offset(Command):
2618
2829
class cmd_commit(Command):
2619
2830
"""Commit changes into a new revision.
2621
If no arguments are given, the entire tree is committed.
2623
If selected files are specified, only changes to those files are
2624
committed. If a directory is specified then the directory and everything
2625
within it is committed.
2627
When excludes are given, they take precedence over selected files.
2628
For example, too commit only changes within foo, but not changes within
2631
bzr commit foo -x foo/bar
2633
If author of the change is not the same person as the committer, you can
2634
specify the author's name using the --author option. The name should be
2635
in the same format as a committer-id, e.g. "John Doe <jdoe@example.com>".
2636
If there is more than one author of the change you can specify the option
2637
multiple times, once for each author.
2639
A selected-file commit may fail in some cases where the committed
2640
tree would be invalid. Consider::
2645
bzr commit foo -m "committing foo"
2646
bzr mv foo/bar foo/baz
2649
bzr commit foo/bar -m "committing bar but not baz"
2651
In the example above, the last commit will fail by design. This gives
2652
the user the opportunity to decide whether they want to commit the
2653
rename at the same time, separately first, or not at all. (As a general
2654
rule, when in doubt, Bazaar has a policy of Doing the Safe Thing.)
2656
Note: A selected-file commit after a merge is not yet supported.
2832
An explanatory message needs to be given for each commit. This is
2833
often done by using the --message option (getting the message from the
2834
command line) or by using the --file option (getting the message from
2835
a file). If neither of these options is given, an editor is opened for
2836
the user to enter the message. To see the changed files in the
2837
boilerplate text loaded into the editor, use the --show-diff option.
2839
By default, the entire tree is committed and the person doing the
2840
commit is assumed to be the author. These defaults can be overridden
2845
If selected files are specified, only changes to those files are
2846
committed. If a directory is specified then the directory and
2847
everything within it is committed.
2849
When excludes are given, they take precedence over selected files.
2850
For example, to commit only changes within foo, but not changes
2853
bzr commit foo -x foo/bar
2855
A selective commit after a merge is not yet supported.
2859
If the author of the change is not the same person as the committer,
2860
you can specify the author's name using the --author option. The
2861
name should be in the same format as a committer-id, e.g.
2862
"John Doe <jdoe@example.com>". If there is more than one author of
2863
the change you can specify the option multiple times, once for each
2868
A common mistake is to forget to add a new file or directory before
2869
running the commit command. The --strict option checks for unknown
2870
files and aborts the commit if any are found. More advanced pre-commit
2871
checks can be implemented by defining hooks. See ``bzr help hooks``
2876
If you accidentially commit the wrong changes or make a spelling
2877
mistake in the commit message say, you can use the uncommit command
2878
to undo it. See ``bzr help uncommit`` for details.
2880
Hooks can also be configured to run after a commit. This allows you
2881
to trigger updates to external systems like bug trackers. The --fixes
2882
option can be used to record the association between a revision and
2883
one or more bugs. See ``bzr help bugs`` for details.
2885
A selective commit may fail in some cases where the committed
2886
tree would be invalid. Consider::
2891
bzr commit foo -m "committing foo"
2892
bzr mv foo/bar foo/baz
2895
bzr commit foo/bar -m "committing bar but not baz"
2897
In the example above, the last commit will fail by design. This gives
2898
the user the opportunity to decide whether they want to commit the
2899
rename at the same time, separately first, or not at all. (As a general
2900
rule, when in doubt, Bazaar has a policy of Doing the Safe Thing.)
2658
2902
# TODO: Run hooks on tree to-be-committed, and after commit.
2700
2945
aliases = ['ci', 'checkin']
2702
def _get_bug_fix_properties(self, fixes, branch):
2947
def _iter_bug_fix_urls(self, fixes, branch):
2704
2948
# Configure the properties for bug fixing attributes.
2705
2949
for fixed_bug in fixes:
2706
2950
tokens = fixed_bug.split(':')
2707
2951
if len(tokens) != 2:
2708
2952
raise errors.BzrCommandError(
2709
"Invalid bug %s. Must be in the form of 'tag:id'. "
2710
"Commit refused." % fixed_bug)
2953
"Invalid bug %s. Must be in the form of 'tracker:id'. "
2954
"See \"bzr help bugs\" for more information on this "
2955
"feature.\nCommit refused." % fixed_bug)
2711
2956
tag, bug_id = tokens
2713
bug_url = bugtracker.get_bug_url(tag, branch, bug_id)
2958
yield bugtracker.get_bug_url(tag, branch, bug_id)
2714
2959
except errors.UnknownBugTrackerAbbreviation:
2715
2960
raise errors.BzrCommandError(
2716
2961
'Unrecognized bug %s. Commit refused.' % fixed_bug)
2717
except errors.MalformedBugIdentifier:
2962
except errors.MalformedBugIdentifier, e:
2718
2963
raise errors.BzrCommandError(
2719
"Invalid bug identifier for %s. Commit refused."
2721
properties.append('%s fixed' % bug_url)
2722
return '\n'.join(properties)
2964
"%s\nCommit refused." % (str(e),))
2724
2966
def run(self, message=None, file=None, verbose=False, selected_list=None,
2725
2967
unchanged=False, strict=False, local=False, fixes=None,
2817
3060
The working tree and branch checks will only give output if a problem is
2818
3061
detected. The output fields of the repository check are:
2820
revisions: This is just the number of revisions checked. It doesn't
2822
versionedfiles: This is just the number of versionedfiles checked. It
2823
doesn't indicate a problem.
2824
unreferenced ancestors: Texts that are ancestors of other texts, but
2825
are not properly referenced by the revision ancestry. This is a
2826
subtle problem that Bazaar can work around.
2827
unique file texts: This is the total number of unique file contents
2828
seen in the checked revisions. It does not indicate a problem.
2829
repeated file texts: This is the total number of repeated texts seen
2830
in the checked revisions. Texts can be repeated when their file
2831
entries are modified, but the file contents are not. It does not
3064
This is just the number of revisions checked. It doesn't
3068
This is just the number of versionedfiles checked. It
3069
doesn't indicate a problem.
3071
unreferenced ancestors
3072
Texts that are ancestors of other texts, but
3073
are not properly referenced by the revision ancestry. This is a
3074
subtle problem that Bazaar can work around.
3077
This is the total number of unique file contents
3078
seen in the checked revisions. It does not indicate a problem.
3081
This is the total number of repeated texts seen
3082
in the checked revisions. Texts can be repeated when their file
3083
entries are modified, but the file contents are not. It does not
2834
3086
If no restrictions are specified, all Bazaar data that is found at the given
2835
3087
location will be checked.
3437
3708
for cleanup in reversed(cleanups):
3440
def _do_preview(self, merger):
3441
from bzrlib.diff import show_diff_trees
3711
def _get_preview(self, merger, cleanups):
3442
3712
tree_merger = merger.make_merger()
3443
3713
tt = tree_merger.make_preview_transform()
3445
result_tree = tt.get_preview_tree()
3446
show_diff_trees(merger.this_tree, result_tree, self.outf,
3447
old_label='', new_label='')
3714
cleanups.append(tt.finalize)
3715
result_tree = tt.get_preview_tree()
3718
def _do_preview(self, merger, cleanups):
3719
from bzrlib.diff import show_diff_trees
3720
result_tree = self._get_preview(merger, cleanups)
3721
show_diff_trees(merger.this_tree, result_tree, self.outf,
3722
old_label='', new_label='')
3451
3724
def _do_merge(self, merger, change_reporter, allow_pending, verified):
3452
3725
merger.change_reporter = change_reporter
4402
def run_smart_server(self, smart_server):
4403
"""Run 'smart_server' forever, with no UI output at all."""
4404
# For the duration of this server, no UI output is permitted. note
4405
# that this may cause problems with blackbox tests. This should be
4406
# changed with care though, as we dont want to use bandwidth sending
4407
# progress over stderr to smart server clients!
4408
from bzrlib import lockdir
4409
old_factory = ui.ui_factory
4410
old_lockdir_timeout = lockdir._DEFAULT_TIMEOUT_SECONDS
4412
ui.ui_factory = ui.SilentUIFactory()
4413
lockdir._DEFAULT_TIMEOUT_SECONDS = 0
4414
smart_server.serve()
4416
ui.ui_factory = old_factory
4417
lockdir._DEFAULT_TIMEOUT_SECONDS = old_lockdir_timeout
4419
4711
def get_host_and_port(self, port):
4420
4712
"""Return the host and port to run the smart server on.
4422
If 'port' is None, the default host (`medium.BZR_DEFAULT_INTERFACE`)
4423
and port (`medium.BZR_DEFAULT_PORT`) will be used.
4714
If 'port' is None, None will be returned for the host and port.
4425
4716
If 'port' has a colon in it, the string before the colon will be
4426
4717
interpreted as the host.
4429
4720
:return: A tuple of (host, port), where 'host' is a host name or IP,
4430
4721
and port is an integer TCP/IP port.
4432
from bzrlib.smart import medium
4433
host = medium.BZR_DEFAULT_INTERFACE
4435
port = medium.BZR_DEFAULT_PORT
4724
if port is not None:
4437
4725
if ':' in port:
4438
4726
host, port = port.split(':')
4439
4727
port = int(port)
4440
4728
return host, port
4442
def get_smart_server(self, transport, inet, port):
4443
"""Construct a smart server.
4445
:param transport: The base transport from which branches will be
4447
:param inet: If True, serve over stdin and stdout. Used for running
4449
:param port: The port to listen on. By default, it's `
4450
medium.BZR_DEFAULT_PORT`. See `get_host_and_port` for more
4452
:return: A smart server.
4454
from bzrlib.smart import medium, server
4456
smart_server = medium.SmartServerPipeStreamMedium(
4457
sys.stdin, sys.stdout, transport)
4459
host, port = self.get_host_and_port(port)
4460
smart_server = server.SmartTCPServer(
4461
transport, host=host, port=port)
4462
note('listening on port: %s' % smart_server.port)
4465
def run(self, port=None, inet=False, directory=None, allow_writes=False):
4466
from bzrlib.transport import get_transport
4467
from bzrlib.transport.chroot import ChrootServer
4730
def run(self, port=None, inet=False, directory=None, allow_writes=False,
4732
from bzrlib.transport import get_transport, transport_server_registry
4468
4733
if directory is None:
4469
4734
directory = os.getcwd()
4735
if protocol is None:
4736
protocol = transport_server_registry.get()
4737
host, port = self.get_host_and_port(port)
4470
4738
url = urlutils.local_path_to_url(directory)
4471
4739
if not allow_writes:
4472
4740
url = 'readonly+' + url
4473
chroot_server = ChrootServer(get_transport(url))
4474
chroot_server.setUp()
4475
t = get_transport(chroot_server.get_url())
4476
smart_server = self.get_smart_server(t, inet, port)
4477
self.run_smart_server(smart_server)
4741
transport = get_transport(url)
4742
protocol(transport, host, port, inet)
4480
4745
class cmd_join(Command):
4481
"""Combine a subtree into its containing tree.
4746
"""Combine a tree into its containing tree.
4483
This command is for experimental use only. It requires the target tree
4484
to be in dirstate-with-subtree format, which cannot be converted into
4748
This command requires the target tree to be in a rich-root format.
4487
4750
The TREE argument should be an independent tree, inside another tree, but
4488
4751
not part of it. (Such trees can be produced by "bzr split", but also by
4729
4986
help='Write merge directive to this file; '
4730
4987
'use - for stdout.',
4990
help='Refuse to send if there are uncommitted changes in'
4991
' the working tree, --no-strict disables the check.'),
4732
4992
Option('mail-to', help='Mail the request to this address.',
4736
RegistryOption.from_kwargs('format',
4737
'Use the specified output format.',
4738
**{'4': 'Bundle format 4, Merge Directive 2 (default)',
4739
'0.9': 'Bundle format 0.9, Merge Directive 1',})
4996
Option('body', help='Body for the email.', type=unicode),
4997
RegistryOption('format',
4998
help='Use the specified output format.',
4999
lazy_registry=('bzrlib.send', 'format_registry')),
4742
5002
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
4743
5003
no_patch=False, revision=None, remember=False, output=None,
4744
format='4', mail_to=None, message=None, **kwargs):
4745
return self._run(submit_branch, revision, public_branch, remember,
4746
format, no_bundle, no_patch, output,
4747
kwargs.get('from', '.'), mail_to, message)
4749
def _run(self, submit_branch, revision, public_branch, remember, format,
4750
no_bundle, no_patch, output, from_, mail_to, message):
4751
from bzrlib.revision import NULL_REVISION
4752
branch = Branch.open_containing(from_)[0]
4754
outfile = cStringIO.StringIO()
4758
outfile = open(output, 'wb')
4759
# we may need to write data into branch's repository to calculate
4764
config = branch.get_config()
4766
mail_to = config.get_user_option('submit_to')
4767
mail_client = config.get_mail_client()
4768
if remember and submit_branch is None:
4769
raise errors.BzrCommandError(
4770
'--remember requires a branch to be specified.')
4771
stored_submit_branch = branch.get_submit_branch()
4772
remembered_submit_branch = None
4773
if submit_branch is None:
4774
submit_branch = stored_submit_branch
4775
remembered_submit_branch = "submit"
4777
if stored_submit_branch is None or remember:
4778
branch.set_submit_branch(submit_branch)
4779
if submit_branch is None:
4780
submit_branch = branch.get_parent()
4781
remembered_submit_branch = "parent"
4782
if submit_branch is None:
4783
raise errors.BzrCommandError('No submit branch known or'
4785
if remembered_submit_branch is not None:
4786
note('Using saved %s location "%s" to determine what '
4787
'changes to submit.', remembered_submit_branch,
4791
submit_config = Branch.open(submit_branch).get_config()
4792
mail_to = submit_config.get_user_option("child_submit_to")
4794
stored_public_branch = branch.get_public_branch()
4795
if public_branch is None:
4796
public_branch = stored_public_branch
4797
elif stored_public_branch is None or remember:
4798
branch.set_public_branch(public_branch)
4799
if no_bundle and public_branch is None:
4800
raise errors.BzrCommandError('No public branch specified or'
4802
base_revision_id = None
4804
if revision is not None:
4805
if len(revision) > 2:
4806
raise errors.BzrCommandError('bzr send takes '
4807
'at most two one revision identifiers')
4808
revision_id = revision[-1].as_revision_id(branch)
4809
if len(revision) == 2:
4810
base_revision_id = revision[0].as_revision_id(branch)
4811
if revision_id is None:
4812
revision_id = branch.last_revision()
4813
if revision_id == NULL_REVISION:
4814
raise errors.BzrCommandError('No revisions to submit.')
4816
directive = merge_directive.MergeDirective2.from_objects(
4817
branch.repository, revision_id, time.time(),
4818
osutils.local_time_offset(), submit_branch,
4819
public_branch=public_branch, include_patch=not no_patch,
4820
include_bundle=not no_bundle, message=message,
4821
base_revision_id=base_revision_id)
4822
elif format == '0.9':
4825
patch_type = 'bundle'
4827
raise errors.BzrCommandError('Format 0.9 does not'
4828
' permit bundle with no patch')
4834
directive = merge_directive.MergeDirective.from_objects(
4835
branch.repository, revision_id, time.time(),
4836
osutils.local_time_offset(), submit_branch,
4837
public_branch=public_branch, patch_type=patch_type,
4840
outfile.writelines(directive.to_lines())
4842
subject = '[MERGE] '
4843
if message is not None:
4846
revision = branch.repository.get_revision(revision_id)
4847
subject += revision.get_summary()
4848
basename = directive.get_disk_name(branch)
4849
mail_client.compose_merge_request(mail_to, subject,
4850
outfile.getvalue(), basename)
5004
format=None, mail_to=None, message=None, body=None,
5005
strict=None, **kwargs):
5006
from bzrlib.send import send
5007
return send(submit_branch, revision, public_branch, remember,
5008
format, no_bundle, no_patch, output,
5009
kwargs.get('from', '.'), mail_to, message, body,
4857
5014
class cmd_bundle_revisions(cmd_send):
4859
5015
"""Create a merge-directive for submitting changes.
4861
5017
A merge directive provides many things needed for requesting merges:
4917
5075
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
4918
5076
no_patch=False, revision=None, remember=False, output=None,
4919
format='4', **kwargs):
5077
format=None, strict=None, **kwargs):
4920
5078
if output is None:
4922
return self._run(submit_branch, revision, public_branch, remember,
5080
from bzrlib.send import send
5081
return send(submit_branch, revision, public_branch, remember,
4923
5082
format, no_bundle, no_patch, output,
4924
kwargs.get('from', '.'), None, None)
5083
kwargs.get('from', '.'), None, None, None,
5084
self.outf, strict=strict)
4927
5087
class cmd_tag(Command):
5028
5188
graph = branch.repository.get_graph()
5029
5189
rev1, rev2 = _get_revision_range(revision, branch, self.name())
5030
5190
revid1, revid2 = rev1.rev_id, rev2.rev_id
5031
5191
# only show revisions between revid1 and revid2 (inclusive)
5032
5192
tags = [(tag, revid) for tag, revid in tags if
5033
5193
graph.is_between(revid, revid1, revid2)]
5038
elif sort == 'time':
5040
for tag, revid in tags:
5042
revobj = branch.repository.get_revision(revid)
5043
except errors.NoSuchRevision:
5044
timestamp = sys.maxint # place them at the end
5046
timestamp = revobj.timestamp
5047
timestamps[revid] = timestamp
5048
tags.sort(key=lambda x: timestamps[x[1]])
5050
# [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
5051
revno_map = branch.get_revision_id_to_revno_map()
5052
tags = [ (tag, '.'.join(map(str, revno_map.get(revid, ('?',)))))
5053
for tag, revid in tags ]
5196
elif sort == 'time':
5198
for tag, revid in tags:
5200
revobj = branch.repository.get_revision(revid)
5201
except errors.NoSuchRevision:
5202
timestamp = sys.maxint # place them at the end
5204
timestamp = revobj.timestamp
5205
timestamps[revid] = timestamp
5206
tags.sort(key=lambda x: timestamps[x[1]])
5208
# [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
5209
for index, (tag, revid) in enumerate(tags):
5211
revno = branch.revision_id_to_dotted_revno(revid)
5212
if isinstance(revno, tuple):
5213
revno = '.'.join(map(str, revno))
5214
except errors.NoSuchRevision:
5215
# Bad tag data/merges can lead to tagged revisions
5216
# which are not in this branch. Fail gracefully ...
5218
tags[index] = (tag, revno)
5054
5221
for tag, revspec in tags:
5055
5222
self.outf.write('%-20s %s\n' % (tag, revspec))
5093
5260
Option('bind-to', help='Branch to bind checkout to.', type=str),
5094
5261
Option('force',
5095
help='Perform reconfiguration even if local changes'
5262
help='Perform reconfiguration even if local changes'
5264
Option('stacked-on',
5265
help='Reconfigure a branch to be stacked on another branch.',
5269
help='Reconfigure a branch to be unstacked. This '
5270
'may require copying substantial data into it.',
5099
def run(self, location=None, target_type=None, bind_to=None, force=False):
5274
def run(self, location=None, target_type=None, bind_to=None, force=False,
5100
5277
directory = bzrdir.BzrDir.open(location)
5278
if stacked_on and unstacked:
5279
raise BzrCommandError("Can't use both --stacked-on and --unstacked")
5280
elif stacked_on is not None:
5281
reconfigure.ReconfigureStackedOn().apply(directory, stacked_on)
5283
reconfigure.ReconfigureUnstacked().apply(directory)
5284
# At the moment you can use --stacked-on and a different
5285
# reconfiguration shape at the same time; there seems no good reason
5101
5287
if target_type is None:
5102
raise errors.BzrCommandError('No target configuration specified')
5288
if stacked_on or unstacked:
5291
raise errors.BzrCommandError('No target configuration '
5103
5293
elif target_type == 'branch':
5104
5294
reconfiguration = reconfigure.Reconfigure.to_branch(directory)
5105
5295
elif target_type == 'tree':
5149
5339
takes_args = ['to_location']
5150
5340
takes_options = [Option('force',
5151
help='Switch even if local commits will be lost.')
5341
help='Switch even if local commits will be lost.'),
5342
Option('create-branch', short_name='b',
5343
help='Create the target branch from this one before'
5344
' switching to it.'),
5154
def run(self, to_location, force=False):
5347
def run(self, to_location, force=False, create_branch=False):
5155
5348
from bzrlib import switch
5156
5349
tree_location = '.'
5157
5350
control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5158
branch = control_dir.open_branch()
5160
to_branch = Branch.open(to_location)
5352
branch = control_dir.open_branch()
5353
had_explicit_nick = branch.get_config().has_explicit_nickname()
5161
5354
except errors.NotBranchError:
5162
this_branch = control_dir.open_branch()
5163
# This may be a heavy checkout, where we want the master branch
5164
this_url = this_branch.get_bound_location()
5165
# If not, use a local sibling
5166
if this_url is None:
5167
this_url = this_branch.base
5168
to_branch = Branch.open(
5169
urlutils.join(this_url, '..', to_location))
5356
had_explicit_nick = False
5359
raise errors.BzrCommandError('cannot create branch without'
5361
if '/' not in to_location and '\\' not in to_location:
5362
# This path is meant to be relative to the existing branch
5363
this_url = self._get_branch_location(control_dir)
5364
to_location = urlutils.join(this_url, '..', to_location)
5365
to_branch = branch.bzrdir.sprout(to_location,
5366
possible_transports=[branch.bzrdir.root_transport],
5367
source_branch=branch).open_branch()
5369
# from_branch = control_dir.open_branch()
5370
# except errors.NotBranchError:
5371
# raise BzrCommandError('Cannot create a branch from this'
5372
# ' location when we cannot open this branch')
5373
# from_branch.bzrdir.sprout(
5377
to_branch = Branch.open(to_location)
5378
except errors.NotBranchError:
5379
this_url = self._get_branch_location(control_dir)
5380
to_branch = Branch.open(
5381
urlutils.join(this_url, '..', to_location))
5170
5382
switch.switch(control_dir, to_branch, force)
5171
if branch.get_config().has_explicit_nickname():
5383
if had_explicit_nick:
5172
5384
branch = control_dir.open_branch() #get the new branch!
5173
5385
branch.nick = to_branch.nick
5174
5386
note('Switched to branch: %s',
5175
5387
urlutils.unescape_for_display(to_branch.base, 'utf-8'))
5389
def _get_branch_location(self, control_dir):
5390
"""Return location of branch for this control dir."""
5392
this_branch = control_dir.open_branch()
5393
# This may be a heavy checkout, where we want the master branch
5394
master_location = this_branch.get_bound_location()
5395
if master_location is not None:
5396
return master_location
5397
# If not, use a local sibling
5398
return this_branch.base
5399
except errors.NotBranchError:
5400
format = control_dir.find_branch_format()
5401
if getattr(format, 'get_reference', None) is not None:
5402
return format.get_reference(control_dir)
5404
return control_dir.root_transport.base
5178
5407
class cmd_view(Command):
5179
5408
"""Manage filtered views.
5332
5561
class cmd_hooks(Command):
5333
"""Show a branch's currently registered hooks.
5337
takes_args = ['path?']
5339
def run(self, path=None):
5342
branch_hooks = Branch.open(path).hooks
5343
for hook_type in branch_hooks:
5344
hooks = branch_hooks[hook_type]
5345
self.outf.write("%s:\n" % (hook_type,))
5348
self.outf.write(" %s\n" %
5349
(branch_hooks.get_hook_name(hook),))
5351
self.outf.write(" <no hooks installed>\n")
5567
for hook_key in sorted(hooks.known_hooks.keys()):
5568
some_hooks = hooks.known_hooks_key_to_object(hook_key)
5569
self.outf.write("%s:\n" % type(some_hooks).__name__)
5570
for hook_name, hook_point in sorted(some_hooks.items()):
5571
self.outf.write(" %s:\n" % (hook_name,))
5572
found_hooks = list(hook_point)
5574
for hook in found_hooks:
5575
self.outf.write(" %s\n" %
5576
(some_hooks.get_hook_name(hook),))
5578
self.outf.write(" <no hooks installed>\n")
5354
5581
class cmd_shelve(Command):
5447
5676
Unshelver.from_args(shelf_id, action).run()
5450
def _create_prefix(cur_transport):
5451
needed = [cur_transport]
5452
# Recurse upwards until we can create a directory successfully
5454
new_transport = cur_transport.clone('..')
5455
if new_transport.base == cur_transport.base:
5456
raise errors.BzrCommandError(
5457
"Failed to create path prefix for %s."
5458
% cur_transport.base)
5460
new_transport.mkdir('.')
5461
except errors.NoSuchFile:
5462
needed.append(new_transport)
5463
cur_transport = new_transport
5679
class cmd_clean_tree(Command):
5680
"""Remove unwanted files from working tree.
5682
By default, only unknown files, not ignored files, are deleted. Versioned
5683
files are never deleted.
5685
Another class is 'detritus', which includes files emitted by bzr during
5686
normal operations and selftests. (The value of these files decreases with
5689
If no options are specified, unknown files are deleted. Otherwise, option
5690
flags are respected, and may be combined.
5692
To check what clean-tree will do, use --dry-run.
5694
takes_options = [Option('ignored', help='Delete all ignored files.'),
5695
Option('detritus', help='Delete conflict files, merge'
5696
' backups, and failed selftest dirs.'),
5698
help='Delete files unknown to bzr (default).'),
5699
Option('dry-run', help='Show files to delete instead of'
5701
Option('force', help='Do not prompt before deleting.')]
5702
def run(self, unknown=False, ignored=False, detritus=False, dry_run=False,
5704
from bzrlib.clean_tree import clean_tree
5705
if not (unknown or ignored or detritus):
5709
clean_tree('.', unknown=unknown, ignored=ignored, detritus=detritus,
5710
dry_run=dry_run, no_prompt=force)
5713
class cmd_reference(Command):
5714
"""list, view and set branch locations for nested trees.
5716
If no arguments are provided, lists the branch locations for nested trees.
5717
If one argument is provided, display the branch location for that tree.
5718
If two arguments are provided, set the branch location for that tree.
5723
takes_args = ['path?', 'location?']
5725
def run(self, path=None, location=None):
5727
if path is not None:
5729
tree, branch, relpath =(
5730
bzrdir.BzrDir.open_containing_tree_or_branch(branchdir))
5731
if path is not None:
5734
tree = branch.basis_tree()
5736
info = branch._get_all_reference_info().iteritems()
5737
self._display_reference_info(tree, branch, info)
5466
# Now we only need to create child directories
5468
cur_transport = needed.pop()
5469
cur_transport.ensure_base()
5739
file_id = tree.path2id(path)
5741
raise errors.NotVersionedError(path)
5742
if location is None:
5743
info = [(file_id, branch.get_reference_info(file_id))]
5744
self._display_reference_info(tree, branch, info)
5746
branch.set_reference_info(file_id, path, location)
5748
def _display_reference_info(self, tree, branch, info):
5750
for file_id, (path, location) in info:
5752
path = tree.id2path(file_id)
5753
except errors.NoSuchId:
5755
ref_list.append((path, location))
5756
for path, location in sorted(ref_list):
5757
self.outf.write('%s %s\n' % (path, location))
5472
5760
# these get imported and then picked up by the scan for cmd_*