~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/remote.py

  • Committer: Vincent Ladeuil
  • Date: 2009-04-27 16:10:10 UTC
  • mto: (4310.1.1 integration)
  • mto: This revision was merged to the branch mainline in revision 4311.
  • Revision ID: v.ladeuil+lp@free.fr-20090427161010-7swfzeagf63cpixd
Fix bug #367726 by reverting some default user handling introduced
while fixing bug #256612.

* bzrlib/transport/ssh.py:
(_paramiko_auth): Explicitly use getpass.getuser() as default
user.

* bzrlib/transport/ftp/_gssapi.py:
(GSSAPIFtpTransport._create_connection): Explicitly use
getpass.getuser() as default user.

* bzrlib/transport/ftp/__init__.py:
(FtpTransport._create_connection): Explicitly use
getpass.getuser() as default user.

* bzrlib/tests/test_sftp_transport.py:
(TestUsesAuthConfig.test_sftp_is_none_if_no_config)
(TestUsesAuthConfig.test_sftp_doesnt_prompt_username): Revert to
None as the default user.

* bzrlib/tests/test_remote.py:
(TestRemoteSSHTransportAuthentication): The really offending one:
revert to None as the default user.

* bzrlib/tests/test_config.py:
(TestAuthenticationConfig.test_username_default_no_prompt): Update
test (and some PEP8).

* bzrlib/smtp_connection.py:
(SMTPConnection._authenticate): Revert to None as the default
user.

* bzrlib/plugins/launchpad/account.py:
(_get_auth_user): Revert default value handling.

* bzrlib/config.py:
(AuthenticationConfig.get_user): Fix doc-string. Leave default
value handling to callers.

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
from bzrlib import (
23
23
    branch,
24
24
    bzrdir,
 
25
    config,
25
26
    debug,
26
27
    errors,
27
28
    graph,
391
392
        return self._real_bzrdir.clone(url, revision_id=revision_id,
392
393
            force_new_repo=force_new_repo, preserve_stacking=preserve_stacking)
393
394
 
394
 
    def get_config(self):
395
 
        self._ensure_real()
396
 
        return self._real_bzrdir.get_config()
 
395
    def _get_config(self):
 
396
        return RemoteBzrDirConfig(self)
397
397
 
398
398
 
399
399
class RemoteRepositoryFormat(repository.RepositoryFormat):
491
491
        # 1) get the network name to use.
492
492
        if self._custom_format:
493
493
            network_name = self._custom_format.network_name()
 
494
        elif self._network_name:
 
495
            network_name = self._network_name
494
496
        else:
495
497
            # Select the current bzrlib default and ask for that.
496
498
            reference_bzrdir_format = bzrdir.format_registry.get('default')()
625
627
    def abort_write_group(self, suppress_errors=False):
626
628
        """Complete a write group on the decorated repository.
627
629
 
628
 
        Smart methods peform operations in a single step so this api
 
630
        Smart methods perform operations in a single step so this API
629
631
        is not really applicable except as a compatibility thunk
630
632
        for older plugins that don't use e.g. the CommitBuilder
631
633
        facility.
649
651
    def commit_write_group(self):
650
652
        """Complete a write group on the decorated repository.
651
653
 
652
 
        Smart methods peform operations in a single step so this api
 
654
        Smart methods perform operations in a single step so this API
653
655
        is not really applicable except as a compatibility thunk
654
656
        for older plugins that don't use e.g. the CommitBuilder
655
657
        facility.
854
856
                self._real_repository.lock_read()
855
857
        else:
856
858
            self._lock_count += 1
 
859
        for repo in self._fallback_repositories:
 
860
            repo.lock_read()
857
861
 
858
862
    def _remote_lock_write(self, token):
859
863
        path = self.bzrdir._path_for_remote_call(self._client)
894
898
            raise errors.ReadOnlyError(self)
895
899
        else:
896
900
            self._lock_count += 1
 
901
        for repo in self._fallback_repositories:
 
902
            # Writes don't affect fallback repos
 
903
            repo.lock_read()
897
904
        return self._lock_token or None
898
905
 
899
906
    def leave_lock_in_place(self):
921
928
        if isinstance(repository, RemoteRepository):
922
929
            raise AssertionError()
923
930
        self._real_repository = repository
924
 
        # If the _real_repository has _fallback_repositories, clear them out,
925
 
        # because we want it to have the same set as this repository.  This is
926
 
        # reasonable to do because the fallbacks we clear here are from a
927
 
        # "real" branch, and we're about to replace them with the equivalents
928
 
        # from a RemoteBranch.
929
 
        self._real_repository._fallback_repositories = []
 
931
        # three code paths happen here:
 
932
        # 1) old servers, RemoteBranch.open() calls _ensure_real before setting
 
933
        # up stacking. In this case self._fallback_repositories is [], and the
 
934
        # real repo is already setup. Preserve the real repo and
 
935
        # RemoteRepository.add_fallback_repository will avoid adding
 
936
        # duplicates.
 
937
        # 2) new servers, RemoteBranch.open() sets up stacking, and when
 
938
        # ensure_real is triggered from a branch, the real repository to
 
939
        # set already has a matching list with separate instances, but
 
940
        # as they are also RemoteRepositories we don't worry about making the
 
941
        # lists be identical.
 
942
        # 3) new servers, RemoteRepository.ensure_real is triggered before
 
943
        # RemoteBranch.ensure real, in this case we get a repo with no fallbacks
 
944
        # and need to populate it.
 
945
        if (self._fallback_repositories and
 
946
            len(self._real_repository._fallback_repositories) !=
 
947
            len(self._fallback_repositories)):
 
948
            if len(self._real_repository._fallback_repositories):
 
949
                raise AssertionError(
 
950
                    "cannot cleanly remove existing _fallback_repositories")
930
951
        for fb in self._fallback_repositories:
931
952
            self._real_repository.add_fallback_repository(fb)
932
953
        if self._lock_mode == 'w':
939
960
    def start_write_group(self):
940
961
        """Start a write group on the decorated repository.
941
962
 
942
 
        Smart methods peform operations in a single step so this api
 
963
        Smart methods perform operations in a single step so this API
943
964
        is not really applicable except as a compatibility thunk
944
965
        for older plugins that don't use e.g. the CommitBuilder
945
966
        facility.
982
1003
            # problem releasing the vfs-based lock.
983
1004
            if old_mode == 'w':
984
1005
                # Only write-locked repositories need to make a remote method
985
 
                # call to perfom the unlock.
 
1006
                # call to perform the unlock.
986
1007
                old_token = self._lock_token
987
1008
                self._lock_token = None
988
1009
                if not self._leave_lock:
1061
1082
        # _real_branch had its get_stacked_on_url method called), then the
1062
1083
        # repository to be added may already be in the _real_repositories list.
1063
1084
        if self._real_repository is not None:
1064
 
            if repository not in self._real_repository._fallback_repositories:
 
1085
            fallback_locations = [repo.bzrdir.root_transport.base for repo in
 
1086
                self._real_repository._fallback_repositories]
 
1087
            if repository.bzrdir.root_transport.base not in fallback_locations:
1065
1088
                self._real_repository.add_fallback_repository(repository)
1066
 
        else:
1067
 
            # They are also seen by the fallback repository.  If it doesn't
1068
 
            # exist yet they'll be added then.  This implicitly copies them.
1069
 
            self._ensure_real()
1070
1089
 
1071
1090
    def add_inventory(self, revid, inv, parents):
1072
1091
        self._ensure_real()
1215
1234
            # in one go, and the user probably will have seen a warning about
1216
1235
            # the server being old anyhow.
1217
1236
            rg = self._get_revision_graph(None)
1218
 
            # There is an api discrepency between get_parent_map and
 
1237
            # There is an API discrepancy between get_parent_map and
1219
1238
            # get_revision_graph. Specifically, a "key:()" pair in
1220
1239
            # get_revision_graph just means a node has no parents. For
1221
1240
            # "get_parent_map" it means the node is a ghost. So fix up the
1271
1290
        # We don't need to send ghosts back to the server as a position to
1272
1291
        # stop either.
1273
1292
        stop_keys.difference_update(self._unstacked_provider.missing_keys)
 
1293
        key_count = len(parents_map)
 
1294
        if (NULL_REVISION in result_parents
 
1295
            and NULL_REVISION in self._unstacked_provider.missing_keys):
 
1296
            # If we pruned NULL_REVISION from the stop_keys because it's also
 
1297
            # in our cache of "missing" keys we need to increment our key count
 
1298
            # by 1, because the reconsitituted SearchResult on the server will
 
1299
            # still consider NULL_REVISION to be an included key.
 
1300
            key_count += 1
1274
1301
        included_keys = start_set.intersection(result_parents)
1275
1302
        start_set.difference_update(included_keys)
1276
 
        recipe = ('manual', start_set, stop_keys, len(parents_map))
 
1303
        recipe = ('manual', start_set, stop_keys, key_count)
1277
1304
        body = self._serialise_search_recipe(recipe)
1278
1305
        path = self.bzrdir._path_for_remote_call(self._client)
1279
1306
        for key in keys:
1619
1646
        if response[0][0] == 'missing-basis':
1620
1647
            tokens, missing_keys = bencode.bdecode_as_tuple(response[0][1])
1621
1648
            resume_tokens = tokens
1622
 
            return resume_tokens, missing_keys
 
1649
            return resume_tokens, set(missing_keys)
1623
1650
        else:
1624
1651
            self.target_repo.refresh_data()
1625
1652
            return [], set()
1897
1924
            self._real_branch.repository = self.repository
1898
1925
        else:
1899
1926
            self._real_branch = None
1900
 
        # Fill out expected attributes of branch for bzrlib api users.
 
1927
        # Fill out expected attributes of branch for bzrlib API users.
1901
1928
        self.base = self.bzrdir.root_transport.base
1902
1929
        self._control_files = None
1903
1930
        self._lock_mode = None
1936
1963
        except (errors.NotStacked, errors.UnstackableBranchFormat,
1937
1964
            errors.UnstackableRepositoryFormat), e:
1938
1965
            return
1939
 
        # it's relative to this branch...
1940
 
        fallback_url = urlutils.join(self.base, fallback_url)
1941
 
        transports = [self.bzrdir.root_transport]
1942
 
        stacked_on = branch.Branch.open(fallback_url,
1943
 
                                        possible_transports=transports)
1944
 
        self.repository.add_fallback_repository(stacked_on.repository)
 
1966
        self._activate_fallback_location(fallback_url, None)
 
1967
 
 
1968
    def _get_config(self):
 
1969
        return RemoteBranchConfig(self)
1945
1970
 
1946
1971
    def _get_real_transport(self):
1947
1972
        # if we try vfs access, return the real branch's vfs transport
2150
2175
                    self._real_branch.unlock()
2151
2176
                if mode != 'w':
2152
2177
                    # Only write-locked branched need to make a remote method
2153
 
                    # call to perfom the unlock.
 
2178
                    # call to perform the unlock.
2154
2179
                    return
2155
2180
                if not self._lock_token:
2156
2181
                    raise AssertionError('Locked, but no token!')
2277
2302
        self._ensure_real()
2278
2303
        return self._real_branch._get_parent_location()
2279
2304
 
2280
 
    def set_parent(self, url):
2281
 
        self._ensure_real()
2282
 
        return self._real_branch.set_parent(url)
2283
 
 
2284
2305
    def _set_parent_location(self, url):
2285
 
        # Used by tests, to poke bad urls into branch configurations
2286
 
        if url is None:
2287
 
            self.set_parent(url)
2288
 
        else:
2289
 
            self._ensure_real()
2290
 
            return self._real_branch._set_parent_location(url)
2291
 
 
2292
 
    def set_stacked_on_url(self, stacked_location):
2293
 
        """Set the URL this branch is stacked against.
2294
 
 
2295
 
        :raises UnstackableBranchFormat: If the branch does not support
2296
 
            stacking.
2297
 
        :raises UnstackableRepositoryFormat: If the repository does not support
2298
 
            stacking.
2299
 
        """
 
2306
        medium = self._client._medium
 
2307
        if medium._is_remote_before((1, 15)):
 
2308
            return self._vfs_set_parent_location(url)
 
2309
        try:
 
2310
            call_url = url or ''
 
2311
            if type(call_url) is not str:
 
2312
                raise AssertionError('url must be a str or None (%s)' % url)
 
2313
            response = self._call('Branch.set_parent_location',
 
2314
                self._remote_path(), self._lock_token, self._repo_lock_token,
 
2315
                call_url)
 
2316
        except errors.UnknownSmartMethod:
 
2317
            medium._remember_remote_is_before((1, 15))
 
2318
            return self._vfs_set_parent_location(url)
 
2319
        if response != ():
 
2320
            raise errors.UnexpectedSmartServerResponse(response)
 
2321
 
 
2322
    def _vfs_set_parent_location(self, url):
2300
2323
        self._ensure_real()
2301
 
        return self._real_branch.set_stacked_on_url(stacked_location)
 
2324
        return self._real_branch._set_parent_location(url)
2302
2325
 
2303
2326
    @needs_write_lock
2304
2327
    def pull(self, source, overwrite=False, stop_revision=None,
2372
2395
        return self._real_branch.set_push_location(location)
2373
2396
 
2374
2397
 
 
2398
class RemoteConfig(object):
 
2399
    """A Config that reads and writes from smart verbs.
 
2400
 
 
2401
    It is a low-level object that considers config data to be name/value pairs
 
2402
    that may be associated with a section. Assigning meaning to the these
 
2403
    values is done at higher levels like bzrlib.config.TreeConfig.
 
2404
    """
 
2405
 
 
2406
    def get_option(self, name, section=None, default=None):
 
2407
        """Return the value associated with a named option.
 
2408
 
 
2409
        :param name: The name of the value
 
2410
        :param section: The section the option is in (if any)
 
2411
        :param default: The value to return if the value is not set
 
2412
        :return: The value or default value
 
2413
        """
 
2414
        try:
 
2415
            configobj = self._get_configobj()
 
2416
            if section is None:
 
2417
                section_obj = configobj
 
2418
            else:
 
2419
                try:
 
2420
                    section_obj = configobj[section]
 
2421
                except KeyError:
 
2422
                    return default
 
2423
            return section_obj.get(name, default)
 
2424
        except errors.UnknownSmartMethod:
 
2425
            return self._vfs_get_option(name, section, default)
 
2426
 
 
2427
    def _response_to_configobj(self, response):
 
2428
        if len(response[0]) and response[0][0] != 'ok':
 
2429
            raise errors.UnexpectedSmartServerResponse(response)
 
2430
        lines = response[1].read_body_bytes().splitlines()
 
2431
        return config.ConfigObj(lines, encoding='utf-8')
 
2432
 
 
2433
 
 
2434
class RemoteBranchConfig(RemoteConfig):
 
2435
    """A RemoteConfig for Branches."""
 
2436
 
 
2437
    def __init__(self, branch):
 
2438
        self._branch = branch
 
2439
 
 
2440
    def _get_configobj(self):
 
2441
        path = self._branch._remote_path()
 
2442
        response = self._branch._client.call_expecting_body(
 
2443
            'Branch.get_config_file', path)
 
2444
        return self._response_to_configobj(response)
 
2445
 
 
2446
    def set_option(self, value, name, section=None):
 
2447
        """Set the value associated with a named option.
 
2448
 
 
2449
        :param value: The value to set
 
2450
        :param name: The name of the value to set
 
2451
        :param section: The section the option is in (if any)
 
2452
        """
 
2453
        medium = self._branch._client._medium
 
2454
        if medium._is_remote_before((1, 14)):
 
2455
            return self._vfs_set_option(value, name, section)
 
2456
        try:
 
2457
            path = self._branch._remote_path()
 
2458
            response = self._branch._client.call('Branch.set_config_option',
 
2459
                path, self._branch._lock_token, self._branch._repo_lock_token,
 
2460
                value.encode('utf8'), name, section or '')
 
2461
        except errors.UnknownSmartMethod:
 
2462
            medium._remember_remote_is_before((1, 14))
 
2463
            return self._vfs_set_option(value, name, section)
 
2464
        if response != ():
 
2465
            raise errors.UnexpectedSmartServerResponse(response)
 
2466
 
 
2467
    def _real_object(self):
 
2468
        self._branch._ensure_real()
 
2469
        return self._branch._real_branch
 
2470
 
 
2471
    def _vfs_set_option(self, value, name, section=None):
 
2472
        return self._real_object()._get_config().set_option(
 
2473
            value, name, section)
 
2474
 
 
2475
 
 
2476
class RemoteBzrDirConfig(RemoteConfig):
 
2477
    """A RemoteConfig for BzrDirs."""
 
2478
 
 
2479
    def __init__(self, bzrdir):
 
2480
        self._bzrdir = bzrdir
 
2481
 
 
2482
    def _get_configobj(self):
 
2483
        medium = self._bzrdir._client._medium
 
2484
        verb = 'BzrDir.get_config_file'
 
2485
        if medium._is_remote_before((1, 15)):
 
2486
            raise errors.UnknownSmartMethod(verb)
 
2487
        path = self._bzrdir._path_for_remote_call(self._bzrdir._client)
 
2488
        response = self._bzrdir._call_expecting_body(
 
2489
            verb, path)
 
2490
        return self._response_to_configobj(response)
 
2491
 
 
2492
    def _vfs_get_option(self, name, section, default):
 
2493
        return self._real_object()._get_config().get_option(
 
2494
            name, section, default)
 
2495
 
 
2496
    def set_option(self, value, name, section=None):
 
2497
        """Set the value associated with a named option.
 
2498
 
 
2499
        :param value: The value to set
 
2500
        :param name: The name of the value to set
 
2501
        :param section: The section the option is in (if any)
 
2502
        """
 
2503
        return self._real_object()._get_config().set_option(
 
2504
            value, name, section)
 
2505
 
 
2506
    def _real_object(self):
 
2507
        self._bzrdir._ensure_real()
 
2508
        return self._bzrdir._real_bzrdir
 
2509
 
 
2510
 
 
2511
 
2375
2512
def _extract_tar(tar, to_dir):
2376
2513
    """Extract all the contents of a tarfile object.
2377
2514