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 <[email protected]> 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> b_dir</a>') + class TestGitBranch(TestController): def setUp(self):
