444
446
parent_path = posixpath.dirname(from_dir)
445
447
parent_id = self.mapping.generate_file_id(parent_path)
446
448
if mode_kind(mode) == 'directory':
447
root_ie = self._get_dir_ie(from_dir.encode("utf-8"), parent_id)
449
root_ie = self._get_dir_ie(encode_git_path(from_dir), parent_id)
449
451
root_ie = self._get_file_ie(
450
store, from_dir.encode("utf-8"),
452
store, encode_git_path(from_dir),
451
453
posixpath.basename(from_dir), mode, hexsha)
453
455
yield (from_dir, "V", root_ie.kind, root_ie)
455
457
if root_ie.kind == 'directory':
456
todo.append((store, from_dir.encode("utf-8"),
458
todo.append((store, encode_git_path(from_dir),
457
459
b"", hexsha, root_ie.file_id))
459
461
(store, path, relpath, hexsha, parent_id) = todo.pop()
697
699
def walkdirs(self, prefix=u""):
698
700
(store, mode, hexsha) = self._lookup_path(prefix)
700
[(store, prefix.encode('utf-8'), hexsha, self.path2id(prefix))])
702
[(store, encode_git_path(prefix), hexsha, self.path2id(prefix))])
702
704
store, path, tree_sha, parent_id = todo.popleft()
703
path_decoded = path.decode('utf-8')
705
path_decoded = decode_git_path(path)
704
706
tree = store[tree_sha]
706
708
for name, mode, hexsha in tree.iteritems():
707
709
if self.mapping.is_special_file(name):
709
711
child_path = posixpath.join(path, name)
710
file_id = self.path2id(child_path.decode('utf-8'))
712
file_id = self.path2id(decode_git_path(child_path))
711
713
if stat.S_ISDIR(mode):
712
714
todo.append((store, child_path, hexsha, file_id))
714
(child_path.decode('utf-8'), name.decode('utf-8'),
716
(decode_git_path(child_path), decode_git_path(name),
715
717
mode_kind(mode), None,
716
718
file_id, mode_kind(mode)))
717
719
yield (path_decoded, parent_id), children
721
def preview_transform(self, pb=None):
722
from .transform import GitTransformPreview
723
return GitTransformPreview(self, pb=pb)
720
726
def tree_delta_from_git_changes(changes, mappings,
721
727
specific_files=None,
1619
1628
def _live_entry(self, relpath):
1620
1629
raise NotImplementedError(self._live_entry)
1622
def get_transform(self, pb=None):
1623
from ..transform import TreeTransform
1624
return TreeTransform(self, pb=pb)
1628
class InterIndexGitTree(InterGitTrees):
1631
def transform(self, pb=None):
1632
from .transform import GitTreeTransform
1633
return GitTreeTransform(self, pb=pb)
1635
def preview_transform(self, pb=None):
1636
from .transform import GitTransformPreview
1637
return GitTransformPreview(self, pb=pb)
1640
class InterToIndexGitTree(InterGitTrees):
1629
1641
"""InterTree that works between a Git revision tree and an index."""
1631
1643
def __init__(self, source, target):
1632
super(InterIndexGitTree, self).__init__(source, target)
1633
self._index = target.index
1644
super(InterToIndexGitTree, self).__init__(source, target)
1634
1645
if self.source.store == self.target.store:
1635
1646
self.store = self.source.store
1659
1670
self.source.store, self.source.tree,
1660
1671
self.target, want_unchanged=want_unchanged,
1661
1672
want_unversioned=want_unversioned,
1662
rename_detector=self.rename_detector)
1673
rename_detector=self.rename_detector,
1674
include_trees=include_trees)
1663
1675
return changes, set(), target_extras
1678
_mod_tree.InterTree.register_optimiser(InterToIndexGitTree)
1681
class InterFromIndexGitTree(InterGitTrees):
1682
"""InterTree that works between a Git revision tree and an index."""
1684
def __init__(self, source, target):
1685
super(InterFromIndexGitTree, self).__init__(source, target)
1686
if self.source.store == self.target.store:
1687
self.store = self.source.store
1689
self.store = OverlayObjectStore(
1690
[self.source.store, self.target.store])
1691
self.rename_detector = RenameDetector(self.store)
1694
def is_compatible(cls, source, target):
1695
return (isinstance(target, GitRevisionTree) and
1696
isinstance(source, MutableGitIndexTree))
1698
def _iter_git_changes(self, want_unchanged=False, specific_files=None,
1699
require_versioned=False, extra_trees=None,
1700
want_unversioned=False, include_trees=True):
1701
trees = [self.source]
1702
if extra_trees is not None:
1703
trees.extend(extra_trees)
1704
if specific_files is not None:
1705
specific_files = self.target.find_related_paths_across_trees(
1706
specific_files, trees,
1707
require_versioned=require_versioned)
1708
# TODO(jelmer): Restrict to specific_files, for performance reasons.
1709
with self.lock_read():
1710
from_tree_sha, extras = snapshot_workingtree(self.source, want_unversioned=want_unversioned)
1711
return tree_changes(
1712
self.store, from_tree_sha, self.target.tree,
1713
include_trees=include_trees,
1714
rename_detector=self.rename_detector,
1715
want_unchanged=want_unchanged, change_type_same=True), extras
1718
_mod_tree.InterTree.register_optimiser(InterFromIndexGitTree)
1721
class InterIndexGitTree(InterGitTrees):
1722
"""InterTree that works between a Git revision tree and an index."""
1724
def __init__(self, source, target):
1725
super(InterIndexGitTree, self).__init__(source, target)
1726
if self.source.store == self.target.store:
1727
self.store = self.source.store
1729
self.store = OverlayObjectStore(
1730
[self.source.store, self.target.store])
1731
self.rename_detector = RenameDetector(self.store)
1734
def is_compatible(cls, source, target):
1735
return (isinstance(target, MutableGitIndexTree) and
1736
isinstance(source, MutableGitIndexTree))
1738
def _iter_git_changes(self, want_unchanged=False, specific_files=None,
1739
require_versioned=False, extra_trees=None,
1740
want_unversioned=False, include_trees=True):
1741
trees = [self.source]
1742
if extra_trees is not None:
1743
trees.extend(extra_trees)
1744
if specific_files is not None:
1745
specific_files = self.target.find_related_paths_across_trees(
1746
specific_files, trees,
1747
require_versioned=require_versioned)
1748
# TODO(jelmer): Restrict to specific_files, for performance reasons.
1749
with self.lock_read():
1750
from_tree_sha, from_extras = snapshot_workingtree(
1751
self.source, want_unversioned=want_unversioned)
1752
to_tree_sha, to_extras = snapshot_workingtree(
1753
self.target, want_unversioned=want_unversioned)
1754
changes = tree_changes(
1755
self.store, from_tree_sha, to_tree_sha,
1756
include_trees=include_trees,
1757
rename_detector=self.rename_detector,
1758
want_unchanged=want_unchanged, change_type_same=True)
1759
return changes, from_extras, to_extras
1666
1762
_mod_tree.InterTree.register_optimiser(InterIndexGitTree)
1669
def changes_between_git_tree_and_working_copy(source_store, from_tree_sha, target,
1670
want_unchanged=False,
1671
want_unversioned=False,
1672
rename_detector=None):
1673
"""Determine the changes between a git tree and a working tree with index.
1765
def snapshot_workingtree(target, want_unversioned=False):
1678
1768
# Report dirified directories to commit_tree first, so that they can be
1739
1829
target.store.add_object(blob)
1740
1830
blobs[np] = (blob.id, cleanup_mode(st.st_mode))
1742
to_tree_sha = commit_tree(
1743
target.store, dirified + [(p, s, m) for (p, (s, m)) in blobs.items()])
1833
target.store, dirified + [(p, s, m) for (p, (s, m)) in blobs.items()]), extras
1836
def changes_between_git_tree_and_working_copy(source_store, from_tree_sha, target,
1837
want_unchanged=False,
1838
want_unversioned=False,
1839
rename_detector=None,
1840
include_trees=True):
1841
"""Determine the changes between a git tree and a working tree with index.
1844
to_tree_sha, extras = snapshot_workingtree(target, want_unversioned=want_unversioned)
1744
1845
store = OverlayObjectStore([source_store, target.store])
1745
1846
return tree_changes(
1746
store, from_tree_sha, to_tree_sha, include_trees=True,
1847
store, from_tree_sha, to_tree_sha, include_trees=include_trees,
1747
1848
rename_detector=rename_detector,
1748
1849
want_unchanged=want_unchanged, change_type_same=True), extras