From 736ea3d93f2b0097d57e431231bf184216be991e Mon Sep 17 00:00:00 2001 From: Rene Pfeuffer Date: Fri, 21 Feb 2020 14:29:09 +0100 Subject: [PATCH] Sort git files --- .../scm/repository/spi/BrowseCommand.java | 15 +++++ .../java/sonia/scm/repository/GitUtil.java | 6 +- .../scm/repository/spi/GitBrowseCommand.java | 66 +++++++++++++++---- .../scm/repository/spi/SvnBrowseCommand.java | 2 +- .../repository/spi/SvnBrowseCommandTest.java | 6 +- 5 files changed, 78 insertions(+), 17 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/BrowseCommand.java b/scm-core/src/main/java/sonia/scm/repository/spi/BrowseCommand.java index ee37d6243e..7859c1845b 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/BrowseCommand.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/BrowseCommand.java @@ -38,6 +38,9 @@ package sonia.scm.repository.spi; import sonia.scm.repository.BrowserResult; import java.io.IOException; +import java.util.List; +import java.util.Locale; +import java.util.function.Function; //~--- JDK imports ------------------------------------------------------------ @@ -60,4 +63,16 @@ public interface BrowseCommand * @throws IOException */ BrowserResult getBrowserResult(BrowseCommandRequest request) throws IOException; + + default void sort(List entries, Function isDirectory, Function nameOf) { + entries.sort((e1, e2) -> { + if (isDirectory.apply(e1).equals(isDirectory.apply(e2))) { + return nameOf.apply(e1).toLowerCase(Locale.ENGLISH).compareTo(nameOf.apply(e2).toLowerCase(Locale.ENGLISH)); + } else if (isDirectory.apply(e1)) { + return -1; + } else { + return 1; + } + }); + } } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java index a93c1b5d81..e816aaf76d 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java @@ -749,9 +749,13 @@ public final class GitUtil } public static Optional getLfsPointer(org.eclipse.jgit.lib.Repository repo, TreeWalk treeWalk, Attributes attributes) throws IOException { + ObjectId blobId = treeWalk.getObjectId(0); + return getLfsPointer(repo, blobId, attributes); + } + + public static Optional getLfsPointer(org.eclipse.jgit.lib.Repository repo, ObjectId blobId, Attributes attributes) throws IOException { Attribute filter = attributes.get("filter"); if (filter != null && "lfs".equals(filter.getValue())) { - ObjectId blobId = treeWalk.getObjectId(0); try (InputStream is = repo.open(blobId, Constants.OBJ_BLOB).openStream()) { return of(LfsPointer.parseLfsPointer(is)); } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitBrowseCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitBrowseCommand.java index f53b7ec0a4..fe75e6d1b1 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitBrowseCommand.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitBrowseCommand.java @@ -69,7 +69,9 @@ import sonia.scm.web.lfs.LfsBlobStoreFactory; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.util.ArrayList; import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Optional; @@ -158,14 +160,14 @@ public class GitBrowseCommand extends AbstractGitCommand } private FileObject createFileObject(org.eclipse.jgit.lib.Repository repo, - BrowseCommandRequest request, ObjectId revId, TreeWalk treeWalk) + BrowseCommandRequest request, ObjectId revId, TreeEntry treeEntry) throws IOException { FileObject file = new FileObject(); - String path = treeWalk.getPathString(); + String path = treeEntry.getPathString(); - file.setName(treeWalk.getNameString()); + file.setName(treeEntry.getNameString()); file.setPath(path); SubRepository sub = null; @@ -183,7 +185,7 @@ public class GitBrowseCommand extends AbstractGitCommand } else { - ObjectLoader loader = repo.open(treeWalk.getObjectId(0)); + ObjectLoader loader = repo.open(treeEntry.getObjectId()); file.setDirectory(loader.getType() == Constants.OBJ_TREE); @@ -195,7 +197,7 @@ public class GitBrowseCommand extends AbstractGitCommand try (RevWalk walk = new RevWalk(repo)) { commit = walk.parseCommit(revId); } - Optional lfsPointer = getLfsPointer(repo, path, commit, treeWalk); + Optional lfsPointer = getLfsPointer(repo, path, commit, treeEntry); if (lfsPointer.isPresent()) { setFileLengthFromLfsBlob(lfsPointer.get(), file); @@ -253,11 +255,18 @@ public class GitBrowseCommand extends AbstractGitCommand } private FileObject findChildren(FileObject parent, org.eclipse.jgit.lib.Repository repo, BrowseCommandRequest request, ObjectId revId, TreeWalk treeWalk) throws IOException { - List files = Lists.newArrayList(); - while (treeWalk.next() && ++resultCount <= request.getLimit() + request.getOffset()) - { + List entries = new ArrayList<>(); + while (treeWalk.next() && ++resultCount <= request.getLimit() + request.getOffset()) { + entries.add(new TreeEntry(repo, treeWalk)); + } + sort(entries, TreeEntry::isDirectory, TreeEntry::getNameString); - FileObject fileObject = createFileObject(repo, request, revId, treeWalk); + List files = Lists.newArrayList(); + Iterator entryIterator = entries.iterator(); + while (entryIterator.hasNext() && ++resultCount <= request.getLimit() + request.getOffset()) + { + TreeEntry entry = entryIterator.next(); + FileObject fileObject = createFileObject(repo, request, revId, entry); if (!fileObject.getPath().startsWith(parent.getPath())) { parent.setChildren(files); return fileObject; @@ -298,7 +307,7 @@ public class GitBrowseCommand extends AbstractGitCommand currentDepth++; if (currentDepth >= limit) { - return createFileObject(repo, request, revId, treeWalk); + return createFileObject(repo, request, revId, new TreeEntry(repo, treeWalk)); } else { treeWalk.enterSubtree(); } @@ -338,11 +347,11 @@ public class GitBrowseCommand extends AbstractGitCommand return null; } - private Optional getLfsPointer(org.eclipse.jgit.lib.Repository repo, String path, RevCommit commit, TreeWalk treeWalk) { + private Optional getLfsPointer(org.eclipse.jgit.lib.Repository repo, String path, RevCommit commit, TreeEntry treeWalk) { try { Attributes attributes = LfsFactory.getAttributesForPath(repo, path, commit); - return GitUtil.getLfsPointer(repo, treeWalk, attributes); + return GitUtil.getLfsPointer(repo, treeWalk.getObjectId(), attributes); } catch (IOException e) { throw new InternalRepositoryException(repository, "could not read lfs pointer", e); } @@ -448,4 +457,37 @@ public class GitBrowseCommand extends AbstractGitCommand return changed; } } + + private static class TreeEntry { + + private final String pathString; + private final String nameString; + private final ObjectId objectId; + private final boolean directory; + + public TreeEntry(org.eclipse.jgit.lib.Repository repo, TreeWalk treeWalk) throws IOException { + this.pathString = treeWalk.getPathString(); + this.nameString = treeWalk.getNameString(); + this.objectId = treeWalk.getObjectId(0); + ObjectLoader loader = repo.open(objectId); + + this.directory = loader.getType() == Constants.OBJ_TREE; + } + + public String getPathString() { + return pathString; + } + + public String getNameString() { + return nameString; + } + + public ObjectId getObjectId() { + return objectId; + } + + public boolean isDirectory() { + return directory; + } + } } diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnBrowseCommand.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnBrowseCommand.java index a6e131fa4a..423b82004a 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnBrowseCommand.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnBrowseCommand.java @@ -134,7 +134,7 @@ public class SvnBrowseCommand extends AbstractSvnCommand throws SVNException { List entries = new ArrayList<>(svnRepository.getDir(parent.getPath(), revisionNumber, null, (Collection) null)); - entries.sort(comparing(SVNDirEntry::getName)); + sort(entries, entry -> entry.getKind() == SVNNodeKind.DIR, SVNDirEntry::getName); for (Iterator iterator = entries.iterator(); resultCount < request.getLimit() + request.getOffset() && iterator.hasNext(); ++resultCount) { SVNDirEntry entry = iterator.next(); FileObject child = createFileObject(request, svnRepository, revisionNumber, entry, basePath); diff --git a/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/spi/SvnBrowseCommandTest.java b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/spi/SvnBrowseCommandTest.java index 0fc39c8174..1c6e228a6d 100644 --- a/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/spi/SvnBrowseCommandTest.java +++ b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/spi/SvnBrowseCommandTest.java @@ -79,8 +79,8 @@ public class SvnBrowseCommandTest extends AbstractSvnCommandTestBase Collection foList = foList1; Iterator iterator = foList.iterator(); - FileObject a = iterator.next(); FileObject c = iterator.next(); + FileObject a = iterator.next(); assertFalse(a.isDirectory()); assertEquals("a.txt", a.getName()); @@ -189,7 +189,7 @@ public class SvnBrowseCommandTest extends AbstractSvnCommandTestBase Collection foList = result.getFile().getChildren(); - assertThat(foList).extracting("name").containsExactly("a.txt"); + assertThat(foList).extracting("name").containsExactly("c"); assertThat(result.getFile().isTruncated()).isTrue(); } @@ -203,7 +203,7 @@ public class SvnBrowseCommandTest extends AbstractSvnCommandTestBase Collection foList = result.getFile().getChildren(); - assertThat(foList).extracting("name").containsExactly("c"); + assertThat(foList).extracting("name").containsExactly("a.txt"); } /**