/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/transform.py

  • Committer: Carl Friedrich Bolz
  • Date: 2006-09-07 10:51:59 UTC
  • mto: (1908.3.21 usecases-benchmarks)
  • mto: This revision was merged to the branch mainline in revision 2068.
  • Revision ID: cfbolz@gmx.de-20060907105159-095161f93d8c498a
Fix bundle benchmarks: don't do install_bundle on too many revisions: takes way
too long. Split up timing of install_bundle and write_bundle.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# Copyright (C) 2006 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
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
7
 
 
 
7
#
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
11
# GNU General Public License for more details.
12
 
 
 
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26
26
                            delete_any)
27
27
from bzrlib.progress import DummyProgress, ProgressPhase
28
28
from bzrlib.trace import mutter, warning
 
29
from bzrlib import tree
29
30
import bzrlib.ui 
 
31
import bzrlib.urlutils as urlutils
30
32
 
31
33
 
32
34
ROOT_PARENT = "root-parent"
79
81
        self._tree.lock_write()
80
82
        try:
81
83
            control_files = self._tree._control_files
82
 
            self._limbodir = control_files.controlfilename('limbo')
 
84
            self._limbodir = urlutils.local_path_from_url(
 
85
                control_files.controlfilename('limbo'))
83
86
            try:
84
87
                os.mkdir(self._limbodir)
85
88
            except OSError, e:
101
104
        self._removed_id = set()
102
105
        self._tree_path_ids = {}
103
106
        self._tree_id_paths = {}
 
107
        self._realpaths = {}
 
108
        # Cache of realpath results, to speed up canonical_path
 
109
        self._relpaths = {}
 
110
        # Cache of relpath results, to speed up canonical_path
104
111
        self._new_root = self.trans_id_tree_file_id(tree.get_root_id())
105
112
        self.__done = False
106
113
        self._pb = pb
211
218
    def canonical_path(self, path):
212
219
        """Get the canonical tree-relative path"""
213
220
        # don't follow final symlinks
214
 
        dirname, basename = os.path.split(self._tree.abspath(path))
215
 
        dirname = os.path.realpath(dirname)
216
 
        return self._tree.relpath(pathjoin(dirname, basename))
 
221
        abs = self._tree.abspath(path)
 
222
        if abs in self._relpaths:
 
223
            return self._relpaths[abs]
 
224
        dirname, basename = os.path.split(abs)
 
225
        if dirname not in self._realpaths:
 
226
            self._realpaths[dirname] = os.path.realpath(dirname)
 
227
        dirname = self._realpaths[dirname]
 
228
        abs = pathjoin(dirname, basename)
 
229
        if dirname in self._relpaths:
 
230
            relpath = pathjoin(self._relpaths[dirname], basename)
 
231
            relpath = relpath.rstrip('/\\')
 
232
        else:
 
233
            relpath = self._tree.relpath(abs)
 
234
        self._relpaths[abs] = relpath
 
235
        return relpath
217
236
 
218
237
    def trans_id_tree_path(self, path):
219
238
        """Determine (and maybe set) the transaction ID for a tree path."""
241
260
        New file takes the permissions of any existing file with that id,
242
261
        unless mode_id is specified.
243
262
        """
244
 
        f = file(self._limbo_name(trans_id), 'wb')
245
 
        unique_add(self._new_contents, trans_id, 'file')
246
 
        for segment in contents:
247
 
            f.write(segment)
248
 
        f.close()
 
263
        name = self._limbo_name(trans_id)
 
264
        f = open(name, 'wb')
 
265
        try:
 
266
            try:
 
267
                unique_add(self._new_contents, trans_id, 'file')
 
268
            except:
 
269
                # Clean up the file, it never got registered so
 
270
                # TreeTransform.finalize() won't clean it up.
 
271
                f.close()
 
272
                os.unlink(name)
 
273
                raise
 
274
 
 
275
            for segment in contents:
 
276
                f.write(segment)
 
277
        finally:
 
278
            f.close()
249
279
        self._set_mode(trans_id, mode_id, S_ISREG)
250
280
 
251
281
    def _set_mode(self, trans_id, mode_id, typefunc):
445
475
 
446
476
    def path_changed(self, trans_id):
447
477
        """Return True if a trans_id's path has changed."""
448
 
        return trans_id in self._new_name or trans_id in self._new_parent
 
478
        return (trans_id in self._new_name) or (trans_id in self._new_parent)
449
479
 
450
480
    def find_conflicts(self):
451
481
        """Find any violations of inventory or filesystem invariants"""
477
507
                        self.tree_kind(t) == 'directory'])
478
508
        for trans_id in self._removed_id:
479
509
            file_id = self.tree_file_id(trans_id)
480
 
            if self._tree.inventory[file_id].kind in ('directory', 
481
 
                                                      'root_directory'):
 
510
            if self._tree.inventory[file_id].kind == 'directory':
482
511
                parents.append(trans_id)
483
512
 
484
513
        for parent_id in parents:
521
550
        if child_id is None:
522
551
            return lexists(self._tree.abspath(childpath))
523
552
        else:
524
 
            if tt.final_parent(child_id) != parent_id:
 
553
            if self.final_parent(child_id) != parent_id:
525
554
                return False
526
 
            if child_id in tt._removed_contents:
 
555
            if child_id in self._removed_contents:
527
556
                # XXX What about dangling file-ids?
528
557
                return False
529
558
            else:
829
858
        parent_id is the transaction id of the parent directory of the file.
830
859
        contents is an iterator of bytestrings, which will be used to produce
831
860
        the file.
832
 
        file_id is the inventory ID of the file, if it is to be versioned.
 
861
        :param file_id: The inventory ID of the file, if it is to be versioned.
 
862
        :param executable: Only valid when a file_id has been supplied.
833
863
        """
834
864
        trans_id = self._new_entry(name, parent_id, file_id)
 
865
        # TODO: rather than scheduling a set_executable call,
 
866
        # have create_file create the file with the right mode.
835
867
        self.create_file(contents, trans_id)
836
868
        if executable is not None:
837
869
            self.set_executability(executable, trans_id)
966
998
 
967
999
def find_interesting(working_tree, target_tree, filenames):
968
1000
    """Find the ids corresponding to specified filenames."""
969
 
    if not filenames:
970
 
        interesting_ids = None
971
 
    else:
972
 
        interesting_ids = set()
973
 
        for tree_path in filenames:
974
 
            not_found = True
975
 
            for tree in (working_tree, target_tree):
976
 
                file_id = tree.inventory.path2id(tree_path)
977
 
                if file_id is not None:
978
 
                    interesting_ids.add(file_id)
979
 
                    not_found = False
980
 
            if not_found:
981
 
                raise NotVersionedError(path=tree_path)
982
 
    return interesting_ids
 
1001
    trees = (working_tree, target_tree)
 
1002
    return tree.find_ids_across_trees(filenames, trees)
983
1003
 
984
1004
 
985
1005
def change_entry(tt, file_id, working_tree, target_tree, 
1045
1065
    try:
1046
1066
        working_kind = working_tree.kind(file_id)
1047
1067
        has_contents = True
1048
 
    except OSError, e:
1049
 
        if e.errno != errno.ENOENT:
1050
 
            raise
 
1068
    except NoSuchFile:
1051
1069
        has_contents = False
1052
1070
        contents_mod = True
1053
1071
        meta_mod = False
1054
1072
    if has_contents is True:
1055
 
        real_e_kind = entry.kind
1056
 
        if real_e_kind == 'root_directory':
1057
 
            real_e_kind = 'directory'
1058
 
        if real_e_kind != working_kind:
 
1073
        if entry.kind != working_kind:
1059
1074
            contents_mod, meta_mod = True, False
1060
1075
        else:
1061
1076
            cur_entry._read_tree_state(working_tree.id2path(file_id), 
1070
1085
    """Revert a working tree's contents to those of a target tree."""
1071
1086
    interesting_ids = find_interesting(working_tree, target_tree, filenames)
1072
1087
    def interesting(file_id):
1073
 
        return interesting_ids is None or file_id in interesting_ids
 
1088
        return interesting_ids is None or (file_id in interesting_ids)
1074
1089
 
1075
1090
    tt = TreeTransform(working_tree, pb)
1076
1091
    try:
1117
1132
                if file_id not in target_tree:
1118
1133
                    trans_id = tt.trans_id_tree_file_id(file_id)
1119
1134
                    tt.unversion_file(trans_id)
1120
 
                    if file_id in merge_modified:
 
1135
                    try:
 
1136
                        file_kind = working_tree.kind(file_id)
 
1137
                    except NoSuchFile:
 
1138
                        file_kind = None
 
1139
                    if file_kind != 'file' and file_kind is not None:
 
1140
                        keep_contents = False
 
1141
                        delete_merge_modified = False
 
1142
                    else:
 
1143
                        if (file_id in merge_modified and 
 
1144
                            merge_modified[file_id] == 
 
1145
                            working_tree.get_file_sha1(file_id)):
 
1146
                            keep_contents = False
 
1147
                            delete_merge_modified = True
 
1148
                        else:
 
1149
                            keep_contents = True
 
1150
                            delete_merge_modified = False
 
1151
                    if not keep_contents:
1121
1152
                        tt.delete_contents(trans_id)
 
1153
                    if delete_merge_modified:
1122
1154
                        del merge_modified[file_id]
1123
1155
        finally:
1124
1156
            child_pb.finished()
1197
1229
            new_conflicts.add((c_type, 'Versioned directory', conflict[1]))
1198
1230
    return new_conflicts
1199
1231
 
 
1232
 
1200
1233
def cook_conflicts(raw_conflicts, tt):
1201
1234
    """Generate a list of cooked conflicts, sorted by file path"""
1202
 
    def key(conflict):
1203
 
        if conflict.path is not None:
1204
 
            return conflict.path, conflict.typestring
1205
 
        elif getattr(conflict, "conflict_path", None) is not None:
1206
 
            return conflict.conflict_path, conflict.typestring
1207
 
        else:
1208
 
            return None, conflict.typestring
 
1235
    from bzrlib.conflicts import Conflict
 
1236
    conflict_iter = iter_cook_conflicts(raw_conflicts, tt)
 
1237
    return sorted(conflict_iter, key=Conflict.sort_key)
1209
1238
 
1210
 
    return sorted(list(iter_cook_conflicts(raw_conflicts, tt)), key=key)
1211
1239
 
1212
1240
def iter_cook_conflicts(raw_conflicts, tt):
1213
1241
    from bzrlib.conflicts import Conflict