81
80
def tree_files_for_add(file_list):
82
"""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
84
tree = WorkingTree.open_containing(file_list[0])[0]
92
tree, relpath = WorkingTree.open_containing(file_list[0])
85
93
if tree.supports_views():
86
94
view_files = tree.views.lookup_view()
88
96
for filename in file_list:
89
97
if not osutils.is_inside_any(view_files, filename):
90
98
raise errors.FileOutsideView(filename, view_files)
99
file_list = file_list[:]
100
file_list[0] = tree.abspath(relpath)
92
102
tree = WorkingTree.open_containing(u'.')[0]
93
103
if tree.supports_views():
530
Option('tree', help='Show revno of working tree'),
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)
534
def run(self, revision=None, directory=u'.', tree=False,
535
revision_info_list=[]):
538
wt = WorkingTree.open_containing(directory)[0]
541
except (errors.NoWorkingTree, errors.NotLocalUrl):
543
b = Branch.open_containing(directory)[0]
547
if revision is not None:
548
revision_ids.extend(rev.as_revision_id(b) for rev in revision)
549
if revision_info_list is not None:
550
for rev_str in revision_info_list:
551
rev_spec = RevisionSpec.from_string(rev_str)
552
revision_ids.append(rev_spec.as_revision_id(b))
553
# No arguments supplied, default to the last revision
554
if len(revision_ids) == 0:
557
raise errors.NoWorkingTree(directory)
558
revision_ids.append(wt.last_revision())
560
revision_ids.append(b.last_revision())
564
for revision_id in revision_ids:
566
dotted_revno = b.revision_id_to_dotted_revno(revision_id)
567
revno = '.'.join(str(i) for i in dotted_revno)
568
except errors.NoSuchRevision:
570
maxlen = max(maxlen, len(revno))
571
revinfos.append([revno, revision_id])
579
self.outf.write('%*s %s\n' % (maxlen, ri[0], ri[1]))
513
582
class cmd_add(Command):
926
999
if branch_to.get_parent() is None or remember:
927
1000
branch_to.set_parent(branch_from.base)
929
if revision is not None:
930
revision_id = revision.as_revision_id(branch_from)
932
branch_to.lock_write()
1002
if branch_from is not branch_to:
1003
branch_from.lock_read()
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,
1005
if revision is not None:
1006
revision_id = revision.as_revision_id(branch_from)
1008
branch_to.lock_write()
1010
if tree_to is not None:
1011
view_info = _get_view_info_for_change_reporter(tree_to)
1012
change_reporter = delta._ChangeReporter(
1013
unversioned_filter=tree_to.is_ignored,
1014
view_info=view_info)
1015
result = tree_to.pull(
1016
branch_from, overwrite, revision_id, change_reporter,
1017
possible_transports=possible_transports, local=local)
1019
result = branch_to.pull(
1020
branch_from, overwrite, revision_id, local=local)
1022
result.report(self.outf)
1023
if verbose and result.old_revid != result.new_revid:
1024
log.show_branch_change(
1025
branch_to, self.outf, result.old_revno,
1030
if branch_from is not branch_to:
1031
branch_from.unlock()
952
1034
class cmd_push(Command):
1006
1091
def run(self, location=None, remember=False, overwrite=False,
1007
1092
create_prefix=False, verbose=False, revision=None,
1008
1093
use_existing_dir=False, directory=None, stacked_on=None,
1094
stacked=False, strict=None):
1010
1095
from bzrlib.push import _show_push_branch
1012
# Get the source branch and revision_id
1013
1097
if directory is None:
1014
1098
directory = '.'
1015
br_from = Branch.open_containing(directory)[0]
1099
# Get the source branch
1101
_unused) = bzrdir.BzrDir.open_containing_tree_or_branch(directory)
1103
strict = br_from.get_config().get_user_option_as_bool('push_strict')
1104
if strict is None: strict = True # default value
1105
# Get the tip's revision_id
1016
1106
revision = _get_one_revision('push', revision)
1017
1107
if revision is not None:
1018
1108
revision_id = revision.in_history(br_from).rev_id
1020
revision_id = br_from.last_revision()
1111
if strict and tree is not None and revision_id is None:
1112
if (tree.has_changes(tree.basis_tree())
1113
or len(tree.get_parent_ids()) > 1):
1114
raise errors.UncommittedChanges(
1115
tree, more='Use --no-strict to force the push.')
1116
if tree.last_revision() != tree.branch.last_revision():
1117
# The tree has lost sync with its branch, there is little
1118
# chance that the user is aware of it but he can still force
1119
# the push with --no-strict
1120
raise errors.OutOfDateTree(
1121
tree, more='Use --no-strict to force the push.')
1022
1123
# Get the stacked_on branch, if any
1023
1124
if stacked_on is not None:
1075
1176
help='Hard-link working tree files where possible.'),
1076
1177
Option('no-tree',
1077
1178
help="Create a branch without a working-tree."),
1180
help="Switch the checkout in the current directory "
1181
"to the new branch."),
1078
1182
Option('stacked',
1079
1183
help='Create a stacked branch referring to the source branch. '
1080
1184
'The new branch will depend on the availability of the source '
1081
1185
'branch for all operations.'),
1082
1186
Option('standalone',
1083
1187
help='Do not use a shared repository, even if available.'),
1188
Option('use-existing-dir',
1189
help='By default branch will fail if the target'
1190
' directory exists, but does not already'
1191
' have a control directory. This flag will'
1192
' allow branch to proceed.'),
1085
1194
aliases = ['get', 'clone']
1087
1196
def run(self, from_location, to_location=None, revision=None,
1088
hardlink=False, stacked=False, standalone=False, no_tree=False):
1197
hardlink=False, stacked=False, standalone=False, no_tree=False,
1198
use_existing_dir=False, switch=False):
1199
from bzrlib import switch as _mod_switch
1089
1200
from bzrlib.tag import _merge_tags_if_possible
1091
1201
accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
1203
if (accelerator_tree is not None and
1204
accelerator_tree.supports_content_filtering()):
1205
accelerator_tree = None
1093
1206
revision = _get_one_revision('branch', revision)
1094
1207
br_from.lock_read()
2149
2276
filter_by_dir = False
2151
# find the file ids to log and check for directory filtering
2152
b, file_info_list, rev1, rev2 = _get_info_for_log_files(revision,
2154
for relpath, file_id, kind in file_info_list:
2156
raise errors.BzrCommandError(
2157
"Path unknown at end or start of revision range: %s" %
2159
# If the relpath is the top of the tree, we log everything
2280
# find the file ids to log and check for directory filtering
2281
b, file_info_list, rev1, rev2 = _get_info_for_log_files(
2282
revision, file_list)
2283
for relpath, file_id, kind in file_info_list:
2285
raise errors.BzrCommandError(
2286
"Path unknown at end or start of revision range: %s" %
2288
# If the relpath is the top of the tree, we log everything
2293
file_ids.append(file_id)
2294
filter_by_dir = filter_by_dir or (
2295
kind in ['directory', 'tree-reference'])
2298
# FIXME ? log the current subdir only RBC 20060203
2299
if revision is not None \
2300
and len(revision) > 0 and revision[0].get_branch():
2301
location = revision[0].get_branch()
2164
file_ids.append(file_id)
2165
filter_by_dir = filter_by_dir or (
2166
kind in ['directory', 'tree-reference'])
2169
# FIXME ? log the current subdir only RBC 20060203
2170
if revision is not None \
2171
and len(revision) > 0 and revision[0].get_branch():
2172
location = revision[0].get_branch()
2175
dir, relpath = bzrdir.BzrDir.open_containing(location)
2176
b = dir.open_branch()
2177
rev1, rev2 = _get_revision_range(revision, b, self.name())
2179
# Decide on the type of delta & diff filtering to use
2180
# TODO: add an --all-files option to make this configurable & consistent
2188
diff_type = 'partial'
2304
dir, relpath = bzrdir.BzrDir.open_containing(location)
2305
b = dir.open_branch()
2307
rev1, rev2 = _get_revision_range(revision, b, self.name())
2309
# Decide on the type of delta & diff filtering to use
2310
# TODO: add an --all-files option to make this configurable & consistent
2318
diff_type = 'partial'
2194
2322
# Build the log formatter
2195
2323
if log_format is None:
2196
2324
log_format = log.log_formatter_registry.get_default(b)
2371
2508
tree.lock_read()
2373
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False):
2374
if fp.startswith(relpath):
2375
rp = fp[len(relpath):]
2376
fp = osutils.pathjoin(prefix, rp)
2377
if not recursive and '/' in rp:
2379
if not all and not selection[fc]:
2381
if kind is not None and fkind != kind:
2385
views.check_path_in_view(tree, fp)
2386
except errors.FileOutsideView:
2388
kindch = entry.kind_character()
2389
outstring = fp + kindch
2391
outstring = '%-8s %s' % (fc, outstring)
2392
if show_ids and fid is not None:
2393
outstring = "%-50s %s" % (outstring, fid)
2394
self.outf.write(outstring + '\n')
2396
self.outf.write(fp + '\0')
2399
self.outf.write(fid)
2400
self.outf.write('\0')
2510
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False,
2511
from_dir=relpath, recursive=recursive):
2512
# Apply additional masking
2513
if not all and not selection[fc]:
2515
if kind is not None and fkind != kind:
2520
fullpath = osutils.pathjoin(relpath, fp)
2523
views.check_path_in_view(tree, fullpath)
2524
except errors.FileOutsideView:
2529
fp = osutils.pathjoin(prefix, fp)
2530
kindch = entry.kind_character()
2531
outstring = fp + kindch
2532
ui.ui_factory.clear_term()
2534
outstring = '%-8s %s' % (fc, outstring)
2535
if show_ids and fid is not None:
2536
outstring = "%-50s %s" % (outstring, fid)
2537
self.outf.write(outstring + '\n')
2539
self.outf.write(fp + '\0')
2542
self.outf.write(fid)
2543
self.outf.write('\0')
2403
2547
if fid is not None:
2408
self.outf.write('%-50s %s\n' % (outstring, my_id))
2410
self.outf.write(outstring + '\n')
2551
self.outf.write('%-50s %s\n' % (outstring, my_id))
2553
self.outf.write(outstring + '\n')
2706
2849
class cmd_commit(Command):
2707
2850
"""Commit changes into a new revision.
2709
If no arguments are given, the entire tree is committed.
2711
If selected files are specified, only changes to those files are
2712
committed. If a directory is specified then the directory and everything
2713
within it is committed.
2715
When excludes are given, they take precedence over selected files.
2716
For example, too commit only changes within foo, but not changes within
2719
bzr commit foo -x foo/bar
2721
If author of the change is not the same person as the committer, you can
2722
specify the author's name using the --author option. The name should be
2723
in the same format as a committer-id, e.g. "John Doe <jdoe@example.com>".
2724
If there is more than one author of the change you can specify the option
2725
multiple times, once for each author.
2727
A selected-file commit may fail in some cases where the committed
2728
tree would be invalid. Consider::
2733
bzr commit foo -m "committing foo"
2734
bzr mv foo/bar foo/baz
2737
bzr commit foo/bar -m "committing bar but not baz"
2739
In the example above, the last commit will fail by design. This gives
2740
the user the opportunity to decide whether they want to commit the
2741
rename at the same time, separately first, or not at all. (As a general
2742
rule, when in doubt, Bazaar has a policy of Doing the Safe Thing.)
2744
Note: A selected-file commit after a merge is not yet supported.
2852
An explanatory message needs to be given for each commit. This is
2853
often done by using the --message option (getting the message from the
2854
command line) or by using the --file option (getting the message from
2855
a file). If neither of these options is given, an editor is opened for
2856
the user to enter the message. To see the changed files in the
2857
boilerplate text loaded into the editor, use the --show-diff option.
2859
By default, the entire tree is committed and the person doing the
2860
commit is assumed to be the author. These defaults can be overridden
2865
If selected files are specified, only changes to those files are
2866
committed. If a directory is specified then the directory and
2867
everything within it is committed.
2869
When excludes are given, they take precedence over selected files.
2870
For example, to commit only changes within foo, but not changes
2873
bzr commit foo -x foo/bar
2875
A selective commit after a merge is not yet supported.
2879
If the author of the change is not the same person as the committer,
2880
you can specify the author's name using the --author option. The
2881
name should be in the same format as a committer-id, e.g.
2882
"John Doe <jdoe@example.com>". If there is more than one author of
2883
the change you can specify the option multiple times, once for each
2888
A common mistake is to forget to add a new file or directory before
2889
running the commit command. The --strict option checks for unknown
2890
files and aborts the commit if any are found. More advanced pre-commit
2891
checks can be implemented by defining hooks. See ``bzr help hooks``
2896
If you accidentially commit the wrong changes or make a spelling
2897
mistake in the commit message say, you can use the uncommit command
2898
to undo it. See ``bzr help uncommit`` for details.
2900
Hooks can also be configured to run after a commit. This allows you
2901
to trigger updates to external systems like bug trackers. The --fixes
2902
option can be used to record the association between a revision and
2903
one or more bugs. See ``bzr help bugs`` for details.
2905
A selective commit may fail in some cases where the committed
2906
tree would be invalid. Consider::
2911
bzr commit foo -m "committing foo"
2912
bzr mv foo/bar foo/baz
2915
bzr commit foo/bar -m "committing bar but not baz"
2917
In the example above, the last commit will fail by design. This gives
2918
the user the opportunity to decide whether they want to commit the
2919
rename at the same time, separately first, or not at all. (As a general
2920
rule, when in doubt, Bazaar has a policy of Doing the Safe Thing.)
2746
2922
# TODO: Run hooks on tree to-be-committed, and after commit.
2904
3084
The working tree and branch checks will only give output if a problem is
2905
3085
detected. The output fields of the repository check are:
2907
revisions: This is just the number of revisions checked. It doesn't
2909
versionedfiles: This is just the number of versionedfiles checked. It
2910
doesn't indicate a problem.
2911
unreferenced ancestors: Texts that are ancestors of other texts, but
2912
are not properly referenced by the revision ancestry. This is a
2913
subtle problem that Bazaar can work around.
2914
unique file texts: This is the total number of unique file contents
2915
seen in the checked revisions. It does not indicate a problem.
2916
repeated file texts: This is the total number of repeated texts seen
2917
in the checked revisions. Texts can be repeated when their file
2918
entries are modified, but the file contents are not. It does not
3088
This is just the number of revisions checked. It doesn't
3092
This is just the number of versionedfiles checked. It
3093
doesn't indicate a problem.
3095
unreferenced ancestors
3096
Texts that are ancestors of other texts, but
3097
are not properly referenced by the revision ancestry. This is a
3098
subtle problem that Bazaar can work around.
3101
This is the total number of unique file contents
3102
seen in the checked revisions. It does not indicate a problem.
3105
This is the total number of repeated texts seen
3106
in the checked revisions. Texts can be repeated when their file
3107
entries are modified, but the file contents are not. It does not
2921
3110
If no restrictions are specified, all Bazaar data that is found at the given
2922
3111
location will be checked.
3539
3732
for cleanup in reversed(cleanups):
3542
def _do_preview(self, merger):
3543
from bzrlib.diff import show_diff_trees
3735
def _get_preview(self, merger, cleanups):
3544
3736
tree_merger = merger.make_merger()
3545
3737
tt = tree_merger.make_preview_transform()
3547
result_tree = tt.get_preview_tree()
3548
show_diff_trees(merger.this_tree, result_tree, self.outf,
3549
old_label='', new_label='')
3738
cleanups.append(tt.finalize)
3739
result_tree = tt.get_preview_tree()
3742
def _do_preview(self, merger, cleanups):
3743
from bzrlib.diff import show_diff_trees
3744
result_tree = self._get_preview(merger, cleanups)
3745
show_diff_trees(merger.this_tree, result_tree, self.outf,
3746
old_label='', new_label='')
3553
3748
def _do_merge(self, merger, change_reporter, allow_pending, verified):
3554
3749
merger.change_reporter = change_reporter
4183
4409
branch.lock_read()
4185
4411
tree = _get_one_revision_tree('annotate', revision, branch=branch)
4187
file_id = wt.path2id(relpath)
4189
file_id = tree.path2id(relpath)
4191
raise errors.NotVersionedError(filename)
4192
file_version = tree.inventory[file_id].revision
4193
if wt is not None and revision is None:
4194
# If there is a tree and we're not annotating historical
4195
# versions, annotate the working tree's content.
4196
annotate_file_tree(wt, file_id, self.outf, long, all,
4199
annotate_file(branch, file_version, file_id, long, all, self.outf,
4415
file_id = wt.path2id(relpath)
4417
file_id = tree.path2id(relpath)
4419
raise errors.NotVersionedError(filename)
4420
file_version = tree.inventory[file_id].revision
4421
if wt is not None and revision is None:
4422
# If there is a tree and we're not annotating historical
4423
# versions, annotate the working tree's content.
4424
annotate_file_tree(wt, file_id, self.outf, long, all,
4427
annotate_file(branch, file_version, file_id, long, all,
4428
self.outf, show_ids=show_ids)
4202
4432
if wt is not None:
4505
def run_smart_server(self, smart_server):
4506
"""Run 'smart_server' forever, with no UI output at all."""
4507
# For the duration of this server, no UI output is permitted. note
4508
# that this may cause problems with blackbox tests. This should be
4509
# changed with care though, as we dont want to use bandwidth sending
4510
# progress over stderr to smart server clients!
4511
from bzrlib import lockdir
4512
old_factory = ui.ui_factory
4513
old_lockdir_timeout = lockdir._DEFAULT_TIMEOUT_SECONDS
4515
ui.ui_factory = ui.SilentUIFactory()
4516
lockdir._DEFAULT_TIMEOUT_SECONDS = 0
4517
smart_server.serve()
4519
ui.ui_factory = old_factory
4520
lockdir._DEFAULT_TIMEOUT_SECONDS = old_lockdir_timeout
4522
4739
def get_host_and_port(self, port):
4523
4740
"""Return the host and port to run the smart server on.
4525
If 'port' is None, the default host (`medium.BZR_DEFAULT_INTERFACE`)
4526
and port (`medium.BZR_DEFAULT_PORT`) will be used.
4742
If 'port' is None, None will be returned for the host and port.
4528
4744
If 'port' has a colon in it, the string before the colon will be
4529
4745
interpreted as the host.
4532
4748
:return: A tuple of (host, port), where 'host' is a host name or IP,
4533
4749
and port is an integer TCP/IP port.
4535
from bzrlib.smart import medium
4536
host = medium.BZR_DEFAULT_INTERFACE
4538
port = medium.BZR_DEFAULT_PORT
4752
if port is not None:
4540
4753
if ':' in port:
4541
4754
host, port = port.split(':')
4542
4755
port = int(port)
4543
4756
return host, port
4545
def get_smart_server(self, transport, inet, port):
4546
"""Construct a smart server.
4548
:param transport: The base transport from which branches will be
4550
:param inet: If True, serve over stdin and stdout. Used for running
4552
:param port: The port to listen on. By default, it's `
4553
medium.BZR_DEFAULT_PORT`. See `get_host_and_port` for more
4555
:return: A smart server.
4557
from bzrlib.smart import medium, server
4559
smart_server = medium.SmartServerPipeStreamMedium(
4560
sys.stdin, sys.stdout, transport)
4562
host, port = self.get_host_and_port(port)
4563
smart_server = server.SmartTCPServer(
4564
transport, host=host, port=port)
4565
note('listening on port: %s' % smart_server.port)
4568
def run(self, port=None, inet=False, directory=None, allow_writes=False):
4569
from bzrlib.transport import get_transport
4570
from bzrlib.transport.chroot import ChrootServer
4758
def run(self, port=None, inet=False, directory=None, allow_writes=False,
4760
from bzrlib.transport import get_transport, transport_server_registry
4571
4761
if directory is None:
4572
4762
directory = os.getcwd()
4763
if protocol is None:
4764
protocol = transport_server_registry.get()
4765
host, port = self.get_host_and_port(port)
4573
4766
url = urlutils.local_path_to_url(directory)
4574
4767
if not allow_writes:
4575
4768
url = 'readonly+' + url
4576
chroot_server = ChrootServer(get_transport(url))
4577
chroot_server.setUp()
4578
t = get_transport(chroot_server.get_url())
4579
smart_server = self.get_smart_server(t, inet, port)
4580
self.run_smart_server(smart_server)
4769
transport = get_transport(url)
4770
protocol(transport, host, port, inet)
4583
4773
class cmd_join(Command):
4824
5014
help='Write merge directive to this file; '
4825
5015
'use - for stdout.',
5018
help='Refuse to send if there are uncommitted changes in'
5019
' the working tree, --no-strict disables the check.'),
4827
5020
Option('mail-to', help='Mail the request to this address.',
4831
5024
Option('body', help='Body for the email.', type=unicode),
4832
RegistryOption.from_kwargs('format',
4833
'Use the specified output format.',
4834
**{'4': 'Bundle format 4, Merge Directive 2 (default)',
4835
'0.9': 'Bundle format 0.9, Merge Directive 1',})
5025
RegistryOption('format',
5026
help='Use the specified output format.',
5027
lazy_registry=('bzrlib.send', 'format_registry')),
4838
5030
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
4839
5031
no_patch=False, revision=None, remember=False, output=None,
4840
format='4', mail_to=None, message=None, body=None, **kwargs):
4841
return self._run(submit_branch, revision, public_branch, remember,
4842
format, no_bundle, no_patch, output,
4843
kwargs.get('from', '.'), mail_to, message, body)
4845
def _run(self, submit_branch, revision, public_branch, remember, format,
4846
no_bundle, no_patch, output, from_, mail_to, message, body):
4847
from bzrlib.revision import NULL_REVISION
4848
branch = Branch.open_containing(from_)[0]
4850
outfile = cStringIO.StringIO()
4854
outfile = open(output, 'wb')
4855
# we may need to write data into branch's repository to calculate
4860
config = branch.get_config()
4862
mail_to = config.get_user_option('submit_to')
4863
mail_client = config.get_mail_client()
4864
if (not getattr(mail_client, 'supports_body', False)
4865
and body is not None):
4866
raise errors.BzrCommandError(
4867
'Mail client "%s" does not support specifying body' %
4868
mail_client.__class__.__name__)
4869
if remember and submit_branch is None:
4870
raise errors.BzrCommandError(
4871
'--remember requires a branch to be specified.')
4872
stored_submit_branch = branch.get_submit_branch()
4873
remembered_submit_branch = None
4874
if submit_branch is None:
4875
submit_branch = stored_submit_branch
4876
remembered_submit_branch = "submit"
4878
if stored_submit_branch is None or remember:
4879
branch.set_submit_branch(submit_branch)
4880
if submit_branch is None:
4881
submit_branch = branch.get_parent()
4882
remembered_submit_branch = "parent"
4883
if submit_branch is None:
4884
raise errors.BzrCommandError('No submit branch known or'
4886
if remembered_submit_branch is not None:
4887
note('Using saved %s location "%s" to determine what '
4888
'changes to submit.', remembered_submit_branch,
4892
submit_config = Branch.open(submit_branch).get_config()
4893
mail_to = submit_config.get_user_option("child_submit_to")
4895
stored_public_branch = branch.get_public_branch()
4896
if public_branch is None:
4897
public_branch = stored_public_branch
4898
elif stored_public_branch is None or remember:
4899
branch.set_public_branch(public_branch)
4900
if no_bundle and public_branch is None:
4901
raise errors.BzrCommandError('No public branch specified or'
4903
base_revision_id = None
4905
if revision is not None:
4906
if len(revision) > 2:
4907
raise errors.BzrCommandError('bzr send takes '
4908
'at most two one revision identifiers')
4909
revision_id = revision[-1].as_revision_id(branch)
4910
if len(revision) == 2:
4911
base_revision_id = revision[0].as_revision_id(branch)
4912
if revision_id is None:
4913
revision_id = branch.last_revision()
4914
if revision_id == NULL_REVISION:
4915
raise errors.BzrCommandError('No revisions to submit.')
4917
directive = merge_directive.MergeDirective2.from_objects(
4918
branch.repository, revision_id, time.time(),
4919
osutils.local_time_offset(), submit_branch,
4920
public_branch=public_branch, include_patch=not no_patch,
4921
include_bundle=not no_bundle, message=message,
4922
base_revision_id=base_revision_id)
4923
elif format == '0.9':
4926
patch_type = 'bundle'
4928
raise errors.BzrCommandError('Format 0.9 does not'
4929
' permit bundle with no patch')
4935
directive = merge_directive.MergeDirective.from_objects(
4936
branch.repository, revision_id, time.time(),
4937
osutils.local_time_offset(), submit_branch,
4938
public_branch=public_branch, patch_type=patch_type,
4941
outfile.writelines(directive.to_lines())
4943
subject = '[MERGE] '
4944
if message is not None:
4947
revision = branch.repository.get_revision(revision_id)
4948
subject += revision.get_summary()
4949
basename = directive.get_disk_name(branch)
4950
mail_client.compose_merge_request(mail_to, subject,
5032
format=None, mail_to=None, message=None, body=None,
5033
strict=None, **kwargs):
5034
from bzrlib.send import send
5035
return send(submit_branch, revision, public_branch, remember,
5036
format, no_bundle, no_patch, output,
5037
kwargs.get('from', '.'), mail_to, message, body,
4959
5042
class cmd_bundle_revisions(cmd_send):
4961
5043
"""Create a merge-directive for submitting changes.
4963
5045
A merge directive provides many things needed for requesting merges:
5019
5103
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
5020
5104
no_patch=False, revision=None, remember=False, output=None,
5021
format='4', **kwargs):
5105
format=None, strict=None, **kwargs):
5022
5106
if output is None:
5024
return self._run(submit_branch, revision, public_branch, remember,
5108
from bzrlib.send import send
5109
return send(submit_branch, revision, public_branch, remember,
5025
5110
format, no_bundle, no_patch, output,
5026
kwargs.get('from', '.'), None, None, None)
5111
kwargs.get('from', '.'), None, None, None,
5112
self.outf, strict=strict)
5029
5115
class cmd_tag(Command):
5130
5216
graph = branch.repository.get_graph()
5131
5217
rev1, rev2 = _get_revision_range(revision, branch, self.name())
5132
5218
revid1, revid2 = rev1.rev_id, rev2.rev_id
5133
5219
# only show revisions between revid1 and revid2 (inclusive)
5134
5220
tags = [(tag, revid) for tag, revid in tags if
5135
5221
graph.is_between(revid, revid1, revid2)]
5140
elif sort == 'time':
5142
for tag, revid in tags:
5144
revobj = branch.repository.get_revision(revid)
5145
except errors.NoSuchRevision:
5146
timestamp = sys.maxint # place them at the end
5148
timestamp = revobj.timestamp
5149
timestamps[revid] = timestamp
5150
tags.sort(key=lambda x: timestamps[x[1]])
5152
# [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
5153
revno_map = branch.get_revision_id_to_revno_map()
5154
tags = [ (tag, '.'.join(map(str, revno_map.get(revid, ('?',)))))
5155
for tag, revid in tags ]
5224
elif sort == 'time':
5226
for tag, revid in tags:
5228
revobj = branch.repository.get_revision(revid)
5229
except errors.NoSuchRevision:
5230
timestamp = sys.maxint # place them at the end
5232
timestamp = revobj.timestamp
5233
timestamps[revid] = timestamp
5234
tags.sort(key=lambda x: timestamps[x[1]])
5236
# [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
5237
for index, (tag, revid) in enumerate(tags):
5239
revno = branch.revision_id_to_dotted_revno(revid)
5240
if isinstance(revno, tuple):
5241
revno = '.'.join(map(str, revno))
5242
except errors.NoSuchRevision:
5243
# Bad tag data/merges can lead to tagged revisions
5244
# which are not in this branch. Fail gracefully ...
5246
tags[index] = (tag, revno)
5156
5249
for tag, revspec in tags:
5157
5250
self.outf.write('%-20s %s\n' % (tag, revspec))
5195
5288
Option('bind-to', help='Branch to bind checkout to.', type=str),
5196
5289
Option('force',
5197
help='Perform reconfiguration even if local changes'
5290
help='Perform reconfiguration even if local changes'
5292
Option('stacked-on',
5293
help='Reconfigure a branch to be stacked on another branch.',
5297
help='Reconfigure a branch to be unstacked. This '
5298
'may require copying substantial data into it.',
5201
def run(self, location=None, target_type=None, bind_to=None, force=False):
5302
def run(self, location=None, target_type=None, bind_to=None, force=False,
5202
5305
directory = bzrdir.BzrDir.open(location)
5306
if stacked_on and unstacked:
5307
raise BzrCommandError("Can't use both --stacked-on and --unstacked")
5308
elif stacked_on is not None:
5309
reconfigure.ReconfigureStackedOn().apply(directory, stacked_on)
5311
reconfigure.ReconfigureUnstacked().apply(directory)
5312
# At the moment you can use --stacked-on and a different
5313
# reconfiguration shape at the same time; there seems no good reason
5203
5315
if target_type is None:
5204
raise errors.BzrCommandError('No target configuration specified')
5316
if stacked_on or unstacked:
5319
raise errors.BzrCommandError('No target configuration '
5205
5321
elif target_type == 'branch':
5206
5322
reconfiguration = reconfigure.Reconfigure.to_branch(directory)
5207
5323
elif target_type == 'tree':
5251
5367
takes_args = ['to_location']
5252
5368
takes_options = [Option('force',
5253
help='Switch even if local commits will be lost.')
5369
help='Switch even if local commits will be lost.'),
5370
Option('create-branch', short_name='b',
5371
help='Create the target branch from this one before'
5372
' switching to it.'),
5256
def run(self, to_location, force=False):
5375
def run(self, to_location, force=False, create_branch=False):
5257
5376
from bzrlib import switch
5258
5377
tree_location = '.'
5259
5378
control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5260
branch = control_dir.open_branch()
5262
to_branch = Branch.open(to_location)
5380
branch = control_dir.open_branch()
5381
had_explicit_nick = branch.get_config().has_explicit_nickname()
5263
5382
except errors.NotBranchError:
5264
this_branch = control_dir.open_branch()
5265
# This may be a heavy checkout, where we want the master branch
5266
this_url = this_branch.get_bound_location()
5267
# If not, use a local sibling
5268
if this_url is None:
5269
this_url = this_branch.base
5270
to_branch = Branch.open(
5271
urlutils.join(this_url, '..', to_location))
5384
had_explicit_nick = False
5387
raise errors.BzrCommandError('cannot create branch without'
5389
if '/' not in to_location and '\\' not in to_location:
5390
# This path is meant to be relative to the existing branch
5391
this_url = self._get_branch_location(control_dir)
5392
to_location = urlutils.join(this_url, '..', to_location)
5393
to_branch = branch.bzrdir.sprout(to_location,
5394
possible_transports=[branch.bzrdir.root_transport],
5395
source_branch=branch).open_branch()
5397
# from_branch = control_dir.open_branch()
5398
# except errors.NotBranchError:
5399
# raise BzrCommandError('Cannot create a branch from this'
5400
# ' location when we cannot open this branch')
5401
# from_branch.bzrdir.sprout(
5405
to_branch = Branch.open(to_location)
5406
except errors.NotBranchError:
5407
this_url = self._get_branch_location(control_dir)
5408
to_branch = Branch.open(
5409
urlutils.join(this_url, '..', to_location))
5272
5410
switch.switch(control_dir, to_branch, force)
5273
if branch.get_config().has_explicit_nickname():
5411
if had_explicit_nick:
5274
5412
branch = control_dir.open_branch() #get the new branch!
5275
5413
branch.nick = to_branch.nick
5276
5414
note('Switched to branch: %s',
5277
5415
urlutils.unescape_for_display(to_branch.base, 'utf-8'))
5417
def _get_branch_location(self, control_dir):
5418
"""Return location of branch for this control dir."""
5420
this_branch = control_dir.open_branch()
5421
# This may be a heavy checkout, where we want the master branch
5422
master_location = this_branch.get_bound_location()
5423
if master_location is not None:
5424
return master_location
5425
# If not, use a local sibling
5426
return this_branch.base
5427
except errors.NotBranchError:
5428
format = control_dir.find_branch_format()
5429
if getattr(format, 'get_reference', None) is not None:
5430
return format.get_reference(control_dir)
5432
return control_dir.root_transport.base
5280
5435
class cmd_view(Command):
5281
5436
"""Manage filtered views.
5583
5746
dry_run=dry_run, no_prompt=force)
5586
def _create_prefix(cur_transport):
5587
needed = [cur_transport]
5588
# Recurse upwards until we can create a directory successfully
5590
new_transport = cur_transport.clone('..')
5591
if new_transport.base == cur_transport.base:
5592
raise errors.BzrCommandError(
5593
"Failed to create path prefix for %s."
5594
% cur_transport.base)
5596
new_transport.mkdir('.')
5597
except errors.NoSuchFile:
5598
needed.append(new_transport)
5599
cur_transport = new_transport
5749
class cmd_reference(Command):
5750
"""list, view and set branch locations for nested trees.
5752
If no arguments are provided, lists the branch locations for nested trees.
5753
If one argument is provided, display the branch location for that tree.
5754
If two arguments are provided, set the branch location for that tree.
5759
takes_args = ['path?', 'location?']
5761
def run(self, path=None, location=None):
5763
if path is not None:
5765
tree, branch, relpath =(
5766
bzrdir.BzrDir.open_containing_tree_or_branch(branchdir))
5767
if path is not None:
5770
tree = branch.basis_tree()
5772
info = branch._get_all_reference_info().iteritems()
5773
self._display_reference_info(tree, branch, info)
5602
# Now we only need to create child directories
5604
cur_transport = needed.pop()
5605
cur_transport.ensure_base()
5775
file_id = tree.path2id(path)
5777
raise errors.NotVersionedError(path)
5778
if location is None:
5779
info = [(file_id, branch.get_reference_info(file_id))]
5780
self._display_reference_info(tree, branch, info)
5782
branch.set_reference_info(file_id, path, location)
5784
def _display_reference_info(self, tree, branch, info):
5786
for file_id, (path, location) in info:
5788
path = tree.id2path(file_id)
5789
except errors.NoSuchId:
5791
ref_list.append((path, location))
5792
for path, location in sorted(ref_list):
5793
self.outf.write('%s %s\n' % (path, location))
5608
5796
# these get imported and then picked up by the scan for cmd_*