/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 breezy/plugins/git/tree.py

  • Committer: Breezy landing bot
  • Author(s): Jelmer Vernooij
  • Date: 2018-05-21 21:16:48 UTC
  • mfrom: (6973.1.1 git-cleanup)
  • Revision ID: breezy.the.bot@gmail.com-20180521211648-d3emlyz0qi3gwxh5
Make InterIndexGitTree suitable for use with MemoryGitTree.

Merged from https://code.launchpad.net/~jelmer/brz/inter-memorygittree/+merge/346426

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
import os
25
25
 
26
26
from dulwich.index import (
 
27
    blob_from_path_and_stat,
 
28
    cleanup_mode,
 
29
    commit_tree,
27
30
    index_entry_from_stat,
28
31
    )
29
32
from dulwich.object_store import (
1184
1187
            else:
1185
1188
                todo = [(p, i) for (p, i) in self._recurse_index_entries() if p.startswith(from_path+'/')]
1186
1189
                for child_path, child_value in todo:
1187
 
                    (child_to_index, child_to_index_path) = self._lookup_index(posixpath.join(to_path, posixpath.relpath(child_path, from_path)))
 
1190
                    (child_to_index, child_to_index_path) = self._lookup_index(
 
1191
                            posixpath.join(to_path, posixpath.relpath(child_path, from_path)))
1188
1192
                    child_to_index[child_to_index_path] = child_value
1189
1193
                    # TODO(jelmer): Mark individual index as dirty
1190
1194
                    self._index_dirty = True
1252
1256
                return 'directory'
1253
1257
        else:
1254
1258
            return kind
 
1259
 
 
1260
    def _live_entry(self, relpath):
 
1261
        raise NotImplementedError(self._live_entry)
 
1262
 
 
1263
 
 
1264
class InterIndexGitTree(InterGitTrees):
 
1265
    """InterTree that works between a Git revision tree and an index."""
 
1266
 
 
1267
    def __init__(self, source, target):
 
1268
        super(InterIndexGitTree, self).__init__(source, target)
 
1269
        self._index = target.index
 
1270
 
 
1271
    @classmethod
 
1272
    def is_compatible(cls, source, target):
 
1273
        return (isinstance(source, GitRevisionTree) and
 
1274
                isinstance(target, MutableGitIndexTree))
 
1275
 
 
1276
    def _iter_git_changes(self, want_unchanged=False, specific_files=None,
 
1277
            require_versioned=False, extra_trees=None,
 
1278
            want_unversioned=False):
 
1279
        trees = [self.source]
 
1280
        if extra_trees is not None:
 
1281
            trees.extend(extra_trees)
 
1282
        if specific_files is not None:
 
1283
            specific_files = self.target.find_related_paths_across_trees(
 
1284
                    specific_files, trees,
 
1285
                    require_versioned=require_versioned)
 
1286
        # TODO(jelmer): Restrict to specific_files, for performance reasons.
 
1287
        with self.lock_read():
 
1288
            return changes_between_git_tree_and_working_copy(
 
1289
                self.source.store, self.source.tree,
 
1290
                self.target, want_unchanged=want_unchanged,
 
1291
                want_unversioned=want_unversioned)
 
1292
 
 
1293
 
 
1294
_mod_tree.InterTree.register_optimiser(InterIndexGitTree)
 
1295
 
 
1296
 
 
1297
def changes_between_git_tree_and_working_copy(store, from_tree_sha, target,
 
1298
        want_unchanged=False, want_unversioned=False):
 
1299
    """Determine the changes between a git tree and a working tree with index.
 
1300
 
 
1301
    """
 
1302
    extras = set()
 
1303
    blobs = {}
 
1304
    # Report dirified directories to commit_tree first, so that they can be
 
1305
    # replaced with non-empty directories if they have contents.
 
1306
    dirified = []
 
1307
    for path, index_entry in target._recurse_index_entries():
 
1308
        try:
 
1309
            live_entry = target._live_entry(path)
 
1310
        except EnvironmentError as e:
 
1311
            if e.errno == errno.ENOENT:
 
1312
                # Entry was removed; keep it listed, but mark it as gone.
 
1313
                blobs[path] = (ZERO_SHA, 0)
 
1314
            elif e.errno == errno.EISDIR:
 
1315
                # Entry was turned into a directory
 
1316
                dirified.append((path, Tree().id, stat.S_IFDIR))
 
1317
                store.add_object(Tree())
 
1318
            else:
 
1319
                raise
 
1320
        else:
 
1321
            blobs[path] = (live_entry.sha, cleanup_mode(live_entry.mode))
 
1322
    if want_unversioned:
 
1323
        for e in target.extras():
 
1324
            st = target._lstat(e)
 
1325
            try:
 
1326
                np, accessible = osutils.normalized_filename(e)
 
1327
            except UnicodeDecodeError:
 
1328
                raise errors.BadFilenameEncoding(
 
1329
                    e, osutils._fs_enc)
 
1330
            if stat.S_ISDIR(st.st_mode):
 
1331
                blob = Tree()
 
1332
            else:
 
1333
                blob = blob_from_path_and_stat(target.abspath(e).encode(osutils._fs_enc), st)
 
1334
            store.add_object(blob)
 
1335
            np = np.encode('utf-8')
 
1336
            blobs[np] = (blob.id, cleanup_mode(st.st_mode))
 
1337
            extras.add(np)
 
1338
    to_tree_sha = commit_tree(store, dirified + [(p, s, m) for (p, (s, m)) in blobs.items()])
 
1339
    return store.tree_changes(
 
1340
        from_tree_sha, to_tree_sha, include_trees=True,
 
1341
        want_unchanged=want_unchanged, change_type_same=True), extras