~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/workingtree.py

(vila) Default to no ssl cert verification on osx and windows (Vincent
 Ladeuil)

Show diffs side-by-side

added added

removed removed

Lines of Context:
261
261
    def supports_views(self):
262
262
        return self.views.supports_views()
263
263
 
264
 
    def get_config_stack(self):
265
 
        """Retrieve the config stack for this tree.
266
 
 
267
 
        :return: A ``bzrlib.config.Stack``
268
 
        """
269
 
        # For the moment, just provide the branch config stack.
270
 
        return self.branch.get_config_stack()
271
 
 
272
264
    @staticmethod
273
265
    def open(path=None, _unsupported=False):
274
266
        """Open an existing working tree at path.
387
379
                                              list_current=list_current)
388
380
        return [tr for tr in iterator if tr is not None]
389
381
 
 
382
    def all_file_ids(self):
 
383
        """See Tree.iter_all_file_ids"""
 
384
        raise NotImplementedError(self.all_file_ids)
 
385
 
390
386
    def __repr__(self):
391
387
        return "<%s of %s>" % (self.__class__.__name__,
392
388
                               getattr(self, 'basedir', None))
1950
1946
            if entry.parent_id == orig_root_id:
1951
1947
                entry.parent_id = inv.root.file_id
1952
1948
 
 
1949
    def all_file_ids(self):
 
1950
        """See Tree.iter_all_file_ids"""
 
1951
        return set(self.inventory)
 
1952
 
1953
1953
    @needs_tree_write_lock
1954
1954
    def set_parent_trees(self, parents_list, allow_leftmost_as_ghost=False):
1955
1955
        """See MutableTree.set_parent_trees."""
1974
1974
                # parent tree from the repository.
1975
1975
                self._cache_basis_inventory(leftmost_parent_id)
1976
1976
            else:
1977
 
                inv = leftmost_parent_tree.root_inventory
 
1977
                inv = leftmost_parent_tree.inventory
1978
1978
                xml = self._create_basis_xml_from_inventory(
1979
1979
                                        leftmost_parent_id, inv)
1980
1980
                self._write_basis_inventory(xml)
2077
2077
 
2078
2078
    def has_id(self, file_id):
2079
2079
        # files that have been deleted are excluded
2080
 
        inv, inv_file_id = self._unpack_file_id(file_id)
2081
 
        if not inv.has_id(inv_file_id):
 
2080
        inv = self.inventory
 
2081
        if not inv.has_id(file_id):
2082
2082
            return False
2083
 
        path = inv.id2path(inv_file_id)
 
2083
        path = inv.id2path(file_id)
2084
2084
        return osutils.lexists(self.abspath(path))
2085
2085
 
2086
2086
    def has_or_had_id(self, file_id):
2087
 
        if file_id == self.get_root_id():
 
2087
        if file_id == self.inventory.root.file_id:
2088
2088
            return True
2089
 
        inv, inv_file_id = self._unpack_file_id(file_id)
2090
 
        return inv.has_id(inv_file_id)
 
2089
        return self.inventory.has_id(file_id)
2091
2090
 
2092
 
    def all_file_ids(self):
 
2091
    @symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4, 0)))
 
2092
    def __iter__(self):
2093
2093
        """Iterate through file_ids for this tree.
2094
2094
 
2095
2095
        file_ids are in a WorkingTree if they are in the working inventory
2096
2096
        and the working file exists.
2097
2097
        """
2098
 
        ret = set()
2099
 
        for path, ie in self.iter_entries_by_dir():
2100
 
            ret.add(ie.file_id)
2101
 
        return ret
 
2098
        inv = self._inventory
 
2099
        for path, ie in inv.iter_entries():
 
2100
            if osutils.lexists(self.abspath(path)):
 
2101
                yield ie.file_id
2102
2102
 
2103
2103
    @needs_tree_write_lock
2104
2104
    def set_last_revision(self, new_revision):
2160
2160
                _mod_revision.NULL_REVISION)
2161
2161
        else:
2162
2162
            rt = self.branch.repository.revision_tree(revision_ids[0])
2163
 
        self._write_inventory(rt.root_inventory)
 
2163
        self._write_inventory(rt.inventory)
2164
2164
        self.set_parent_ids(revision_ids)
2165
2165
 
2166
2166
    def flush(self):
2178
2178
    def get_file_mtime(self, file_id, path=None):
2179
2179
        """See Tree.get_file_mtime."""
2180
2180
        if not path:
2181
 
            path = self.id2path(file_id)
 
2181
            path = self.inventory.id2path(file_id)
2182
2182
        try:
2183
2183
            return os.lstat(self.abspath(path)).st_mtime
2184
2184
        except OSError, e:
2187
2187
            raise
2188
2188
 
2189
2189
    def _is_executable_from_path_and_stat_from_basis(self, path, stat_result):
2190
 
        inv, file_id = self._path2inv_file_id(path)
 
2190
        file_id = self.path2id(path)
2191
2191
        if file_id is None:
2192
2192
            # For unversioned files on win32, we just assume they are not
2193
2193
            # executable
2194
2194
            return False
2195
 
        return inv[file_id].executable
 
2195
        return self._inventory[file_id].executable
2196
2196
 
2197
2197
    def _is_executable_from_path_and_stat_from_stat(self, path, stat_result):
2198
2198
        mode = stat_result.st_mode
2200
2200
 
2201
2201
    def is_executable(self, file_id, path=None):
2202
2202
        if not self._supports_executable():
2203
 
            inv, inv_file_id = self._unpack_file_id(file_id)
2204
 
            return inv[inv_file_id].executable
 
2203
            return self._inventory[file_id].executable
2205
2204
        else:
2206
2205
            if not path:
2207
2206
                path = self.id2path(file_id)
2221
2220
        # should probably put it back with the previous ID.
2222
2221
        # the read and write working inventory should not occur in this
2223
2222
        # function - they should be part of lock_write and unlock.
2224
 
        # FIXME: nested trees
2225
 
        inv = self.root_inventory
 
2223
        inv = self.inventory
2226
2224
        for f, file_id, kind in zip(files, ids, kinds):
2227
2225
            if file_id is None:
2228
2226
                inv.add_path(f, kind=kind)
2269
2267
                parent_tree = self.branch.repository.revision_tree(parent_id)
2270
2268
            parent_tree.lock_read()
2271
2269
            try:
2272
 
                try:
2273
 
                    kind = parent_tree.kind(file_id)
2274
 
                except errors.NoSuchId:
 
2270
                if not parent_tree.has_id(file_id):
2275
2271
                    continue
2276
 
                if kind != 'file':
 
2272
                ie = parent_tree.inventory[file_id]
 
2273
                if ie.kind != 'file':
2277
2274
                    # Note: this is slightly unnecessary, because symlinks and
2278
2275
                    # directories have a "text" which is the empty text, and we
2279
2276
                    # know that won't mess up annotations. But it seems cleaner
2280
2277
                    continue
2281
 
                parent_text_key = (
2282
 
                    file_id, parent_tree.get_file_revision(file_id))
 
2278
                parent_text_key = (file_id, ie.revision)
2283
2279
                if parent_text_key not in maybe_file_parent_keys:
2284
2280
                    maybe_file_parent_keys.append(parent_text_key)
2285
2281
            finally:
2339
2335
            for s in _mod_rio.RioReader(hashfile):
2340
2336
                # RioReader reads in Unicode, so convert file_ids back to utf8
2341
2337
                file_id = osutils.safe_file_id(s.get("file_id"), warn=False)
2342
 
                if not self.has_id(file_id):
 
2338
                if not self.inventory.has_id(file_id):
2343
2339
                    continue
2344
2340
                text_hash = s.get("hash")
2345
2341
                if text_hash == self.get_file_sha1(file_id):
2375
2371
        other_tree.lock_tree_write()
2376
2372
        try:
2377
2373
            new_parents = other_tree.get_parent_ids()
2378
 
            other_root = other_tree.root_inventory.root
 
2374
            other_root = other_tree.inventory.root
2379
2375
            other_root.parent_id = new_root_parent
2380
2376
            other_root.name = osutils.basename(other_tree_path)
2381
 
            self.root_inventory.add(other_root)
2382
 
            add_children(self.root_inventory, other_root)
2383
 
            self._write_inventory(self.root_inventory)
 
2377
            self.inventory.add(other_root)
 
2378
            add_children(self.inventory, other_root)
 
2379
            self._write_inventory(self.inventory)
2384
2380
            # normally we don't want to fetch whole repositories, but i think
2385
2381
            # here we really do want to consolidate the whole thing.
2386
2382
            for parent_id in other_tree.get_parent_ids():
2429
2425
            tree_bzrdir = branch_bzrdir
2430
2426
        wt = tree_bzrdir.create_workingtree(_mod_revision.NULL_REVISION)
2431
2427
        wt.set_parent_ids(self.get_parent_ids())
2432
 
        # FIXME: Support nested trees
2433
 
        my_inv = self.root_inventory
 
2428
        my_inv = self.inventory
2434
2429
        child_inv = inventory.Inventory(root_id=None)
2435
2430
        new_root = my_inv[file_id]
2436
2431
        my_inv.remove_recursive_id(file_id)
2456
2451
        if not self.is_locked():
2457
2452
            raise errors.ObjectNotLocked(self)
2458
2453
 
 
2454
        inv = self.inventory
2459
2455
        if from_dir is None and include_root is True:
2460
 
            yield ('', 'V', 'directory', self.get_root_id(), self.root_inventory.root)
 
2456
            yield ('', 'V', 'directory', inv.root.file_id, inv.root)
2461
2457
        # Convert these into local objects to save lookup times
2462
2458
        pathjoin = osutils.pathjoin
2463
2459
        file_kind = self._kind
2470
2466
 
2471
2467
        # directory file_id, relative path, absolute path, reverse sorted children
2472
2468
        if from_dir is not None:
2473
 
            inv, from_dir_id = self._path2inv_file_id(from_dir)
 
2469
            from_dir_id = inv.path2id(from_dir)
2474
2470
            if from_dir_id is None:
2475
2471
                # Directory not versioned
2476
2472
                return
2477
2473
            from_dir_abspath = pathjoin(self.basedir, from_dir)
2478
2474
        else:
2479
 
            inv = self.root_inventory
2480
2475
            from_dir_id = inv.root.file_id
2481
2476
            from_dir_abspath = self.basedir
2482
2477
        children = os.listdir(from_dir_abspath)
2605
2600
        rename_entries = []
2606
2601
        rename_tuples = []
2607
2602
 
2608
 
        invs_to_write = set()
2609
 
 
2610
2603
        # check for deprecated use of signature
2611
2604
        if to_dir is None:
2612
2605
            raise TypeError('You must supply a target directory')
2613
2606
        # check destination directory
2614
2607
        if isinstance(from_paths, basestring):
2615
2608
            raise ValueError()
 
2609
        inv = self.inventory
2616
2610
        to_abs = self.abspath(to_dir)
2617
2611
        if not isdir(to_abs):
2618
2612
            raise errors.BzrMoveFailedError('',to_dir,
2620
2614
        if not self.has_filename(to_dir):
2621
2615
            raise errors.BzrMoveFailedError('',to_dir,
2622
2616
                errors.NotInWorkingDirectory(to_dir))
2623
 
        to_inv, to_dir_id = self._path2inv_file_id(to_dir)
 
2617
        to_dir_id = inv.path2id(to_dir)
2624
2618
        if to_dir_id is None:
2625
2619
            raise errors.BzrMoveFailedError('',to_dir,
2626
2620
                errors.NotVersionedError(path=to_dir))
2627
2621
 
2628
 
        to_dir_ie = to_inv[to_dir_id]
 
2622
        to_dir_ie = inv[to_dir_id]
2629
2623
        if to_dir_ie.kind != 'directory':
2630
2624
            raise errors.BzrMoveFailedError('',to_dir,
2631
2625
                errors.NotADirectory(to_abs))
2633
2627
        # create rename entries and tuples
2634
2628
        for from_rel in from_paths:
2635
2629
            from_tail = splitpath(from_rel)[-1]
2636
 
            from_inv, from_id = self._path2inv_file_id(from_rel)
 
2630
            from_id = inv.path2id(from_rel)
2637
2631
            if from_id is None:
2638
2632
                raise errors.BzrMoveFailedError(from_rel,to_dir,
2639
2633
                    errors.NotVersionedError(path=from_rel))
2640
2634
 
2641
 
            from_entry = from_inv[from_id]
 
2635
            from_entry = inv[from_id]
2642
2636
            from_parent_id = from_entry.parent_id
2643
2637
            to_rel = pathjoin(to_dir, from_tail)
2644
2638
            rename_entry = InventoryWorkingTree._RenameEntry(
2663
2657
            # restore the inventory on error
2664
2658
            self._inventory_is_modified = original_modified
2665
2659
            raise
2666
 
        #FIXME: Should potentially also write the from_invs
2667
 
        self._write_inventory(to_inv)
 
2660
        self._write_inventory(inv)
2668
2661
        return rename_tuples
2669
2662
 
2670
2663
    @needs_tree_write_lock
2690
2683
 
2691
2684
        Everything else results in an error.
2692
2685
        """
 
2686
        inv = self.inventory
2693
2687
        rename_entries = []
2694
2688
 
2695
2689
        # create rename entries and tuples
2696
2690
        from_tail = splitpath(from_rel)[-1]
2697
 
        from_inv, from_id = self._path2inv_file_id(from_rel)
 
2691
        from_id = inv.path2id(from_rel)
2698
2692
        if from_id is None:
2699
2693
            # if file is missing in the inventory maybe it's in the basis_tree
2700
2694
            basis_tree = self.branch.basis_tree()
2703
2697
                raise errors.BzrRenameFailedError(from_rel,to_rel,
2704
2698
                    errors.NotVersionedError(path=from_rel))
2705
2699
            # put entry back in the inventory so we can rename it
2706
 
            from_entry = basis_tree.root_inventory[from_id].copy()
2707
 
            from_inv.add(from_entry)
 
2700
            from_entry = basis_tree.inventory[from_id].copy()
 
2701
            inv.add(from_entry)
2708
2702
        else:
2709
 
            from_inv, from_inv_id = self._unpack_file_id(from_id)
2710
 
            from_entry = from_inv[from_inv_id]
 
2703
            from_entry = inv[from_id]
2711
2704
        from_parent_id = from_entry.parent_id
2712
2705
        to_dir, to_tail = os.path.split(to_rel)
2713
 
        to_inv, to_dir_id = self._path2inv_file_id(to_dir)
 
2706
        to_dir_id = inv.path2id(to_dir)
2714
2707
        rename_entry = InventoryWorkingTree._RenameEntry(from_rel=from_rel,
2715
2708
                                     from_id=from_id,
2716
2709
                                     from_tail=from_tail,
2738
2731
               from_id, from_rel, to_rel, to_dir, to_dir_id)
2739
2732
 
2740
2733
        self._move(rename_entries)
2741
 
        self._write_inventory(to_inv)
 
2734
        self._write_inventory(inv)
2742
2735
 
2743
2736
    class _RenameEntry(object):
2744
2737
        def __init__(self, from_rel, from_id, from_tail, from_parent_id,
2760
2753
 
2761
2754
        Also does basic plausability tests.
2762
2755
        """
2763
 
        # FIXME: Handling of nested trees
2764
 
        inv = self.root_inventory
 
2756
        inv = self.inventory
2765
2757
 
2766
2758
        for rename_entry in rename_entries:
2767
2759
            # store to local variables for easier reference
2825
2817
        Depending on the value of the flag 'only_change_inv', the
2826
2818
        file will be moved on the file system or not.
2827
2819
        """
 
2820
        inv = self.inventory
2828
2821
        moved = []
2829
2822
 
2830
2823
        for entry in rename_entries:
2837
2830
 
2838
2831
    def _rollback_move(self, moved):
2839
2832
        """Try to rollback a previous move in case of an filesystem error."""
 
2833
        inv = self.inventory
2840
2834
        for entry in moved:
2841
2835
            try:
2842
2836
                self._move_entry(WorkingTree._RenameEntry(
2851
2845
                        " Error message is: %s" % e)
2852
2846
 
2853
2847
    def _move_entry(self, entry):
2854
 
        inv = self.root_inventory
 
2848
        inv = self.inventory
2855
2849
        from_rel_abs = self.abspath(entry.from_rel)
2856
2850
        to_rel_abs = self.abspath(entry.to_rel)
2857
2851
        if from_rel_abs == to_rel_abs:
2898
2892
 
2899
2893
    def stored_kind(self, file_id):
2900
2894
        """See Tree.stored_kind"""
2901
 
        inv, inv_file_id = self._unpack_file_id(file_id)
2902
 
        return inv[inv_file_id].kind
 
2895
        return self.inventory[file_id].kind
2903
2896
 
2904
2897
    def extras(self):
2905
2898
        """Yield all unversioned files in this WorkingTree.
2912
2905
        This is the same order used by 'osutils.walkdirs'.
2913
2906
        """
2914
2907
        ## TODO: Work from given directory downwards
2915
 
        for path, dir_entry in self.iter_entries_by_dir():
2916
 
            if dir_entry.kind != 'directory':
2917
 
                continue
 
2908
        for path, dir_entry in self.inventory.directories():
2918
2909
            # mutter("search for unknowns in %r", path)
2919
2910
            dirabs = self.abspath(path)
2920
2911
            if not isdir(dirabs):
2957
2948
        """
2958
2949
        _directory = 'directory'
2959
2950
        # get the root in the inventory
2960
 
        inv, top_id = self._path2inv_file_id(prefix)
 
2951
        inv = self.inventory
 
2952
        top_id = inv.path2id(prefix)
2961
2953
        if top_id is None:
2962
2954
            pending = []
2963
2955
        else: