/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/workingtree.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2010-01-14 00:01:32 UTC
  • mfrom: (4957.1.1 jam-integration)
  • Revision ID: pqm@pqm.ubuntu.com-20100114000132-3p3rabnonjw3gzqb
(jam) Merge bzr.stable, bringing in bug fixes #175839, #504390

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007, 2008, 2009 Canonical Ltd
 
1
# Copyright (C) 2005-2010 Canonical Ltd
2
2
#
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
65
65
    merge,
66
66
    revision as _mod_revision,
67
67
    revisiontree,
68
 
    textui,
69
68
    trace,
70
69
    transform,
71
70
    ui,
544
543
        else:
545
544
            parents = [last_rev]
546
545
        try:
547
 
            merges_file = self._transport.get('pending-merges')
 
546
            merges_bytes = self._transport.get_bytes('pending-merges')
548
547
        except errors.NoSuchFile:
549
548
            pass
550
549
        else:
551
 
            for l in merges_file.readlines():
 
550
            for l in osutils.split_lines(merges_bytes):
552
551
                revision_id = l.rstrip('\n')
553
552
                parents.append(revision_id)
554
553
        return parents
636
635
 
637
636
    def _is_executable_from_path_and_stat_from_basis(self, path, stat_result):
638
637
        file_id = self.path2id(path)
 
638
        if file_id is None:
 
639
            # For unversioned files on win32, we just assume they are not
 
640
            # executable
 
641
            return False
639
642
        return self._inventory[file_id].executable
640
643
 
641
644
    def _is_executable_from_path_and_stat_from_stat(self, path, stat_result):
896
899
 
897
900
    @needs_write_lock # because merge pulls data into the branch.
898
901
    def merge_from_branch(self, branch, to_revision=None, from_revision=None,
899
 
        merge_type=None):
 
902
                          merge_type=None, force=False):
900
903
        """Merge from a branch into this working tree.
901
904
 
902
905
        :param branch: The branch to merge from.
911
914
            merger = Merger(self.branch, this_tree=self, pb=pb)
912
915
            merger.pp = ProgressPhase("Merge phase", 5, pb)
913
916
            merger.pp.next_phase()
914
 
            # check that there are no
915
 
            # local alterations
916
 
            merger.check_basis(check_clean=True, require_commits=False)
 
917
            # check that there are no local alterations
 
918
            if not force and self.has_changes():
 
919
                raise errors.UncommittedChanges(self)
917
920
            if to_revision is None:
918
921
                to_revision = _mod_revision.ensure_null(branch.last_revision())
919
922
            merger.other_rev_id = to_revision
1624
1627
                                this_tree=self,
1625
1628
                                pb=pb,
1626
1629
                                change_reporter=change_reporter)
1627
 
                    if (basis_tree.inventory.root is None and
1628
 
                        new_basis_tree.inventory.root is not None):
1629
 
                        self.set_root_id(new_basis_tree.get_root_id())
 
1630
                    basis_root_id = basis_tree.get_root_id()
 
1631
                    new_root_id = new_basis_tree.get_root_id()
 
1632
                    if basis_root_id != new_root_id:
 
1633
                        self.set_root_id(new_root_id)
1630
1634
                finally:
1631
1635
                    pb.finished()
1632
1636
                    basis_tree.unlock()
1841
1845
    def _reset_data(self):
1842
1846
        """Reset transient data that cannot be revalidated."""
1843
1847
        self._inventory_is_modified = False
1844
 
        result = self._deserialize(self._transport.get('inventory'))
 
1848
        f = self._transport.get('inventory')
 
1849
        try:
 
1850
            result = self._deserialize(f)
 
1851
        finally:
 
1852
            f.close()
1845
1853
        self._set_inventory(result, dirty=False)
1846
1854
 
1847
1855
    @needs_tree_write_lock
1923
1931
        # binary.
1924
1932
        if self._inventory_is_modified:
1925
1933
            raise errors.InventoryModified(self)
1926
 
        result = self._deserialize(self._transport.get('inventory'))
 
1934
        f = self._transport.get('inventory')
 
1935
        try:
 
1936
            result = self._deserialize(f)
 
1937
        finally:
 
1938
            f.close()
1927
1939
        self._set_inventory(result, dirty=False)
1928
1940
        return result
1929
1941
 
1944
1956
 
1945
1957
        new_files=set()
1946
1958
        unknown_nested_files=set()
 
1959
        if to_file is None:
 
1960
            to_file = sys.stdout
1947
1961
 
1948
1962
        def recurse_directory_to_add_files(directory):
1949
1963
            # Recurse directory and add all files
2019
2033
                        new_status = 'I'
2020
2034
                    else:
2021
2035
                        new_status = '?'
2022
 
                    textui.show_status(new_status, self.kind(fid), f,
2023
 
                                       to_file=to_file)
 
2036
                    # XXX: Really should be a more abstract reporter interface
 
2037
                    kind_ch = osutils.kind_marker(self.kind(fid))
 
2038
                    to_file.write(new_status + '       ' + f + kind_ch + '\n')
2024
2039
                # Unversion file
2025
2040
                inv_delta.append((f, None, fid, None))
2026
2041
                message = "removed %s" % (f,)
2177
2192
        """
2178
2193
        raise NotImplementedError(self.unlock)
2179
2194
 
2180
 
    def update(self, change_reporter=None, possible_transports=None):
 
2195
    _marker = object()
 
2196
 
 
2197
    def update(self, change_reporter=None, possible_transports=None,
 
2198
               revision=None, old_tip=_marker):
2181
2199
        """Update a working tree along its branch.
2182
2200
 
2183
2201
        This will update the branch if its bound too, which means we have
2201
2219
        - Merge current state -> basis tree of the master w.r.t. the old tree
2202
2220
          basis.
2203
2221
        - Do a 'normal' merge of the old branch basis if it is relevant.
 
2222
 
 
2223
        :param revision: The target revision to update to. Must be in the
 
2224
            revision history.
 
2225
        :param old_tip: If branch.update() has already been run, the value it
 
2226
            returned (old tip of the branch or None). _marker is used
 
2227
            otherwise.
2204
2228
        """
2205
2229
        if self.branch.get_bound_location() is not None:
2206
2230
            self.lock_write()
2207
 
            update_branch = True
 
2231
            update_branch = (old_tip is self._marker)
2208
2232
        else:
2209
2233
            self.lock_tree_write()
2210
2234
            update_branch = False
2212
2236
            if update_branch:
2213
2237
                old_tip = self.branch.update(possible_transports)
2214
2238
            else:
2215
 
                old_tip = None
2216
 
            return self._update_tree(old_tip, change_reporter)
 
2239
                if old_tip is self._marker:
 
2240
                    old_tip = None
 
2241
            return self._update_tree(old_tip, change_reporter, revision)
2217
2242
        finally:
2218
2243
            self.unlock()
2219
2244
 
2220
2245
    @needs_tree_write_lock
2221
 
    def _update_tree(self, old_tip=None, change_reporter=None):
 
2246
    def _update_tree(self, old_tip=None, change_reporter=None, revision=None):
2222
2247
        """Update a tree to the master branch.
2223
2248
 
2224
2249
        :param old_tip: if supplied, the previous tip revision the branch,
2239
2264
            last_rev = self.get_parent_ids()[0]
2240
2265
        except IndexError:
2241
2266
            last_rev = _mod_revision.NULL_REVISION
2242
 
        if last_rev != _mod_revision.ensure_null(self.branch.last_revision()):
2243
 
            # merge tree state up to new branch tip.
 
2267
        if revision is None:
 
2268
            revision = self.branch.last_revision()
 
2269
        else:
 
2270
            if revision not in self.branch.revision_history():
 
2271
                raise errors.NoSuchRevision(self.branch, revision)
 
2272
        if last_rev != _mod_revision.ensure_null(revision):
 
2273
            # merge tree state up to specified revision.
2244
2274
            basis = self.basis_tree()
2245
2275
            basis.lock_read()
2246
2276
            try:
2247
 
                to_tree = self.branch.basis_tree()
2248
 
                if basis.inventory.root is None:
2249
 
                    self.set_root_id(to_tree.get_root_id())
 
2277
                to_tree = self.branch.repository.revision_tree(revision)
 
2278
                to_root_id = to_tree.get_root_id()
 
2279
                if (basis.inventory.root is None
 
2280
                    or basis.inventory.root.file_id != to_root_id):
 
2281
                    self.set_root_id(to_root_id)
2250
2282
                    self.flush()
2251
2283
                result += merge.merge_inner(
2252
2284
                                      self.branch,
2254
2286
                                      basis,
2255
2287
                                      this_tree=self,
2256
2288
                                      change_reporter=change_reporter)
 
2289
                self.set_last_revision(revision)
2257
2290
            finally:
2258
2291
                basis.unlock()
2259
2292
            # TODO - dedup parents list with things merged by pull ?
2260
2293
            # reuse the tree we've updated to to set the basis:
2261
 
            parent_trees = [(self.branch.last_revision(), to_tree)]
 
2294
            parent_trees = [(revision, to_tree)]
2262
2295
            merges = self.get_parent_ids()[1:]
2263
2296
            # Ideally we ask the tree for the trees here, that way the working
2264
2297
            # tree can decide whether to give us the entire tree or give us a
2294
2327
            #       should be able to remove this extra flush.
2295
2328
            self.flush()
2296
2329
            graph = self.branch.repository.get_graph()
2297
 
            base_rev_id = graph.find_unique_lca(self.branch.last_revision(),
2298
 
                                                old_tip)
 
2330
            base_rev_id = graph.find_unique_lca(revision, old_tip)
2299
2331
            base_tree = self.branch.repository.revision_tree(base_rev_id)
2300
2332
            other_tree = self.branch.repository.revision_tree(old_tip)
2301
2333
            result += merge.merge_inner(
2580
2612
        """
2581
2613
        return
2582
2614
 
2583
 
    @needs_read_lock
2584
2615
    def _get_rules_searcher(self, default_searcher):
2585
2616
        """See Tree._get_rules_searcher."""
2586
2617
        if self._rules_searcher is None:
2765
2796
        """Return the format for the working tree object in a_bzrdir."""
2766
2797
        try:
2767
2798
            transport = a_bzrdir.get_workingtree_transport(None)
2768
 
            format_string = transport.get("format").read()
 
2799
            format_string = transport.get_bytes("format")
2769
2800
            return klass._formats[format_string]
2770
2801
        except errors.NoSuchFile:
2771
2802
            raise errors.NoWorkingTree(base=transport.base)