253
252
def __init__(self, repository, revision_id):
254
253
self._revision_id = revision_id
255
254
self._repository = repository
255
self._submodules = None
256
256
self.store = repository._git.object_store
257
257
if not isinstance(revision_id, bytes):
258
258
raise TypeError(revision_id)
261
261
if revision_id == NULL_REVISION:
263
263
self.mapping = default_mapping
264
self._fileid_map = GitFileIdMap(
269
266
commit = self.store[self.commit_id]
271
268
raise errors.NoSuchRevision(repository, revision_id)
272
269
self.tree = commit.tree
273
self._fileid_map = self.mapping.get_fileid_map(
274
self.store.__getitem__, self.tree)
276
def _get_nested_repository(self, path):
277
nested_repo_transport = self._repository.user_transport.clone(path)
271
def _submodule_info(self):
272
if self._submodules is None:
274
with self.get_file('.gitmodules') as f:
275
config = GitConfigFile.from_file(f)
278
for path, url, section in parse_submodules(config)}
279
except errors.NoSuchFile:
280
self._submodules = {}
281
return self._submodules
283
def _get_submodule_repository(self, relpath):
284
if not isinstance(relpath, bytes):
285
raise TypeError(relpath)
287
info = self._submodule_info()[relpath]
289
nested_repo_transport = self._repository.user_transport.clone(relpath.decode('utf-8'))
291
nested_repo_transport = self._repository.control_transport.clone(
292
posixpath.join('modules', info[0]))
278
293
nested_controldir = _mod_controldir.ControlDir.open_from_transport(
279
294
nested_repo_transport)
280
295
return nested_controldir.find_repository()
297
def get_nested_tree(self, path):
298
encoded_path = path.encode('utf-8')
299
nested_repo = self._get_submodule_repository(encoded_path)
300
ref_rev = self.get_reference_revision(path)
301
return nested_repo.revision_tree(ref_rev)
282
303
def supports_rename_tracking(self):
305
326
def id2path(self, file_id):
307
path = self._fileid_map.lookup_path(file_id)
328
path = self.mapping.parse_file_id(file_id)
308
329
except ValueError:
309
330
raise errors.NoSuchId(self, file_id)
310
331
if self.is_versioned(path):
320
341
if not self.is_versioned(path):
322
return self._fileid_map.lookup_file_id(osutils.safe_unicode(path))
343
return self.mapping.generate_file_id(osutils.safe_unicode(path))
324
345
def all_file_ids(self):
325
346
raise errors.UnsupportedOperation(self.all_file_ids, self)
401
417
root_ie = self._get_dir_ie(b"", None)
403
419
parent_path = posixpath.dirname(from_dir)
404
parent_id = self._fileid_map.lookup_file_id(parent_path)
420
parent_id = self.mapping.generate_file_id(parent_path)
405
421
if mode_kind(mode) == 'directory':
406
422
root_ie = self._get_dir_ie(from_dir.encode("utf-8"), parent_id)
441
457
kind = mode_kind(mode)
442
458
path = path.decode('utf-8')
443
459
name = name.decode("utf-8")
444
file_id = self._fileid_map.lookup_file_id(path)
460
file_id = self.mapping.generate_file_id(path)
445
461
ie = entry_factory[kind](file_id, name, parent_id)
446
462
if kind == 'symlink':
447
463
ie.symlink_target = store[hexsha].data.decode('utf-8')
458
474
def _get_dir_ie(self, path, parent_id):
459
475
path = path.decode('utf-8')
460
file_id = self._fileid_map.lookup_file_id(path)
476
file_id = self.mapping.generate_file_id(path)
461
477
return GitTreeDirectory(file_id, posixpath.basename(path), parent_id)
463
479
def iter_child_entries(self, path):
492
508
specific_files = set([p.encode('utf-8')
493
509
for p in specific_files])
494
todo = deque([(self.store, b"", self.tree, self.get_root_id())])
510
todo = deque([(self.store, b"", self.tree, self.path2id(''))])
495
511
if specific_files is None or u"" in specific_files:
496
512
yield u"", self._get_dir_ie(b"", None)
565
581
"""See RevisionTree.get_symlink_target."""
566
582
(store, mode, hexsha) = self._lookup_path(path)
567
583
if S_ISGITLINK(mode):
568
nested_repo = self._get_nested_repository(path)
584
nested_repo = self._get_submodule_repository(path.encode('utf-8'))
569
585
return nested_repo.lookup_foreign_revision_id(hexsha)
590
606
elif kind == 'symlink':
591
607
return (kind, None, None, store[hexsha].data.decode('utf-8'))
592
608
elif kind == 'tree-reference':
593
nested_repo = self._get_nested_repository(path)
609
nested_repo = self._get_submodule_repository(path.encode('utf-8'))
594
610
return (kind, None, None,
595
611
nested_repo.lookup_foreign_revision_id(hexsha))
666
682
yield (path_decoded, parent_id), children
669
def tree_delta_from_git_changes(changes, mapping,
670
fileid_maps, specific_files=None,
685
def tree_delta_from_git_changes(changes, mappings,
671
687
require_versioned=False, include_root=False,
672
688
target_extras=None):
673
689
"""Create a TreeDelta from two git trees.
675
691
source and target are iterators over tuples with:
676
692
(filename, sha, mode)
678
(old_fileid_map, new_fileid_map) = fileid_maps
694
(old_mapping, new_mapping) = mappings
679
695
if target_extras is None:
680
696
target_extras = set()
681
697
ret = delta.TreeDelta()
699
715
osutils.is_inside_or_parent_of_any(
700
716
specific_files, newpath_decoded))):
702
if mapping.is_special_file(oldpath):
718
if old_mapping.is_special_file(oldpath):
704
if mapping.is_special_file(newpath):
720
if new_mapping.is_special_file(newpath):
706
722
if oldpath is None and newpath is None:
708
724
if oldpath is None:
709
725
added.append((newpath, mode_kind(newmode)))
710
726
elif newpath is None or newmode == 0:
711
file_id = old_fileid_map.lookup_file_id(oldpath_decoded)
727
file_id = old_mapping.generate_file_id(oldpath_decoded)
712
728
ret.removed.append((oldpath_decoded, file_id, mode_kind(oldmode)))
713
729
elif oldpath != newpath:
714
file_id = old_fileid_map.lookup_file_id(oldpath_decoded)
730
file_id = old_mapping.generate_file_id(oldpath_decoded)
715
731
ret.renamed.append(
716
732
(oldpath_decoded, newpath.decode('utf-8'), file_id,
717
733
mode_kind(newmode), (oldsha != newsha),
718
734
(oldmode != newmode)))
719
735
elif mode_kind(oldmode) != mode_kind(newmode):
720
file_id = new_fileid_map.lookup_file_id(newpath_decoded)
736
file_id = new_mapping.generate_file_id(newpath_decoded)
721
737
ret.kind_changed.append(
722
738
(newpath_decoded, file_id, mode_kind(oldmode),
723
739
mode_kind(newmode)))
724
740
elif oldsha != newsha or oldmode != newmode:
725
741
if stat.S_ISDIR(oldmode) and stat.S_ISDIR(newmode):
727
file_id = new_fileid_map.lookup_file_id(newpath_decoded)
743
file_id = new_mapping.generate_file_id(newpath_decoded)
728
744
ret.modified.append(
729
745
(newpath_decoded, file_id, mode_kind(newmode),
730
746
(oldsha != newsha), (oldmode != newmode)))
732
file_id = new_fileid_map.lookup_file_id(newpath_decoded)
748
file_id = new_mapping.generate_file_id(newpath_decoded)
733
749
ret.unchanged.append(
734
750
(newpath_decoded, file_id, mode_kind(newmode)))
746
762
if path in target_extras:
747
763
ret.unversioned.append((path_decoded, None, kind))
749
file_id = new_fileid_map.lookup_file_id(path_decoded)
765
file_id = new_mapping.generate_file_id(path_decoded)
750
766
ret.added.append((path_decoded, file_id, kind))
857
873
specific_files=specific_files,
858
874
extra_trees=extra_trees,
859
875
want_unversioned=want_unversioned)
860
source_fileid_map = self.source._fileid_map
861
target_fileid_map = self.target._fileid_map
862
876
return tree_delta_from_git_changes(
863
changes, self.target.mapping,
864
(source_fileid_map, target_fileid_map),
877
changes, (self.source.mapping, self.target.mapping),
865
878
specific_files=specific_files,
866
879
include_root=include_root, target_extras=target_extras)
988
1001
raise TypeError(file_id)
989
1002
with self.lock_read():
991
path = self._fileid_map.lookup_path(file_id)
1004
path = self.mapping.parse_file_id(file_id)
992
1005
except ValueError:
993
1006
raise errors.NoSuchId(self, file_id)
994
1007
if self.is_versioned(path):
998
1011
def _set_root_id(self, file_id):
999
1012
raise errors.UnsupportedOperation(self._set_root_id, self)
1001
def get_root_id(self):
1002
return self.path2id(u"")
1004
1014
def _add(self, files, ids, kinds):
1005
1015
for (path, file_id, kind) in zip(files, ids, kinds):
1006
1016
if file_id is not None: