521
Option('tree', help='Show revno of working tree'),
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]))
500
def run(self, revision=None, directory=u'.', revision_info_list=[]):
503
if revision is not None:
504
revs.extend(revision)
505
if revision_info_list is not None:
506
for rev in revision_info_list:
507
revs.append(RevisionSpec.from_string(rev))
509
b = Branch.open_containing(directory)[0]
512
revs.append(RevisionSpec.from_string('-1'))
515
revision_id = rev.as_revision_id(b)
517
revno = '%4d' % (b.revision_id_to_revno(revision_id))
518
except errors.NoSuchRevision:
519
dotted_map = b.get_revision_id_to_revno_map()
520
revno = '.'.join(str(i) for i in dotted_map[revision_id])
521
print '%s %s' % (revno, revision_id)
573
524
class cmd_add(Command):
995
937
if branch_to.get_parent() is None or remember:
996
938
branch_to.set_parent(branch_from.base)
998
if branch_from is not branch_to:
999
branch_from.lock_read()
940
if revision is not None:
941
revision_id = revision.as_revision_id(branch_from)
943
branch_to.lock_write()
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,
945
if tree_to is not None:
946
view_info = _get_view_info_for_change_reporter(tree_to)
947
change_reporter = delta._ChangeReporter(
948
unversioned_filter=tree_to.is_ignored, view_info=view_info)
949
result = tree_to.pull(branch_from, overwrite, revision_id,
951
possible_transports=possible_transports)
953
result = branch_to.pull(branch_from, overwrite, revision_id)
955
result.report(self.outf)
956
if verbose and result.old_revid != result.new_revid:
957
log.show_branch_change(branch_to, self.outf, result.old_revno,
1026
if branch_from is not branch_to:
1027
branch_from.unlock()
1030
963
class cmd_push(Command):
1087
1017
def run(self, location=None, remember=False, overwrite=False,
1088
1018
create_prefix=False, verbose=False, revision=None,
1089
1019
use_existing_dir=False, directory=None, stacked_on=None,
1090
stacked=False, strict=None):
1091
1021
from bzrlib.push import _show_push_branch
1023
# Get the source branch and revision_id
1093
1024
if directory is None:
1094
1025
directory = '.'
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
1026
br_from = Branch.open_containing(directory)[0]
1102
1027
revision = _get_one_revision('push', revision)
1103
1028
if revision is not None:
1104
1029
revision_id = revision.in_history(br_from).rev_id
1106
1031
revision_id = None
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.')
1119
1033
# Get the stacked_on branch, if any
1120
1034
if stacked_on is not None:
1178
1092
'branch for all operations.'),
1179
1093
Option('standalone',
1180
1094
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.'),
1187
1096
aliases = ['get', 'clone']
1189
1098
def run(self, from_location, to_location=None, revision=None,
1190
hardlink=False, stacked=False, standalone=False, no_tree=False,
1191
use_existing_dir=False):
1099
hardlink=False, stacked=False, standalone=False, no_tree=False):
1192
1100
from bzrlib.tag import _merge_tags_if_possible
1194
1102
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
1199
1104
revision = _get_one_revision('branch', revision)
1200
1105
br_from.lock_read()
2488
2382
tree.lock_read()
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')
2384
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False):
2385
if fp.startswith(relpath):
2386
rp = fp[len(relpath):]
2387
fp = osutils.pathjoin(prefix, rp)
2388
if not recursive and '/' in rp:
2390
if not all and not selection[fc]:
2392
if kind is not None and fkind != kind:
2396
views.check_path_in_view(tree, fp)
2397
except errors.FileOutsideView:
2399
kindch = entry.kind_character()
2400
outstring = fp + kindch
2402
outstring = '%-8s %s' % (fc, outstring)
2403
if show_ids and fid is not None:
2404
outstring = "%-50s %s" % (outstring, fid)
2405
self.outf.write(outstring + '\n')
2407
self.outf.write(fp + '\0')
2410
self.outf.write(fid)
2411
self.outf.write('\0')
2527
2414
if fid is not None:
2531
self.outf.write('%-50s %s\n' % (outstring, my_id))
2533
self.outf.write(outstring + '\n')
2419
self.outf.write('%-50s %s\n' % (outstring, my_id))
2421
self.outf.write(outstring + '\n')
2829
2717
class cmd_commit(Command):
2830
2718
"""Commit changes into a new revision.
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.)
2720
If no arguments are given, the entire tree is committed.
2722
If selected files are specified, only changes to those files are
2723
committed. If a directory is specified then the directory and everything
2724
within it is committed.
2726
When excludes are given, they take precedence over selected files.
2727
For example, too commit only changes within foo, but not changes within
2730
bzr commit foo -x foo/bar
2732
If author of the change is not the same person as the committer, you can
2733
specify the author's name using the --author option. The name should be
2734
in the same format as a committer-id, e.g. "John Doe <jdoe@example.com>".
2735
If there is more than one author of the change you can specify the option
2736
multiple times, once for each author.
2738
A selected-file commit may fail in some cases where the committed
2739
tree would be invalid. Consider::
2744
bzr commit foo -m "committing foo"
2745
bzr mv foo/bar foo/baz
2748
bzr commit foo/bar -m "committing bar but not baz"
2750
In the example above, the last commit will fail by design. This gives
2751
the user the opportunity to decide whether they want to commit the
2752
rename at the same time, separately first, or not at all. (As a general
2753
rule, when in doubt, Bazaar has a policy of Doing the Safe Thing.)
2755
Note: A selected-file commit after a merge is not yet supported.
2902
2757
# TODO: Run hooks on tree to-be-committed, and after commit.
3060
2915
The working tree and branch checks will only give output if a problem is
3061
2916
detected. The output fields of the repository check are:
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
2918
revisions: This is just the number of revisions checked. It doesn't
2920
versionedfiles: This is just the number of versionedfiles checked. It
2921
doesn't indicate a problem.
2922
unreferenced ancestors: Texts that are ancestors of other texts, but
2923
are not properly referenced by the revision ancestry. This is a
2924
subtle problem that Bazaar can work around.
2925
unique file texts: This is the total number of unique file contents
2926
seen in the checked revisions. It does not indicate a problem.
2927
repeated file texts: This is the total number of repeated texts seen
2928
in the checked revisions. Texts can be repeated when their file
2929
entries are modified, but the file contents are not. It does not
3086
2932
If no restrictions are specified, all Bazaar data that is found at the given
3087
2933
location will be checked.
3708
3550
for cleanup in reversed(cleanups):
3711
def _get_preview(self, merger, cleanups):
3553
def _do_preview(self, merger):
3554
from bzrlib.diff import show_diff_trees
3712
3555
tree_merger = merger.make_merger()
3713
3556
tt = tree_merger.make_preview_transform()
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='')
3558
result_tree = tt.get_preview_tree()
3559
show_diff_trees(merger.this_tree, result_tree, self.outf,
3560
old_label='', new_label='')
3724
3564
def _do_merge(self, merger, change_reporter, allow_pending, verified):
3725
3565
merger.change_reporter = change_reporter
4516
def run_smart_server(self, smart_server):
4517
"""Run 'smart_server' forever, with no UI output at all."""
4518
# For the duration of this server, no UI output is permitted. note
4519
# that this may cause problems with blackbox tests. This should be
4520
# changed with care though, as we dont want to use bandwidth sending
4521
# progress over stderr to smart server clients!
4522
from bzrlib import lockdir
4523
old_factory = ui.ui_factory
4524
old_lockdir_timeout = lockdir._DEFAULT_TIMEOUT_SECONDS
4526
ui.ui_factory = ui.SilentUIFactory()
4527
lockdir._DEFAULT_TIMEOUT_SECONDS = 0
4528
smart_server.serve()
4530
ui.ui_factory = old_factory
4531
lockdir._DEFAULT_TIMEOUT_SECONDS = old_lockdir_timeout
4711
4533
def get_host_and_port(self, port):
4712
4534
"""Return the host and port to run the smart server on.
4714
If 'port' is None, None will be returned for the host and port.
4536
If 'port' is None, the default host (`medium.BZR_DEFAULT_INTERFACE`)
4537
and port (`medium.BZR_DEFAULT_PORT`) will be used.
4716
4539
If 'port' has a colon in it, the string before the colon will be
4717
4540
interpreted as the host.
4720
4543
:return: A tuple of (host, port), where 'host' is a host name or IP,
4721
4544
and port is an integer TCP/IP port.
4724
if port is not None:
4546
from bzrlib.smart import medium
4547
host = medium.BZR_DEFAULT_INTERFACE
4549
port = medium.BZR_DEFAULT_PORT
4725
4551
if ':' in port:
4726
4552
host, port = port.split(':')
4727
4553
port = int(port)
4728
4554
return host, port
4730
def run(self, port=None, inet=False, directory=None, allow_writes=False,
4732
from bzrlib.transport import get_transport, transport_server_registry
4556
def get_smart_server(self, transport, inet, port):
4557
"""Construct a smart server.
4559
:param transport: The base transport from which branches will be
4561
:param inet: If True, serve over stdin and stdout. Used for running
4563
:param port: The port to listen on. By default, it's `
4564
medium.BZR_DEFAULT_PORT`. See `get_host_and_port` for more
4566
:return: A smart server.
4568
from bzrlib.smart import medium, server
4570
smart_server = medium.SmartServerPipeStreamMedium(
4571
sys.stdin, sys.stdout, transport)
4573
host, port = self.get_host_and_port(port)
4574
smart_server = server.SmartTCPServer(
4575
transport, host=host, port=port)
4576
note('listening on port: %s' % smart_server.port)
4579
def run(self, port=None, inet=False, directory=None, allow_writes=False):
4580
from bzrlib.transport import get_transport
4581
from bzrlib.transport.chroot import ChrootServer
4733
4582
if directory is None:
4734
4583
directory = os.getcwd()
4735
if protocol is None:
4736
protocol = transport_server_registry.get()
4737
host, port = self.get_host_and_port(port)
4738
4584
url = urlutils.local_path_to_url(directory)
4739
4585
if not allow_writes:
4740
4586
url = 'readonly+' + url
4741
transport = get_transport(url)
4742
protocol(transport, host, port, inet)
4587
chroot_server = ChrootServer(get_transport(url))
4588
chroot_server.setUp()
4589
t = get_transport(chroot_server.get_url())
4590
smart_server = self.get_smart_server(t, inet, port)
4591
self.run_smart_server(smart_server)
4745
4594
class cmd_join(Command):
4986
4835
help='Write merge directive to this file; '
4987
4836
'use - for stdout.',
4990
help='Refuse to send if there are uncommitted changes in'
4991
' the working tree, --no-strict disables the check.'),
4992
4838
Option('mail-to', help='Mail the request to this address.',
4996
4842
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')),
4843
RegistryOption.from_kwargs('format',
4844
'Use the specified output format.',
4845
**{'4': 'Bundle format 4, Merge Directive 2 (default)',
4846
'0.9': 'Bundle format 0.9, Merge Directive 1',})
5002
4849
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
5003
4850
no_patch=False, revision=None, remember=False, output=None,
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,
4851
format='4', mail_to=None, message=None, body=None, **kwargs):
4852
return self._run(submit_branch, revision, public_branch, remember,
4853
format, no_bundle, no_patch, output,
4854
kwargs.get('from', '.'), mail_to, message, body)
4856
def _run(self, submit_branch, revision, public_branch, remember, format,
4857
no_bundle, no_patch, output, from_, mail_to, message, body):
4858
from bzrlib.revision import NULL_REVISION
4859
branch = Branch.open_containing(from_)[0]
4861
outfile = cStringIO.StringIO()
4865
outfile = open(output, 'wb')
4866
# we may need to write data into branch's repository to calculate
4871
config = branch.get_config()
4873
mail_to = config.get_user_option('submit_to')
4874
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
if remember and submit_branch is None:
4881
raise errors.BzrCommandError(
4882
'--remember requires a branch to be specified.')
4883
stored_submit_branch = branch.get_submit_branch()
4884
remembered_submit_branch = None
4885
if submit_branch is None:
4886
submit_branch = stored_submit_branch
4887
remembered_submit_branch = "submit"
4889
if stored_submit_branch is None or remember:
4890
branch.set_submit_branch(submit_branch)
4891
if submit_branch is None:
4892
submit_branch = branch.get_parent()
4893
remembered_submit_branch = "parent"
4894
if submit_branch is None:
4895
raise errors.BzrCommandError('No submit branch known or'
4897
if remembered_submit_branch is not None:
4898
note('Using saved %s location "%s" to determine what '
4899
'changes to submit.', remembered_submit_branch,
4903
submit_config = Branch.open(submit_branch).get_config()
4904
mail_to = submit_config.get_user_option("child_submit_to")
4906
stored_public_branch = branch.get_public_branch()
4907
if public_branch is None:
4908
public_branch = stored_public_branch
4909
elif stored_public_branch is None or remember:
4910
branch.set_public_branch(public_branch)
4911
if no_bundle and public_branch is None:
4912
raise errors.BzrCommandError('No public branch specified or'
4914
base_revision_id = None
4916
if revision is not None:
4917
if len(revision) > 2:
4918
raise errors.BzrCommandError('bzr send takes '
4919
'at most two one revision identifiers')
4920
revision_id = revision[-1].as_revision_id(branch)
4921
if len(revision) == 2:
4922
base_revision_id = revision[0].as_revision_id(branch)
4923
if revision_id is None:
4924
revision_id = branch.last_revision()
4925
if revision_id == NULL_REVISION:
4926
raise errors.BzrCommandError('No revisions to submit.')
4928
directive = merge_directive.MergeDirective2.from_objects(
4929
branch.repository, revision_id, time.time(),
4930
osutils.local_time_offset(), submit_branch,
4931
public_branch=public_branch, include_patch=not no_patch,
4932
include_bundle=not no_bundle, message=message,
4933
base_revision_id=base_revision_id)
4934
elif format == '0.9':
4937
patch_type = 'bundle'
4939
raise errors.BzrCommandError('Format 0.9 does not'
4940
' permit bundle with no patch')
4946
directive = merge_directive.MergeDirective.from_objects(
4947
branch.repository, revision_id, time.time(),
4948
osutils.local_time_offset(), submit_branch,
4949
public_branch=public_branch, patch_type=patch_type,
4952
outfile.writelines(directive.to_lines())
4954
subject = '[MERGE] '
4955
if message is not None:
4958
revision = branch.repository.get_revision(revision_id)
4959
subject += revision.get_summary()
4960
basename = directive.get_disk_name(branch)
4961
mail_client.compose_merge_request(mail_to, subject,
5014
4970
class cmd_bundle_revisions(cmd_send):
5015
4972
"""Create a merge-directive for submitting changes.
5017
4974
A merge directive provides many things needed for requesting merges:
5075
5030
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
5076
5031
no_patch=False, revision=None, remember=False, output=None,
5077
format=None, strict=None, **kwargs):
5032
format='4', **kwargs):
5078
5033
if output is None:
5080
from bzrlib.send import send
5081
return send(submit_branch, revision, public_branch, remember,
5035
return self._run(submit_branch, revision, public_branch, remember,
5082
5036
format, no_bundle, no_patch, output,
5083
kwargs.get('from', '.'), None, None, None,
5084
self.outf, strict=strict)
5037
kwargs.get('from', '.'), None, None, None)
5087
5040
class cmd_tag(Command):
5188
5141
graph = branch.repository.get_graph()
5189
5142
rev1, rev2 = _get_revision_range(revision, branch, self.name())
5190
5143
revid1, revid2 = rev1.rev_id, rev2.rev_id
5191
5144
# only show revisions between revid1 and revid2 (inclusive)
5192
5145
tags = [(tag, revid) for tag, revid in tags if
5193
5146
graph.is_between(revid, revid1, revid2)]
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)
5151
elif sort == 'time':
5153
for tag, revid in tags:
5155
revobj = branch.repository.get_revision(revid)
5156
except errors.NoSuchRevision:
5157
timestamp = sys.maxint # place them at the end
5159
timestamp = revobj.timestamp
5160
timestamps[revid] = timestamp
5161
tags.sort(key=lambda x: timestamps[x[1]])
5163
# [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
5164
revno_map = branch.get_revision_id_to_revno_map()
5165
tags = [ (tag, '.'.join(map(str, revno_map.get(revid, ('?',)))))
5166
for tag, revid in tags ]
5221
5167
for tag, revspec in tags:
5222
5168
self.outf.write('%-20s %s\n' % (tag, revspec))
5260
5206
Option('bind-to', help='Branch to bind checkout to.', type=str),
5261
5207
Option('force',
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.',
5208
help='Perform reconfiguration even if local changes'
5274
def run(self, location=None, target_type=None, bind_to=None, force=False,
5212
def run(self, location=None, target_type=None, bind_to=None, force=False):
5277
5213
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
5287
5214
if target_type is None:
5288
if stacked_on or unstacked:
5291
raise errors.BzrCommandError('No target configuration '
5215
raise errors.BzrCommandError('No target configuration specified')
5293
5216
elif target_type == 'branch':
5294
5217
reconfiguration = reconfigure.Reconfigure.to_branch(directory)
5295
5218
elif target_type == 'tree':
5339
5262
takes_args = ['to_location']
5340
5263
takes_options = [Option('force',
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.'),
5264
help='Switch even if local commits will be lost.')
5347
def run(self, to_location, force=False, create_branch=False):
5267
def run(self, to_location, force=False):
5348
5268
from bzrlib import switch
5349
5269
tree_location = '.'
5350
5270
control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5271
branch = control_dir.open_branch()
5352
branch = control_dir.open_branch()
5353
had_explicit_nick = branch.get_config().has_explicit_nickname()
5273
to_branch = Branch.open(to_location)
5354
5274
except errors.NotBranchError:
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))
5275
this_branch = control_dir.open_branch()
5276
# This may be a heavy checkout, where we want the master branch
5277
this_url = this_branch.get_bound_location()
5278
# If not, use a local sibling
5279
if this_url is None:
5280
this_url = this_branch.base
5281
to_branch = Branch.open(
5282
urlutils.join(this_url, '..', to_location))
5382
5283
switch.switch(control_dir, to_branch, force)
5383
if had_explicit_nick:
5284
if branch.get_config().has_explicit_nickname():
5384
5285
branch = control_dir.open_branch() #get the new branch!
5385
5286
branch.nick = to_branch.nick
5386
5287
note('Switched to branch: %s',
5387
5288
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
5407
5291
class cmd_view(Command):
5408
5292
"""Manage filtered views.