1339
1339
for hook in MutableTree.hooks['post_build_tree']:
1344
class InterIndexGitTree(InterGitTrees):
1345
"""InterTree that works between a Git revision tree and an index."""
1347
def __init__(self, source, target):
1348
super(InterIndexGitTree, self).__init__(source, target)
1349
self._index = target.index
1352
def is_compatible(cls, source, target):
1353
from .repository import GitRevisionTree
1354
return (isinstance(source, GitRevisionTree) and
1355
isinstance(target, GitWorkingTree))
1357
def _iter_git_changes(self, want_unchanged=False, specific_files=None,
1358
require_versioned=False, extra_trees=None,
1359
want_unversioned=False):
1360
trees = [self.source]
1361
if extra_trees is not None:
1362
trees.extend(extra_trees)
1363
if specific_files is not None:
1364
specific_files = self.target.find_related_paths_across_trees(
1365
specific_files, trees,
1366
require_versioned=require_versioned)
1367
# TODO(jelmer): Restrict to specific_files, for performance reasons.
1368
with self.lock_read():
1369
return changes_between_git_tree_and_working_copy(
1370
self.source.store, self.source.tree,
1371
self.target, want_unchanged=want_unchanged,
1372
want_unversioned=want_unversioned)
1375
tree.InterTree.register_optimiser(InterIndexGitTree)
1378
def changes_between_git_tree_and_working_copy(store, from_tree_sha, target,
1379
want_unchanged=False, want_unversioned=False):
1380
"""Determine the changes between a git tree and a working tree with index.
1385
# Report dirified directories to commit_tree first, so that they can be
1386
# replaced with non-empty directories if they have contents.
1388
target_root_path = target.abspath('.').encode(sys.getfilesystemencoding())
1389
for path, index_entry in target._recurse_index_entries():
1391
live_entry = index_entry_from_path(
1392
target.abspath(path.decode('utf-8')).encode(osutils._fs_enc))
1393
except EnvironmentError as e:
1394
if e.errno == errno.ENOENT:
1395
# Entry was removed; keep it listed, but mark it as gone.
1396
blobs[path] = (ZERO_SHA, 0)
1397
elif e.errno == errno.EISDIR:
1398
# Entry was turned into a directory
1399
dirified.append((path, Tree().id, stat.S_IFDIR))
1400
store.add_object(Tree())
1404
blobs[path] = (live_entry.sha, cleanup_mode(live_entry.mode))
1405
if want_unversioned:
1406
for e in target.extras():
1407
ap = target.abspath(e)
1410
np, accessible = osutils.normalized_filename(e)
1411
except UnicodeDecodeError:
1412
raise errors.BadFilenameEncoding(
1414
if stat.S_ISDIR(st.st_mode):
1417
blob = blob_from_path_and_stat(ap.encode('utf-8'), st)
1418
store.add_object(blob)
1419
np = np.encode('utf-8')
1420
blobs[np] = (blob.id, cleanup_mode(st.st_mode))
1422
to_tree_sha = commit_tree(store, dirified + [(p, s, m) for (p, (s, m)) in blobs.items()])
1423
return store.tree_changes(
1424
from_tree_sha, to_tree_sha, include_trees=True,
1425
want_unchanged=want_unchanged, change_type_same=True), extras