1# Copyright 2013 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5from caching_file_system import CachingFileSystem 6from local_file_system import LocalFileSystem 7from offline_file_system import OfflineFileSystem 8from subversion_file_system import SubversionFileSystem 9from third_party.json_schema_compiler.memoize import memoize 10 11 12class HostFileSystemProvider(object): 13 '''Provides host file systems ("host" meaning the file system that hosts the 14 server's source code and templates) tracking trunk, or any branch. 15 16 File system instances are memoized to maintain the in-memory caches across 17 multiple callers. 18 ''' 19 def __init__(self, 20 object_store_creator, 21 max_trunk_revision=None, 22 default_trunk_instance=None, 23 offline=False, 24 constructor_for_test=None): 25 ''' 26 |object_store_creator| 27 Provides caches for file systems that need one. 28 |max_trunk_revision| 29 If not None, the maximum revision that a 'trunk' file system will be 30 created at. If None, 'trunk' file systems will use HEAD. 31 |default_trunk_instance| 32 If not None, 'trunk' file systems provided by this class without a 33 specific revision will return |default_trunk_instance| instead. 34 |offline| 35 If True all provided file systems will be wrapped in an OfflineFileSystem. 36 |constructor_for_test| 37 Provides a custom constructor rather than creating SubversionFileSystems. 38 ''' 39 self._object_store_creator = object_store_creator 40 self._max_trunk_revision = max_trunk_revision 41 self._default_trunk_instance = default_trunk_instance 42 self._offline = offline 43 self._constructor_for_test = constructor_for_test 44 45 @memoize 46 def GetTrunk(self, revision=None): 47 '''Gets a file system tracking 'trunk'. Use this method rather than 48 GetBranch('trunk') because the behaviour is subtly different; 'trunk' can 49 be pinned to a max revision (|max_trunk_revision| in constructor) and can 50 have its default instance overridden (|default_trunk_instance| in 51 constructor). 52 53 |revision| if non-None determines a specific revision to pin the host file 54 system at, though it will be ignored if it exceeds |max_trunk_revision|. 55 If None then |revision| will track |max_trunk_revision| if is has been 56 set, or just HEAD (which might change during server runtime!). 57 ''' 58 if revision is None: 59 if self._default_trunk_instance is not None: 60 return self._default_trunk_instance 61 return self._Create('trunk', revision=self._max_trunk_revision) 62 if self._max_trunk_revision is not None: 63 revision = min(revision, self._max_trunk_revision) 64 return self._Create('trunk', revision=revision) 65 66 @memoize 67 def GetBranch(self, branch): 68 '''Gets a file system tracking |branch|, for example '1150' - anything other 69 than 'trunk', which must be constructed via the GetTrunk() method. 70 71 Note: Unlike GetTrunk this function doesn't take a |revision| argument 72 since we assume that branches hardly ever change, while trunk frequently 73 changes. 74 ''' 75 assert isinstance(branch, basestring), 'Branch %s must be a string' % branch 76 assert branch != 'trunk', 'Cannot specify branch=\'trunk\', use GetTrunk()' 77 return self._Create(branch) 78 79 def _Create(self, branch, revision=None): 80 '''Creates SVN file systems (or if in a test, potentially whatever 81 |self._constructor_for_test specifies). Wraps the resulting file system in 82 an Offline file system if the offline flag is set, and finally wraps it in 83 a Caching file system. 84 ''' 85 if self._constructor_for_test is not None: 86 file_system = self._constructor_for_test(branch=branch, revision=revision) 87 else: 88 file_system = SubversionFileSystem.Create(branch=branch, 89 revision=revision) 90 if self._offline: 91 file_system = OfflineFileSystem(file_system) 92 return CachingFileSystem(file_system, self._object_store_creator) 93 94 @staticmethod 95 def ForLocal(object_store_creator, **optargs): 96 '''Used in creating a server instance on localhost. 97 ''' 98 return HostFileSystemProvider( 99 object_store_creator, 100 constructor_for_test=lambda **_: LocalFileSystem.Create(), 101 **optargs) 102 103 @staticmethod 104 def ForTest(file_system, object_store_creator, **optargs): 105 '''Used in creating a test server instance. The HostFileSystemProvider 106 returned here will always return |file_system| when its Create() method is 107 called. 108 ''' 109 return HostFileSystemProvider( 110 object_store_creator, 111 constructor_for_test=lambda **_: file_system, 112 **optargs) 113