]> source.dussan.org Git - gitblit.git/commitdiff
#230 - Improve empty folder navigation. 241/head 34/234/1
authorMilos Cubrilo <milos.cubrilo@gmail.com>
Sun, 11 Jan 2015 12:41:29 +0000 (13:41 +0100)
committerMilos Cubrilo <milos.cubrilo@gmail.com>
Sun, 11 Jan 2015 12:41:29 +0000 (13:41 +0100)
Empty folders are automatically skipped when browsing repository tree  (similar to github "folder jumping" feature).

src/main/java/com/gitblit/utils/JGitUtils.java
src/main/java/com/gitblit/utils/PathUtils.java [new file with mode: 0644]
src/main/java/com/gitblit/wicket/pages/TreePage.java
src/test/java/com/gitblit/tests/GitBlitSuite.java
src/test/java/com/gitblit/tests/JGitUtilsTest.java
src/test/java/com/gitblit/tests/PathUtilsTest.java [new file with mode: 0644]

index 68c62ead110acb8e39f6e88538acdaca209288cf..69084ca1a2d3d8acd005099e7523c0479fdcce6b 100644 (file)
@@ -30,6 +30,7 @@ import java.util.Map;
 import java.util.Map.Entry;\r
 import java.util.regex.Pattern;\r
 \r
+import com.google.common.base.Strings;\r
 import org.apache.commons.io.filefilter.TrueFileFilter;\r
 import org.eclipse.jgit.api.CloneCommand;\r
 import org.eclipse.jgit.api.FetchCommand;\r
@@ -890,6 +891,63 @@ public class JGitUtils {
                return list;\r
        }\r
 \r
+       /**\r
+        * Returns the list of files in the specified folder at the specified\r
+        * commit. If the repository does not exist or is empty, an empty list is\r
+        * returned.\r
+        *\r
+        * This is modified version that implements path compression feature.\r
+        *\r
+        * @param repository\r
+        * @param path\r
+        *            if unspecified, root folder is assumed.\r
+        * @param commit\r
+        *            if null, HEAD is assumed.\r
+        * @return list of files in specified path\r
+        */\r
+       public static List<PathModel> getFilesInPath2(Repository repository, String path, RevCommit commit) {\r
+\r
+               List<PathModel> list = new ArrayList<PathModel>();\r
+               if (!hasCommits(repository)) {\r
+                       return list;\r
+               }\r
+               if (commit == null) {\r
+                       commit = getCommit(repository, null);\r
+               }\r
+               final TreeWalk tw = new TreeWalk(repository);\r
+               try {\r
+\r
+                       tw.addTree(commit.getTree());\r
+                       final boolean isPathEmpty = Strings.isNullOrEmpty(path);\r
+\r
+                       if (!isPathEmpty) {\r
+                               PathFilter f = PathFilter.create(path);\r
+                               tw.setFilter(f);\r
+                       }\r
+\r
+                       tw.setRecursive(true);\r
+                       List<String> paths = new ArrayList<>();\r
+\r
+                       while (tw.next()) {\r
+                                       String child = isPathEmpty ? tw.getPathString()\r
+                                                       : tw.getPathString().replaceFirst(String.format("%s/", path), "");\r
+                                       paths.add(child);\r
+                       }\r
+\r
+                       for(String p: PathUtils.compressPaths(paths)) {\r
+                               String pathString = isPathEmpty ? p : String.format("%s/%s", path, p);\r
+                               list.add(getPathModel(repository, pathString, path, commit));\r
+                       }\r
+\r
+               } catch (IOException e) {\r
+                       error(e, repository, "{0} failed to get files for commit {1}", commit.getName());\r
+               } finally {\r
+                       tw.release();\r
+               }\r
+               Collections.sort(list);\r
+               return list;\r
+       }\r
+\r
        /**\r
         * Returns the list of files changed in a specified commit. If the\r
         * repository does not exist or is empty, an empty list is returned.\r
@@ -1123,6 +1181,46 @@ public class JGitUtils {
                                objectId.getName(), commit.getName());\r
        }\r
 \r
+       /**\r
+        * Returns a path model by path string\r
+        *\r
+        * @param repo\r
+        * @param path\r
+        * @param filter\r
+        * @param commit\r
+        * @return a path model of the specified object\r
+        */\r
+       private static PathModel getPathModel(Repository repo, String path, String filter, RevCommit commit)\r
+                       throws IOException {\r
+\r
+               long size = 0;\r
+               TreeWalk tw = TreeWalk.forPath(repo, path, commit.getTree());\r
+               String pathString = path;\r
+\r
+                       if (!tw.isSubtree() && (tw.getFileMode(0) != FileMode.GITLINK)) {\r
+                               size = tw.getObjectReader().getObjectSize(tw.getObjectId(0), Constants.OBJ_BLOB);\r
+                               pathString = PathUtils.getLastPathComponent(pathString);\r
+\r
+                       } else if (tw.isSubtree()) {\r
+\r
+                               // do not display dirs that are behind in the path\r
+                               if (!Strings.isNullOrEmpty(filter)) {\r
+                                       pathString = path.replaceFirst(filter + "/", "");\r
+                               }\r
+\r
+                               // remove the last slash from path in displayed link\r
+                               if (pathString != null && pathString.charAt(pathString.length()-1) == '/') {\r
+                                       pathString = pathString.substring(0, pathString.length()-1);\r
+                               }\r
+                       }\r
+\r
+                       return new PathModel(pathString, tw.getPathString(), size, tw.getFileMode(0).getBits(),\r
+                                       tw.getObjectId(0).getName(), commit.getName());\r
+\r
+\r
+       }\r
+\r
+\r
        /**\r
         * Returns a permissions representation of the mode bits.\r
         *\r
@@ -2194,97 +2292,97 @@ public class JGitUtils {
                }\r
                return false;\r
        }\r
-
-       /**
-        * Returns true if the commit identified by commitId is an ancestor or the
-        * the commit identified by tipId.
-        *
-        * @param repository
-        * @param commitId
-        * @param tipId
-        * @return true if there is the commit is an ancestor of the tip
-        */
-       public static boolean isMergedInto(Repository repository, String commitId, String tipId) {
-               try {
-                       return isMergedInto(repository, repository.resolve(commitId), repository.resolve(tipId));
-               } catch (Exception e) {
-                       LOGGER.error("Failed to determine isMergedInto", e);
-               }
-               return false;
-       }
-
-       /**
-        * Returns true if the commit identified by commitId is an ancestor or the
-        * the commit identified by tipId.
-        *
-        * @param repository
-        * @param commitId
-        * @param tipId
-        * @return true if there is the commit is an ancestor of the tip
-        */
-       public static boolean isMergedInto(Repository repository, ObjectId commitId, ObjectId tipCommitId) {
-               // traverse the revlog looking for a commit chain between the endpoints
-               RevWalk rw = new RevWalk(repository);
-               try {
-                       // must re-lookup RevCommits to workaround undocumented RevWalk bug
-                       RevCommit tip = rw.lookupCommit(tipCommitId);
-                       RevCommit commit = rw.lookupCommit(commitId);
-                       return rw.isMergedInto(commit, tip);
-               } catch (Exception e) {
-                       LOGGER.error("Failed to determine isMergedInto", e);
-               } finally {
-                       rw.dispose();
-               }
-               return false;
-       }
-
-       /**
-        * Returns the merge base of two commits or null if there is no common
-        * ancestry.
-        *
-        * @param repository
-        * @param commitIdA
-        * @param commitIdB
-        * @return the commit id of the merge base or null if there is no common base
-        */
-       public static String getMergeBase(Repository repository, ObjectId commitIdA, ObjectId commitIdB) {
-               RevWalk rw = new RevWalk(repository);
-               try {
-                       RevCommit a = rw.lookupCommit(commitIdA);
-                       RevCommit b = rw.lookupCommit(commitIdB);
-
-                       rw.setRevFilter(RevFilter.MERGE_BASE);
-                       rw.markStart(a);
-                       rw.markStart(b);
-                       RevCommit mergeBase = rw.next();
-                       if (mergeBase == null) {
-                               return null;
-                       }
-                       return mergeBase.getName();
-               } catch (Exception e) {
-                       LOGGER.error("Failed to determine merge base", e);
-               } finally {
-                       rw.dispose();
-               }
-               return null;
-       }
-
-       public static enum MergeStatus {
-               MISSING_INTEGRATION_BRANCH, MISSING_SRC_BRANCH, NOT_MERGEABLE, FAILED, ALREADY_MERGED, MERGEABLE, MERGED;
-       }
-
-       /**
-        * Determines if we can cleanly merge one branch into another.  Returns true
-        * if we can merge without conflict, otherwise returns false.
-        *
-        * @param repository
-        * @param src
-        * @param toBranch
-        * @return true if we can merge without conflict
-        */
-       public static MergeStatus canMerge(Repository repository, String src, String toBranch) {
-               RevWalk revWalk = null;
-               try {
+\r
+       /**\r
+        * Returns true if the commit identified by commitId is an ancestor or the\r
+        * the commit identified by tipId.\r
+        *\r
+        * @param repository\r
+        * @param commitId\r
+        * @param tipId\r
+        * @return true if there is the commit is an ancestor of the tip\r
+        */\r
+       public static boolean isMergedInto(Repository repository, String commitId, String tipId) {\r
+               try {\r
+                       return isMergedInto(repository, repository.resolve(commitId), repository.resolve(tipId));\r
+               } catch (Exception e) {\r
+                       LOGGER.error("Failed to determine isMergedInto", e);\r
+               }\r
+               return false;\r
+       }\r
+\r
+       /**\r
+        * Returns true if the commit identified by commitId is an ancestor or the\r
+        * the commit identified by tipId.\r
+        *\r
+        * @param repository\r
+        * @param commitId\r
+        * @param tipId\r
+        * @return true if there is the commit is an ancestor of the tip\r
+        */\r
+       public static boolean isMergedInto(Repository repository, ObjectId commitId, ObjectId tipCommitId) {\r
+               // traverse the revlog looking for a commit chain between the endpoints\r
+               RevWalk rw = new RevWalk(repository);\r
+               try {\r
+                       // must re-lookup RevCommits to workaround undocumented RevWalk bug\r
+                       RevCommit tip = rw.lookupCommit(tipCommitId);\r
+                       RevCommit commit = rw.lookupCommit(commitId);\r
+                       return rw.isMergedInto(commit, tip);\r
+               } catch (Exception e) {\r
+                       LOGGER.error("Failed to determine isMergedInto", e);\r
+               } finally {\r
+                       rw.dispose();\r
+               }\r
+               return false;\r
+       }\r
+\r
+       /**\r
+        * Returns the merge base of two commits or null if there is no common\r
+        * ancestry.\r
+        *\r
+        * @param repository\r
+        * @param commitIdA\r
+        * @param commitIdB\r
+        * @return the commit id of the merge base or null if there is no common base\r
+        */\r
+       public static String getMergeBase(Repository repository, ObjectId commitIdA, ObjectId commitIdB) {\r
+               RevWalk rw = new RevWalk(repository);\r
+               try {\r
+                       RevCommit a = rw.lookupCommit(commitIdA);\r
+                       RevCommit b = rw.lookupCommit(commitIdB);\r
+\r
+                       rw.setRevFilter(RevFilter.MERGE_BASE);\r
+                       rw.markStart(a);\r
+                       rw.markStart(b);\r
+                       RevCommit mergeBase = rw.next();\r
+                       if (mergeBase == null) {\r
+                               return null;\r
+                       }\r
+                       return mergeBase.getName();\r
+               } catch (Exception e) {\r
+                       LOGGER.error("Failed to determine merge base", e);\r
+               } finally {\r
+                       rw.dispose();\r
+               }\r
+               return null;\r
+       }\r
+\r
+       public static enum MergeStatus {\r
+               MISSING_INTEGRATION_BRANCH, MISSING_SRC_BRANCH, NOT_MERGEABLE, FAILED, ALREADY_MERGED, MERGEABLE, MERGED;\r
+       }\r
+\r
+       /**\r
+        * Determines if we can cleanly merge one branch into another.  Returns true\r
+        * if we can merge without conflict, otherwise returns false.\r
+        *\r
+        * @param repository\r
+        * @param src\r
+        * @param toBranch\r
+        * @return true if we can merge without conflict\r
+        */\r
+       public static MergeStatus canMerge(Repository repository, String src, String toBranch) {\r
+               RevWalk revWalk = null;\r
+               try {\r
                        revWalk = new RevWalk(repository);\r
                        ObjectId branchId = repository.resolve(toBranch);\r
                        if (branchId == null) {\r
@@ -2294,122 +2392,122 @@ public class JGitUtils {
                        if (srcId == null) {\r
                                return MergeStatus.MISSING_SRC_BRANCH;\r
                        }\r
-                       RevCommit branchTip = revWalk.lookupCommit(branchId);
-                       RevCommit srcTip = revWalk.lookupCommit(srcId);
-                       if (revWalk.isMergedInto(srcTip, branchTip)) {
-                               // already merged
-                               return MergeStatus.ALREADY_MERGED;
-                       } else if (revWalk.isMergedInto(branchTip, srcTip)) {
-                               // fast-forward
-                               return MergeStatus.MERGEABLE;
-                       }
-                       RecursiveMerger merger = (RecursiveMerger) MergeStrategy.RECURSIVE.newMerger(repository, true);
-                       boolean canMerge = merger.merge(branchTip, srcTip);
-                       if (canMerge) {
-                               return MergeStatus.MERGEABLE;
-                       }
+                       RevCommit branchTip = revWalk.lookupCommit(branchId);\r
+                       RevCommit srcTip = revWalk.lookupCommit(srcId);\r
+                       if (revWalk.isMergedInto(srcTip, branchTip)) {\r
+                               // already merged\r
+                               return MergeStatus.ALREADY_MERGED;\r
+                       } else if (revWalk.isMergedInto(branchTip, srcTip)) {\r
+                               // fast-forward\r
+                               return MergeStatus.MERGEABLE;\r
+                       }\r
+                       RecursiveMerger merger = (RecursiveMerger) MergeStrategy.RECURSIVE.newMerger(repository, true);\r
+                       boolean canMerge = merger.merge(branchTip, srcTip);\r
+                       if (canMerge) {\r
+                               return MergeStatus.MERGEABLE;\r
+                       }\r
                } catch (NullPointerException e) {\r
                        LOGGER.error("Failed to determine canMerge", e);\r
-               } catch (IOException e) {
-                       LOGGER.error("Failed to determine canMerge", e);
+               } catch (IOException e) {\r
+                       LOGGER.error("Failed to determine canMerge", e);\r
                } finally {\r
-                       if (revWalk != null) {
+                       if (revWalk != null) {\r
                                revWalk.release();\r
-                       }
-               }
-               return MergeStatus.NOT_MERGEABLE;
-       }
-
-
-       public static class MergeResult {
-               public final MergeStatus status;
-               public final String sha;
-
-               MergeResult(MergeStatus status, String sha) {
-                       this.status = status;
-                       this.sha = sha;
-               }
-       }
-
-       /**
-        * Tries to merge a commit into a branch.  If there are conflicts, the merge
-        * will fail.
-        *
-        * @param repository
-        * @param src
-        * @param toBranch
-        * @param committer
-        * @param message
-        * @return the merge result
-        */
-       public static MergeResult merge(Repository repository, String src, String toBranch,
-                       PersonIdent committer, String message) {
-
-               if (!toBranch.startsWith(Constants.R_REFS)) {
-                       // branch ref doesn't start with ref, assume this is a branch head
-                       toBranch = Constants.R_HEADS + toBranch;
-               }
-
-               RevWalk revWalk = null;
-               try {
-                       revWalk = new RevWalk(repository);
-                       RevCommit branchTip = revWalk.lookupCommit(repository.resolve(toBranch));
-                       RevCommit srcTip = revWalk.lookupCommit(repository.resolve(src));
-                       if (revWalk.isMergedInto(srcTip, branchTip)) {
-                               // already merged
-                               return new MergeResult(MergeStatus.ALREADY_MERGED, null);
-                       }
-                       RecursiveMerger merger = (RecursiveMerger) MergeStrategy.RECURSIVE.newMerger(repository, true);
-                       boolean merged = merger.merge(branchTip, srcTip);
-                       if (merged) {
-                               // create a merge commit and a reference to track the merge commit
-                               ObjectId treeId = merger.getResultTreeId();
-                               ObjectInserter odi = repository.newObjectInserter();
-                               try {
-                                       // Create a commit object
-                                       CommitBuilder commitBuilder = new CommitBuilder();
-                                       commitBuilder.setCommitter(committer);
-                                       commitBuilder.setAuthor(committer);
-                                       commitBuilder.setEncoding(Constants.CHARSET);
-                                       if (StringUtils.isEmpty(message)) {
-                                               message = MessageFormat.format("merge {0} into {1}", srcTip.getName(), branchTip.getName());
-                                       }
-                                       commitBuilder.setMessage(message);
-                                       commitBuilder.setParentIds(branchTip.getId(), srcTip.getId());
-                                       commitBuilder.setTreeId(treeId);
-
-                                       // Insert the merge commit into the repository
-                                       ObjectId mergeCommitId = odi.insert(commitBuilder);
-                                       odi.flush();
-
-                                       // set the merge ref to the merge commit
-                                       RevCommit mergeCommit = revWalk.parseCommit(mergeCommitId);
-                                       RefUpdate mergeRefUpdate = repository.updateRef(toBranch);
-                                       mergeRefUpdate.setNewObjectId(mergeCommitId);
-                                       mergeRefUpdate.setRefLogMessage("commit: " + mergeCommit.getShortMessage(), false);
-                                       RefUpdate.Result rc = mergeRefUpdate.update();
-                                       switch (rc) {
-                                       case FAST_FORWARD:
-                                               // successful, clean merge
+                       }\r
+               }\r
+               return MergeStatus.NOT_MERGEABLE;\r
+       }\r
+\r
+\r
+       public static class MergeResult {\r
+               public final MergeStatus status;\r
+               public final String sha;\r
+\r
+               MergeResult(MergeStatus status, String sha) {\r
+                       this.status = status;\r
+                       this.sha = sha;\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Tries to merge a commit into a branch.  If there are conflicts, the merge\r
+        * will fail.\r
+        *\r
+        * @param repository\r
+        * @param src\r
+        * @param toBranch\r
+        * @param committer\r
+        * @param message\r
+        * @return the merge result\r
+        */\r
+       public static MergeResult merge(Repository repository, String src, String toBranch,\r
+                       PersonIdent committer, String message) {\r
+\r
+               if (!toBranch.startsWith(Constants.R_REFS)) {\r
+                       // branch ref doesn't start with ref, assume this is a branch head\r
+                       toBranch = Constants.R_HEADS + toBranch;\r
+               }\r
+\r
+               RevWalk revWalk = null;\r
+               try {\r
+                       revWalk = new RevWalk(repository);\r
+                       RevCommit branchTip = revWalk.lookupCommit(repository.resolve(toBranch));\r
+                       RevCommit srcTip = revWalk.lookupCommit(repository.resolve(src));\r
+                       if (revWalk.isMergedInto(srcTip, branchTip)) {\r
+                               // already merged\r
+                               return new MergeResult(MergeStatus.ALREADY_MERGED, null);\r
+                       }\r
+                       RecursiveMerger merger = (RecursiveMerger) MergeStrategy.RECURSIVE.newMerger(repository, true);\r
+                       boolean merged = merger.merge(branchTip, srcTip);\r
+                       if (merged) {\r
+                               // create a merge commit and a reference to track the merge commit\r
+                               ObjectId treeId = merger.getResultTreeId();\r
+                               ObjectInserter odi = repository.newObjectInserter();\r
+                               try {\r
+                                       // Create a commit object\r
+                                       CommitBuilder commitBuilder = new CommitBuilder();\r
+                                       commitBuilder.setCommitter(committer);\r
+                                       commitBuilder.setAuthor(committer);\r
+                                       commitBuilder.setEncoding(Constants.CHARSET);\r
+                                       if (StringUtils.isEmpty(message)) {\r
+                                               message = MessageFormat.format("merge {0} into {1}", srcTip.getName(), branchTip.getName());\r
+                                       }\r
+                                       commitBuilder.setMessage(message);\r
+                                       commitBuilder.setParentIds(branchTip.getId(), srcTip.getId());\r
+                                       commitBuilder.setTreeId(treeId);\r
+\r
+                                       // Insert the merge commit into the repository\r
+                                       ObjectId mergeCommitId = odi.insert(commitBuilder);\r
+                                       odi.flush();\r
+\r
+                                       // set the merge ref to the merge commit\r
+                                       RevCommit mergeCommit = revWalk.parseCommit(mergeCommitId);\r
+                                       RefUpdate mergeRefUpdate = repository.updateRef(toBranch);\r
+                                       mergeRefUpdate.setNewObjectId(mergeCommitId);\r
+                                       mergeRefUpdate.setRefLogMessage("commit: " + mergeCommit.getShortMessage(), false);\r
+                                       RefUpdate.Result rc = mergeRefUpdate.update();\r
+                                       switch (rc) {\r
+                                       case FAST_FORWARD:\r
+                                               // successful, clean merge\r
                                                break;\r
-                                       default:
-                                               throw new GitBlitException(MessageFormat.format("Unexpected result \"{0}\" when merging commit {1} into {2} in {3}",
-                                                               rc.name(), srcTip.getName(), branchTip.getName(), repository.getDirectory()));
-                                       }
-
-                                       // return the merge commit id
-                                       return new MergeResult(MergeStatus.MERGED, mergeCommitId.getName());
-                               } finally {
-                                       odi.release();
-                               }
-                       }
-               } catch (IOException e) {
-                       LOGGER.error("Failed to merge", e);
+                                       default:\r
+                                               throw new GitBlitException(MessageFormat.format("Unexpected result \"{0}\" when merging commit {1} into {2} in {3}",\r
+                                                               rc.name(), srcTip.getName(), branchTip.getName(), repository.getDirectory()));\r
+                                       }\r
+\r
+                                       // return the merge commit id\r
+                                       return new MergeResult(MergeStatus.MERGED, mergeCommitId.getName());\r
+                               } finally {\r
+                                       odi.release();\r
+                               }\r
+                       }\r
+               } catch (IOException e) {\r
+                       LOGGER.error("Failed to merge", e);\r
                } finally {\r
-                       if (revWalk != null) {
+                       if (revWalk != null) {\r
                                revWalk.release();\r
-                       }
-               }
-               return new MergeResult(MergeStatus.FAILED, null);
-       }
+                       }\r
+               }\r
+               return new MergeResult(MergeStatus.FAILED, null);\r
+       }\r
 }\r
diff --git a/src/main/java/com/gitblit/utils/PathUtils.java b/src/main/java/com/gitblit/utils/PathUtils.java
new file mode 100644 (file)
index 0000000..a3c7d8d
--- /dev/null
@@ -0,0 +1,92 @@
+package com.gitblit.utils;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Iterables;
+
+import java.util.*;
+
+/**
+ *  Utils for handling path strings
+ *
+ */
+public class PathUtils {
+
+    private PathUtils() {}
+
+    /**
+     *  Compress paths containing no files
+     *
+     * @param paths lines from `git ls-tree -r --name-only ${branch}`
+     * @return compressed paths
+     */
+    public static List<String> compressPaths(final Iterable<String> paths)  {
+
+        ArrayList<String> pathList = new ArrayList<>();
+        Map<String, List<String[]>> folderRoots = new LinkedHashMap<>();
+
+        for (String s: paths) {
+            String[] components = s.split("/");
+
+            // File in current directory
+            if (components.length == 1) {
+                pathList.add(components[0]);
+
+                // Directory path
+            } else {
+                List<String[]> rootedPaths = folderRoots.get(components[0]);
+                if (rootedPaths == null) {
+                    rootedPaths = new ArrayList<>();
+                }
+                rootedPaths.add(components);
+                folderRoots.put(components[0], rootedPaths);
+            }
+        }
+
+        for (String folder: folderRoots.keySet()) {
+            List<String[]> matchingPaths = folderRoots.get(folder);
+
+            if (matchingPaths.size() == 1) {
+                pathList.add(toStringPath(matchingPaths.get(0)));
+            } else {
+                pathList.add(longestCommonSequence(matchingPaths));
+            }
+        }
+        return pathList;
+    }
+
+    /**
+     *  Get last path component
+     *
+     *
+     * @param path string path separated by slashes
+     * @return rightmost entry
+     */
+    public static String getLastPathComponent(final String path) {
+        return Iterables.getLast(Splitter.on("/").omitEmptyStrings().split(path), path);
+    }
+
+    private static String toStringPath(final String[] pathComponents) {
+        List<String> tmp = Arrays.asList(pathComponents);
+        return Joiner.on('/').join(tmp.subList(0,tmp.size()-1)) + '/';
+    }
+
+
+    private static String longestCommonSequence(final List<String[]> paths) {
+
+        StringBuilder path = new StringBuilder();
+
+        for (int i = 0; i < paths.get(0).length; i++) {
+            String current = paths.get(0)[i];
+            for (int j = 1; j < paths.size(); j++) {
+                if (!current.equals(paths.get(j)[i])) {
+                    return path.toString();
+                }
+            }
+            path.append(current);
+            path.append('/');
+        }
+        return path.toString();
+    }
+
+}
index 9ddbecf6485fb1ee6b3f9c590f54cde6553ab862..d7899dcb057ca63fbe05cc47af371908137d9181 100644 (file)
@@ -52,7 +52,7 @@ public class TreePage extends RepositoryPage {
 \r
                Repository r = getRepository();\r
                RevCommit commit = getCommit();\r
-               List<PathModel> paths = JGitUtils.getFilesInPath(r, path, commit);\r
+               List<PathModel> paths = JGitUtils.getFilesInPath2(r, path, commit);\r
 \r
                // tree page links\r
                add(new BookmarkablePageLink<Void>("historyLink", HistoryPage.class,\r
index f2dfcc0cd4f919753a4032add5dccef3e1082f67..bf6834d304818e3e5d8da5a85efa009b8838a673 100644 (file)
@@ -63,9 +63,9 @@ import com.gitblit.utils.JGitUtils;
                GitBlitTest.class, FederationTests.class, RpcTests.class, GitServletTest.class, GitDaemonTest.class,\r
                SshDaemonTest.class, GroovyScriptTest.class, LuceneExecutorTest.class, RepositoryModelTest.class,\r
                FanoutServiceTest.class, Issue0259Test.class, Issue0271Test.class, HtpasswdAuthenticationTest.class,\r
-               ModelUtilsTest.class, JnaUtilsTest.class, LdapSyncServiceTest.class, FileTicketServiceTest.class,
+               ModelUtilsTest.class, JnaUtilsTest.class, LdapSyncServiceTest.class, FileTicketServiceTest.class,\r
                BranchTicketServiceTest.class, RedisTicketServiceTest.class, AuthenticationManagerTest.class,\r
-               SshKeysDispatcherTest.class, UITicketTest.class })
+               SshKeysDispatcherTest.class, UITicketTest.class, PathUtilsTest.class })\r
 public class GitBlitSuite {\r
 \r
        public static final File BASEFOLDER = new File("data");\r
@@ -110,11 +110,11 @@ public class GitBlitSuite {
                return getRepository("test/gitective.git");\r
        }\r
 \r
-       public static Repository getTicketsTestRepository() {
-               JGitUtils.createRepository(REPOSITORIES, "gb-tickets.git").close();
-               return getRepository("gb-tickets.git");
-       }
-
+       public static Repository getTicketsTestRepository() {\r
+               JGitUtils.createRepository(REPOSITORIES, "gb-tickets.git").close();\r
+               return getRepository("gb-tickets.git");\r
+       }\r
+\r
        private static Repository getRepository(String name) {\r
                try {\r
                        File gitDir = FileKey.resolve(new File(REPOSITORIES, name), FS.DETECTED);\r
index c2cfb3314aa9d998aa5ba7f3ed23689d383f5fec..2cf4a5a11d30546be6528152a423f78d80adffc2 100644 (file)
@@ -475,6 +475,15 @@ public class JGitUtilsTest extends GitblitUnitTest {
                assertTrue(files.size() > 10);\r
        }\r
 \r
+       @Test\r
+       public void testFilesInPath2() throws Exception {\r
+               assertEquals(0, JGitUtils.getFilesInPath2(null, null, null).size());\r
+               Repository repository = GitBlitSuite.getHelloworldRepository();\r
+               List<PathModel> files = JGitUtils.getFilesInPath2(repository, null, null);\r
+               repository.close();\r
+               assertTrue(files.size() > 10);\r
+       }\r
+\r
        @Test\r
        public void testDocuments() throws Exception {\r
                Repository repository = GitBlitSuite.getTicgitRepository();\r
diff --git a/src/test/java/com/gitblit/tests/PathUtilsTest.java b/src/test/java/com/gitblit/tests/PathUtilsTest.java
new file mode 100644 (file)
index 0000000..209b8ee
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2011 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.gitblit.tests;
+
+import com.gitblit.utils.PathUtils;
+import org.junit.Test;
+
+import java.util.Arrays;
+
+public class PathUtilsTest extends GitblitUnitTest {
+
+       private static final String[][][] testData = {
+
+                       {
+                                       // Folder contents
+                                       {".gitignore","src/main/java/a.java", "src/main/java/b.java", "docs/c.md"},
+                                       // Expected after compressing
+                                       {".gitignore", "src/main/java/", "docs/"}
+                       },
+
+                       {
+                                       {".gitignore","src/main/java/a.java", "src/main/b.java", "docs/c.md"},
+                                       {".gitignore", "src/main/", "docs/"}
+                       },
+
+                       {
+                                       {".gitignore","src/x.java","src/main/java/a.java", "src/main/java/b.java", "docs/c.md"},
+                                       {".gitignore", "src/", "docs/"}
+                       },
+       };
+
+
+
+
+       @Test
+       public void testCompressPaths() throws Exception {
+
+               for (String[][] test : testData ) {
+                       assertArrayEquals(test[1], PathUtils.compressPaths(Arrays.asList(test[0])).toArray(new String[]{}));
+               }
+
+       }
+
+       @Test
+       public void testGetLastPathComponent() {
+               assertEquals(PathUtils.getLastPathComponent("/a/b/c/d/e.out"), "e.out");
+               assertEquals(PathUtils.getLastPathComponent("e.out"), "e.out");
+               assertEquals(PathUtils.getLastPathComponent("/a/b/c/d/"), "d");
+               assertEquals(PathUtils.getLastPathComponent("/a/b/c/d"), "d");
+               assertEquals(PathUtils.getLastPathComponent("/"), "/");
+       }
+
+}
\ No newline at end of file