87
87
if file_list is None or len(file_list) == 0:
88
88
return WorkingTree.open_containing(default_branch)[0], file_list
89
89
tree = WorkingTree.open_containing(osutils.realpath(file_list[0]))[0]
90
return tree, safe_relpath_files(tree, file_list)
93
def safe_relpath_files(tree, file_list):
94
"""Convert file_list into a list of relpaths in tree.
96
:param tree: A tree to operate on.
97
:param file_list: A list of user provided paths or None.
98
:return: A list of relative paths.
99
:raises errors.PathNotChild: When a provided path is in a different tree
102
if file_list is None:
105
91
for filename in file_list:
107
93
new_list.append(tree.relpath(osutils.dereference_path(filename)))
108
94
except errors.PathNotChild:
109
95
raise errors.FileInWrongBranch(tree.branch, filename)
99
@symbol_versioning.deprecated_function(symbol_versioning.zero_fifteen)
100
def get_format_type(typestring):
101
"""Parse and return a format specifier."""
102
# Have to use BzrDirMetaFormat1 directly, so that
103
# RepositoryFormat.set_default_format works
104
if typestring == "default":
105
return bzrdir.BzrDirMetaFormat1()
107
return bzrdir.format_registry.make_bzrdir(typestring)
109
msg = 'Unknown bzr format "%s". See "bzr help formats".' % typestring
110
raise errors.BzrCommandError(msg)
113
113
# TODO: Make sure no commands unconditionally use the working directory as a
664
624
mergeable.get_merge_request(branch_to.repository)
665
625
branch_from = branch_to
667
branch_from = Branch.open(location,
668
possible_transports=possible_transports)
627
branch_from = Branch.open_from_transport(location_transport)
670
629
if branch_to.get_parent() is None or remember:
671
630
branch_to.set_parent(branch_from.base)
673
632
if revision is not None:
674
633
if len(revision) == 1:
675
revision_id = revision[0].as_revision_id(branch_from)
634
revision_id = revision[0].in_history(branch_from).rev_id
677
636
raise errors.BzrCommandError(
678
637
'bzr pull --revision takes one value.')
680
branch_to.lock_write()
682
if tree_to is not None:
683
change_reporter = delta._ChangeReporter(
684
unversioned_filter=tree_to.is_ignored)
685
result = tree_to.pull(branch_from, overwrite, revision_id,
687
possible_transports=possible_transports)
689
result = branch_to.pull(branch_from, overwrite, revision_id)
640
old_rh = branch_to.revision_history()
641
if tree_to is not None:
642
change_reporter = delta._ChangeReporter(
643
unversioned_filter=tree_to.is_ignored)
644
result = tree_to.pull(branch_from, overwrite, revision_id,
646
possible_transports=possible_transports)
648
result = branch_to.pull(branch_from, overwrite, revision_id)
691
result.report(self.outf)
692
if verbose and result.old_revid != result.new_revid:
694
branch_to.repository.iter_reverse_revision_history(
697
new_rh = branch_to.revision_history()
698
log.show_changed_revisions(branch_to, old_rh, new_rh,
650
result.report(self.outf)
652
new_rh = branch_to.revision_history()
653
log.show_changed_revisions(branch_to, old_rh, new_rh,
704
657
class cmd_push(Command):
743
696
' directory exists, but does not already'
744
697
' have a control directory. This flag will'
745
698
' allow push to proceed.'),
747
help='Create a stacked branch that references the public location '
748
'of the parent branch.'),
750
help='Create a stacked branch that refers to another branch '
751
'for the commit history. Only the work not present in the '
752
'referenced branch is included in the branch created.',
755
700
takes_args = ['location?']
756
701
encoding_type = 'replace'
758
703
def run(self, location=None, remember=False, overwrite=False,
759
create_prefix=False, verbose=False, revision=None,
760
use_existing_dir=False, directory=None, stacked_on=None,
762
from bzrlib.push import _show_push_branch
764
# Get the source branch and revision_id
704
create_prefix=False, verbose=False,
705
use_existing_dir=False,
707
# FIXME: Way too big! Put this into a function called from the
765
709
if directory is None:
767
711
br_from = Branch.open_containing(directory)[0]
768
if revision is not None:
769
if len(revision) == 1:
770
revision_id = revision[0].in_history(br_from).rev_id
772
raise errors.BzrCommandError(
773
'bzr push --revision takes one value.')
775
revision_id = br_from.last_revision()
777
# Get the stacked_on branch, if any
778
if stacked_on is not None:
779
stacked_on = urlutils.normalize_url(stacked_on)
781
parent_url = br_from.get_parent()
783
parent = Branch.open(parent_url)
784
stacked_on = parent.get_public_branch()
786
# I considered excluding non-http url's here, thus forcing
787
# 'public' branches only, but that only works for some
788
# users, so it's best to just depend on the user spotting an
789
# error by the feedback given to them. RBC 20080227.
790
stacked_on = parent_url
792
raise errors.BzrCommandError(
793
"Could not determine branch to refer to.")
795
# Get the destination location
712
stored_loc = br_from.get_push_location()
796
713
if location is None:
797
stored_loc = br_from.get_push_location()
798
714
if stored_loc is None:
799
raise errors.BzrCommandError(
800
"No push location known or specified.")
715
raise errors.BzrCommandError("No push location known or specified.")
802
717
display_url = urlutils.unescape_for_display(stored_loc,
803
718
self.outf.encoding)
804
719
self.outf.write("Using saved location: %s\n" % display_url)
805
720
location = stored_loc
807
_show_push_branch(br_from, revision_id, location, self.outf,
808
verbose=verbose, overwrite=overwrite, remember=remember,
809
stacked_on=stacked_on, create_prefix=create_prefix,
810
use_existing_dir=use_existing_dir)
722
to_transport = transport.get_transport(location)
724
br_to = repository_to = dir_to = None
726
dir_to = bzrdir.BzrDir.open_from_transport(to_transport)
727
except errors.NotBranchError:
728
pass # Didn't find anything
730
# If we can open a branch, use its direct repository, otherwise see
731
# if there is a repository without a branch.
733
br_to = dir_to.open_branch()
734
except errors.NotBranchError:
735
# Didn't find a branch, can we find a repository?
737
repository_to = dir_to.find_repository()
738
except errors.NoRepositoryPresent:
741
# Found a branch, so we must have found a repository
742
repository_to = br_to.repository
747
# The destination doesn't exist; create it.
748
# XXX: Refactor the create_prefix/no_create_prefix code into a
749
# common helper function
751
def make_directory(transport):
755
def redirected(redirected_transport, e, redirection_notice):
756
return transport.get_transport(e.get_target_url())
759
to_transport = transport.do_catching_redirections(
760
make_directory, to_transport, redirected)
761
except errors.FileExists:
762
if not use_existing_dir:
763
raise errors.BzrCommandError("Target directory %s"
764
" already exists, but does not have a valid .bzr"
765
" directory. Supply --use-existing-dir to push"
766
" there anyway." % location)
767
except errors.NoSuchFile:
768
if not create_prefix:
769
raise errors.BzrCommandError("Parent directory of %s"
771
"\nYou may supply --create-prefix to create all"
772
" leading parent directories."
774
_create_prefix(to_transport)
775
except errors.TooManyRedirections:
776
raise errors.BzrCommandError("Too many redirections trying "
777
"to make %s." % location)
779
# Now the target directory exists, but doesn't have a .bzr
780
# directory. So we need to create it, along with any work to create
781
# all of the dependent branches, etc.
782
dir_to = br_from.bzrdir.clone_on_transport(to_transport,
783
revision_id=br_from.last_revision())
784
br_to = dir_to.open_branch()
785
# TODO: Some more useful message about what was copied
786
note('Created new branch.')
787
# We successfully created the target, remember it
788
if br_from.get_push_location() is None or remember:
789
br_from.set_push_location(br_to.base)
790
elif repository_to is None:
791
# we have a bzrdir but no branch or repository
792
# XXX: Figure out what to do other than complain.
793
raise errors.BzrCommandError("At %s you have a valid .bzr control"
794
" directory, but not a branch or repository. This is an"
795
" unsupported configuration. Please move the target directory"
796
" out of the way and try again."
799
# We have a repository but no branch, copy the revisions, and then
801
last_revision_id = br_from.last_revision()
802
repository_to.fetch(br_from.repository,
803
revision_id=last_revision_id)
804
br_to = br_from.clone(dir_to, revision_id=last_revision_id)
805
note('Created new branch.')
806
if br_from.get_push_location() is None or remember:
807
br_from.set_push_location(br_to.base)
808
else: # We have a valid to branch
809
# We were able to connect to the remote location, so remember it
810
# we don't need to successfully push because of possible divergence.
811
if br_from.get_push_location() is None or remember:
812
br_from.set_push_location(br_to.base)
814
old_rh = br_to.revision_history()
817
tree_to = dir_to.open_workingtree()
818
except errors.NotLocalUrl:
819
warning("This transport does not update the working "
820
"tree of: %s. See 'bzr help working-trees' for "
821
"more information." % br_to.base)
822
push_result = br_from.push(br_to, overwrite)
823
except errors.NoWorkingTree:
824
push_result = br_from.push(br_to, overwrite)
828
push_result = br_from.push(tree_to.branch, overwrite)
832
except errors.DivergedBranches:
833
raise errors.BzrCommandError('These branches have diverged.'
834
' Try using "merge" and then "push".')
835
if push_result is not None:
836
push_result.report(self.outf)
838
new_rh = br_to.revision_history()
841
from bzrlib.log import show_changed_revisions
842
show_changed_revisions(br_to, old_rh, new_rh,
845
# we probably did a clone rather than a push, so a message was
813
850
class cmd_branch(Command):
870
904
# preserve whatever source format we have.
871
905
dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
872
906
possible_transports=[to_transport],
873
accelerator_tree=accelerator_tree,
874
hardlink=hardlink, stacked=stacked)
907
accelerator_tree=accelerator_tree)
875
908
branch = dir.open_branch()
876
909
except errors.NoSuchRevision:
877
910
to_transport.delete_tree('.')
878
msg = "The branch %s has no revision %s." % (from_location,
911
msg = "The branch %s has no revision %s." % (from_location, revision[0])
880
912
raise errors.BzrCommandError(msg)
914
branch.control_files.put_utf8('branch-name', name)
881
915
_merge_tags_if_possible(br_from, branch)
882
# If the source branch is stacked, the new branch may
883
# be stacked whether we asked for that explicitly or not.
884
# We therefore need a try/except here and not just 'if stacked:'
886
note('Created new stacked branch referring to %s.' %
887
branch.get_stacked_on_url())
888
except (errors.NotStacked, errors.UnstackableBranchFormat,
889
errors.UnstackableRepositoryFormat), e:
890
note('Branched %d revision(s).' % branch.revno())
916
note('Branched %d revision(s).' % branch.revno())
1100
1128
if file_list is not None:
1101
1129
file_list = [f for f in file_list]
1131
raise errors.BzrCommandError('Specify one or more files to'
1132
' remove, or use --new.')
1105
# Heuristics should probably all move into tree.remove_smart or
1108
added = tree.changes_from(tree.basis_tree(),
1109
specific_files=file_list).added
1110
file_list = sorted([f[0] for f in added], reverse=True)
1111
if len(file_list) == 0:
1112
raise errors.BzrCommandError('No matching files.')
1113
elif file_list is None:
1114
# missing files show up in iter_changes(basis) as
1115
# versioned-with-no-kind.
1117
for change in tree.iter_changes(tree.basis_tree()):
1118
# Find paths in the working tree that have no kind:
1119
if change[1][1] is not None and change[6][1] is None:
1120
missing.append(change[1][1])
1121
file_list = sorted(missing, reverse=True)
1122
file_deletion_strategy = 'keep'
1123
tree.remove(file_list, verbose=verbose, to_file=self.outf,
1124
keep_files=file_deletion_strategy=='keep',
1125
force=file_deletion_strategy=='force')
1135
added = tree.changes_from(tree.basis_tree(),
1136
specific_files=file_list).added
1137
file_list = sorted([f[0] for f in added], reverse=True)
1138
if len(file_list) == 0:
1139
raise errors.BzrCommandError('No matching files.')
1140
tree.remove(file_list, verbose=verbose, to_file=self.outf,
1141
keep_files=file_deletion_strategy=='keep',
1142
force=file_deletion_strategy=='force')
1130
1145
class cmd_file_id(Command):
2357
2374
in the checked revisions. Texts can be repeated when their file
2358
2375
entries are modified, but the file contents are not. It does not
2359
2376
indicate a problem.
2361
If no restrictions are specified, all Bazaar data that is found at the given
2362
location will be checked.
2366
Check the tree and branch at 'foo'::
2368
bzr check --tree --branch foo
2370
Check only the repository at 'bar'::
2372
bzr check --repo bar
2374
Check everything at 'baz'::
2379
2379
_see_also = ['reconcile']
2380
takes_args = ['path?']
2381
takes_options = ['verbose',
2382
Option('branch', help="Check the branch related to the"
2383
" current directory."),
2384
Option('repo', help="Check the repository related to the"
2385
" current directory."),
2386
Option('tree', help="Check the working tree related to"
2387
" the current directory.")]
2380
takes_args = ['branch?']
2381
takes_options = ['verbose']
2389
def run(self, path=None, verbose=False, branch=False, repo=False,
2391
from bzrlib.check import check_dwim
2394
if not branch and not repo and not tree:
2395
branch = repo = tree = True
2396
check_dwim(path, verbose, do_branch=branch, do_repo=repo, do_tree=tree)
2383
def run(self, branch=None, verbose=False):
2384
from bzrlib.check import check
2386
branch_obj = Branch.open_containing('.')[0]
2388
branch_obj = Branch.open(branch)
2389
check(branch_obj, verbose)
2390
# bit hacky, check the tree parent is accurate
2393
tree = WorkingTree.open_containing('.')[0]
2395
tree = WorkingTree.open(branch)
2396
except (errors.NoWorkingTree, errors.NotLocalUrl):
2399
# This is a primitive 'check' for tree state. Currently this is not
2400
# integrated into the main check logic as yet.
2403
tree_basis = tree.basis_tree()
2404
tree_basis.lock_read()
2406
repo_basis = tree.branch.repository.revision_tree(
2407
tree.last_revision())
2408
if len(list(repo_basis._iter_changes(tree_basis))):
2409
raise errors.BzrCheckError(
2410
"Mismatched basis inventory content.")
2399
2418
class cmd_upgrade(Command):
2493
2512
print branch.nick
2496
class cmd_alias(Command):
2497
"""Set/unset and display aliases.
2500
Show the current aliases::
2504
Show the alias specified for 'll'::
2508
Set an alias for 'll'::
2510
bzr alias ll="log --line -r-10..-1"
2512
To remove an alias for 'll'::
2514
bzr alias --remove ll
2517
takes_args = ['name?']
2519
Option('remove', help='Remove the alias.'),
2522
def run(self, name=None, remove=False):
2524
self.remove_alias(name)
2526
self.print_aliases()
2528
equal_pos = name.find('=')
2530
self.print_alias(name)
2532
self.set_alias(name[:equal_pos], name[equal_pos+1:])
2534
def remove_alias(self, alias_name):
2535
if alias_name is None:
2536
raise errors.BzrCommandError(
2537
'bzr alias --remove expects an alias to remove.')
2538
# If alias is not found, print something like:
2539
# unalias: foo: not found
2540
c = config.GlobalConfig()
2541
c.unset_alias(alias_name)
2544
def print_aliases(self):
2545
"""Print out the defined aliases in a similar format to bash."""
2546
aliases = config.GlobalConfig().get_aliases()
2547
for key, value in sorted(aliases.iteritems()):
2548
self.outf.write('bzr alias %s="%s"\n' % (key, value))
2551
def print_alias(self, alias_name):
2552
from bzrlib.commands import get_alias
2553
alias = get_alias(alias_name)
2555
self.outf.write("bzr alias: %s: not found\n" % alias_name)
2558
'bzr alias %s="%s"\n' % (alias_name, ' '.join(alias)))
2560
def set_alias(self, alias_name, alias_command):
2561
"""Save the alias in the global config."""
2562
c = config.GlobalConfig()
2563
c.set_alias(alias_name, alias_command)
2566
2515
class cmd_selftest(Command):
2567
2516
"""Run internal test suite.
3043
2951
``revision`` and ``index`` must be supplied.)
3045
2953
Otherwise, the ``location`` parameter is used. If it is None, then the
3046
``submit`` or ``parent`` location is used, and a note is printed.
2954
``parent`` location is used, and a note is printed.
3048
2956
:param tree: The working tree to select a branch for merging into
3049
2957
:param location: The location entered by the user
3050
2958
:param revision: The revision parameter to the command
3051
2959
:param index: The index to use for the revision parameter. Negative
3052
2960
indices are permitted.
3053
:return: (selected_location, user_location). The default location
3054
will be the user-entered location.
2961
:return: (selected_location, default_location). The default location
2962
will be the user-entered location, if any, or else the remembered
3056
2965
if (revision is not None and index is not None
3057
2966
and revision[index] is not None):
3058
2967
branch = revision[index].get_branch()
3059
2968
if branch is not None:
3060
return branch, branch
3061
if user_location is None:
3062
location = self._get_remembered(tree, 'Merging from')
3064
location = user_location
3065
return location, user_location
2969
return branch, location
2970
location = self._get_remembered_parent(tree, location, 'Merging from')
2971
return location, location
3067
def _get_remembered(self, tree, verb_string):
2973
# TODO: move up to common parent; this isn't merge-specific anymore.
2974
def _get_remembered_parent(self, tree, supplied_location, verb_string):
3068
2975
"""Use tree.branch's parent if none was supplied.
3070
2977
Report if the remembered location was used.
3072
stored_location = tree.branch.get_submit_branch()
3073
if stored_location is None:
3074
stored_location = tree.branch.get_parent()
2979
if supplied_location is not None:
2980
return supplied_location
2981
stored_location = tree.branch.get_parent()
3075
2982
mutter("%s", stored_location)
3076
2983
if stored_location is None:
3077
2984
raise errors.BzrCommandError("No location specified or remembered")
3078
display_url = urlutils.unescape_for_display(stored_location, 'utf-8')
3079
note(u"%s remembered location %s", verb_string, display_url)
2985
display_url = urlutils.unescape_for_display(stored_location,
2987
self.outf.write("%s remembered location %s\n" % (verb_string,
3080
2989
return stored_location