1
# Copyright (C) 2005, 2006, 2007, 2008 Canonical Ltd
1
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
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
246
246
# permitted to do this.
247
247
self._set_inventory(_inventory, dirty=False)
248
248
self._detect_case_handling()
249
self._rules_searcher = None
251
250
def _detect_case_handling(self):
252
251
wt_trans = self.bzrdir.get_workingtree_transport(None)
306
path = osutils.getcwd()
305
path = os.path.getcwdu()
307
306
control = bzrdir.BzrDir.open(path, _unsupported)
308
307
return control.open_workingtree(_unsupported)
311
310
def open_containing(path=None):
312
311
"""Open an existing working tree which has its root about path.
314
313
This probes for a working tree at path and searches upwards from there.
316
315
Basically we keep looking up until we find the control directory or
379
378
"""Return RevisionTree for the current last revision.
381
380
If the left most parent is a ghost then the returned tree will be an
382
empty tree - one obtained by calling
383
repository.revision_tree(NULL_REVISION).
381
empty tree - one obtained by calling repository.revision_tree(None).
386
384
revision_id = self.get_parent_ids()[0]
388
386
# no parents, return an empty revision tree.
389
387
# in the future this should return the tree for
390
388
# 'empty:' - the implicit root empty tree.
391
return self.branch.repository.revision_tree(
392
_mod_revision.NULL_REVISION)
389
return self.branch.repository.revision_tree(None)
394
391
return self.revision_tree(revision_id)
395
392
except errors.NoSuchRevision:
399
396
# at this point ?
401
398
return self.branch.repository.revision_tree(revision_id)
402
except (errors.RevisionNotPresent, errors.NoSuchRevision):
399
except errors.RevisionNotPresent:
403
400
# the basis tree *may* be a ghost or a low level error may have
404
401
# occured. If the revision is present, its a problem, if its not
406
403
if self.branch.repository.has_revision(revision_id):
408
405
# the basis tree is a ghost so return an empty tree.
409
return self.branch.repository.revision_tree(
410
_mod_revision.NULL_REVISION)
406
return self.branch.repository.revision_tree(None)
412
408
def _cleanup(self):
413
409
self._flush_ignore_list_cache()
424
420
return osutils.lexists(self.abspath(filename))
426
422
def get_file(self, file_id, path=None):
427
return self.get_file_with_stat(file_id, path)[0]
429
def get_file_with_stat(self, file_id, path=None, _fstat=os.fstat):
430
"""See MutableTree.get_file_with_stat."""
432
424
path = self.id2path(file_id)
433
file_obj = self.get_file_byname(path)
434
return (file_obj, _fstat(file_obj.fileno()))
425
return self.get_file_byname(path)
427
def get_file_text(self, file_id):
428
return self.get_file(file_id).read()
436
430
def get_file_byname(self, filename):
437
431
return file(self.abspath(filename), 'rb')
439
def get_file_lines(self, file_id, path=None):
440
"""See Tree.get_file_lines()"""
441
file = self.get_file(file_id, path)
443
return file.readlines()
448
434
def annotate_iter(self, file_id, default_revision=CURRENT_REVISION):
449
435
"""See Tree.annotate_iter
533
519
and this one merged in.
535
521
# assumes the target bzr dir format is compatible.
536
result = to_bzrdir.create_workingtree()
522
result = self._format.initialize(to_bzrdir)
537
523
self.copy_content_into(result, revision_id)
910
896
hashfile = self._transport.get('merge-hashes')
911
897
except errors.NoSuchFile:
916
if hashfile.next() != MERGE_MODIFIED_HEADER_1 + '\n':
917
raise errors.MergeModifiedFormatError()
918
except StopIteration:
901
if hashfile.next() != MERGE_MODIFIED_HEADER_1 + '\n':
919
902
raise errors.MergeModifiedFormatError()
920
for s in RioReader(hashfile):
921
# RioReader reads in Unicode, so convert file_ids back to utf8
922
file_id = osutils.safe_file_id(s.get("file_id"), warn=False)
923
if file_id not in self.inventory:
925
text_hash = s.get("hash")
926
if text_hash == self.get_file_sha1(file_id):
927
merge_hashes[file_id] = text_hash
903
except StopIteration:
904
raise errors.MergeModifiedFormatError()
905
for s in RioReader(hashfile):
906
# RioReader reads in Unicode, so convert file_ids back to utf8
907
file_id = osutils.safe_file_id(s.get("file_id"), warn=False)
908
if file_id not in self.inventory:
910
text_hash = s.get("hash")
911
if text_hash == self.get_file_sha1(file_id):
912
merge_hashes[file_id] = text_hash
932
915
@needs_write_lock
933
916
def mkdir(self, path, file_id=None):
1332
1315
only_change_inv = True
1333
1316
elif self.has_filename(from_rel) and not self.has_filename(to_rel):
1334
1317
only_change_inv = False
1335
elif (not self.case_sensitive
1336
and from_rel.lower() == to_rel.lower()
1337
and self.has_filename(from_rel)):
1318
elif (sys.platform == 'win32'
1319
and from_rel.lower() == to_rel.lower()
1320
and self.has_filename(from_rel)):
1338
1321
only_change_inv = False
1340
1323
# something is wrong, so lets determine what exactly
1608
1591
if subf == '.bzr':
1610
1593
if subf not in dir_entry.children:
1613
can_access) = osutils.normalized_filename(subf)
1614
except UnicodeDecodeError:
1615
path_os_enc = path.encode(osutils._fs_enc)
1616
relpath = path_os_enc + '/' + subf
1617
raise errors.BadFilenameEncoding(relpath,
1594
subf_norm, can_access = osutils.normalized_filename(subf)
1619
1595
if subf_norm != subf and can_access:
1620
1596
if subf_norm not in dir_entry.children:
1621
1597
fl.append(subf_norm)
1875
1851
# Recurse directory and add all files
1876
1852
# so we can check if they have changed.
1877
1853
for parent_info, file_infos in\
1878
self.walkdirs(directory):
1879
for relpath, basename, kind, lstat, fileid, kind in file_infos:
1854
osutils.walkdirs(self.abspath(directory),
1856
for relpath, basename, kind, lstat, abspath in file_infos:
1880
1857
# Is it versioned or ignored?
1881
1858
if self.path2id(relpath) or self.is_ignored(relpath):
1882
1859
# Add nested content for deletion.
2337
2315
bzrdir_loc = bisect_left(cur_disk_dir_content,
2338
2316
('.bzr', '.bzr'))
2339
if (bzrdir_loc < len(cur_disk_dir_content)
2340
and cur_disk_dir_content[bzrdir_loc][0] == '.bzr'):
2317
if cur_disk_dir_content[bzrdir_loc][0] == '.bzr':
2341
2318
# we dont yield the contents of, or, .bzr itself.
2342
2319
del cur_disk_dir_content[bzrdir_loc]
2343
2320
if inv_finished:
2434
2411
# FIXME: stash the node in pending
2435
2412
entry = inv[top_id]
2436
if entry.kind == 'directory':
2437
for name, child in entry.sorted_children():
2438
dirblock.append((relroot + name, name, child.kind, None,
2439
child.file_id, child.kind
2413
for name, child in entry.sorted_children():
2414
dirblock.append((relroot + name, name, child.kind, None,
2415
child.file_id, child.kind
2441
2417
yield (currentdir[0], entry.file_id), dirblock
2442
2418
# push the user specified dirs from dirblock
2443
2419
for dir in reversed(dirblock):
2476
2452
self.set_conflicts(un_resolved)
2477
2453
return un_resolved, resolved
2481
tree_basis = self.basis_tree()
2482
tree_basis.lock_read()
2484
repo_basis = self.branch.repository.revision_tree(
2485
self.last_revision())
2486
if len(list(repo_basis.iter_changes(tree_basis))) > 0:
2487
raise errors.BzrCheckError(
2488
"Mismatched basis inventory content.")
2493
2455
def _validate(self):
2494
2456
"""Validate internal structures.
2505
def _get_rules_searcher(self, default_searcher):
2506
"""See Tree._get_rules_searcher."""
2507
if self._rules_searcher is None:
2508
self._rules_searcher = super(WorkingTree,
2509
self)._get_rules_searcher(default_searcher)
2510
return self._rules_searcher
2513
2467
class WorkingTree2(WorkingTree):
2514
2468
"""This is the Format 2 working tree.
2610
2564
except errors.NoSuchFile:
2611
2565
return _mod_conflicts.ConflictList()
2614
if confile.next() != CONFLICT_HEADER_1 + '\n':
2615
raise errors.ConflictFormatError()
2616
except StopIteration:
2567
if confile.next() != CONFLICT_HEADER_1 + '\n':
2617
2568
raise errors.ConflictFormatError()
2618
return _mod_conflicts.ConflictList.from_stanzas(RioReader(confile))
2569
except StopIteration:
2570
raise errors.ConflictFormatError()
2571
return _mod_conflicts.ConflictList.from_stanzas(RioReader(confile))
2622
2573
def unlock(self):
2623
2574
# do non-implementation specific cleanup
2734
2685
"""See WorkingTreeFormat.get_format_description()."""
2735
2686
return "Working tree format 2"
2737
def _stub_initialize_on_transport(self, transport, file_mode):
2738
"""Workaround: create control files for a remote working tree.
2688
def _stub_initialize_remote(self, branch):
2689
"""As a special workaround create critical control files for a remote working tree.
2740
2691
This ensures that it can later be updated and dealt with locally,
2741
since BzrDirFormat6 and BzrDirFormat5 cannot represent dirs with
2692
since BzrDirFormat6 and BzrDirFormat5 cannot represent dirs with
2742
2693
no working tree. (See bug #43064).
2744
2695
sio = StringIO()
2745
2696
inv = Inventory()
2746
2697
xml5.serializer_v5.write_inventory(inv, sio, working=True)
2748
transport.put_file('inventory', sio, file_mode)
2749
transport.put_bytes('pending-merges', '', file_mode)
2699
branch._transport.put_file('inventory', sio,
2700
mode=branch.control_files._file_mode)
2701
branch._transport.put_bytes('pending-merges', '',
2702
mode=branch.control_files._file_mode)
2751
2705
def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
2752
2706
accelerator_tree=None, hardlink=False):