25
25
At the moment every WorkingTree has its own branch. Remote
26
26
WorkingTrees aren't supported.
28
To get a WorkingTree, call WorkingTree(dir[, branch])
28
To get a WorkingTree, call bzrdir.open_workingtree() or
29
WorkingTree.open(dir).
186
187
not listed in the Inventory and vice versa.
189
def __init__(self, basedir='.', branch=None, _inventory=None, _control_files=None):
190
def __init__(self, basedir='.', branch=None, _inventory=None, _control_files=None, _internal=False):
190
191
"""Construct a WorkingTree for basedir.
192
193
If the branch is not supplied, it is opened automatically.
194
195
(branch.base is not cross checked, because for remote branches that
195
196
would be meaningless).
199
# created via open etc.
200
wt = WorkingTree.open(basedir, branch)
201
self.branch = wt.branch
202
self.basedir = wt.basedir
203
self._control_files = wt._control_files
204
self._hashcache = wt._hashcache
205
self._set_inventory(wt._inventory)
197
206
from bzrlib.hashcache import HashCache
198
207
from bzrlib.trace import note, mutter
199
208
assert isinstance(basedir, basestring), \
244
253
self.path2id = self._inventory.path2id
256
def open(path=None, _unsupported=False):
257
"""Open an existing working tree at path.
261
path = os.path.getcwdu()
262
control = bzrdir.BzrDir.open(path, _unsupported)
263
return control.open_workingtree(_unsupported)
247
266
def open_containing(path=None):
248
267
"""Open an existing working tree which has its root about path.
255
274
If there is one, it is returned, along with the unused portion of path.
261
if path.find('://') != -1:
262
raise NotBranchError(path=path)
268
return WorkingTree(path), tail
269
except NotBranchError:
272
tail = pathjoin(os.path.basename(path), tail)
274
tail = os.path.basename(path)
276
path = os.path.dirname(path)
278
# reached the root, whatever that may be
279
raise NotBranchError(path=orig_path)
278
control, relpath = bzrdir.BzrDir.open_containing(path)
279
return control.open_workingtree(), relpath
282
def open_downlevel(path=None):
283
"""Open an unsupported working tree.
285
Only intended for advanced situations like upgrading part of a bzrdir.
287
return WorkingTree.open(path, _unsupported=True)
281
289
def __iter__(self):
282
290
"""Iterate through file_ids for this tree.
325
333
XXX: When BzrDir is present, these should be created through that
326
334
interface instead.
336
transport = get_transport(directory)
337
if branch.bzrdir.transport.clone('..').base == transport.base:
339
return branch.bzrdir.create_workingtree()
340
# different directory,
341
# create a branch reference
342
# and now a working tree.
343
raise NotImplementedError
329
345
os.mkdir(directory)
330
346
except OSError, e:
338
354
revision_tree = branch.repository.revision_tree(branch.last_revision())
339
355
inv = revision_tree.inventory
340
wt = WorkingTree(directory, branch, inv)
356
wt = WorkingTree(directory, branch, inv, _internal=True)
341
357
wt._write_inventory(inv)
342
358
wt.set_root_id(revision_tree.inventory.root.file_id)
343
359
if branch.last_revision() is not None:
366
@deprecated_method(zero_eight)
350
367
def create_standalone(directory):
351
368
"""Create a checkout and a branch and a repo at directory.
353
370
Directory must exist and be empty.
355
XXX: When BzrDir is present, these should be created through that
372
please use BzrDir.create_standalone_workingtree
358
directory = safe_unicode(directory)
359
b = bzrdir.BzrDir.create_branch_and_repo(directory)
360
return WorkingTree.create(b, directory)
374
return bzrdir.BzrDir.create_standalone_workingtree(directory)
362
376
def relpath(self, abs):
363
377
"""Return the local path portion from a given absolute path."""
1127
1141
object will be created every time regardless.
1144
_default_format = None
1145
"""The default format used for new trees."""
1148
"""The known formats."""
1151
def find_format(klass, a_bzrdir):
1152
"""Return the format for the working tree object in a_bzrdir."""
1154
transport = a_bzrdir.get_workingtree_transport(None)
1155
format_string = transport.get("format").read()
1156
return klass._formats[format_string]
1158
raise errors.NotBranchError(path=transport.base)
1160
raise errors.UnknownFormatError(format_string)
1163
def get_default_format(klass):
1164
"""Return the current default format."""
1165
return klass._default_format
1130
1167
def get_format_string(self):
1131
1168
"""Return the ASCII format string that identifies this format."""
1132
1169
raise NotImplementedError(self.get_format_string)
1171
def is_supported(self):
1172
"""Is this format supported?
1174
Supported formats can be initialized and opened.
1175
Unsupported formats may not support initialization or committing or
1176
some other features depending on the reason for not being supported.
1181
def register_format(klass, format):
1182
klass._formats[format.get_format_string()] = format
1185
def set_default_format(klass, format):
1186
klass._default_format = format
1189
def unregister_format(klass, format):
1190
assert klass._formats[format.get_format_string()] is format
1191
del klass._formats[format.get_format_string()]
1136
1195
class WorkingTreeFormat2(WorkingTreeFormat):
1143
1202
"""See WorkingTreeFormat.initialize()."""
1144
1203
if not isinstance(a_bzrdir.transport, LocalTransport):
1145
1204
raise errors.NotLocalUrl(a_bzrdir.transport.base)
1146
result = WorkingTree.create(a_bzrdir.open_branch(),
1147
a_bzrdir.transport.clone('..').base)
1148
result.bzrdir = a_bzrdir
1149
result._format = self
1205
b = a_bzrdir.open_branch()
1206
r = a_bzrdir.open_repository()
1207
revision = b.last_revision()
1208
basis_tree = r.revision_tree(revision)
1209
inv = basis_tree.inventory
1210
wt = WorkingTree(a_bzrdir.transport.clone('..').base, b, inv, _internal=True)
1211
wt._write_inventory(inv)
1212
wt.set_root_id(inv.root.file_id)
1213
wt.set_last_revision(revision)
1214
wt.set_pending_merges([])
1216
wt.bzrdir = a_bzrdir
1221
super(WorkingTreeFormat2, self).__init__()
1222
self._matchingbzrdir = bzrdir.BzrDirFormat6()
1152
1224
def open(self, a_bzrdir, _found=False):
1153
1225
"""Return the WorkingTree object for a_bzrdir
1159
1231
# we are being called directly and must probe.
1160
1232
raise NotImplementedError
1161
result = WorkingTree(a_bzrdir.transport.clone('..').base)
1233
if not isinstance(a_bzrdir.transport, LocalTransport):
1234
raise errors.NotLocalUrl(a_bzrdir.transport.base)
1235
result = WorkingTree(a_bzrdir.transport.clone('..').base, _internal=True)
1162
1236
result.bzrdir = a_bzrdir
1163
1237
result._format = self
1178
1252
"""See WorkingTreeFormat.initialize()."""
1179
1253
if not isinstance(a_bzrdir.transport, LocalTransport):
1180
1254
raise errors.NotLocalUrl(a_bzrdir.transport.base)
1181
result = WorkingTree.create(a_bzrdir.open_branch(),
1182
a_bzrdir.transport.clone('..').base)
1183
result.bzrdir = a_bzrdir
1184
result._format = self
1255
transport = a_bzrdir.get_workingtree_transport(self)
1256
control_files = LockableFiles(transport, 'lock')
1257
control_files.put_utf8('format', self.get_format_string())
1258
b = a_bzrdir.open_branch()
1259
r = a_bzrdir.open_repository()
1260
revision = b.last_revision()
1261
basis_tree = r.revision_tree(revision)
1262
inv = basis_tree.inventory
1263
wt = WorkingTree(a_bzrdir.transport.clone('..').base, b, inv, _internal=True)
1264
wt._write_inventory(inv)
1265
wt.set_root_id(inv.root.file_id)
1266
wt.set_last_revision(revision)
1267
wt.set_pending_merges([])
1269
wt.bzrdir = a_bzrdir
1274
super(WorkingTreeFormat3, self).__init__()
1275
self._matchingbzrdir = bzrdir.BzrDirMetaFormat1()
1187
1277
def open(self, a_bzrdir, _found=False):
1188
1278
"""Return the WorkingTree object for a_bzrdir
1194
1284
# we are being called directly and must probe.
1195
1285
raise NotImplementedError
1196
result = WorkingTree(a_bzrdir.transport.clone('..').base)
1286
if not isinstance(a_bzrdir.transport, LocalTransport):
1287
raise errors.NotLocalUrl(a_bzrdir.transport.base)
1288
result = WorkingTree(a_bzrdir.transport.clone('..').base, _internal=True)
1197
1289
result.bzrdir = a_bzrdir
1198
1290
result._format = self
1294
# formats which have no format string are not discoverable
1295
# and not independently creatable, so are not registered.
1296
__default_format = WorkingTreeFormat3()
1297
WorkingTreeFormat.register_format(__default_format)
1298
WorkingTreeFormat.set_default_format(__default_format)
1299
_legacy_formats = [WorkingTreeFormat2(),
1303
class WorkingTreeTestProviderAdapter(object):
1304
"""A tool to generate a suite testing multiple workingtree formats at once.
1306
This is done by copying the test once for each transport and injecting
1307
the transport_server, transport_readonly_server, and workingtree_format
1308
classes into each copy. Each copy is also given a new id() to make it
1312
def __init__(self, transport_server, transport_readonly_server, formats):
1313
self._transport_server = transport_server
1314
self._transport_readonly_server = transport_readonly_server
1315
self._formats = formats
1317
def adapt(self, test):
1318
from bzrlib.tests import TestSuite
1319
result = TestSuite()
1320
for workingtree_format, bzrdir_format in self._formats:
1321
new_test = deepcopy(test)
1322
new_test.transport_server = self._transport_server
1323
new_test.transport_readonly_server = self._transport_readonly_server
1324
new_test.bzrdir_format = bzrdir_format
1325
new_test.workingtree_format = workingtree_format
1326
def make_new_test_id():
1327
new_id = "%s(%s)" % (new_test.id(), workingtree_format.__class__.__name__)
1328
return lambda: new_id
1329
new_test.id = make_new_test_id()
1330
result.addTest(new_test)