瀏覽代碼

Support staging submodules.

Jelmer Vernooij 3 年之前
父節點
當前提交
e377b3c8ae
共有 4 個文件被更改,包括 32 次插入7 次删除
  1. 3 0
      NEWS
  2. 10 6
      dulwich/index.py
  3. 11 1
      dulwich/repo.py
  4. 8 0
      dulwich/tests/test_repository.py

+ 3 - 0
NEWS

@@ -1,5 +1,8 @@
 0.20.29	UNRELEASED
 
+ * Support staging submodules.
+   (Jelmer Vernooij)
+
 0.20.28	2022-01-05
 
  * Fix hook test on Mac OSX / Linux when dulwich is

+ 10 - 6
dulwich/index.py

@@ -878,6 +878,15 @@ def _fs_to_tree_path(fs_path):
     return tree_path
 
 
+def index_entry_from_directory(st, path):
+    if os.path.exists(os.path.join(path, b".git")):
+        head = read_submodule_head(path)
+        if head is None:
+            return None
+        return index_entry_from_stat(st, head, 0, mode=S_IFGITLINK)
+    return None
+
+
 def index_entry_from_path(path, object_store=None):
     """Create an index from a filesystem path.
 
@@ -894,12 +903,7 @@ def index_entry_from_path(path, object_store=None):
     assert isinstance(path, bytes)
     st = os.lstat(path)
     if stat.S_ISDIR(st.st_mode):
-        if os.path.exists(os.path.join(path, b".git")):
-            head = read_submodule_head(path)
-            if head is None:
-                return None
-            return index_entry_from_stat(st, head, 0, mode=S_IFGITLINK)
-        return None
+        return index_entry_from_directory(st, path)
 
     if stat.S_ISREG(st.st_mode) or stat.S_ISLNK(st.st_mode):
         blob = blob_from_path_and_stat(path, st)

+ 11 - 1
dulwich/repo.py

@@ -1271,6 +1271,7 @@ class Repo(BaseRepo):
         from dulwich.index import (
             blob_from_path_and_stat,
             index_entry_from_stat,
+            index_entry_from_directory,
             _fs_to_tree_path,
         )
 
@@ -1295,7 +1296,16 @@ class Repo(BaseRepo):
                 except KeyError:
                     pass  # already removed
             else:
-                if not stat.S_ISREG(st.st_mode) and not stat.S_ISLNK(st.st_mode):
+                if stat.S_ISDIR(st.st_mode):
+                    entry = index_entry_from_directory(st, full_path)
+                    if entry:
+                        index[tree_path] = entry
+                    else:
+                        try:
+                            del index[tree_path]
+                        except KeyError:
+                            pass
+                elif not stat.S_ISREG(st.st_mode) and not stat.S_ISLNK(st.st_mode):
                     try:
                         del index[tree_path]
                     except KeyError:

+ 8 - 0
dulwich/tests/test_repository.py

@@ -1268,6 +1268,7 @@ class BuildRepoRootTests(TestCase):
         os.remove(os.path.join(r.path, "a"))
         r.stage(["a"])
         r.stage(["a"])  # double-stage a deleted path
+        self.assertEqual([], list(r.open_index()))
 
     def test_stage_directory(self):
         r = self._repo
@@ -1275,6 +1276,13 @@ class BuildRepoRootTests(TestCase):
         r.stage(["c"])
         self.assertEqual([b"a"], list(r.open_index()))
 
+    def test_stage_submodule(self):
+        r = self._repo
+        s = Repo.init(os.path.join(r.path, "sub"), mkdir=True)
+        s.do_commit(b'message')
+        r.stage(["sub"])
+        self.assertEqual([b"a", b"sub"], list(r.open_index()))
+
     def test_unstage_midify_file_with_dir(self):
         os.mkdir(os.path.join(self._repo.path, 'new_dir'))
         full_path = os.path.join(self._repo.path, 'new_dir', 'foo')