~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

  • Committer: Patch Queue Manager
  • Date: 2014-04-09 13:36:25 UTC
  • mfrom: (6592.1.2 1303879-py27-issues)
  • Revision ID: pqm@pqm.ubuntu.com-20140409133625-s24spv3kha2w2860
(vila) Fix python-2.7.6 test failures. (Vincent Ladeuil)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2011 Canonical Ltd
 
1
# Copyright (C) 2005-2012 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
86
86
def _get_branch_location(control_dir, possible_transports=None):
87
87
    """Return location of branch for this control dir."""
88
88
    try:
89
 
        this_branch = control_dir.open_branch(
90
 
            possible_transports=possible_transports)
91
 
        # This may be a heavy checkout, where we want the master branch
92
 
        master_location = this_branch.get_bound_location()
93
 
        if master_location is not None:
94
 
            return master_location
95
 
        # If not, use a local sibling
96
 
        return this_branch.base
 
89
        target = control_dir.get_branch_reference()
97
90
    except errors.NotBranchError:
98
 
        format = control_dir.find_branch_format()
99
 
        if getattr(format, 'get_reference', None) is not None:
100
 
            return format.get_reference(control_dir)
101
 
        else:
102
 
            return control_dir.root_transport.base
 
91
        return control_dir.root_transport.base
 
92
    if target is not None:
 
93
        return target
 
94
    this_branch = control_dir.open_branch(
 
95
        possible_transports=possible_transports)
 
96
    # This may be a heavy checkout, where we want the master branch
 
97
    master_location = this_branch.get_bound_location()
 
98
    if master_location is not None:
 
99
        return master_location
 
100
    # If not, use a local sibling
 
101
    return this_branch.base
103
102
 
104
103
 
105
104
def _is_colocated(control_dir, possible_transports=None):
106
105
    """Check if the branch in control_dir is colocated.
107
106
 
108
107
    :param control_dir: Control directory
109
 
    :return: Boolean indicating whether 
 
108
    :return: Tuple with boolean indicating whether the branch is colocated
 
109
        and the full URL to the actual branch
110
110
    """
111
111
    # This path is meant to be relative to the existing branch
112
112
    this_url = _get_branch_location(control_dir,
132
132
def lookup_new_sibling_branch(control_dir, location, possible_transports=None):
133
133
    """Lookup the location for a new sibling branch.
134
134
 
135
 
    :param control_dir: Control directory relative to which to look up
136
 
        the name.
 
135
    :param control_dir: Control directory to find sibling branches from
137
136
    :param location: Name of the new branch
138
137
    :return: Full location to the new branch
139
138
    """
149
148
    return location
150
149
 
151
150
 
152
 
def lookup_sibling_branch(control_dir, location, possible_transports=None):
153
 
    """Lookup sibling branch.
154
 
    
 
151
def open_sibling_branch(control_dir, location, possible_transports=None):
 
152
    """Open a branch, possibly a sibling of another.
 
153
 
155
154
    :param control_dir: Control directory relative to which to lookup the
156
155
        location.
157
156
    :param location: Location to look up
162
161
        return control_dir.open_branch(location, 
163
162
            possible_transports=possible_transports)
164
163
    except (errors.NotBranchError, errors.NoColocatedBranchSupport):
 
164
        this_url = _get_branch_location(control_dir)
 
165
        return Branch.open(
 
166
            urlutils.join(
 
167
                this_url, '..', urlutils.escape(location)))
 
168
 
 
169
 
 
170
def open_nearby_branch(near=None, location=None, possible_transports=None):
 
171
    """Open a nearby branch.
 
172
 
 
173
    :param near: Optional location of container from which to open branch
 
174
    :param location: Location of the branch
 
175
    :return: Branch instance
 
176
    """
 
177
    if near is None:
 
178
        if location is None:
 
179
            location = "."
165
180
        try:
166
 
            return Branch.open(location)
 
181
            return Branch.open(location,
 
182
                possible_transports=possible_transports)
167
183
        except errors.NotBranchError:
168
 
            this_url = _get_branch_location(control_dir)
169
 
            return Branch.open(
170
 
                urlutils.join(
171
 
                    this_url, '..', urlutils.escape(location)))
172
 
 
173
 
 
174
 
@symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
175
 
def tree_files(file_list, default_branch=u'.', canonicalize=True,
176
 
    apply_view=True):
177
 
    return internal_tree_files(file_list, default_branch, canonicalize,
178
 
        apply_view)
 
184
            near = "."
 
185
    cdir = controldir.ControlDir.open(near,
 
186
        possible_transports=possible_transports)
 
187
    return open_sibling_branch(cdir, location,
 
188
        possible_transports=possible_transports)
 
189
 
 
190
 
 
191
def iter_sibling_branches(control_dir, possible_transports=None):
 
192
    """Iterate over the siblings of a branch.
 
193
 
 
194
    :param control_dir: Control directory for which to look up the siblings
 
195
    :return: Iterator over tuples with branch name and branch object
 
196
    """
 
197
    seen_urls = set()
 
198
    try:
 
199
        reference = control_dir.get_branch_reference()
 
200
    except errors.NotBranchError:
 
201
        # There is no active branch, just return the colocated branches.
 
202
        for name, branch in control_dir.get_branches().iteritems():
 
203
            yield name, branch
 
204
        return
 
205
    if reference is not None:
 
206
        ref_branch = Branch.open(reference,
 
207
            possible_transports=possible_transports)
 
208
    else:
 
209
        ref_branch = None
 
210
    if ref_branch is None or ref_branch.name:
 
211
        if ref_branch is not None:
 
212
            control_dir = ref_branch.bzrdir
 
213
        for name, branch in control_dir.get_branches().iteritems():
 
214
            yield name, branch
 
215
    else:
 
216
        repo = ref_branch.bzrdir.find_repository()
 
217
        for branch in repo.find_branches(using=True):
 
218
            name = urlutils.relative_url(repo.user_url,
 
219
                branch.user_url).rstrip("/")
 
220
            yield name, branch
179
221
 
180
222
 
181
223
def tree_files_for_add(file_list):
243
285
    return rev_tree
244
286
 
245
287
 
246
 
# XXX: Bad function name; should possibly also be a class method of
247
 
# WorkingTree rather than a function.
248
 
@symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
249
 
def internal_tree_files(file_list, default_branch=u'.', canonicalize=True,
250
 
    apply_view=True):
251
 
    """Convert command-line paths to a WorkingTree and relative paths.
252
 
 
253
 
    Deprecated: use WorkingTree.open_containing_paths instead.
254
 
 
255
 
    This is typically used for command-line processors that take one or
256
 
    more filenames, and infer the workingtree that contains them.
257
 
 
258
 
    The filenames given are not required to exist.
259
 
 
260
 
    :param file_list: Filenames to convert.
261
 
 
262
 
    :param default_branch: Fallback tree path to use if file_list is empty or
263
 
        None.
264
 
 
265
 
    :param apply_view: if True and a view is set, apply it or check that
266
 
        specified files are within it
267
 
 
268
 
    :return: workingtree, [relative_paths]
269
 
    """
270
 
    return WorkingTree.open_containing_paths(
271
 
        file_list, default_directory='.',
272
 
        canonicalize=True,
273
 
        apply_view=True)
274
 
 
275
 
 
276
288
def _get_view_info_for_change_reporter(tree):
277
289
    """Get the view information from a tree for change reporting."""
278
290
    view_info = None
356
368
    This will produce the same results as calling 'bzr diff --summarize'.
357
369
    """
358
370
 
359
 
    # TODO: --no-recurse, --recurse options
 
371
    # TODO: --no-recurse/-N, --recurse options
360
372
 
361
373
    takes_args = ['file*']
362
374
    takes_options = ['show-ids', 'revision', 'change', 'verbose',
673
685
            if revision:
674
686
                if len(revision) != 1:
675
687
                    raise errors.BzrCommandError(gettext(
676
 
                        "Tags can only be placed on a single revision, "
677
 
                        "not on a range"))
 
688
                        "Revision numbers only make sense for single "
 
689
                        "revisions, not ranges"))
678
690
                revid = revision[0].as_revision_id(b)
679
691
            else:
680
692
                revid = b.last_revision()
791
803
    takes_args = ['file*']
792
804
    takes_options = [
793
805
        Option('no-recurse',
794
 
               help="Don't recursively add the contents of directories."),
 
806
               help="Don't recursively add the contents of directories.",
 
807
               short_name='N'),
795
808
        Option('dry-run',
796
809
               help="Show what would be done, but don't actually do anything."),
797
810
        'verbose',
937
950
            tree = work_tree
938
951
            extra_trees = []
939
952
 
 
953
        self.add_cleanup(tree.lock_read().unlock)
940
954
        if file_list is not None:
941
955
            file_ids = tree.paths2ids(file_list, trees=extra_trees,
942
956
                                      require_versioned=True)
943
957
            # find_ids_across_trees may include some paths that don't
944
958
            # exist in 'tree'.
945
 
            entries = sorted(
946
 
                (tree.id2path(file_id), tree.inventory[file_id])
947
 
                for file_id in file_ids if tree.has_id(file_id))
 
959
            entries = tree.iter_entries_by_dir(specific_file_ids=file_ids)
948
960
        else:
949
 
            entries = tree.inventory.entries()
 
961
            entries = tree.iter_entries_by_dir()
950
962
 
951
 
        self.cleanup_now()
952
 
        for path, entry in entries:
 
963
        for path, entry in sorted(entries):
953
964
            if kind and kind != entry.kind:
954
965
                continue
 
966
            if path == "":
 
967
                continue
955
968
            if show_ids:
956
969
                self.outf.write('%-50s %s\n' % (path, entry.file_id))
957
970
            else:
1029
1042
                and rel_names[0].lower() == rel_names[1].lower()):
1030
1043
                into_existing = False
1031
1044
            else:
1032
 
                inv = tree.inventory
1033
1045
                # 'fix' the case of a potential 'from'
1034
1046
                from_id = tree.path2id(
1035
1047
                            tree.get_canonical_inventory_path(rel_names[0]))
1036
1048
                if (not osutils.lexists(names_list[0]) and
1037
 
                    from_id and inv.get_file_kind(from_id) == "directory"):
 
1049
                    from_id and tree.stored_kind(from_id) == "directory"):
1038
1050
                    into_existing = False
1039
1051
        # move/rename
1040
1052
        if into_existing:
1141
1153
                 "the master branch."
1142
1154
            ),
1143
1155
        Option('show-base',
1144
 
            help="Show base revision text in conflicts.")
 
1156
            help="Show base revision text in conflicts."),
 
1157
        Option('overwrite-tags',
 
1158
            help="Overwrite tags only."),
1145
1159
        ]
1146
1160
    takes_args = ['location?']
1147
1161
    encoding_type = 'replace'
1149
1163
    def run(self, location=None, remember=None, overwrite=False,
1150
1164
            revision=None, verbose=False,
1151
1165
            directory=None, local=False,
1152
 
            show_base=False):
 
1166
            show_base=False, overwrite_tags=False):
 
1167
 
 
1168
        if overwrite:
 
1169
            overwrite = ["history", "tags"]
 
1170
        elif overwrite_tags:
 
1171
            overwrite = ["tags"]
 
1172
        else:
 
1173
            overwrite = []
1153
1174
        # FIXME: too much stuff is in the command class
1154
1175
        revision_id = None
1155
1176
        mergeable = None
1163
1184
            tree_to = None
1164
1185
            branch_to = Branch.open_containing(directory)[0]
1165
1186
            self.add_cleanup(branch_to.lock_write().unlock)
1166
 
 
1167
 
        if tree_to is None and show_base:
1168
 
            raise errors.BzrCommandError(gettext("Need working tree for --show-base."))
 
1187
            if show_base:
 
1188
                warning(gettext("No working tree, ignoring --show-base"))
1169
1189
 
1170
1190
        if local and not branch_to.get_bound_location():
1171
1191
            raise errors.LocalRequiresBoundBranch()
1206
1226
            # Remembers if asked explicitly or no previous location is set
1207
1227
            if (remember
1208
1228
                or (remember is None and branch_to.get_parent() is None)):
 
1229
                # FIXME: This shouldn't be done before the pull
 
1230
                # succeeds... -- vila 2012-01-02
1209
1231
                branch_to.set_parent(branch_from.base)
1210
1232
 
1211
1233
        if revision is not None:
1291
1313
        Option('no-tree',
1292
1314
               help="Don't populate the working tree, even for protocols"
1293
1315
               " that support it."),
 
1316
        Option('overwrite-tags',
 
1317
              help="Overwrite tags only."),
1294
1318
        ]
1295
1319
    takes_args = ['location?']
1296
1320
    encoding_type = 'replace'
1298
1322
    def run(self, location=None, remember=None, overwrite=False,
1299
1323
        create_prefix=False, verbose=False, revision=None,
1300
1324
        use_existing_dir=False, directory=None, stacked_on=None,
1301
 
        stacked=False, strict=None, no_tree=False):
 
1325
        stacked=False, strict=None, no_tree=False,
 
1326
        overwrite_tags=False):
1302
1327
        from bzrlib.push import _show_push_branch
1303
1328
 
 
1329
        if overwrite:
 
1330
            overwrite = ["history", "tags"]
 
1331
        elif overwrite_tags:
 
1332
            overwrite = ["tags"]
 
1333
        else:
 
1334
            overwrite = []
 
1335
 
1304
1336
        if directory is None:
1305
1337
            directory = '.'
1306
1338
        # Get the source branch
1540
1572
                active_branch = dir.open_branch(name="")
1541
1573
            except errors.NotBranchError:
1542
1574
                active_branch = None
1543
 
            branches = dir.get_branches()
1544
1575
            names = {}
1545
 
            for name, branch in branches.iteritems():
 
1576
            for name, branch in iter_sibling_branches(dir):
1546
1577
                if name == "":
1547
1578
                    continue
1548
1579
                active = (active_branch is not None and
1583
1614
    code.)
1584
1615
    """
1585
1616
 
1586
 
    _see_also = ['checkouts', 'branch']
 
1617
    _see_also = ['checkouts', 'branch', 'working-trees', 'remove-tree']
1587
1618
    takes_args = ['branch_location?', 'to_location?']
1588
1619
    takes_options = ['revision',
1589
1620
                     Option('lightweight',
1649
1680
    def run(self, dir=u'.'):
1650
1681
        tree = WorkingTree.open_containing(dir)[0]
1651
1682
        self.add_cleanup(tree.lock_read().unlock)
1652
 
        new_inv = tree.inventory
1653
1683
        old_tree = tree.basis_tree()
1654
1684
        self.add_cleanup(old_tree.lock_read().unlock)
1655
 
        old_inv = old_tree.inventory
1656
1685
        renames = []
1657
1686
        iterator = tree.iter_changes(old_tree, include_unchanged=True)
1658
1687
        for f, paths, c, v, p, n, k, e in iterator:
1829
1858
 
1830
1859
    This makes Bazaar stop tracking changes to the specified files. Bazaar will
1831
1860
    delete them if they can easily be recovered using revert otherwise they
1832
 
    will be backed up (adding an extention of the form .~#~). If no options or
 
1861
    will be backed up (adding an extension of the form .~#~). If no options or
1833
1862
    parameters are given Bazaar will scan for files that are being tracked by
1834
1863
    Bazaar but missing in your tree and stop tracking them for you.
1835
1864
    """
1841
1870
            title='Deletion Strategy', value_switches=True, enum_switch=False,
1842
1871
            safe='Backup changed files (default).',
1843
1872
            keep='Delete from bzr but leave the working copy.',
1844
 
            no_backup='Don\'t backup changed files.',
1845
 
            force='Delete all the specified files, even if they can not be '
1846
 
                'recovered and even if they are non-empty directories. '
1847
 
                '(deprecated, use no-backup)')]
 
1873
            no_backup='Don\'t backup changed files.'),
 
1874
        ]
1848
1875
    aliases = ['rm', 'del']
1849
1876
    encoding_type = 'replace'
1850
1877
 
1851
1878
    def run(self, file_list, verbose=False, new=False,
1852
1879
        file_deletion_strategy='safe'):
1853
 
        if file_deletion_strategy == 'force':
1854
 
            note(gettext("(The --force option is deprecated, rather use --no-backup "
1855
 
                "in future.)"))
1856
 
            file_deletion_strategy = 'no-backup'
1857
1880
 
1858
1881
        tree, file_list = WorkingTree.open_containing_paths(file_list)
1859
1882
 
2043
2066
         RegistryOption('format',
2044
2067
                help='Specify a format for this branch. '
2045
2068
                'See "help formats".',
2046
 
                lazy_registry=('bzrlib.bzrdir', 'format_registry'),
 
2069
                lazy_registry=('bzrlib.controldir', 'format_registry'),
2047
2070
                converter=lambda name: controldir.format_registry.make_bzrdir(name),
2048
2071
                value_switches=True,
2049
2072
                title="Branch format",
2305
2328
            help='Diff format to use.',
2306
2329
            lazy_registry=('bzrlib.diff', 'format_registry'),
2307
2330
            title='Diff format'),
 
2331
        Option('context',
 
2332
            help='How many lines of context to show.',
 
2333
            type=int,
 
2334
            ),
2308
2335
        ]
2309
2336
    aliases = ['di', 'dif']
2310
2337
    encoding_type = 'exact'
2311
2338
 
2312
2339
    @display_command
2313
2340
    def run(self, revision=None, file_list=None, diff_options=None,
2314
 
            prefix=None, old=None, new=None, using=None, format=None):
 
2341
            prefix=None, old=None, new=None, using=None, format=None, 
 
2342
            context=None):
2315
2343
        from bzrlib.diff import (get_trees_and_branches_to_diff_locked,
2316
2344
            show_diff_trees)
2317
2345
 
2350
2378
                               old_label=old_label, new_label=new_label,
2351
2379
                               extra_trees=extra_trees,
2352
2380
                               path_encoding=path_encoding,
2353
 
                               using=using,
 
2381
                               using=using, context=context,
2354
2382
                               format_cls=format)
2355
2383
 
2356
2384
 
2372
2400
        self.add_cleanup(tree.lock_read().unlock)
2373
2401
        old = tree.basis_tree()
2374
2402
        self.add_cleanup(old.lock_read().unlock)
2375
 
        for path, ie in old.inventory.iter_entries():
 
2403
        for path, ie in old.iter_entries_by_dir():
2376
2404
            if not tree.has_id(ie.file_id):
2377
2405
                self.outf.write(path)
2378
2406
                if show_ids:
2416
2444
        self.add_cleanup(wt.lock_read().unlock)
2417
2445
        basis = wt.basis_tree()
2418
2446
        self.add_cleanup(basis.lock_read().unlock)
2419
 
        basis_inv = basis.inventory
2420
 
        inv = wt.inventory
2421
 
        for file_id in inv:
2422
 
            if basis_inv.has_id(file_id):
2423
 
                continue
2424
 
            if inv.is_root(file_id) and len(basis_inv) == 0:
2425
 
                continue
2426
 
            path = inv.id2path(file_id)
 
2447
        root_id = wt.get_root_id()
 
2448
        for file_id in wt.all_file_ids():
 
2449
            if basis.has_id(file_id):
 
2450
                continue
 
2451
            if root_id == file_id:
 
2452
                continue
 
2453
            path = wt.id2path(file_id)
2427
2454
            if not os.access(osutils.pathjoin(wt.basedir, path), os.F_OK):
2428
2455
                continue
2429
2456
            if null:
2791
2818
            self.add_cleanup(b.lock_read().unlock)
2792
2819
            rev1, rev2 = _get_revision_range(revision, b, self.name())
2793
2820
 
2794
 
        if b.get_config().validate_signatures_in_log():
 
2821
        if b.get_config_stack().get('validate_signatures_in_log'):
2795
2822
            signatures = True
2796
2823
 
2797
2824
        if signatures:
3517
3544
            tokens = fixed_bug.split(':')
3518
3545
            if len(tokens) == 1:
3519
3546
                if default_bugtracker is None:
3520
 
                    branch_config = branch.get_config()
3521
 
                    default_bugtracker = branch_config.get_user_option(
 
3547
                    branch_config = branch.get_config_stack()
 
3548
                    default_bugtracker = branch_config.get(
3522
3549
                        "bugtracker")
3523
3550
                if default_bugtracker is None:
3524
3551
                    raise errors.BzrCommandError(gettext(
3863
3890
            if directory is None:
3864
3891
                c = Branch.open_containing(u'.')[0].get_config_stack()
3865
3892
            else:
3866
 
                c = Branch.open(directory).get_config_stack()
 
3893
                b = Branch.open(directory)
 
3894
                self.add_cleanup(b.lock_write().unlock)
 
3895
                c = b.get_config_stack()
3867
3896
        else:
3868
3897
            c = _mod_config.GlobalStack()
3869
3898
        c.set('email', name)
4676
4705
                if tree.kind(file_id) != "directory":
4677
4706
                    continue
4678
4707
 
4679
 
                for name, ie in tree.inventory.iter_entries(file_id):
 
4708
                # FIXME: Support nested trees
 
4709
                for name, ie in tree.root_inventory.iter_entries(file_id):
4680
4710
                    interesting_ids.add(ie.file_id)
4681
4711
            new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
4682
4712
        else:
4715
4745
 
4716
4746
 
4717
4747
class cmd_revert(Command):
4718
 
    __doc__ = """Revert files to a previous revision.
 
4748
    __doc__ = """\
 
4749
    Set files in the working tree back to the contents of a previous revision.
4719
4750
 
4720
4751
    Giving a list of files will revert only those files.  Otherwise, all files
4721
4752
    will be reverted.  If the revision is not specified with '--revision', the
4722
 
    last committed revision is used.
 
4753
    working tree basis revision is used. A revert operation affects only the
 
4754
    working tree, not any revision history like the branch and repository or
 
4755
    the working tree basis revision.
4723
4756
 
4724
4757
    To remove only some changes, without reverting to a prior version, use
4725
4758
    merge instead.  For example, "merge . -r -2..-3" (don't forget the ".")
4726
4759
    will remove the changes introduced by the second last commit (-2), without
4727
4760
    affecting the changes introduced by the last commit (-1).  To remove
4728
4761
    certain changes on a hunk-by-hunk basis, see the shelve command.
 
4762
    To update the branch to a specific revision or the latest revision and
 
4763
    update the working tree accordingly while preserving local changes, see the
 
4764
    update command.
4729
4765
 
4730
 
    By default, any files that have been manually changed will be backed up
4731
 
    first.  (Files changed only by merge are not backed up.)  Backup files have
4732
 
    '.~#~' appended to their name, where # is a number.
 
4766
    Uncommitted changes to files that are reverted will be discarded.
 
4767
    Howver, by default, any files that have been manually changed will be
 
4768
    backed up first.  (Files changed only by merge are not backed up.)  Backup
 
4769
    files have '.~#~' appended to their name, where # is a number.
4733
4770
 
4734
4771
    When you provide files, you can use their current pathname or the pathname
4735
4772
    from the target revision.  So you can use revert to "undelete" a file by
4982
5019
                             "You have %d extra revisions:\n", 
4983
5020
                             len(local_extra)) %
4984
5021
                len(local_extra))
 
5022
            rev_tag_dict = {}
 
5023
            if local_branch.supports_tags():
 
5024
                rev_tag_dict = local_branch.tags.get_reverse_tag_dict()
4985
5025
            for revision in iter_log_revisions(local_extra,
4986
5026
                                local_branch.repository,
4987
 
                                verbose):
 
5027
                                verbose,
 
5028
                                rev_tag_dict):
4988
5029
                lf.log_revision(revision)
4989
5030
            printed_local = True
4990
5031
            status_code = 1
4998
5039
                             "You are missing %d revisions:\n",
4999
5040
                             len(remote_extra)) %
5000
5041
                len(remote_extra))
 
5042
            if remote_branch.supports_tags():
 
5043
                rev_tag_dict = remote_branch.tags.get_reverse_tag_dict()
5001
5044
            for revision in iter_log_revisions(remote_extra,
5002
5045
                                remote_branch.repository,
5003
 
                                verbose):
 
5046
                                verbose,
 
5047
                                rev_tag_dict):
5004
5048
                lf.log_revision(revision)
5005
5049
            status_code = 1
5006
5050
 
5096
5140
            Option('strict',
5097
5141
                   help='Produce a strict-format testament.')]
5098
5142
    takes_args = ['branch?']
 
5143
    encoding_type = 'exact'
5099
5144
    @display_command
5100
5145
    def run(self, branch=u'.', revision=None, long=False, strict=False):
5101
5146
        from bzrlib.testament import Testament, StrictTestament
5114
5159
            rev_id = revision[0].as_revision_id(b)
5115
5160
        t = testament_class.from_revision(b.repository, rev_id)
5116
5161
        if long:
5117
 
            sys.stdout.writelines(t.as_text_lines())
 
5162
            self.outf.writelines(t.as_text_lines())
5118
5163
        else:
5119
 
            sys.stdout.write(t.as_short_text())
 
5164
            self.outf.write(t.as_short_text())
5120
5165
 
5121
5166
 
5122
5167
class cmd_annotate(Command):
5263
5308
            else:
5264
5309
                if location is None:
5265
5310
                    if b.get_bound_location() is not None:
5266
 
                        raise errors.BzrCommandError(gettext('Branch is already bound'))
 
5311
                        raise errors.BzrCommandError(
 
5312
                            gettext('Branch is already bound'))
5267
5313
                    else:
5268
 
                        raise errors.BzrCommandError(gettext('No location supplied '
5269
 
                            'and no previous location known'))
 
5314
                        raise errors.BzrCommandError(
 
5315
                            gettext('No location supplied'
 
5316
                                    ' and no previous location known'))
5270
5317
        b_other = Branch.open(location)
5271
5318
        try:
5272
5319
            b.bind(b_other)
5476
5523
               help="Protocol to serve.",
5477
5524
               lazy_registry=('bzrlib.transport', 'transport_server_registry'),
5478
5525
               value_switches=True),
 
5526
        Option('listen',
 
5527
               help='Listen for connections on nominated address.', type=str),
5479
5528
        Option('port',
5480
 
               help='Listen for connections on nominated port of the form '
5481
 
                    '[hostname:]portnumber.  Passing 0 as the port number will '
5482
 
                    'result in a dynamically allocated port.  The default port '
5483
 
                    'depends on the protocol.',
5484
 
               type=str),
 
5529
               help='Listen for connections on nominated port.  Passing 0 as '
 
5530
                    'the port number will result in a dynamically allocated '
 
5531
                    'port.  The default port depends on the protocol.',
 
5532
               type=int),
5485
5533
        custom_help('directory',
5486
5534
               help='Serve contents of this directory.'),
5487
5535
        Option('allow-writes',
5497
5545
               help='Override the default idle client timeout (5min).'),
5498
5546
        ]
5499
5547
 
5500
 
    def get_host_and_port(self, port):
5501
 
        """Return the host and port to run the smart server on.
5502
 
 
5503
 
        If 'port' is None, None will be returned for the host and port.
5504
 
 
5505
 
        If 'port' has a colon in it, the string before the colon will be
5506
 
        interpreted as the host.
5507
 
 
5508
 
        :param port: A string of the port to run the server on.
5509
 
        :return: A tuple of (host, port), where 'host' is a host name or IP,
5510
 
            and port is an integer TCP/IP port.
5511
 
        """
5512
 
        host = None
5513
 
        if port is not None:
5514
 
            if ':' in port:
5515
 
                host, port = port.split(':')
5516
 
            port = int(port)
5517
 
        return host, port
5518
 
 
5519
 
    def run(self, port=None, inet=False, directory=None, allow_writes=False,
5520
 
            protocol=None, client_timeout=None):
 
5548
    def run(self, listen=None, port=None, inet=False, directory=None,
 
5549
            allow_writes=False, protocol=None, client_timeout=None):
5521
5550
        from bzrlib import transport
5522
5551
        if directory is None:
5523
5552
            directory = os.getcwd()
5524
5553
        if protocol is None:
5525
5554
            protocol = transport.transport_server_registry.get()
5526
 
        host, port = self.get_host_and_port(port)
5527
5555
        url = transport.location_to_url(directory)
5528
5556
        if not allow_writes:
5529
5557
            url = 'readonly+' + url
5530
5558
        t = transport.get_transport_from_url(url)
5531
 
        try:
5532
 
            protocol(t, host, port, inet, client_timeout)
5533
 
        except TypeError, e:
5534
 
            # We use symbol_versioning.deprecated_in just so that people
5535
 
            # grepping can find it here.
5536
 
            # symbol_versioning.deprecated_in((2, 5, 0))
5537
 
            symbol_versioning.warn(
5538
 
                'Got TypeError(%s)\ntrying to call protocol: %s.%s\n'
5539
 
                'Most likely it needs to be updated to support a'
5540
 
                ' "timeout" parameter (added in bzr 2.5.0)'
5541
 
                % (e, protocol.__module__, protocol),
5542
 
                DeprecationWarning)
5543
 
            protocol(t, host, port, inet)
 
5559
        protocol(t, listen, port, inet, client_timeout)
5544
5560
 
5545
5561
 
5546
5562
class cmd_join(Command):
5682
5698
        if public_branch is None:
5683
5699
            public_branch = stored_public_branch
5684
5700
        elif stored_public_branch is None:
 
5701
            # FIXME: Should be done only if we succeed ? -- vila 2012-01-03
5685
5702
            branch.set_public_branch(public_branch)
5686
5703
        if not include_bundle and public_branch is None:
5687
5704
            raise errors.BzrCommandError(gettext('No public branch specified or'
6215
6232
                     Option('create-branch', short_name='b',
6216
6233
                        help='Create the target branch from this one before'
6217
6234
                             ' switching to it.'),
 
6235
                     Option('store',
 
6236
                        help='Store and restore uncommitted changes in the'
 
6237
                             ' branch.'),
6218
6238
                    ]
6219
6239
 
6220
6240
    def run(self, to_location=None, force=False, create_branch=False,
6221
 
            revision=None, directory=u'.'):
 
6241
            revision=None, directory=u'.', store=False):
6222
6242
        from bzrlib import switch
6223
6243
        tree_location = directory
6224
6244
        revision = _get_one_revision('switch', revision)
6247
6267
                 possible_transports=possible_transports,
6248
6268
                 source_branch=branch).open_branch()
6249
6269
        else:
6250
 
            to_branch = lookup_sibling_branch(control_dir, to_location)
 
6270
            try:
 
6271
                to_branch = Branch.open(to_location,
 
6272
                    possible_transports=possible_transports)
 
6273
            except errors.NotBranchError:
 
6274
                to_branch = open_sibling_branch(control_dir, to_location,
 
6275
                    possible_transports=possible_transports)
6251
6276
        if revision is not None:
6252
6277
            revision = revision.as_revision_id(to_branch)
6253
 
        switch.switch(control_dir, to_branch, force, revision_id=revision)
 
6278
        switch.switch(control_dir, to_branch, force, revision_id=revision,
 
6279
                      store_uncommitted=store)
6254
6280
        if had_explicit_nick:
6255
6281
            branch = control_dir.open_branch() #get the new branch!
6256
6282
            branch.nick = to_branch.nick
6450
6476
 
6451
6477
    takes_args = ["location?"]
6452
6478
 
 
6479
    takes_options = ['directory',
 
6480
        Option('force', help='Remove branch even if it is the active branch.')]
 
6481
 
6453
6482
    aliases = ["rmbranch"]
6454
6483
 
6455
 
    def run(self, location=None):
6456
 
        if location is None:
6457
 
            location = "."
6458
 
        cdir = controldir.ControlDir.open_containing(location)[0]
6459
 
        cdir.destroy_branch()
 
6484
    def run(self, directory=None, location=None, force=False):
 
6485
        br = open_nearby_branch(near=directory, location=location)
 
6486
        if not force and br.bzrdir.has_workingtree():
 
6487
            try:
 
6488
                active_branch = br.bzrdir.open_branch(name="")
 
6489
            except errors.NotBranchError:
 
6490
                active_branch = None
 
6491
            if (active_branch is not None and
 
6492
                br.control_url == active_branch.control_url):
 
6493
                raise errors.BzrCommandError(
 
6494
                    gettext("Branch is active. Use --force to remove it."))
 
6495
        br.bzrdir.destroy_branch(br.name)
6460
6496
 
6461
6497
 
6462
6498
class cmd_shelve(Command):
6691
6727
        ('cmd_version_info', [], 'bzrlib.cmd_version_info'),
6692
6728
        ('cmd_resolve', ['resolved'], 'bzrlib.conflicts'),
6693
6729
        ('cmd_conflicts', [], 'bzrlib.conflicts'),
 
6730
        ('cmd_ping', [], 'bzrlib.smart.ping'),
6694
6731
        ('cmd_sign_my_commits', [], 'bzrlib.commit_signature_commands'),
6695
 
        ('cmd_verify_signatures', [],
6696
 
                                        'bzrlib.commit_signature_commands'),
 
6732
        ('cmd_verify_signatures', [], 'bzrlib.commit_signature_commands'),
6697
6733
        ('cmd_test_script', [], 'bzrlib.cmd_test_script'),
6698
6734
        ]:
6699
6735
        builtin_command_registry.register_lazy(name, aliases, module_name)