80
81
def tree_files_for_add(file_list):
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
"""Add handles files a bit differently so it a custom implementation."""
92
tree, relpath = WorkingTree.open_containing(file_list[0])
84
tree = WorkingTree.open_containing(file_list[0])[0]
93
85
if tree.supports_views():
94
86
view_files = tree.views.lookup_view()
96
88
for filename in file_list:
97
89
if not osutils.is_inside_any(view_files, filename):
98
90
raise errors.FileOutsideView(filename, view_files)
99
file_list = file_list[:]
100
file_list[0] = tree.abspath(relpath)
102
92
tree = WorkingTree.open_containing(u'.')[0]
103
93
if tree.supports_views():
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]))
489
def run(self, revision=None, directory=u'.', revision_info_list=[]):
492
if revision is not None:
493
revs.extend(revision)
494
if revision_info_list is not None:
495
for rev in revision_info_list:
496
revs.append(RevisionSpec.from_string(rev))
498
b = Branch.open_containing(directory)[0]
501
revs.append(RevisionSpec.from_string('-1'))
504
revision_id = rev.as_revision_id(b)
506
revno = '%4d' % (b.revision_id_to_revno(revision_id))
507
except errors.NoSuchRevision:
508
dotted_map = b.get_revision_id_to_revno_map()
509
revno = '.'.join(str(i) for i in dotted_map[revision_id])
510
print '%s %s' % (revno, revision_id)
573
513
class cmd_add(Command):
990
926
if branch_to.get_parent() is None or remember:
991
927
branch_to.set_parent(branch_from.base)
993
if branch_from is not branch_to:
994
branch_from.lock_read()
929
if revision is not None:
930
revision_id = revision.as_revision_id(branch_from)
932
branch_to.lock_write()
996
if revision is not None:
997
revision_id = revision.as_revision_id(branch_from)
999
branch_to.lock_write()
1001
if tree_to is not None:
1002
view_info = _get_view_info_for_change_reporter(tree_to)
1003
change_reporter = delta._ChangeReporter(
1004
unversioned_filter=tree_to.is_ignored,
1005
view_info=view_info)
1006
result = tree_to.pull(
1007
branch_from, overwrite, revision_id, change_reporter,
1008
possible_transports=possible_transports, local=local)
1010
result = branch_to.pull(
1011
branch_from, overwrite, revision_id, local=local)
1013
result.report(self.outf)
1014
if verbose and result.old_revid != result.new_revid:
1015
log.show_branch_change(
1016
branch_to, self.outf, result.old_revno,
934
if tree_to is not None:
935
view_info = _get_view_info_for_change_reporter(tree_to)
936
change_reporter = delta._ChangeReporter(
937
unversioned_filter=tree_to.is_ignored, view_info=view_info)
938
result = tree_to.pull(branch_from, overwrite, revision_id,
940
possible_transports=possible_transports)
942
result = branch_to.pull(branch_from, overwrite, revision_id)
944
result.report(self.outf)
945
if verbose and result.old_revid != result.new_revid:
946
log.show_branch_change(branch_to, self.outf, result.old_revno,
1021
if branch_from is not branch_to:
1022
branch_from.unlock()
1025
952
class cmd_push(Command):
1082
1006
def run(self, location=None, remember=False, overwrite=False,
1083
1007
create_prefix=False, verbose=False, revision=None,
1084
1008
use_existing_dir=False, directory=None, stacked_on=None,
1085
stacked=False, strict=None):
1086
1010
from bzrlib.push import _show_push_branch
1012
# Get the source branch and revision_id
1088
1013
if directory is None:
1089
1014
directory = '.'
1090
# Get the source branch
1092
_unused) = bzrdir.BzrDir.open_containing_tree_or_branch(directory)
1094
strict = br_from.get_config().get_user_option_as_bool('push_strict')
1095
if strict is None: strict = True # default value
1096
# Get the tip's revision_id
1015
br_from = Branch.open_containing(directory)[0]
1097
1016
revision = _get_one_revision('push', revision)
1098
1017
if revision is not None:
1099
1018
revision_id = revision.in_history(br_from).rev_id
1102
if strict and tree is not None and revision_id is None:
1103
if (tree.has_changes(tree.basis_tree())
1104
or len(tree.get_parent_ids()) > 1):
1105
raise errors.UncommittedChanges(
1106
tree, more='Use --no-strict to force the push.')
1107
if tree.last_revision() != tree.branch.last_revision():
1108
# The tree has lost sync with its branch, there is little
1109
# chance that the user is aware of it but he can still force
1110
# the push with --no-strict
1111
raise errors.OutOfDateTree(
1112
tree, more='Use --no-strict to force the push.')
1020
revision_id = br_from.last_revision()
1114
1022
# Get the stacked_on branch, if any
1115
1023
if stacked_on is not None:
1173
1081
'branch for all operations.'),
1174
1082
Option('standalone',
1175
1083
help='Do not use a shared repository, even if available.'),
1176
Option('use-existing-dir',
1177
help='By default branch will fail if the target'
1178
' directory exists, but does not already'
1179
' have a control directory. This flag will'
1180
' allow branch to proceed.'),
1182
1085
aliases = ['get', 'clone']
1184
1087
def run(self, from_location, to_location=None, revision=None,
1185
hardlink=False, stacked=False, standalone=False, no_tree=False,
1186
use_existing_dir=False):
1088
hardlink=False, stacked=False, standalone=False, no_tree=False):
1187
1089
from bzrlib.tag import _merge_tags_if_possible
1189
1091
accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
1191
if (accelerator_tree is not None and
1192
accelerator_tree.supports_content_filtering()):
1193
accelerator_tree = None
1194
1093
revision = _get_one_revision('branch', revision)
1195
1094
br_from.lock_read()
2483
2361
tree.lock_read()
2485
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False,
2486
from_dir=relpath, recursive=recursive):
2487
# Apply additional masking
2488
if not all and not selection[fc]:
2490
if kind is not None and fkind != kind:
2495
fullpath = osutils.pathjoin(relpath, fp)
2498
views.check_path_in_view(tree, fullpath)
2499
except errors.FileOutsideView:
2504
fp = osutils.pathjoin(prefix, fp)
2505
kindch = entry.kind_character()
2506
outstring = fp + kindch
2507
ui.ui_factory.clear_term()
2509
outstring = '%-8s %s' % (fc, outstring)
2510
if show_ids and fid is not None:
2511
outstring = "%-50s %s" % (outstring, fid)
2512
self.outf.write(outstring + '\n')
2514
self.outf.write(fp + '\0')
2517
self.outf.write(fid)
2518
self.outf.write('\0')
2363
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False):
2364
if fp.startswith(relpath):
2365
rp = fp[len(relpath):]
2366
fp = osutils.pathjoin(prefix, rp)
2367
if not recursive and '/' in rp:
2369
if not all and not selection[fc]:
2371
if kind is not None and fkind != kind:
2375
views.check_path_in_view(tree, fp)
2376
except errors.FileOutsideView:
2378
kindch = entry.kind_character()
2379
outstring = fp + kindch
2381
outstring = '%-8s %s' % (fc, outstring)
2382
if show_ids and fid is not None:
2383
outstring = "%-50s %s" % (outstring, fid)
2384
self.outf.write(outstring + '\n')
2386
self.outf.write(fp + '\0')
2389
self.outf.write(fid)
2390
self.outf.write('\0')
2522
2393
if fid is not None:
2526
self.outf.write('%-50s %s\n' % (outstring, my_id))
2528
self.outf.write(outstring + '\n')
2398
self.outf.write('%-50s %s\n' % (outstring, my_id))
2400
self.outf.write(outstring + '\n')
2824
2696
class cmd_commit(Command):
2825
2697
"""Commit changes into a new revision.
2827
An explanatory message needs to be given for each commit. This is
2828
often done by using the --message option (getting the message from the
2829
command line) or by using the --file option (getting the message from
2830
a file). If neither of these options is given, an editor is opened for
2831
the user to enter the message. To see the changed files in the
2832
boilerplate text loaded into the editor, use the --show-diff option.
2834
By default, the entire tree is committed and the person doing the
2835
commit is assumed to be the author. These defaults can be overridden
2840
If selected files are specified, only changes to those files are
2841
committed. If a directory is specified then the directory and
2842
everything within it is committed.
2844
When excludes are given, they take precedence over selected files.
2845
For example, to commit only changes within foo, but not changes
2848
bzr commit foo -x foo/bar
2850
A selective commit after a merge is not yet supported.
2854
If the author of the change is not the same person as the committer,
2855
you can specify the author's name using the --author option. The
2856
name should be in the same format as a committer-id, e.g.
2857
"John Doe <jdoe@example.com>". If there is more than one author of
2858
the change you can specify the option multiple times, once for each
2863
A common mistake is to forget to add a new file or directory before
2864
running the commit command. The --strict option checks for unknown
2865
files and aborts the commit if any are found. More advanced pre-commit
2866
checks can be implemented by defining hooks. See ``bzr help hooks``
2871
If you accidentially commit the wrong changes or make a spelling
2872
mistake in the commit message say, you can use the uncommit command
2873
to undo it. See ``bzr help uncommit`` for details.
2875
Hooks can also be configured to run after a commit. This allows you
2876
to trigger updates to external systems like bug trackers. The --fixes
2877
option can be used to record the association between a revision and
2878
one or more bugs. See ``bzr help bugs`` for details.
2880
A selective commit may fail in some cases where the committed
2881
tree would be invalid. Consider::
2886
bzr commit foo -m "committing foo"
2887
bzr mv foo/bar foo/baz
2890
bzr commit foo/bar -m "committing bar but not baz"
2892
In the example above, the last commit will fail by design. This gives
2893
the user the opportunity to decide whether they want to commit the
2894
rename at the same time, separately first, or not at all. (As a general
2895
rule, when in doubt, Bazaar has a policy of Doing the Safe Thing.)
2699
If no arguments are given, the entire tree is committed.
2701
If selected files are specified, only changes to those files are
2702
committed. If a directory is specified then the directory and everything
2703
within it is committed.
2705
When excludes are given, they take precedence over selected files.
2706
For example, too commit only changes within foo, but not changes within
2709
bzr commit foo -x foo/bar
2711
If author of the change is not the same person as the committer, you can
2712
specify the author's name using the --author option. The name should be
2713
in the same format as a committer-id, e.g. "John Doe <jdoe@example.com>".
2714
If there is more than one author of the change you can specify the option
2715
multiple times, once for each author.
2717
A selected-file commit may fail in some cases where the committed
2718
tree would be invalid. Consider::
2723
bzr commit foo -m "committing foo"
2724
bzr mv foo/bar foo/baz
2727
bzr commit foo/bar -m "committing bar but not baz"
2729
In the example above, the last commit will fail by design. This gives
2730
the user the opportunity to decide whether they want to commit the
2731
rename at the same time, separately first, or not at all. (As a general
2732
rule, when in doubt, Bazaar has a policy of Doing the Safe Thing.)
2734
Note: A selected-file commit after a merge is not yet supported.
2897
2736
# TODO: Run hooks on tree to-be-committed, and after commit.
3055
2894
The working tree and branch checks will only give output if a problem is
3056
2895
detected. The output fields of the repository check are:
3059
This is just the number of revisions checked. It doesn't
3063
This is just the number of versionedfiles checked. It
3064
doesn't indicate a problem.
3066
unreferenced ancestors
3067
Texts that are ancestors of other texts, but
3068
are not properly referenced by the revision ancestry. This is a
3069
subtle problem that Bazaar can work around.
3072
This is the total number of unique file contents
3073
seen in the checked revisions. It does not indicate a problem.
3076
This is the total number of repeated texts seen
3077
in the checked revisions. Texts can be repeated when their file
3078
entries are modified, but the file contents are not. It does not
2897
revisions: This is just the number of revisions checked. It doesn't
2899
versionedfiles: This is just the number of versionedfiles checked. It
2900
doesn't indicate a problem.
2901
unreferenced ancestors: Texts that are ancestors of other texts, but
2902
are not properly referenced by the revision ancestry. This is a
2903
subtle problem that Bazaar can work around.
2904
unique file texts: This is the total number of unique file contents
2905
seen in the checked revisions. It does not indicate a problem.
2906
repeated file texts: This is the total number of repeated texts seen
2907
in the checked revisions. Texts can be repeated when their file
2908
entries are modified, but the file contents are not. It does not
3081
2911
If no restrictions are specified, all Bazaar data that is found at the given
3082
2912
location will be checked.
3703
3529
for cleanup in reversed(cleanups):
3706
def _get_preview(self, merger, cleanups):
3532
def _do_preview(self, merger):
3533
from bzrlib.diff import show_diff_trees
3707
3534
tree_merger = merger.make_merger()
3708
3535
tt = tree_merger.make_preview_transform()
3709
cleanups.append(tt.finalize)
3710
result_tree = tt.get_preview_tree()
3713
def _do_preview(self, merger, cleanups):
3714
from bzrlib.diff import show_diff_trees
3715
result_tree = self._get_preview(merger, cleanups)
3716
show_diff_trees(merger.this_tree, result_tree, self.outf,
3717
old_label='', new_label='')
3537
result_tree = tt.get_preview_tree()
3538
show_diff_trees(merger.this_tree, result_tree, self.outf,
3539
old_label='', new_label='')
3719
3543
def _do_merge(self, merger, change_reporter, allow_pending, verified):
3720
3544
merger.change_reporter = change_reporter
4495
def run_smart_server(self, smart_server):
4496
"""Run 'smart_server' forever, with no UI output at all."""
4497
# For the duration of this server, no UI output is permitted. note
4498
# that this may cause problems with blackbox tests. This should be
4499
# changed with care though, as we dont want to use bandwidth sending
4500
# progress over stderr to smart server clients!
4501
from bzrlib import lockdir
4502
old_factory = ui.ui_factory
4503
old_lockdir_timeout = lockdir._DEFAULT_TIMEOUT_SECONDS
4505
ui.ui_factory = ui.SilentUIFactory()
4506
lockdir._DEFAULT_TIMEOUT_SECONDS = 0
4507
smart_server.serve()
4509
ui.ui_factory = old_factory
4510
lockdir._DEFAULT_TIMEOUT_SECONDS = old_lockdir_timeout
4706
4512
def get_host_and_port(self, port):
4707
4513
"""Return the host and port to run the smart server on.
4709
If 'port' is None, None will be returned for the host and port.
4515
If 'port' is None, the default host (`medium.BZR_DEFAULT_INTERFACE`)
4516
and port (`medium.BZR_DEFAULT_PORT`) will be used.
4711
4518
If 'port' has a colon in it, the string before the colon will be
4712
4519
interpreted as the host.
4715
4522
:return: A tuple of (host, port), where 'host' is a host name or IP,
4716
4523
and port is an integer TCP/IP port.
4719
if port is not None:
4525
from bzrlib.smart import medium
4526
host = medium.BZR_DEFAULT_INTERFACE
4528
port = medium.BZR_DEFAULT_PORT
4720
4530
if ':' in port:
4721
4531
host, port = port.split(':')
4722
4532
port = int(port)
4723
4533
return host, port
4725
def run(self, port=None, inet=False, directory=None, allow_writes=False,
4727
from bzrlib.transport import get_transport, transport_server_registry
4535
def get_smart_server(self, transport, inet, port):
4536
"""Construct a smart server.
4538
:param transport: The base transport from which branches will be
4540
:param inet: If True, serve over stdin and stdout. Used for running
4542
:param port: The port to listen on. By default, it's `
4543
medium.BZR_DEFAULT_PORT`. See `get_host_and_port` for more
4545
:return: A smart server.
4547
from bzrlib.smart import medium, server
4549
smart_server = medium.SmartServerPipeStreamMedium(
4550
sys.stdin, sys.stdout, transport)
4552
host, port = self.get_host_and_port(port)
4553
smart_server = server.SmartTCPServer(
4554
transport, host=host, port=port)
4555
note('listening on port: %s' % smart_server.port)
4558
def run(self, port=None, inet=False, directory=None, allow_writes=False):
4559
from bzrlib.transport import get_transport
4560
from bzrlib.transport.chroot import ChrootServer
4728
4561
if directory is None:
4729
4562
directory = os.getcwd()
4730
if protocol is None:
4731
protocol = transport_server_registry.get()
4732
host, port = self.get_host_and_port(port)
4733
4563
url = urlutils.local_path_to_url(directory)
4734
4564
if not allow_writes:
4735
4565
url = 'readonly+' + url
4736
transport = get_transport(url)
4737
protocol(transport, host, port, inet)
4566
chroot_server = ChrootServer(get_transport(url))
4567
chroot_server.setUp()
4568
t = get_transport(chroot_server.get_url())
4569
smart_server = self.get_smart_server(t, inet, port)
4570
self.run_smart_server(smart_server)
4740
4573
class cmd_join(Command):
4981
4814
help='Write merge directive to this file; '
4982
4815
'use - for stdout.',
4985
help='Refuse to send if there are uncommitted changes in'
4986
' the working tree, --no-strict disables the check.'),
4987
4817
Option('mail-to', help='Mail the request to this address.',
4991
4821
Option('body', help='Body for the email.', type=unicode),
4992
RegistryOption('format',
4993
help='Use the specified output format.',
4994
lazy_registry=('bzrlib.send', 'format_registry')),
4822
RegistryOption.from_kwargs('format',
4823
'Use the specified output format.',
4824
**{'4': 'Bundle format 4, Merge Directive 2 (default)',
4825
'0.9': 'Bundle format 0.9, Merge Directive 1',})
4997
4828
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
4998
4829
no_patch=False, revision=None, remember=False, output=None,
4999
format=None, mail_to=None, message=None, body=None,
5000
strict=None, **kwargs):
5001
from bzrlib.send import send
5002
return send(submit_branch, revision, public_branch, remember,
5003
format, no_bundle, no_patch, output,
5004
kwargs.get('from', '.'), mail_to, message, body,
4830
format='4', mail_to=None, message=None, body=None, **kwargs):
4831
return self._run(submit_branch, revision, public_branch, remember,
4832
format, no_bundle, no_patch, output,
4833
kwargs.get('from', '.'), mail_to, message, body)
4835
def _run(self, submit_branch, revision, public_branch, remember, format,
4836
no_bundle, no_patch, output, from_, mail_to, message, body):
4837
from bzrlib.revision import NULL_REVISION
4838
branch = Branch.open_containing(from_)[0]
4840
outfile = cStringIO.StringIO()
4844
outfile = open(output, 'wb')
4845
# we may need to write data into branch's repository to calculate
4850
config = branch.get_config()
4852
mail_to = config.get_user_option('submit_to')
4853
mail_client = config.get_mail_client()
4854
if (not getattr(mail_client, 'supports_body', False)
4855
and body is not None):
4856
raise errors.BzrCommandError(
4857
'Mail client "%s" does not support specifying body' %
4858
mail_client.__class__.__name__)
4859
if remember and submit_branch is None:
4860
raise errors.BzrCommandError(
4861
'--remember requires a branch to be specified.')
4862
stored_submit_branch = branch.get_submit_branch()
4863
remembered_submit_branch = None
4864
if submit_branch is None:
4865
submit_branch = stored_submit_branch
4866
remembered_submit_branch = "submit"
4868
if stored_submit_branch is None or remember:
4869
branch.set_submit_branch(submit_branch)
4870
if submit_branch is None:
4871
submit_branch = branch.get_parent()
4872
remembered_submit_branch = "parent"
4873
if submit_branch is None:
4874
raise errors.BzrCommandError('No submit branch known or'
4876
if remembered_submit_branch is not None:
4877
note('Using saved %s location "%s" to determine what '
4878
'changes to submit.', remembered_submit_branch,
4882
submit_config = Branch.open(submit_branch).get_config()
4883
mail_to = submit_config.get_user_option("child_submit_to")
4885
stored_public_branch = branch.get_public_branch()
4886
if public_branch is None:
4887
public_branch = stored_public_branch
4888
elif stored_public_branch is None or remember:
4889
branch.set_public_branch(public_branch)
4890
if no_bundle and public_branch is None:
4891
raise errors.BzrCommandError('No public branch specified or'
4893
base_revision_id = None
4895
if revision is not None:
4896
if len(revision) > 2:
4897
raise errors.BzrCommandError('bzr send takes '
4898
'at most two one revision identifiers')
4899
revision_id = revision[-1].as_revision_id(branch)
4900
if len(revision) == 2:
4901
base_revision_id = revision[0].as_revision_id(branch)
4902
if revision_id is None:
4903
revision_id = branch.last_revision()
4904
if revision_id == NULL_REVISION:
4905
raise errors.BzrCommandError('No revisions to submit.')
4907
directive = merge_directive.MergeDirective2.from_objects(
4908
branch.repository, revision_id, time.time(),
4909
osutils.local_time_offset(), submit_branch,
4910
public_branch=public_branch, include_patch=not no_patch,
4911
include_bundle=not no_bundle, message=message,
4912
base_revision_id=base_revision_id)
4913
elif format == '0.9':
4916
patch_type = 'bundle'
4918
raise errors.BzrCommandError('Format 0.9 does not'
4919
' permit bundle with no patch')
4925
directive = merge_directive.MergeDirective.from_objects(
4926
branch.repository, revision_id, time.time(),
4927
osutils.local_time_offset(), submit_branch,
4928
public_branch=public_branch, patch_type=patch_type,
4931
outfile.writelines(directive.to_lines())
4933
subject = '[MERGE] '
4934
if message is not None:
4937
revision = branch.repository.get_revision(revision_id)
4938
subject += revision.get_summary()
4939
basename = directive.get_disk_name(branch)
4940
mail_client.compose_merge_request(mail_to, subject,
5009
4949
class cmd_bundle_revisions(cmd_send):
5010
4951
"""Create a merge-directive for submitting changes.
5012
4953
A merge directive provides many things needed for requesting merges:
5070
5009
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
5071
5010
no_patch=False, revision=None, remember=False, output=None,
5072
format=None, strict=None, **kwargs):
5011
format='4', **kwargs):
5073
5012
if output is None:
5075
from bzrlib.send import send
5076
return send(submit_branch, revision, public_branch, remember,
5014
return self._run(submit_branch, revision, public_branch, remember,
5077
5015
format, no_bundle, no_patch, output,
5078
kwargs.get('from', '.'), None, None, None,
5079
self.outf, strict=strict)
5016
kwargs.get('from', '.'), None, None, None)
5082
5019
class cmd_tag(Command):
5183
5120
graph = branch.repository.get_graph()
5184
5121
rev1, rev2 = _get_revision_range(revision, branch, self.name())
5185
5122
revid1, revid2 = rev1.rev_id, rev2.rev_id
5186
5123
# only show revisions between revid1 and revid2 (inclusive)
5187
5124
tags = [(tag, revid) for tag, revid in tags if
5188
5125
graph.is_between(revid, revid1, revid2)]
5191
elif sort == 'time':
5193
for tag, revid in tags:
5195
revobj = branch.repository.get_revision(revid)
5196
except errors.NoSuchRevision:
5197
timestamp = sys.maxint # place them at the end
5199
timestamp = revobj.timestamp
5200
timestamps[revid] = timestamp
5201
tags.sort(key=lambda x: timestamps[x[1]])
5203
# [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
5204
for index, (tag, revid) in enumerate(tags):
5206
revno = branch.revision_id_to_dotted_revno(revid)
5207
if isinstance(revno, tuple):
5208
revno = '.'.join(map(str, revno))
5209
except errors.NoSuchRevision:
5210
# Bad tag data/merges can lead to tagged revisions
5211
# which are not in this branch. Fail gracefully ...
5213
tags[index] = (tag, revno)
5130
elif sort == 'time':
5132
for tag, revid in tags:
5134
revobj = branch.repository.get_revision(revid)
5135
except errors.NoSuchRevision:
5136
timestamp = sys.maxint # place them at the end
5138
timestamp = revobj.timestamp
5139
timestamps[revid] = timestamp
5140
tags.sort(key=lambda x: timestamps[x[1]])
5142
# [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
5143
revno_map = branch.get_revision_id_to_revno_map()
5144
tags = [ (tag, '.'.join(map(str, revno_map.get(revid, ('?',)))))
5145
for tag, revid in tags ]
5216
5146
for tag, revspec in tags:
5217
5147
self.outf.write('%-20s %s\n' % (tag, revspec))
5255
5185
Option('bind-to', help='Branch to bind checkout to.', type=str),
5256
5186
Option('force',
5257
help='Perform reconfiguration even if local changes'
5259
Option('stacked-on',
5260
help='Reconfigure a branch to be stacked on another branch.',
5264
help='Reconfigure a branch to be unstacked. This '
5265
'may require copying substantial data into it.',
5187
help='Perform reconfiguration even if local changes'
5269
def run(self, location=None, target_type=None, bind_to=None, force=False,
5191
def run(self, location=None, target_type=None, bind_to=None, force=False):
5272
5192
directory = bzrdir.BzrDir.open(location)
5273
if stacked_on and unstacked:
5274
raise BzrCommandError("Can't use both --stacked-on and --unstacked")
5275
elif stacked_on is not None:
5276
reconfigure.ReconfigureStackedOn().apply(directory, stacked_on)
5278
reconfigure.ReconfigureUnstacked().apply(directory)
5279
# At the moment you can use --stacked-on and a different
5280
# reconfiguration shape at the same time; there seems no good reason
5282
5193
if target_type is None:
5283
if stacked_on or unstacked:
5286
raise errors.BzrCommandError('No target configuration '
5194
raise errors.BzrCommandError('No target configuration specified')
5288
5195
elif target_type == 'branch':
5289
5196
reconfiguration = reconfigure.Reconfigure.to_branch(directory)
5290
5197
elif target_type == 'tree':
5334
5241
takes_args = ['to_location']
5335
5242
takes_options = [Option('force',
5336
help='Switch even if local commits will be lost.'),
5337
Option('create-branch', short_name='b',
5338
help='Create the target branch from this one before'
5339
' switching to it.'),
5243
help='Switch even if local commits will be lost.')
5342
def run(self, to_location, force=False, create_branch=False):
5246
def run(self, to_location, force=False):
5343
5247
from bzrlib import switch
5344
5248
tree_location = '.'
5345
5249
control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5250
branch = control_dir.open_branch()
5347
branch = control_dir.open_branch()
5348
had_explicit_nick = branch.get_config().has_explicit_nickname()
5252
to_branch = Branch.open(to_location)
5349
5253
except errors.NotBranchError:
5351
had_explicit_nick = False
5354
raise errors.BzrCommandError('cannot create branch without'
5356
if '/' not in to_location and '\\' not in to_location:
5357
# This path is meant to be relative to the existing branch
5358
this_url = self._get_branch_location(control_dir)
5359
to_location = urlutils.join(this_url, '..', to_location)
5360
to_branch = branch.bzrdir.sprout(to_location,
5361
possible_transports=[branch.bzrdir.root_transport],
5362
source_branch=branch).open_branch()
5364
# from_branch = control_dir.open_branch()
5365
# except errors.NotBranchError:
5366
# raise BzrCommandError('Cannot create a branch from this'
5367
# ' location when we cannot open this branch')
5368
# from_branch.bzrdir.sprout(
5372
to_branch = Branch.open(to_location)
5373
except errors.NotBranchError:
5374
this_url = self._get_branch_location(control_dir)
5375
to_branch = Branch.open(
5376
urlutils.join(this_url, '..', to_location))
5254
this_branch = control_dir.open_branch()
5255
# This may be a heavy checkout, where we want the master branch
5256
this_url = this_branch.get_bound_location()
5257
# If not, use a local sibling
5258
if this_url is None:
5259
this_url = this_branch.base
5260
to_branch = Branch.open(
5261
urlutils.join(this_url, '..', to_location))
5377
5262
switch.switch(control_dir, to_branch, force)
5378
if had_explicit_nick:
5263
if branch.get_config().has_explicit_nickname():
5379
5264
branch = control_dir.open_branch() #get the new branch!
5380
5265
branch.nick = to_branch.nick
5381
5266
note('Switched to branch: %s',
5382
5267
urlutils.unescape_for_display(to_branch.base, 'utf-8'))
5384
def _get_branch_location(self, control_dir):
5385
"""Return location of branch for this control dir."""
5387
this_branch = control_dir.open_branch()
5388
# This may be a heavy checkout, where we want the master branch
5389
master_location = this_branch.get_bound_location()
5390
if master_location is not None:
5391
return master_location
5392
# If not, use a local sibling
5393
return this_branch.base
5394
except errors.NotBranchError:
5395
format = control_dir.find_branch_format()
5396
if getattr(format, 'get_reference', None) is not None:
5397
return format.get_reference(control_dir)
5399
return control_dir.root_transport.base
5402
5270
class cmd_view(Command):
5403
5271
"""Manage filtered views.
5705
5573
dry_run=dry_run, no_prompt=force)
5708
class cmd_reference(Command):
5709
"""list, view and set branch locations for nested trees.
5711
If no arguments are provided, lists the branch locations for nested trees.
5712
If one argument is provided, display the branch location for that tree.
5713
If two arguments are provided, set the branch location for that tree.
5718
takes_args = ['path?', 'location?']
5720
def run(self, path=None, location=None):
5722
if path is not None:
5724
tree, branch, relpath =(
5725
bzrdir.BzrDir.open_containing_tree_or_branch(branchdir))
5726
if path is not None:
5729
tree = branch.basis_tree()
5731
info = branch._get_all_reference_info().iteritems()
5732
self._display_reference_info(tree, branch, info)
5576
def _create_prefix(cur_transport):
5577
needed = [cur_transport]
5578
# Recurse upwards until we can create a directory successfully
5580
new_transport = cur_transport.clone('..')
5581
if new_transport.base == cur_transport.base:
5582
raise errors.BzrCommandError(
5583
"Failed to create path prefix for %s."
5584
% cur_transport.base)
5586
new_transport.mkdir('.')
5587
except errors.NoSuchFile:
5588
needed.append(new_transport)
5589
cur_transport = new_transport
5734
file_id = tree.path2id(path)
5736
raise errors.NotVersionedError(path)
5737
if location is None:
5738
info = [(file_id, branch.get_reference_info(file_id))]
5739
self._display_reference_info(tree, branch, info)
5741
branch.set_reference_info(file_id, path, location)
5743
def _display_reference_info(self, tree, branch, info):
5745
for file_id, (path, location) in info:
5747
path = tree.id2path(file_id)
5748
except errors.NoSuchId:
5750
ref_list.append((path, location))
5751
for path, location in sorted(ref_list):
5752
self.outf.write('%s %s\n' % (path, location))
5592
# Now we only need to create child directories
5594
cur_transport = needed.pop()
5595
cur_transport.ensure_base()
5755
5598
# these get imported and then picked up by the scan for cmd_*