~bzr-explorer-dev/bzr-explorer/ppa

« back to all changes in this revision

Viewing changes to lib/workspace_models.py

  • Committer: Andrew Starr-Bochicchio
  • Date: 2010-01-24 00:35:42 UTC
  • mfrom: (321.1.4 unstable)
  • Revision ID: a.starr.b@gmail.com-20100124003542-dkgsjwbqllkoeib2
* New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
 
"""Initialization of a repository and/or branch for common workspace models."""
 
17
"""Initialization of a repository, branch and tree in various ways."""
18
18
 
19
19
 
20
20
from bzrlib.lazy_import import lazy_import
21
21
lazy_import(globals(), '''
22
22
 
 
23
import os
 
24
 
23
25
from bzrlib import (
24
26
    builtins,
25
27
    bzrdir,
26
28
    commands,
27
29
    errors,
28
30
    osutils,
 
31
    registry,
29
32
    trace,
30
33
    transport,
31
34
    )
32
35
from bzrlib.trace import note, mutter
33
36
''')
34
 
 
35
 
 
36
 
# Model identifiers
37
 
MODEL_FEATURE_BRANCHES = "feature-branches"
38
 
MODEL_SHARED_TREE = "shared-tree"
39
 
MODEL_PLAIN_BRANCH = "plain-branch"
40
 
MODEL_SHARED_REPO = "shared-repo"
41
 
MODEL_SHARED_REPO_NO_TREES = "shared-repo-no-trees"
 
37
from bzrlib.option import Option, RegistryOption
42
38
 
43
39
 
44
40
class MissingParentDirectory(errors.BzrError):
58
54
 
59
55
 
60
56
def init_workspace(location, model=None, format=None, create_parent_dirs=False,
61
 
    trunk_name='trunk', work_name='work', outf=None):
 
57
    outf=None, model_params=None):
62
58
    """Initialise a workspace.
63
59
    
64
60
    :param location: base location of the workspace
65
 
    :param model: one of the following:
66
 
        * feature-branches - create a shared repository at location
67
 
          then create a trunk branch inside it (default)
68
 
        * shared-tree - create a (no-trees) shared repository at location,
69
 
          then create a trunk branch and separate working tree
70
 
          (lightweight checkout) inside it
71
 
        * plain-branch - create a plain branch at location; if inside a
72
 
          shared repository, that will be used, otherwise the branch will
73
 
          be a standalone branch
74
 
        * shared-repo - create a shared repository at location
75
 
        * shared-repo-no-trees - create a shared repository at location
76
 
          and configure it so branches have no trees
 
61
    :param model: the workspace model to use
77
62
    :param format: storage format to use
78
63
    :param create_parent_dirs: create parent directories of location if
79
64
      they don't already exist
80
 
    :param trunk_name: name of trunk branch for feature-branches and
81
 
      shared-tree models
82
 
    :param work_name: name of trunk branch for feature-branches and
83
 
      shared-tree models
84
65
    :param outf: output stream; if None, standard output is used
 
66
    :param model_params: a dictionary of model-specific parameters
85
67
    """
86
 
    # Assign defaults to parameters
 
68
    # Assign defaults
87
69
    if model is None:
88
 
        model = MODEL_FEATURE_BRANCHES
 
70
        model = workspace_model_registry.get()
89
71
    if format is None:
90
72
        format = bzrdir.format_registry.make_bzrdir('default')
91
73
    if outf is None:
95
77
    # Create the parent directories if required
96
78
    _ensure_base_of_location(location, create_parent_dirs)
97
79
 
98
 
    # For feature branching, we need to start with a trunk
99
 
    # branch in a shared repository
100
 
    if model == MODEL_FEATURE_BRANCHES:
101
 
        trunk_location = osutils.pathjoin(location, trunk_name)
102
 
        _init_repository(outf, location, format)
103
 
        _init_branch(outf, trunk_location, format)
104
 
 
105
 
    # For the shared tree model, we start with a treeless shared repository,
106
 
    # create a trunk branch and then a work checkout pointing to that trunk
107
 
    elif model == MODEL_SHARED_TREE:
108
 
        trunk_location = osutils.pathjoin(location, trunk_name)
109
 
        work_location = osutils.pathjoin(location, work_name)
110
 
        _init_repository(outf, location, format, no_trees=True)
111
 
        _init_branch(outf, trunk_location, format)
112
 
        _init_working_tree(outf, trunk_location, work_location)
113
 
 
114
 
    elif model == MODEL_PLAIN_BRANCH:
115
 
        _init_branch(outf, location, format)
116
 
    elif model == MODEL_SHARED_REPO:
117
 
        _init_repository(outf, location, format)
118
 
    elif model == MODEL_SHARED_REPO_NO_TREES:
119
 
        _init_repository(outf, location, format, no_trees=True)
 
80
    # Build the workspace
 
81
    ws_model = model()
 
82
    if model_params:
 
83
        model_params = dict([(k.replace('-', '_'), v)
 
84
            for k, v in model_params.items()])
120
85
    else:
121
 
        raise UnknownWorkspaceModel(model)
 
86
        model_params = {}
 
87
    repo_dir, branch_dir, tree_dir = ws_model.build(outf, location,
 
88
        format, **model_params)
 
89
 
 
90
    # Move existing files if this is required
 
91
    #if tree_dir != location:
 
92
    #    mutter("moving files from %s to %s" % (location, tree_dir))
122
93
 
123
94
 
124
95
def _ensure_base_of_location(location, create_parent_dirs):
134
105
        to_transport.create_prefix()
135
106
 
136
107
 
137
 
def _init_repository(outf, location, format, no_trees=False):
 
108
## Helper routines for building workspaces ##
 
109
 
 
110
def init_repository(outf, location, format, no_trees=False):
138
111
    """Initialise a repository."""
139
112
    old_verbosity = trace.get_verbosity_level()
140
113
    trace.set_verbosity_level(-1)
149
122
        note("Created repository at %s" % (location,))
150
123
 
151
124
 
152
 
def _init_branch(outf, location, format):
 
125
def init_branch(outf, location, format):
153
126
    """Initialise a branch."""
154
127
    old_verbosity = trace.get_verbosity_level()
155
128
    trace.set_verbosity_level(-1)
161
134
    note("Created branch at %s" % (location,))
162
135
 
163
136
 
164
 
def _init_working_tree(outf, branch_location, to_location):
 
137
def init_working_tree(outf, branch_location, to_location):
165
138
    """Initialise a lightweight checkout to use as a working tree."""
166
139
    old_verbosity = trace.get_verbosity_level()
167
140
    trace.set_verbosity_level(-1)
179
152
    # setup a fresh one here
180
153
    cmd_obj.outf = outf
181
154
    return cmd_obj
 
155
 
 
156
 
 
157
## The workspace model registry ##
 
158
 
 
159
class WorkspaceModel(object):
 
160
    """Abstract workspace model.
 
161
    
 
162
    The following attributes may be defined:
 
163
        
 
164
    * title - the label for this model in the GUI
 
165
    * just_repository - if True, this model only creates a repository
 
166
    * parameters - a list of model-specific options
 
167
    """
 
168
 
 
169
    title = "???"
 
170
    just_repository = False
 
171
    parameters = []
 
172
    
 
173
    def build(self, outf, location, format, **model_params):
 
174
        """Build a workspace.
 
175
 
 
176
        :param outf: the output file for reporting actions
 
177
        :param location: the location of the workspace
 
178
        :param format: the format to use
 
179
        :param model_params: model-specific parameters
 
180
        :return: repo_dir, branch_dir, tree_dir - the directories
 
181
            created for the various parts, if any.
 
182
        """
 
183
        raise NotImplementedError(WorkspaceModel.build)
 
184
 
 
185
 
 
186
class WorkspaceModelRegistry(registry.Registry):
 
187
    """Registry for workspace models.
 
188
    
 
189
    The registered object should be a WorkspaceModel.
 
190
    The doc-string for the registered object will be used as help by default.
 
191
    """
 
192
 
 
193
    def get_help(self, key=None):
 
194
        result = registry.Registry.get_help(self, key)
 
195
        if result is None:
 
196
            from inspect import getdoc
 
197
            model = self.get(key)
 
198
            result = getdoc(model)
 
199
        return result
 
200
 
 
201
 
 
202
workspace_model_registry = WorkspaceModelRegistry()
 
203
 
 
204
 
 
205
## Standard workspace models ##
 
206
 
 
207
class FeatureBranchesWorkspaceModel(WorkspaceModel):
 
208
    """Create a shared repository at location then create a trunk branch inside it."""
 
209
 
 
210
    title = "Feature branches"
 
211
    parameters = [
 
212
             Option('with-shared-tree',
 
213
                 help='Create a work checkout to share across branches.'),
 
214
            ]
 
215
 
 
216
    def build(self, outf, location, format, with_shared_tree=False):
 
217
        trunk_location = osutils.pathjoin(location, 'trunk')
 
218
        if with_shared_tree:
 
219
            work_location = osutils.pathjoin(location, 'work')
 
220
            init_repository(outf, location, format, no_trees=True)
 
221
            init_branch(outf, trunk_location, format)
 
222
            init_working_tree(outf, trunk_location, work_location)
 
223
        else:
 
224
            init_repository(outf, location, format)
 
225
            init_branch(outf, trunk_location, format)
 
226
            work_location = trunk_location
 
227
        return location, trunk_location, work_location
 
228
 
 
229
 
 
230
_repo_in_registry = registry.Registry()
 
231
_repo_in_registry.register(".bzrbranches", ".bzrbranches",
 
232
    help="Put repository in .bzrbranches")
 
233
_repo_in_registry.register(".bzr/branches", ".bzr/branches",
 
234
    help="Put repository in .bzr/branches")
 
235
_repo_in_registry.default_key = ".bzrbranches"
 
236
 
 
237
 
 
238
class ColocatedBranchesWorkspaceModel(WorkspaceModel):
 
239
    """Create a working tree at location pointing to a trunk branch
 
240
    in an embedded (no-trees) shared repository.
 
241
    """
 
242
 
 
243
    title = "Colocated branches"
 
244
    parameters = [
 
245
             RegistryOption('repository-location',
 
246
                 registry=_repo_in_registry,
 
247
                 help="Location for the shared repository."),
 
248
            ]
 
249
 
 
250
    def build(self, outf, location, format, repository_location=None):
 
251
        if repository_location is None:
 
252
            repository_location = _repo_in_registry.get()
 
253
        if repository_location == '.bzrbranches':
 
254
            repo_location = osutils.pathjoin(location, ".bzrbranches")
 
255
            trunk_location = osutils.pathjoin(repo_location, 'trunk')
 
256
            init_repository(outf, repo_location, format, no_trees=True)
 
257
            init_branch(outf, trunk_location, format)
 
258
            init_working_tree(outf, trunk_location, location)
 
259
        else:
 
260
            # Note: These os calls should become transport calls to
 
261
            # ensure this works on non-local transports ...
 
262
            bzr_location = osutils.pathjoin(location, ".bzr")
 
263
            os.mkdir(bzr_location)
 
264
            repo_location = osutils.pathjoin(bzr_location, "branches")
 
265
            trunk_location = osutils.pathjoin(repo_location, 'trunk')
 
266
            init_repository(outf, repo_location, format, no_trees=True)
 
267
            init_branch(outf, trunk_location, format)
 
268
            # Move the .bzr directory aside so we can create the checkout
 
269
            tmp_location = osutils.pathjoin(location, ".bzr-tmp")
 
270
            os.rename(bzr_location, tmp_location)
 
271
            try:
 
272
                tmp_repo = osutils.pathjoin(tmp_location, "branches")
 
273
                tmp_trunk = osutils.pathjoin(tmp_repo, "trunk")
 
274
                init_working_tree(outf, tmp_trunk, location)
 
275
                # Now move the repository into the .bzr directory.
 
276
                os.rename(tmp_repo, repo_location)
 
277
            finally:
 
278
                os.rmdir(tmp_location)
 
279
            # Update the checkout reference
 
280
            self._switch_checkout(location, trunk_location)
 
281
        return repo_location, trunk_location, location
 
282
 
 
283
    def _switch_checkout(self, checkout_location, branch_location):
 
284
        from bzrlib.branch import Branch
 
285
        control = bzrdir.BzrDir.open(checkout_location)
 
286
        to_branch = Branch.open(branch_location)
 
287
        control.find_branch_format().set_reference(control, to_branch)
 
288
 
 
289
 
 
290
class PlainBranchWorkspaceModel(WorkspaceModel):
 
291
    """Create a plain branch at location;
 
292
    if inside a shared repository, that will be used,
 
293
    otherwise the branch will be a standalone branch.
 
294
    """
 
295
 
 
296
    title = "Plain branch"
 
297
 
 
298
    def build(self, outf, location, format):
 
299
        init_branch(outf, location, format)
 
300
        return None, location, location
 
301
 
 
302
 
 
303
class SharedRepoWorkspaceModel(WorkspaceModel):
 
304
    """Create a shared repository at location."""
 
305
 
 
306
    title = "Shared repository"
 
307
    just_repository = True
 
308
    parameters = [
 
309
             Option('no-trees',
 
310
                 help='Branches in the repository will default to'
 
311
                      ' not having a working tree.'),
 
312
            ]
 
313
 
 
314
    def build(self, outf, location, format, no_trees=False):
 
315
        init_repository(outf, location, format, no_trees=no_trees)
 
316
        return location, None, None
 
317
 
 
318
 
 
319
workspace_model_registry.register("feature-branches",
 
320
    FeatureBranchesWorkspaceModel)
 
321
workspace_model_registry.register("colocated-branches",
 
322
        ColocatedBranchesWorkspaceModel)
 
323
workspace_model_registry.register("plain-branch", PlainBranchWorkspaceModel)
 
324
workspace_model_registry.register("shared-repository", SharedRepoWorkspaceModel)
 
325
workspace_model_registry.default_key = "feature-branches"