You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by br...@apache.org on 2022/05/23 15:57:27 UTC

[allura] 02/03: [#8431] support git symlinks formally a bit

This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8431
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 5508aaeb8081aa292ea486f332ea227f007ddfd6
Author: Dave Brondsema <db...@slashdotmedia.com>
AuthorDate: Mon May 23 11:02:28 2022 -0400

    [#8431] support git symlinks formally a bit
---
 Allura/allura/controllers/repository.py             |  12 ++++++++++--
 Allura/allura/model/repository.py                   |  20 ++++++++++++++------
 Allura/allura/templates/repo/commit.html            |   2 ++
 .../allura/templates/widgets/repo/tree_widget.html  |   4 +++-
 ForgeGit/forgegit/model/git_repo.py                 |   9 +++++++--
 .../forgegit/tests/data/testrename.git/info/refs    |   1 +
 .../13/951944969cf45a701bf90f83647b309815e6d5       |   2 --
 .../25/9c77dd6ee0e6091d11e429b56c44ccbf1e64a3       |   2 --
 .../25/ac990c253975ab297e9955825e4ef9dc515d82       | Bin 35 -> 0 bytes
 .../30/b7068f50c7e14fdd08e3b14f7386d686edcfb9       | Bin 0 -> 185 bytes
 .../65/3667b582ef2950c1954a0c7e1e8797b19d778a       |   3 ---
 .../6b/0bbf7169927069f7839b682307ec4ecb85c2e9       | Bin 56 -> 0 bytes
 .../72/68e74cd78a7c34f1a4a6dfb6ce861e35f571d4       | Bin 43 -> 0 bytes
 .../7b/57bd29ea8afbdeb9bac64cf7074f4b531492a8       | Bin 26 -> 0 bytes
 .../7c/09182e61af959e4f1fb0e354bab49f14ef810d       | Bin 133 -> 0 bytes
 .../89/b97e3324e20b57543ae48ced731e31a052548c       | Bin 49 -> 0 bytes
 .../9a/cb8ca3e5703fa90f1cdc708dd070c17d0c26d8       | Bin 50 -> 0 bytes
 .../b1/20505a61225e6c14bee3e5b5862db81628c35c       | Bin 160 -> 0 bytes
 .../c5/5a64046f8618a4c84c74dc834eb5722dabd58a       | Bin 51 -> 0 bytes
 .../d4/99ed2dc5606d4d0953937bca92157743df79ab       | Bin 77 -> 0 bytes
 .../dd/633a6dd42e52a66b277324fb75d83295d20f98       | Bin 50 -> 0 bytes
 .../fb/b0644603bb6ecee3ebb62efe8c86efc9b84ee6       | Bin 168 -> 0 bytes
 .../tests/data/testrename.git/objects/info/packs    |   2 ++
 ...ack-80c9fa56e425c3db146865b4433d5666803e75fb.idx | Bin 0 -> 1716 bytes
 ...ck-80c9fa56e425c3db146865b4433d5666803e75fb.pack | Bin 0 -> 2026 bytes
 .../forgegit/tests/data/testrename.git/packed-refs  |   2 ++
 .../tests/data/testrename.git/refs/heads/master     |   1 -
 .../forgegit/tests/functional/test_controllers.py   |  17 +++++++++++++++++
 28 files changed, 58 insertions(+), 19 deletions(-)

diff --git a/Allura/allura/controllers/repository.py b/Allura/allura/controllers/repository.py
index ad26a9fc5..73d4eee96 100644
--- a/Allura/allura/controllers/repository.py
+++ b/Allura/allura/controllers/repository.py
@@ -685,9 +685,17 @@ class CommitBrowser(BaseController):
                     filepath = f['new']
                 else:
                     filepath = f
-                is_text = filepath and tree.get_blob_by_path(filepath) and tree.get_blob_by_path(filepath).has_html_view
+                is_text = False
+                fileobj_type = 'tree'
+                if filepath:
+                    fileobj = tree.get_obj_by_path(filepath)
+                    if isinstance(fileobj, M.repository.Symlink):
+                        fileobj_type = 'symlink'
+                    elif isinstance(fileobj, M.repository.Blob):
+                        fileobj_type = 'blob'
+                        is_text = fileobj.has_html_view
                 result['artifacts'].append(
-                    (t, f, 'blob' if tree.get_blob_by_path(f) else 'tree', is_text)
+                    (t, f, fileobj_type, is_text)
                 )
         count = diffs['total']
         result.update(dict(page=page, limit=limit, count=count))
diff --git a/Allura/allura/model/repository.py b/Allura/allura/model/repository.py
index 71878952b..8e2dcc183 100644
--- a/Allura/allura/model/repository.py
+++ b/Allura/allura/model/repository.py
@@ -14,6 +14,7 @@
 #       KIND, either express or implied.  See the License for the
 #       specific language governing permissions and limitations
 #       under the License.
+from __future__ import annotations
 import json
 import os
 import stat
@@ -79,7 +80,7 @@ VIEWABLE_EXTENSIONS = frozenset([
 
 # Some schema types
 SUser = dict(name=str, email=str, date=datetime)
-SObjType = S.OneOf('blob', 'tree', 'submodule')
+SObjType = S.OneOf('blob', 'tree', 'submodule', 'symlink')
 
 # Used for when we're going to batch queries using $in
 QSIZE = 100
@@ -133,7 +134,7 @@ class RepositoryImplementation:
         commit'''
         raise NotImplementedError('commit_parents')
 
-    def refresh_commit_info(self, oid, lazy=True):  # pragma no cover
+    def refresh_commit_info(self, oid, seen, lazy=True):  # pragma no cover
         '''Refresh the data in the commit with id oid'''
         raise NotImplementedError('refresh_commit_info')
 
@@ -1336,7 +1337,7 @@ class Tree(MappedClass, RepoObject):
     parent = None
     name = None
 
-    def __getitem__(self, name):
+    def __getitem__(self, name: str) -> Tree | Blob:
         cache = getattr(c, 'model_cache', '') or ModelCache()
         obj = self.by_name[name]
         if obj['type'] == 'blob':
@@ -1344,6 +1345,8 @@ class Tree(MappedClass, RepoObject):
         if obj['type'] == 'submodule':
             log.info('Skipping submodule "%s"' % name)
             raise KeyError(name)
+        if obj['type'] == 'symlink':
+            return Symlink(self, name, obj['id'])
         obj = cache.get(Tree, dict(_id=obj['id']))
         if obj is None:
             oid = self.repo.compute_tree_new(
@@ -1423,11 +1426,11 @@ class Tree(MappedClass, RepoObject):
             commit.set_context(self.repo)
         commit_infos = {c._id: c.info for c in commits}
         tree_names = sorted(n.name for n in self.tree_ids)
-        blob_names = sorted(
-            n.name for n in chain(self.blob_ids, self.other_ids))
+        blob_names = sorted(n.name for n in self.blob_ids)
+        other_names = sorted(n.name for n in self.other_ids)
 
         results = []
-        for type, names in (('DIR', tree_names), ('BLOB', blob_names)):
+        for type, names in (('DIR', tree_names), ('BLOB', blob_names), ('OTHER', other_names)):
             for name in names:
                 commit_info = commit_infos.get(lcd.by_name.get(name))
                 if not commit_info:
@@ -1573,6 +1576,11 @@ class EmptyBlob(Blob):
         return False
 
 
+class Symlink(Blob):
+    # maybe this shouldn't inherit from Blob, but its handy for now and works well with git (where symlinks are blobs)
+    pass
+
+
 # this is duplicative with the LastCommit model
 # would be nice to get rid of this "doc" based view, but it is used a lot
 LastCommitDoc = collection(
diff --git a/Allura/allura/templates/repo/commit.html b/Allura/allura/templates/repo/commit.html
index c929b29a4..781164182 100644
--- a/Allura/allura/templates/repo/commit.html
+++ b/Allura/allura/templates/repo/commit.html
@@ -180,6 +180,8 @@ Commit <a href="{{commit.url()}}">{{commit.shorthand_id()}}</a> {{commit_labels(
                       });
                     </script>
                   {% endif %}
+                {% elif obj_type == 'symlink' %}
+                    <span class="empty-diff">Symlink.</span>
                 {% elif obj_type == 'tree' %}
                     <span class="empty-diff">Directory.</span>
                 {% elif not is_text %}
diff --git a/Allura/allura/templates/widgets/repo/tree_widget.html b/Allura/allura/templates/widgets/repo/tree_widget.html
index 14dd26a06..5e75fcba4 100644
--- a/Allura/allura/templates/widgets/repo/tree_widget.html
+++ b/Allura/allura/templates/widgets/repo/tree_widget.html
@@ -45,8 +45,10 @@
       <td class="nowrap">
         {% if dirent.kind == 'DIR' %}
           {% set icon_name = 'folder' %}
-        {% else %}
+        {% elif dirent.kind == 'BLOB' %}
           {% set icon_name = 'file' %}
+        {% else %}
+          {% set icon_name = 'star' %}
         {% endif %}
         {{ g.icons[icon_name].render(
             href=h.urlquote(dirent.href),
diff --git a/ForgeGit/forgegit/model/git_repo.py b/ForgeGit/forgegit/model/git_repo.py
index 6279ea0a7..78185b48a 100644
--- a/ForgeGit/forgegit/model/git_repo.py
+++ b/ForgeGit/forgegit/model/git_repo.py
@@ -14,6 +14,7 @@
 #       KIND, either express or implied.  See the License for the
 #       specific language governing permissions and limitations
 #       under the License.
+from __future__ import annotations
 
 import os
 import shutil
@@ -310,7 +311,7 @@ class GitImplementation(M.RepositoryImplementation):
         self.refresh_tree_info(ci.tree, seen, lazy)
         return True
 
-    def refresh_tree_info(self, tree, seen, lazy=True):
+    def refresh_tree_info(self, tree: git.objects.tree.Tree, seen: set, lazy=True):
         from allura.model.repository import Tree
         if lazy and tree.binsha in seen:
             return
@@ -330,7 +331,11 @@ class GitImplementation(M.RepositoryImplementation):
                 self.refresh_tree_info(o, seen, lazy)
                 doc.tree_ids.append(obj)
             elif o.type == 'blob':
-                doc.blob_ids.append(obj)
+                if o.mode == o.link_mode:
+                    obj.type = 'symlink'
+                    doc.other_ids.append(obj)
+                else:
+                    doc.blob_ids.append(obj)
             else:
                 obj.type = o.type
                 doc.other_ids.append(obj)
diff --git a/ForgeGit/forgegit/tests/data/testrename.git/info/refs b/ForgeGit/forgegit/tests/data/testrename.git/info/refs
new file mode 100644
index 000000000..cac55eef7
--- /dev/null
+++ b/ForgeGit/forgegit/tests/data/testrename.git/info/refs
@@ -0,0 +1 @@
+7b1c9ef214eb0ef8c06bada0966dd941f442beec	refs/heads/master
diff --git a/ForgeGit/forgegit/tests/data/testrename.git/objects/13/951944969cf45a701bf90f83647b309815e6d5 b/ForgeGit/forgegit/tests/data/testrename.git/objects/13/951944969cf45a701bf90f83647b309815e6d5
deleted file mode 100644
index 49fdaba6c..000000000
--- a/ForgeGit/forgegit/tests/data/testrename.git/objects/13/951944969cf45a701bf90f83647b309815e6d5
+++ /dev/null
@@ -1,2 +0,0 @@
-x���JA�=�S�A�?��C����`oKO��; {�SQ|�[�L�)��a��L�J.�hRG9R�*L�g�uC�|�널IU����ȫ���\$%��y+���_r,k^�m��O9�4o+VO����_�������Wݭ1<j���������L/� �=���F
-�ݑ�X�i�-o6�
~yp���i���io
\ No newline at end of file
diff --git a/ForgeGit/forgegit/tests/data/testrename.git/objects/25/9c77dd6ee0e6091d11e429b56c44ccbf1e64a3 b/ForgeGit/forgegit/tests/data/testrename.git/objects/25/9c77dd6ee0e6091d11e429b56c44ccbf1e64a3
deleted file mode 100644
index c2ab91814..000000000
--- a/ForgeGit/forgegit/tests/data/testrename.git/objects/25/9c77dd6ee0e6091d11e429b56c44ccbf1e64a3
+++ /dev/null
@@ -1,2 +0,0 @@
-x��Kj1��)z���
&�k���j�,)�(���:C����I�u��Ʈ
-��)ژ�q���"�f\�/��޵
��[��qޣ&q1�Ō�|��'	(�ǣ�pm�7���ǭ��R�V\�c���Vޞ�����`H�X���Z3��sR�.�C���ඪy|2K�
\ No newline at end of file
diff --git a/ForgeGit/forgegit/tests/data/testrename.git/objects/25/ac990c253975ab297e9955825e4ef9dc515d82 b/ForgeGit/forgegit/tests/data/testrename.git/objects/25/ac990c253975ab297e9955825e4ef9dc515d82
deleted file mode 100644
index 3fabb2c92..000000000
Binary files a/ForgeGit/forgegit/tests/data/testrename.git/objects/25/ac990c253975ab297e9955825e4ef9dc515d82 and /dev/null differ
diff --git a/ForgeGit/forgegit/tests/data/testrename.git/objects/30/b7068f50c7e14fdd08e3b14f7386d686edcfb9 b/ForgeGit/forgegit/tests/data/testrename.git/objects/30/b7068f50c7e14fdd08e3b14f7386d686edcfb9
new file mode 100644
index 000000000..657bb57e1
Binary files /dev/null and b/ForgeGit/forgegit/tests/data/testrename.git/objects/30/b7068f50c7e14fdd08e3b14f7386d686edcfb9 differ
diff --git a/ForgeGit/forgegit/tests/data/testrename.git/objects/65/3667b582ef2950c1954a0c7e1e8797b19d778a b/ForgeGit/forgegit/tests/data/testrename.git/objects/65/3667b582ef2950c1954a0c7e1e8797b19d778a
deleted file mode 100644
index bf8f5c91e..000000000
--- a/ForgeGit/forgegit/tests/data/testrename.git/objects/65/3667b582ef2950c1954a0c7e1e8797b19d778a
+++ /dev/null
@@ -1,3 +0,0 @@
-x��A
-�0E]��J21�DD�H&��`�����m���z���?�Z�
-Hf���q�#��8�:3H�I��3J�i��[4��D�e�c'�} ,,a���.=��&8���ij�2KM�/���|K�4�R��ϭ��u)ؚ%��.wU�-��F����
F�R���S�
\ No newline at end of file
diff --git a/ForgeGit/forgegit/tests/data/testrename.git/objects/6b/0bbf7169927069f7839b682307ec4ecb85c2e9 b/ForgeGit/forgegit/tests/data/testrename.git/objects/6b/0bbf7169927069f7839b682307ec4ecb85c2e9
deleted file mode 100644
index 7e248841b..000000000
Binary files a/ForgeGit/forgegit/tests/data/testrename.git/objects/6b/0bbf7169927069f7839b682307ec4ecb85c2e9 and /dev/null differ
diff --git a/ForgeGit/forgegit/tests/data/testrename.git/objects/72/68e74cd78a7c34f1a4a6dfb6ce861e35f571d4 b/ForgeGit/forgegit/tests/data/testrename.git/objects/72/68e74cd78a7c34f1a4a6dfb6ce861e35f571d4
deleted file mode 100644
index d7cc85eff..000000000
Binary files a/ForgeGit/forgegit/tests/data/testrename.git/objects/72/68e74cd78a7c34f1a4a6dfb6ce861e35f571d4 and /dev/null differ
diff --git a/ForgeGit/forgegit/tests/data/testrename.git/objects/7b/57bd29ea8afbdeb9bac64cf7074f4b531492a8 b/ForgeGit/forgegit/tests/data/testrename.git/objects/7b/57bd29ea8afbdeb9bac64cf7074f4b531492a8
deleted file mode 100644
index 71d6c5a87..000000000
Binary files a/ForgeGit/forgegit/tests/data/testrename.git/objects/7b/57bd29ea8afbdeb9bac64cf7074f4b531492a8 and /dev/null differ
diff --git a/ForgeGit/forgegit/tests/data/testrename.git/objects/7c/09182e61af959e4f1fb0e354bab49f14ef810d b/ForgeGit/forgegit/tests/data/testrename.git/objects/7c/09182e61af959e4f1fb0e354bab49f14ef810d
deleted file mode 100644
index 7d51fe9b5..000000000
Binary files a/ForgeGit/forgegit/tests/data/testrename.git/objects/7c/09182e61af959e4f1fb0e354bab49f14ef810d and /dev/null differ
diff --git a/ForgeGit/forgegit/tests/data/testrename.git/objects/89/b97e3324e20b57543ae48ced731e31a052548c b/ForgeGit/forgegit/tests/data/testrename.git/objects/89/b97e3324e20b57543ae48ced731e31a052548c
deleted file mode 100644
index 8c65cdd09..000000000
Binary files a/ForgeGit/forgegit/tests/data/testrename.git/objects/89/b97e3324e20b57543ae48ced731e31a052548c and /dev/null differ
diff --git a/ForgeGit/forgegit/tests/data/testrename.git/objects/9a/cb8ca3e5703fa90f1cdc708dd070c17d0c26d8 b/ForgeGit/forgegit/tests/data/testrename.git/objects/9a/cb8ca3e5703fa90f1cdc708dd070c17d0c26d8
deleted file mode 100644
index c2eeea8bc..000000000
Binary files a/ForgeGit/forgegit/tests/data/testrename.git/objects/9a/cb8ca3e5703fa90f1cdc708dd070c17d0c26d8 and /dev/null differ
diff --git a/ForgeGit/forgegit/tests/data/testrename.git/objects/b1/20505a61225e6c14bee3e5b5862db81628c35c b/ForgeGit/forgegit/tests/data/testrename.git/objects/b1/20505a61225e6c14bee3e5b5862db81628c35c
deleted file mode 100644
index c1249a02d..000000000
Binary files a/ForgeGit/forgegit/tests/data/testrename.git/objects/b1/20505a61225e6c14bee3e5b5862db81628c35c and /dev/null differ
diff --git a/ForgeGit/forgegit/tests/data/testrename.git/objects/c5/5a64046f8618a4c84c74dc834eb5722dabd58a b/ForgeGit/forgegit/tests/data/testrename.git/objects/c5/5a64046f8618a4c84c74dc834eb5722dabd58a
deleted file mode 100644
index 5068b353e..000000000
Binary files a/ForgeGit/forgegit/tests/data/testrename.git/objects/c5/5a64046f8618a4c84c74dc834eb5722dabd58a and /dev/null differ
diff --git a/ForgeGit/forgegit/tests/data/testrename.git/objects/d4/99ed2dc5606d4d0953937bca92157743df79ab b/ForgeGit/forgegit/tests/data/testrename.git/objects/d4/99ed2dc5606d4d0953937bca92157743df79ab
deleted file mode 100644
index cdd95260f..000000000
Binary files a/ForgeGit/forgegit/tests/data/testrename.git/objects/d4/99ed2dc5606d4d0953937bca92157743df79ab and /dev/null differ
diff --git a/ForgeGit/forgegit/tests/data/testrename.git/objects/dd/633a6dd42e52a66b277324fb75d83295d20f98 b/ForgeGit/forgegit/tests/data/testrename.git/objects/dd/633a6dd42e52a66b277324fb75d83295d20f98
deleted file mode 100644
index 297abfcdb..000000000
Binary files a/ForgeGit/forgegit/tests/data/testrename.git/objects/dd/633a6dd42e52a66b277324fb75d83295d20f98 and /dev/null differ
diff --git a/ForgeGit/forgegit/tests/data/testrename.git/objects/fb/b0644603bb6ecee3ebb62efe8c86efc9b84ee6 b/ForgeGit/forgegit/tests/data/testrename.git/objects/fb/b0644603bb6ecee3ebb62efe8c86efc9b84ee6
deleted file mode 100644
index 4eef534e3..000000000
Binary files a/ForgeGit/forgegit/tests/data/testrename.git/objects/fb/b0644603bb6ecee3ebb62efe8c86efc9b84ee6 and /dev/null differ
diff --git a/ForgeGit/forgegit/tests/data/testrename.git/objects/info/packs b/ForgeGit/forgegit/tests/data/testrename.git/objects/info/packs
new file mode 100644
index 000000000..ccfd7693b
--- /dev/null
+++ b/ForgeGit/forgegit/tests/data/testrename.git/objects/info/packs
@@ -0,0 +1,2 @@
+P pack-80c9fa56e425c3db146865b4433d5666803e75fb.pack
+
diff --git a/ForgeGit/forgegit/tests/data/testrename.git/objects/pack/pack-80c9fa56e425c3db146865b4433d5666803e75fb.idx b/ForgeGit/forgegit/tests/data/testrename.git/objects/pack/pack-80c9fa56e425c3db146865b4433d5666803e75fb.idx
new file mode 100644
index 000000000..14b3b20b2
Binary files /dev/null and b/ForgeGit/forgegit/tests/data/testrename.git/objects/pack/pack-80c9fa56e425c3db146865b4433d5666803e75fb.idx differ
diff --git a/ForgeGit/forgegit/tests/data/testrename.git/objects/pack/pack-80c9fa56e425c3db146865b4433d5666803e75fb.pack b/ForgeGit/forgegit/tests/data/testrename.git/objects/pack/pack-80c9fa56e425c3db146865b4433d5666803e75fb.pack
new file mode 100644
index 000000000..866a9eec8
Binary files /dev/null and b/ForgeGit/forgegit/tests/data/testrename.git/objects/pack/pack-80c9fa56e425c3db146865b4433d5666803e75fb.pack differ
diff --git a/ForgeGit/forgegit/tests/data/testrename.git/packed-refs b/ForgeGit/forgegit/tests/data/testrename.git/packed-refs
new file mode 100644
index 000000000..1cf0c88e6
--- /dev/null
+++ b/ForgeGit/forgegit/tests/data/testrename.git/packed-refs
@@ -0,0 +1,2 @@
+# pack-refs with: peeled fully-peeled sorted 
+7b1c9ef214eb0ef8c06bada0966dd941f442beec refs/heads/master
diff --git a/ForgeGit/forgegit/tests/data/testrename.git/refs/heads/master b/ForgeGit/forgegit/tests/data/testrename.git/refs/heads/master
deleted file mode 100644
index a0aeefbb3..000000000
--- a/ForgeGit/forgegit/tests/data/testrename.git/refs/heads/master
+++ /dev/null
@@ -1 +0,0 @@
-13951944969cf45a701bf90f83647b309815e6d5
diff --git a/ForgeGit/forgegit/tests/functional/test_controllers.py b/ForgeGit/forgegit/tests/functional/test_controllers.py
index be07cbd6f..b40a2149d 100644
--- a/ForgeGit/forgegit/tests/functional/test_controllers.py
+++ b/ForgeGit/forgegit/tests/functional/test_controllers.py
@@ -1038,6 +1038,23 @@ class TestGitRename(TestController):
                   .replace(' ', ''), resp_no_ws)
         assert '<span class="empty-diff">File was renamed.</span>' in resp
 
+    def test_directory_changed_type(self):
+        # change a_dir to a file; b_dir to a symlink
+        resp = self.app.get('/src-git/ci/7b1c9ef214eb0ef8c06bada0966dd941f442beec/')
+
+        resp_no_ws = re.sub(r'\s+', '', str(resp))
+        assert_in('<a href="/p/test/src-git/ci/7b1c9ef214eb0ef8c06bada0966dd941f442beec/tree/b_dir">b_dir</a>'
+                  '</h6>'
+                  '<div id="diff-3" class="inline-diff-body">'
+                  '<span class="empty-diff">Symlink.</span>'
+                  .replace(' ', ''), resp_no_ws)
+
+    def test_symlink_in_tree(self):
+        # change a_dir to a file; b_dir to a symlink
+        resp = self.app.get('/src-git/ci/7b1c9ef214eb0ef8c06bada0966dd941f442beec/tree/')
+
+        resp.mustcontain('<a class="icon" href="b_dir" title="b_dir"><i class="fa fa-star"></i>&nbsp;b_dir</a>')
+
 
 class TestGitBranch(TestController):
     def setUp(self):