136
135
self.executable == other.executable)
138
137
def __repr__(self):
139
return "%s(file_id=%r, name=%r, parent_id=%r, text_size=%r, text_sha1=%r, executable=%r)" % (
138
return ("%s(file_id=%r, name=%r, parent_id=%r, text_size=%r, "
139
"text_sha1=%r, executable=%r)") % (
140
140
type(self).__name__, self.file_id, self.name, self.parent_id,
141
141
self.text_size, self.text_sha1, self.executable)
144
144
ret = self.__class__(
145
self.file_id, self.name, self.parent_id)
145
self.file_id, self.name, self.parent_id)
146
146
ret.text_sha1 = self.text_sha1
147
147
ret.text_size = self.text_size
148
148
ret.executable = self.executable
269
271
raise errors.NoSuchRevision(repository, revision_id)
270
272
self.tree = commit.tree
271
self._fileid_map = self.mapping.get_fileid_map(self.store.__getitem__, self.tree)
273
self._fileid_map = self.mapping.get_fileid_map(
274
self.store.__getitem__, self.tree)
273
276
def _get_nested_repository(self, path):
274
277
nested_repo_transport = self._repository.user_transport.clone(path)
275
nested_controldir = _mod_controldir.ControlDir.open_from_transport(nested_repo_transport)
278
nested_controldir = _mod_controldir.ControlDir.open_from_transport(
279
nested_repo_transport)
276
280
return nested_controldir.find_repository()
278
282
def supports_rename_tracking(self):
281
def get_file_revision(self, path, file_id=None):
285
def get_file_revision(self, path):
282
286
change_scanner = self._repository._file_change_scanner
283
287
if self.commit_id == ZERO_SHA:
284
288
return NULL_REVISION
285
289
(unused_path, commit_id) = change_scanner.find_last_change_revision(
286
290
path.encode('utf-8'), self.commit_id)
287
return self._repository.lookup_foreign_revision_id(commit_id, self.mapping)
291
return self._repository.lookup_foreign_revision_id(
292
commit_id, self.mapping)
289
def get_file_mtime(self, path, file_id=None):
294
def get_file_mtime(self, path):
291
revid = self.get_file_revision(path, file_id)
296
revid = self.get_file_revision(path)
293
298
raise errors.NoSuchFile(path)
357
362
if self.tree is None:
358
363
raise errors.NoSuchFile(path)
360
(mode, hexsha) = tree_lookup_path(self.store.__getitem__, self.tree,
361
path.encode('utf-8'))
365
(mode, hexsha) = tree_lookup_path(
366
self.store.__getitem__, self.tree, path.encode('utf-8'))
363
368
raise errors.NoSuchFile(self, path)
365
370
return (self.store, mode, hexsha)
367
def is_executable(self, path, file_id=None):
372
def is_executable(self, path):
368
373
(store, mode, hexsha) = self._lookup_path(path)
370
375
# the tree root is a directory
372
377
return mode_is_executable(mode)
374
def kind(self, path, file_id=None):
379
def kind(self, path):
375
380
(store, mode, hexsha) = self._lookup_path(path)
377
382
# the tree root is a directory
400
405
if mode_kind(mode) == 'directory':
401
406
root_ie = self._get_dir_ie(from_dir.encode("utf-8"), parent_id)
403
root_ie = self._get_file_ie(store, from_dir.encode("utf-8"),
408
root_ie = self._get_file_ie(
409
store, from_dir.encode("utf-8"),
404
410
posixpath.basename(from_dir), mode, hexsha)
406
412
yield (from_dir, "V", root_ie.kind, root_ie.file_id, root_ie)
408
414
if root_ie.kind == 'directory':
409
todo.append((store, from_dir.encode("utf-8"), b"", hexsha, root_ie.file_id))
415
todo.append((store, from_dir.encode("utf-8"),
416
b"", hexsha, root_ie.file_id))
411
418
(store, path, relpath, hexsha, parent_id) = todo.pop()
412
419
tree = store[hexsha]
418
425
if stat.S_ISDIR(mode):
419
426
ie = self._get_dir_ie(child_path, parent_id)
421
todo.append((store, child_path, child_relpath, hexsha, ie.file_id))
429
(store, child_path, child_relpath, hexsha,
423
ie = self._get_file_ie(store, child_path, name, mode, hexsha, parent_id)
424
yield child_relpath.decode('utf-8'), "V", ie.kind, ie.file_id, ie
432
ie = self._get_file_ie(
433
store, child_path, name, mode, hexsha, parent_id)
434
yield (child_relpath.decode('utf-8'), "V", ie.kind, ie.file_id,
426
437
def _get_file_ie(self, store, path, name, mode, hexsha, parent_id):
427
438
if not isinstance(path, bytes):
478
490
if specific_files in ([""], []):
479
491
specific_files = None
481
specific_files = set([p.encode('utf-8') for p in specific_files])
493
specific_files = set([p.encode('utf-8')
494
for p in specific_files])
482
495
todo = deque([(self.store, b"", self.tree, self.get_root_id())])
483
496
if specific_files is None or u"" in specific_files:
484
497
yield u"", self._get_dir_ie(b"", None)
493
506
child_path_decoded = child_path.decode('utf-8')
494
507
if stat.S_ISDIR(mode):
495
508
if (specific_files is None or
496
any(filter(lambda p: p.startswith(child_path), specific_files))):
509
any([p for p in specific_files if p.startswith(
497
511
extradirs.append(
498
(store, child_path, hexsha, self.path2id(child_path_decoded)))
512
(store, child_path, hexsha,
513
self.path2id(child_path_decoded)))
499
514
if specific_files is None or child_path in specific_files:
500
515
if stat.S_ISDIR(mode):
501
516
yield (child_path_decoded,
516
531
"""See RevisionTree.get_revision_id."""
517
532
return self._revision_id
519
def get_file_sha1(self, path, file_id=None, stat_value=None):
534
def get_file_sha1(self, path, stat_value=None):
520
535
if self.tree is None:
521
536
raise errors.NoSuchFile(path)
522
return osutils.sha_string(self.get_file_text(path, file_id))
537
return osutils.sha_string(self.get_file_text(path))
524
def get_file_verifier(self, path, file_id=None, stat_value=None):
539
def get_file_verifier(self, path, stat_value=None):
525
540
(store, mode, hexsha) = self._lookup_path(path)
526
541
return ("GIT", hexsha)
528
def get_file_size(self, path, file_id=None):
543
def get_file_size(self, path):
529
544
(store, mode, hexsha) = self._lookup_path(path)
530
545
if stat.S_ISREG(mode):
531
546
return len(store[hexsha].data)
534
def get_file_text(self, path, file_id=None):
549
def get_file_text(self, path):
535
550
"""See RevisionTree.get_file_text."""
536
551
(store, mode, hexsha) = self._lookup_path(path)
537
552
if stat.S_ISREG(mode):
571
586
if kind == 'file':
572
587
executable = mode_is_executable(mode)
573
588
contents = store[hexsha].data
574
return (kind, len(contents), executable, osutils.sha_string(contents))
589
return (kind, len(contents), executable,
590
osutils.sha_string(contents))
575
591
elif kind == 'symlink':
576
592
return (kind, None, None, store[hexsha].data.decode('utf-8'))
577
593
elif kind == 'tree-reference':
602
618
if self.tree is None:
604
620
return self.store.iter_tree_contents(
605
self.tree, include_trees=include_trees)
621
self.tree, include_trees=include_trees)
607
def annotate_iter(self, path, file_id=None,
608
default_revision=CURRENT_REVISION):
623
def annotate_iter(self, path, default_revision=CURRENT_REVISION):
609
624
"""Return an iterator of revision_id, line tuples.
611
626
For working trees (and mutable trees in general), the special
612
627
revision_id 'current:' will be used for lines that are new in this
613
628
tree, e.g. uncommitted changes.
614
:param file_id: The file to produce an annotated version from
615
629
:param default_revision: For lines that don't match a basis, mark them
616
630
with this revision id. Not all implementations will make use of
633
647
def walkdirs(self, prefix=u""):
634
648
(store, mode, hexsha) = self._lookup_path(prefix)
635
todo = deque([(store, prefix.encode('utf-8'), hexsha, self.path2id(prefix))])
650
[(store, prefix.encode('utf-8'), hexsha, self.path2id(prefix))])
637
652
store, path, tree_sha, parent_id = todo.popleft()
638
653
path_decoded = path.decode('utf-8')
655
670
def tree_delta_from_git_changes(changes, mapping,
656
fileid_maps, specific_files=None,
657
require_versioned=False, include_root=False,
671
fileid_maps, specific_files=None,
672
require_versioned=False, include_root=False,
659
674
"""Create a TreeDelta from two git trees.
661
676
source and target are iterators over tuples with:
678
693
newpath_decoded = newpath.decode('utf-8')
679
694
if not (specific_files is None or
680
(oldpath is not None and osutils.is_inside_or_parent_of_any(specific_files, oldpath_decoded)) or
681
(newpath is not None and osutils.is_inside_or_parent_of_any(specific_files, newpath_decoded))):
695
(oldpath is not None and
696
osutils.is_inside_or_parent_of_any(
697
specific_files, oldpath_decoded)) or
698
(newpath is not None and
699
osutils.is_inside_or_parent_of_any(
700
specific_files, newpath_decoded))):
683
702
if mapping.is_special_file(oldpath):
689
708
if oldpath is None:
690
709
if newpath in target_extras:
691
710
ret.unversioned.append(
692
(osutils.normalized_filename(newpath)[0], None, mode_kind(newmode)))
711
(osutils.normalized_filename(newpath)[0], None,
694
714
file_id = new_fileid_map.lookup_file_id(newpath_decoded)
695
ret.added.append((newpath_decoded, file_id, mode_kind(newmode)))
716
(newpath_decoded, file_id, mode_kind(newmode)))
696
717
elif newpath is None or newmode == 0:
697
718
file_id = old_fileid_map.lookup_file_id(oldpath_decoded)
698
719
ret.removed.append((oldpath_decoded, file_id, mode_kind(oldmode)))
700
721
file_id = old_fileid_map.lookup_file_id(oldpath_decoded)
701
722
ret.renamed.append(
702
723
(oldpath_decoded, newpath.decode('utf-8'), file_id,
703
mode_kind(newmode), (oldsha != newsha),
704
(oldmode != newmode)))
724
mode_kind(newmode), (oldsha != newsha),
725
(oldmode != newmode)))
705
726
elif mode_kind(oldmode) != mode_kind(newmode):
706
727
file_id = new_fileid_map.lookup_file_id(newpath_decoded)
707
728
ret.kind_changed.append(
708
729
(newpath_decoded, file_id, mode_kind(oldmode),
710
731
elif oldsha != newsha or oldmode != newmode:
711
732
if stat.S_ISDIR(oldmode) and stat.S_ISDIR(newmode):
713
734
file_id = new_fileid_map.lookup_file_id(newpath_decoded)
714
735
ret.modified.append(
715
736
(newpath_decoded, file_id, mode_kind(newmode),
716
(oldsha != newsha), (oldmode != newmode)))
737
(oldsha != newsha), (oldmode != newmode)))
718
739
file_id = new_fileid_map.lookup_file_id(newpath_decoded)
719
ret.unchanged.append((newpath_decoded, file_id, mode_kind(newmode)))
740
ret.unchanged.append(
741
(newpath_decoded, file_id, mode_kind(newmode)))
724
def changes_from_git_changes(changes, mapping, specific_files=None, include_unchanged=False,
746
def changes_from_git_changes(changes, mapping, specific_files=None,
747
include_unchanged=False, target_extras=None):
726
748
"""Create a iter_changes-like generator from a git stream.
728
750
source and target are iterators over tuples with:
741
763
newpath_decoded = None
742
764
if not (specific_files is None or
743
(oldpath_decoded is not None and osutils.is_inside_or_parent_of_any(specific_files, oldpath_decoded)) or
744
(newpath_decoded is not None and osutils.is_inside_or_parent_of_any(specific_files, newpath_decoded))):
765
(oldpath_decoded is not None and
766
osutils.is_inside_or_parent_of_any(
767
specific_files, oldpath_decoded)) or
768
(newpath_decoded is not None and
769
osutils.is_inside_or_parent_of_any(
770
specific_files, newpath_decoded))):
746
772
if oldpath is not None and mapping.is_special_file(oldpath):
791
817
newparent = mapping.generate_file_id(newparentpath)
792
818
if (not include_unchanged and
793
819
oldkind == 'directory' and newkind == 'directory' and
794
oldpath_decoded == newpath_decoded):
820
oldpath_decoded == newpath_decoded):
796
822
yield (fileid, (oldpath_decoded, newpath_decoded), (oldsha != newsha),
797
(oldversioned, newversioned),
798
(oldparent, newparent), (oldname, newname),
799
(oldkind, newkind), (oldexe, newexe))
823
(oldversioned, newversioned),
824
(oldparent, newparent), (oldname, newname),
825
(oldkind, newkind), (oldexe, newexe))
802
828
class InterGitTrees(_mod_tree.InterTree):
816
842
want_unversioned=False):
817
843
with self.lock_read():
818
844
changes, target_extras = self._iter_git_changes(
819
want_unchanged=want_unchanged,
820
require_versioned=require_versioned,
821
specific_files=specific_files,
822
extra_trees=extra_trees,
823
want_unversioned=want_unversioned)
845
want_unchanged=want_unchanged,
846
require_versioned=require_versioned,
847
specific_files=specific_files,
848
extra_trees=extra_trees,
849
want_unversioned=want_unversioned)
824
850
source_fileid_map = self.source._fileid_map
825
851
target_fileid_map = self.target._fileid_map
826
return tree_delta_from_git_changes(changes, self.target.mapping,
852
return tree_delta_from_git_changes(
853
changes, self.target.mapping,
827
854
(source_fileid_map, target_fileid_map),
828
specific_files=specific_files, include_root=include_root,
829
target_extras=target_extras)
855
specific_files=specific_files,
856
include_root=include_root, target_extras=target_extras)
831
858
def iter_changes(self, include_unchanged=False, specific_files=None,
832
859
pb=None, extra_trees=[], require_versioned=True,
833
860
want_unversioned=False):
834
861
with self.lock_read():
835
862
changes, target_extras = self._iter_git_changes(
836
want_unchanged=include_unchanged,
837
require_versioned=require_versioned,
838
specific_files=specific_files,
839
extra_trees=extra_trees,
840
want_unversioned=want_unversioned)
863
want_unchanged=include_unchanged,
864
require_versioned=require_versioned,
865
specific_files=specific_files,
866
extra_trees=extra_trees,
867
want_unversioned=want_unversioned)
841
868
return changes_from_git_changes(
842
changes, self.target.mapping,
843
specific_files=specific_files,
844
include_unchanged=include_unchanged,
845
target_extras=target_extras)
869
changes, self.target.mapping,
870
specific_files=specific_files,
871
include_unchanged=include_unchanged,
872
target_extras=target_extras)
847
874
def _iter_git_changes(self, want_unchanged=False, specific_files=None,
848
require_versioned=False, extra_trees=None,
849
want_unversioned=False):
875
require_versioned=False, extra_trees=None,
876
want_unversioned=False):
850
877
raise NotImplementedError(self._iter_git_changes)
863
890
isinstance(target, GitRevisionTree))
865
892
def _iter_git_changes(self, want_unchanged=False, specific_files=None,
866
require_versioned=True, extra_trees=None,
867
want_unversioned=False):
893
require_versioned=True, extra_trees=None,
894
want_unversioned=False):
868
895
trees = [self.source]
869
896
if extra_trees is not None:
870
897
trees.extend(extra_trees)
871
898
if specific_files is not None:
872
899
specific_files = self.target.find_related_paths_across_trees(
873
specific_files, trees,
874
require_versioned=require_versioned)
900
specific_files, trees,
901
require_versioned=require_versioned)
876
if self.source._repository._git.object_store != self.target._repository._git.object_store:
877
store = OverlayObjectStore([self.source._repository._git.object_store,
878
self.target._repository._git.object_store])
903
if (self.source._repository._git.object_store !=
904
self.target._repository._git.object_store):
905
store = OverlayObjectStore(
906
[self.source._repository._git.object_store,
907
self.target._repository._git.object_store])
880
909
store = self.source._repository._git.object_store
881
return self.source._repository._git.object_store.tree_changes(
910
return store.tree_changes(
882
911
self.source.tree, self.target.tree, want_unchanged=want_unchanged,
883
912
include_trees=True, change_type_same=True), set()
994
1024
file, stat_val = self.get_file_with_stat(path)
995
1025
except (errors.NoSuchFile, IOError):
996
# TODO: Rather than come up with something here, use the old index
1026
# TODO: Rather than come up with something here, use the old
997
1028
file = BytesIO()
998
1029
stat_val = os.stat_result(
999
1030
(stat.S_IFREG | 0o644, 0, 0, 0, 0, 0, 0, 0, 0, 0))
1001
1032
blob.set_raw_string(file.read())
1002
1033
# Add object to the repository if it didn't exist yet
1003
if not blob.id in self.store:
1034
if blob.id not in self.store:
1004
1035
self.store.add_object(blob)
1005
1036
hexsha = blob.id
1006
1037
elif kind == "symlink":
1015
1046
blob.set_raw_string(
1016
1047
self.get_symlink_target(path).encode("utf-8"))
1017
1048
# Add object to the repository if it didn't exist yet
1018
if not blob.id in self.store:
1049
if blob.id not in self.store:
1019
1050
self.store.add_object(blob)
1020
1051
hexsha = blob.id
1021
1052
elif kind == "tree-reference":
1022
1053
if reference_revision is not None:
1023
hexsha = self.branch.lookup_bzr_revision_id(reference_revision)[0]
1054
hexsha = self.branch.lookup_bzr_revision_id(
1055
reference_revision)[0]
1025
1057
hexsha = self._read_submodule_head(path)
1026
1058
if hexsha is None:
1053
1085
index = self.index
1054
1086
for path, value in index.items():
1055
1087
yield (posixpath.join(basepath, path), value)
1056
(ctime, mtime, dev, ino, mode, uid, gid, size, sha, flags) = value
1088
(ctime, mtime, dev, ino, mode, uid, gid, size, sha,
1057
1090
if S_ISGITLINK(mode):
1058
pass # TODO(jelmer): dive into submodule
1091
pass # TODO(jelmer): dive into submodule
1061
1093
def iter_entries_by_dir(self, specific_files=None, yield_parents=False):
1062
1094
if yield_parents:
1083
1115
except errors.NoSuchFile:
1085
1117
if yield_parents or specific_files is None:
1086
for (dir_path, dir_ie) in self._add_missing_parent_ids(parent,
1118
for (dir_path, dir_ie) in self._add_missing_parent_ids(
1088
1120
ret[(posixpath.dirname(dir_path), dir_path)] = dir_ie
1089
1121
file_ie.parent_id = self.path2id(parent)
1090
1122
ret[(posixpath.dirname(path), path)] = file_ie
1099
1131
def _get_dir_ie(self, path, parent_id):
1100
1132
file_id = self.path2id(path)
1101
1133
return GitTreeDirectory(file_id,
1102
posixpath.basename(path).strip("/"), parent_id)
1134
posixpath.basename(path).strip("/"), parent_id)
1104
1136
def _get_file_ie(self, name, path, value, parent_id):
1105
1137
if not isinstance(name, text_type):
1115
1147
kind = mode_kind(mode)
1116
1148
ie = entry_factory[kind](file_id, name, parent_id)
1117
1149
if kind == 'symlink':
1118
ie.symlink_target = self.get_symlink_target(path, file_id)
1150
ie.symlink_target = self.get_symlink_target(path)
1119
1151
elif kind == 'tree-reference':
1120
ie.reference_revision = self.get_reference_revision(path, file_id)
1152
ie.reference_revision = self.get_reference_revision(path)
1123
data = self.get_file_text(path, file_id)
1155
data = self.get_file_text(path)
1124
1156
except errors.NoSuchFile:
1126
1158
except IOError as e:
1185
1217
# TODO(jelmer): This shouldn't be called, it's inventory specific.
1186
1218
for (old_path, new_path, file_id, ie) in delta:
1187
1219
if old_path is not None:
1188
(index, old_subpath) = self._lookup_index(old_path.encode('utf-8'))
1220
(index, old_subpath) = self._lookup_index(
1221
old_path.encode('utf-8'))
1189
1222
if old_subpath in index:
1190
1223
self._index_del_entry(index, old_subpath)
1191
1224
self._versioned_dirs = None
1225
1258
not self.is_versioned(to_rel))
1227
1260
if not self.has_filename(to_rel):
1228
raise errors.BzrMoveFailedError(from_rel, to_rel,
1229
errors.NoSuchFile(to_rel))
1261
raise errors.BzrMoveFailedError(
1262
from_rel, to_rel, errors.NoSuchFile(to_rel))
1230
1263
if self.basis_tree().is_versioned(to_rel):
1231
raise errors.BzrMoveFailedError(from_rel, to_rel,
1232
errors.AlreadyVersionedError(to_rel))
1264
raise errors.BzrMoveFailedError(
1265
from_rel, to_rel, errors.AlreadyVersionedError(to_rel))
1234
1267
kind = self.kind(to_rel)
1242
1275
exc_type = errors.BzrMoveFailedError
1243
1276
if self.is_versioned(to_rel):
1244
1277
raise exc_type(from_rel, to_rel,
1245
errors.AlreadyVersionedError(to_rel))
1278
errors.AlreadyVersionedError(to_rel))
1246
1279
if not self.has_filename(from_rel):
1247
raise errors.BzrMoveFailedError(from_rel, to_rel,
1248
errors.NoSuchFile(from_rel))
1280
raise errors.BzrMoveFailedError(
1281
from_rel, to_rel, errors.NoSuchFile(from_rel))
1249
1282
kind = self.kind(from_rel)
1250
1283
if not self.is_versioned(from_rel) and kind != 'directory':
1251
1284
raise exc_type(from_rel, to_rel,
1252
errors.NotVersionedError(from_rel))
1285
errors.NotVersionedError(from_rel))
1253
1286
if self.has_filename(to_rel):
1254
1287
raise errors.RenameFailedFilesExist(
1255
1288
from_rel, to_rel, errors.FileExists(to_rel))
1268
1302
self._rename_one(from_rel, to_rel)
1269
1303
except OSError as e:
1270
1304
if e.errno == errno.ENOENT:
1271
raise errors.BzrMoveFailedError(from_rel, to_rel,
1272
errors.NoSuchFile(to_rel))
1305
raise errors.BzrMoveFailedError(
1306
from_rel, to_rel, errors.NoSuchFile(to_rel))
1274
1308
if kind != 'directory':
1275
1309
(index, from_index_path) = self._lookup_index(from_path)
1280
1314
self._index_add_entry(to_rel, kind)
1282
todo = [(p, i) for (p, i) in self._recurse_index_entries() if p.startswith(from_path+b'/')]
1316
todo = [(p, i) for (p, i) in self._recurse_index_entries()
1317
if p.startswith(from_path + b'/')]
1283
1318
for child_path, child_value in todo:
1284
1319
(child_to_index, child_to_index_path) = self._lookup_index(
1285
posixpath.join(to_path, posixpath.relpath(child_path, from_path)))
1320
posixpath.join(to_path, posixpath.relpath(child_path, from_path)))
1286
1321
child_to_index[child_to_index_path] = child_value
1287
1322
# TODO(jelmer): Mark individual index as dirty
1288
1323
self._index_dirty = True
1289
(child_from_index, child_from_index_path) = self._lookup_index(child_path)
1290
self._index_del_entry(child_from_index, child_from_index_path)
1324
(child_from_index, child_from_index_path) = self._lookup_index(
1326
self._index_del_entry(
1327
child_from_index, child_from_index_path)
1292
1329
self._versioned_dirs = None
1295
1332
def find_related_paths_across_trees(self, paths, trees=[],
1296
require_versioned=True):
1333
require_versioned=True):
1297
1334
if paths is None:
1370
1407
isinstance(target, MutableGitIndexTree))
1372
1409
def _iter_git_changes(self, want_unchanged=False, specific_files=None,
1373
require_versioned=False, extra_trees=None,
1374
want_unversioned=False):
1410
require_versioned=False, extra_trees=None,
1411
want_unversioned=False):
1375
1412
trees = [self.source]
1376
1413
if extra_trees is not None:
1377
1414
trees.extend(extra_trees)
1378
1415
if specific_files is not None:
1379
1416
specific_files = self.target.find_related_paths_across_trees(
1380
specific_files, trees,
1381
require_versioned=require_versioned)
1417
specific_files, trees,
1418
require_versioned=require_versioned)
1382
1419
# TODO(jelmer): Restrict to specific_files, for performance reasons.
1383
1420
with self.lock_read():
1384
1421
return changes_between_git_tree_and_working_copy(
1408
1446
# Entry was removed; keep it listed, but mark it as gone.
1409
1447
blobs[path] = (ZERO_SHA, 0)
1410
1448
elif e.errno == errno.EISDIR:
1411
# Entry was turned into a directory
1412
dirified.append((path, Tree().id, stat.S_IFDIR))
1413
store.add_object(Tree())
1449
# TODO(jelmer): Only do this if 'path' appears in .gitmodules?
1450
if S_ISGITLINK(index_entry.mode):
1451
blobs[path] = (index_entry.sha, index_entry.mode)
1453
# Entry was turned into a directory
1454
dirified.append((path, Tree().id, stat.S_IFDIR))
1455
store.add_object(Tree())
1426
1468
if stat.S_ISDIR(st.st_mode):
1429
blob = blob_from_path_and_stat(target.abspath(e).encode(osutils._fs_enc), st)
1471
blob = blob_from_path_and_stat(
1472
target.abspath(e).encode(osutils._fs_enc), st)
1430
1473
store.add_object(blob)
1431
1474
np = np.encode('utf-8')
1432
1475
blobs[np] = (blob.id, cleanup_mode(st.st_mode))
1434
to_tree_sha = commit_tree(store, dirified + [(p, s, m) for (p, (s, m)) in blobs.items()])
1477
to_tree_sha = commit_tree(
1478
store, dirified + [(p, s, m) for (p, (s, m)) in blobs.items()])
1435
1479
return store.tree_changes(
1436
1480
from_tree_sha, to_tree_sha, include_trees=True,
1437
1481
want_unchanged=want_unchanged, change_type_same=True), extras