29
29
WorkingTree.open(dir).
32
# TODO: Give the workingtree sole responsibility for the working inventory;
33
# remove the variable and references to it from the branch. This may require
34
# updating the commit code so as to update the inventory within the working
35
# copy, and making sure there's only one WorkingTree for any directory on disk.
36
# At the moment they may alias the inventory and have old copies of it in
37
# memory. (Now done? -- mbp 20060309)
33
39
from cStringIO import StringIO
95
101
from bzrlib.filters import filtered_input_file
96
102
from bzrlib.trace import mutter, note
97
103
from bzrlib.transport.local import LocalTransport
104
from bzrlib.progress import DummyProgress, ProgressPhase
98
105
from bzrlib.revision import CURRENT_REVISION
99
106
from bzrlib.rio import RioReader, rio_file, Stanza
100
107
from bzrlib.symbol_versioning import (
247
253
self._rules_searcher = None
248
254
self.views = self._make_views()
251
def user_transport(self):
252
return self.bzrdir.user_transport
255
def control_transport(self):
256
return self._transport
258
256
def _detect_case_handling(self):
259
257
wt_trans = self.bzrdir.get_workingtree_transport(None)
914
912
branch.last_revision().
916
914
from bzrlib.merge import Merger, Merge3Merger
917
merger = Merger(self.branch, this_tree=self)
918
# check that there are no local alterations
919
if not force and self.has_changes():
920
raise errors.UncommittedChanges(self)
921
if to_revision is None:
922
to_revision = _mod_revision.ensure_null(branch.last_revision())
923
merger.other_rev_id = to_revision
924
if _mod_revision.is_null(merger.other_rev_id):
925
raise errors.NoCommits(branch)
926
self.branch.fetch(branch, last_revision=merger.other_rev_id)
927
merger.other_basis = merger.other_rev_id
928
merger.other_tree = self.branch.repository.revision_tree(
930
merger.other_branch = branch
931
if from_revision is None:
934
merger.set_base_revision(from_revision, branch)
935
if merger.base_rev_id == merger.other_rev_id:
936
raise errors.PointlessMerge
937
merger.backup_files = False
938
if merge_type is None:
939
merger.merge_type = Merge3Merger
941
merger.merge_type = merge_type
942
merger.set_interesting_files(None)
943
merger.show_base = False
944
merger.reprocess = False
945
conflicts = merger.do_merge()
915
pb = ui.ui_factory.nested_progress_bar()
917
merger = Merger(self.branch, this_tree=self, pb=pb)
918
merger.pp = ProgressPhase("Merge phase", 5, pb)
919
merger.pp.next_phase()
920
# check that there are no local alterations
921
if not force and self.has_changes():
922
raise errors.UncommittedChanges(self)
923
if to_revision is None:
924
to_revision = _mod_revision.ensure_null(branch.last_revision())
925
merger.other_rev_id = to_revision
926
if _mod_revision.is_null(merger.other_rev_id):
927
raise errors.NoCommits(branch)
928
self.branch.fetch(branch, last_revision=merger.other_rev_id)
929
merger.other_basis = merger.other_rev_id
930
merger.other_tree = self.branch.repository.revision_tree(
932
merger.other_branch = branch
933
merger.pp.next_phase()
934
if from_revision is None:
937
merger.set_base_revision(from_revision, branch)
938
if merger.base_rev_id == merger.other_rev_id:
939
raise errors.PointlessMerge
940
merger.backup_files = False
941
if merge_type is None:
942
merger.merge_type = Merge3Merger
944
merger.merge_type = merge_type
945
merger.set_interesting_files(None)
946
merger.show_base = False
947
merger.reprocess = False
948
conflicts = merger.do_merge()
1096
1101
tree_transport = self.bzrdir.root_transport.clone(sub_path)
1097
1102
if tree_transport.base != branch_transport.base:
1098
1103
tree_bzrdir = format.initialize_on_transport(tree_transport)
1099
branch.BranchReferenceFormat().initialize(tree_bzrdir,
1100
target_branch=new_branch)
1104
branch.BranchReferenceFormat().initialize(tree_bzrdir, new_branch)
1102
1106
tree_bzrdir = branch_bzrdir
1103
1107
wt = tree_bzrdir.create_workingtree(_mod_revision.NULL_REVISION)
1141
1145
This does not include files that have been deleted in this
1142
1146
tree. Skips the control directory.
1144
:param include_root: if True, return an entry for the root
1148
:param include_root: if True, do not return an entry for the root
1145
1149
:param from_dir: start from this directory or None for the root
1146
1150
:param recursive: whether to recurse into subdirectories or not
1601
1605
@needs_write_lock
1602
1606
def pull(self, source, overwrite=False, stop_revision=None,
1603
1607
change_reporter=None, possible_transports=None, local=False):
1608
top_pb = ui.ui_factory.nested_progress_bar()
1604
1609
source.lock_read()
1611
pp = ProgressPhase("Pull phase", 2, top_pb)
1606
1613
old_revision_info = self.branch.last_revision_info()
1607
1614
basis_tree = self.basis_tree()
1608
1615
count = self.branch.pull(source, overwrite, stop_revision,
1619
1628
new_basis_tree,
1621
1630
this_tree=self,
1623
1632
change_reporter=change_reporter)
1624
1633
basis_root_id = basis_tree.get_root_id()
1625
1634
new_root_id = new_basis_tree.get_root_id()
1626
1635
if basis_root_id != new_root_id:
1627
1636
self.set_root_id(new_root_id)
1629
1639
basis_tree.unlock()
1630
1640
# TODO - dedup parents list with things merged by pull ?
1631
1641
# reuse the revisiontree we merged against to set the new
2059
2070
@needs_tree_write_lock
2060
2071
def revert(self, filenames=None, old_tree=None, backups=True,
2061
pb=None, report_changes=False):
2072
pb=DummyProgress(), report_changes=False):
2062
2073
from bzrlib.conflicts import resolve
2063
2074
if filenames == []:
2064
2075
filenames = None
2253
2264
# We MUST save it even if an error occurs, because otherwise the users
2254
2265
# local work is unreferenced and will appear to have been lost.
2258
2269
last_rev = self.get_parent_ids()[0]
2259
2270
except IndexError:
2260
2271
last_rev = _mod_revision.NULL_REVISION
2261
2272
if revision is None:
2262
2273
revision = self.branch.last_revision()
2264
old_tip = old_tip or _mod_revision.NULL_REVISION
2266
if not _mod_revision.is_null(old_tip) and old_tip != last_rev:
2267
# the branch we are bound to was updated
2268
# merge those changes in first
2269
base_tree = self.basis_tree()
2270
other_tree = self.branch.repository.revision_tree(old_tip)
2271
nb_conflicts = merge.merge_inner(self.branch, other_tree,
2272
base_tree, this_tree=self,
2273
change_reporter=change_reporter)
2275
self.add_parent_tree((old_tip, other_tree))
2276
trace.note('Rerun update after fixing the conflicts.')
2275
if revision not in self.branch.revision_history():
2276
raise errors.NoSuchRevision(self.branch, revision)
2279
2277
if last_rev != _mod_revision.ensure_null(revision):
2280
# the working tree is up to date with the branch
2281
# we can merge the specified revision from master
2282
to_tree = self.branch.repository.revision_tree(revision)
2283
to_root_id = to_tree.get_root_id()
2278
# merge tree state up to specified revision.
2285
2279
basis = self.basis_tree()
2286
2280
basis.lock_read()
2282
to_tree = self.branch.repository.revision_tree(revision)
2283
to_root_id = to_tree.get_root_id()
2288
2284
if (basis.inventory.root is None
2289
2285
or basis.inventory.root.file_id != to_root_id):
2290
2286
self.set_root_id(to_root_id)
2288
result += merge.merge_inner(
2293
change_reporter=change_reporter)
2294
self.set_last_revision(revision)
2295
# determine the branch point
2296
graph = self.branch.repository.get_graph()
2297
base_rev_id = graph.find_unique_lca(self.branch.last_revision(),
2299
base_tree = self.branch.repository.revision_tree(base_rev_id)
2301
nb_conflicts = merge.merge_inner(self.branch, to_tree, base_tree,
2303
change_reporter=change_reporter)
2304
self.set_last_revision(revision)
2305
2297
# TODO - dedup parents list with things merged by pull ?
2306
2298
# reuse the tree we've updated to to set the basis:
2307
2299
parent_trees = [(revision, to_tree)]
2314
2306
for parent in merges:
2315
2307
parent_trees.append(
2316
2308
(parent, self.branch.repository.revision_tree(parent)))
2317
if not _mod_revision.is_null(old_tip):
2309
if (old_tip is not None and not _mod_revision.is_null(old_tip)):
2318
2310
parent_trees.append(
2319
2311
(old_tip, self.branch.repository.revision_tree(old_tip)))
2320
2312
self.set_parent_trees(parent_trees)
2321
2313
last_rev = parent_trees[0][0]
2315
# the working tree had the same last-revision as the master
2316
# branch did. We may still have pivot local work from the local
2317
# branch into old_tip:
2318
if (old_tip is not None and not _mod_revision.is_null(old_tip)):
2319
self.add_parent_tree_id(old_tip)
2320
if (old_tip is not None and not _mod_revision.is_null(old_tip)
2321
and old_tip != last_rev):
2322
# our last revision was not the prior branch last revision
2323
# and we have converted that last revision to a pending merge.
2324
# base is somewhere between the branch tip now
2325
# and the now pending merge
2327
# Since we just modified the working tree and inventory, flush out
2328
# the current state, before we modify it again.
2329
# TODO: jam 20070214 WorkingTree3 doesn't require this, dirstate
2330
# requires it only because TreeTransform directly munges the
2331
# inventory and calls tree._write_inventory(). Ultimately we
2332
# should be able to remove this extra flush.
2334
graph = self.branch.repository.get_graph()
2335
base_rev_id = graph.find_unique_lca(revision, old_tip)
2336
base_tree = self.branch.repository.revision_tree(base_rev_id)
2337
other_tree = self.branch.repository.revision_tree(old_tip)
2338
result += merge.merge_inner(
2343
change_reporter=change_reporter)
2324
2346
def _write_hashcache_if_dirty(self):
2325
2347
"""Write out the hashcache if it is dirty."""