]> source.dussan.org Git - gitblit.git/commitdiff
Display entire fork network. Link as appropriate for user permissions.
authorJames Moger <james.moger@gitblit.com>
Wed, 3 Oct 2012 13:18:51 +0000 (09:18 -0400)
committerJames Moger <james.moger@gitblit.com>
Wed, 3 Oct 2012 13:18:51 +0000 (09:18 -0400)
src/com/gitblit/GitBlit.java
src/com/gitblit/models/ForkModel.java
src/com/gitblit/models/RepositoryModel.java
src/com/gitblit/models/UserModel.java
src/com/gitblit/wicket/pages/ForksPage.html
src/com/gitblit/wicket/pages/ForksPage.java

index 4ada74814120f20e30b61b088ec002a8fec5aef5..1ebc4c70b598825be957a7a553f1b888cfce7f73 100644 (file)
@@ -1425,7 +1425,7 @@ public class GitBlit implements ServletContextListener {
        \r
        private ForkModel getForkModel(String repository) {\r
                RepositoryModel model = repositoryListCache.get(repository);\r
-               ForkModel fork = new ForkModel(model.originRepository, model.name);\r
+               ForkModel fork = new ForkModel(model);\r
                if (!ArrayUtils.isEmpty(model.forks)) {\r
                        for (String aFork : model.forks) {\r
                                ForkModel fm = getForkModel(aFork);\r
index b394396b3a7075d98dd6f7f213666318db26c29d..849986c1059fe3b506a046db4f92b9333adba230 100644 (file)
@@ -32,20 +32,17 @@ public class ForkModel implements Serializable {
 
        private static final long serialVersionUID = 1L;
        
-       public final String originRepository;
-       
-       public final String repository;
+       public final RepositoryModel repository;
        
        public final List<ForkModel> forks;
        
-       public ForkModel(String origin, String repository) {
-               this.originRepository = origin;
+       public ForkModel(RepositoryModel repository) {
                this.repository = repository;
                this.forks = new ArrayList<ForkModel>();
        }
        
        public boolean isRoot() {
-               return StringUtils.isEmpty(originRepository);
+               return StringUtils.isEmpty(repository.originRepository);
        }
        
        public boolean isNode() {
@@ -57,7 +54,7 @@ public class ForkModel implements Serializable {
        }
        
        public boolean isPersonalRepository() {
-               return repository.charAt(0) == '~';
+               return repository.isPersonalRepository();
        }
        
        @Override
@@ -75,6 +72,6 @@ public class ForkModel implements Serializable {
        
        @Override
        public String toString() {
-               return repository;
+               return repository.toString();
        }
 }
index 3148b5b4b2fb9876ea93fd063e2c40b76c066f49..a28536d1d70ead6eb612f5475ec5a72930ef1b18 100644 (file)
@@ -121,6 +121,19 @@ public class RepositoryModel implements Serializable, Comparable<RepositoryModel
        public void resetDisplayName() {\r
                displayName = null;\r
        }\r
+       \r
+       @Override\r
+       public int hashCode() {\r
+               return name.hashCode();\r
+       }\r
+       \r
+       @Override\r
+       public boolean equals(Object o) {\r
+               if (o instanceof RepositoryModel) {\r
+                       return name.equals(((RepositoryModel) o).name);\r
+               }\r
+               return false;\r
+       }\r
 \r
        @Override\r
        public String toString() {\r
@@ -143,6 +156,10 @@ public class RepositoryModel implements Serializable, Comparable<RepositoryModel
                return !StringUtils.isEmpty(projectPath) && projectPath.equalsIgnoreCase("~" + username);\r
        }\r
        \r
+       public boolean allowAnonymousView() {\r
+               return !accessRestriction.atLeast(AccessRestrictionType.VIEW);\r
+       }\r
+       \r
        public RepositoryModel cloneAs(String cloneName) {\r
                RepositoryModel clone = new RepositoryModel();\r
                clone.originRepository = name;\r
index 25787a15ae70c4b1defc17001f4bcb5470b94385..7c32a5556e5129ffd800ca2299c4f9279f2196f1 100644 (file)
@@ -36,6 +36,8 @@ public class UserModel implements Principal, Serializable, Comparable<UserModel>
 \r
        private static final long serialVersionUID = 1L;\r
 \r
+       public static final UserModel ANONYMOUS = new UserModel("anonymous", false);\r
+       \r
        // field names are reflectively mapped in EditUser page\r
        public String username;\r
        public String password;\r
@@ -56,6 +58,11 @@ public class UserModel implements Principal, Serializable, Comparable<UserModel>
                this.isAuthenticated = true;\r
        }\r
 \r
+       private UserModel(String username, boolean authenticated) {\r
+               this.username = username;\r
+               this.isAuthenticated = authenticated;\r
+       }\r
+\r
        /**\r
         * This method does not take into consideration Ownership where the\r
         * administrator has not explicitly granted access to the owner.\r
index f59f9ca25313a8d1fea9aeb8de06781b9778a4d9..c18d2a491c20863396e20140d9e4b8b1d32d4b17 100644 (file)
@@ -7,27 +7,14 @@
 <body>\r
 <wicket:extend>\r
 \r
-       <div class="forkSource">\r
-               <div>\r
-                       <b><span class="repositorySwatch" wicket:id="forkSourceSwatch"></span></b>\r
-                       <span wicket:id="forkSourceAvatar" style="vertical-align: baseline;"></span>\r
-                       <span wicket:id="forkSourceProject">[a project]</span> / <span wicket:id="forkSource">[a fork]</span>\r
-               </div> \r
-               <div style="padding-left:32px;" wicket:id="forkSourceOrigin">[origin repository]</div>\r
-       </div>\r
-       \r
        <div wicket:id="fork">\r
-               <div class="forkEntry" style="margin-left:32px;">\r
-                       <span wicket:id="anAvatar" style="vertical-align: baseline;"></span>\r
+               <div>\r
+                       <span wicket:id="anAvatar" style="vertical-align: baseline;font-weight:bold;"></span>\r
                        <span wicket:id="aProject">[a project]</span> / <span wicket:id="aFork">[a fork]</span>\r
-                       <span wicket:id="anIcon" class="forks"></span>\r
+                       <span style="padding-left:10px;" wicket:id="lastChange"></span>\r
                </div>\r
        </div>\r
        \r
-       <wicket:fragment wicket:id="originFragment">\r
-               <p class="originRepository"><wicket:message key="gb.forkedFrom">[forked from]</wicket:message> <span wicket:id="originRepository">[origin repository]</span></p>\r
-       </wicket:fragment>\r
-       \r
 </wicket:extend>       \r
 </body>\r
 </html>
\ No newline at end of file
index 44f0ed14de8833eb5033db5355ed8ff651ef9ab0..2e67e2b779d87e74c4c62fb73c5b3882ad07c302 100644 (file)
  */\r
 package com.gitblit.wicket.pages;\r
 \r
-import java.text.MessageFormat;\r
+import java.io.Serializable;\r
 import java.util.ArrayList;\r
 import java.util.List;\r
 \r
 import org.apache.wicket.Component;\r
 import org.apache.wicket.PageParameters;\r
 import org.apache.wicket.markup.html.basic.Label;\r
-import org.apache.wicket.markup.html.panel.Fragment;\r
 import org.apache.wicket.markup.repeater.Item;\r
 import org.apache.wicket.markup.repeater.data.DataView;\r
 import org.apache.wicket.markup.repeater.data.ListDataProvider;\r
@@ -30,9 +29,9 @@ import org.eclipse.jgit.lib.PersonIdent;
 \r
 import com.gitblit.GitBlit;\r
 import com.gitblit.Keys;\r
+import com.gitblit.models.ForkModel;\r
 import com.gitblit.models.RepositoryModel;\r
 import com.gitblit.models.UserModel;\r
-import com.gitblit.utils.ArrayUtils;\r
 import com.gitblit.utils.StringUtils;\r
 import com.gitblit.wicket.GitBlitWebSession;\r
 import com.gitblit.wicket.WicketUtils;\r
@@ -44,132 +43,114 @@ public class ForksPage extends RepositoryPage {
        public ForksPage(PageParameters params) {\r
                super(params);\r
                \r
-               UserModel user = GitBlitWebSession.get().getUser();\r
-               RepositoryModel model = getRepositoryModel();\r
-               RepositoryModel origin = model;\r
-               List<String> list;\r
-               if (ArrayUtils.isEmpty(model.forks)) {\r
-                       if (!StringUtils.isEmpty(model.originRepository)) {\r
-                               // try origin repository\r
-                               origin = GitBlit.self().getRepositoryModel(model.originRepository);\r
-                       }\r
-                       if (origin == null || origin.forks == null) {\r
-                               list = new ArrayList<String>();\r
-                       } else {\r
-                               list = new ArrayList<String>(origin.forks);\r
-                       }\r
-               } else {\r
-                       // this repository has forks\r
-                       list = new ArrayList<String>(model.forks);\r
-               }\r
-               \r
-               if (origin.isPersonalRepository()) {\r
-                       // personal repository\r
-                       UserModel originUser = GitBlit.self().getUserModel(origin.projectPath.substring(1));\r
-                       PersonIdent ident = new PersonIdent(originUser.getDisplayName(), originUser.emailAddress);\r
-                       add(new GravatarImage("forkSourceAvatar", ident, 20));\r
-                       add(new Label("forkSourceSwatch").setVisible(false));\r
-                       add(new LinkPanel("forkSourceProject", null, originUser.getDisplayName(), UserPage.class, WicketUtils.newUsernameParameter(originUser.username)));\r
-               } else {\r
-                       // standard repository\r
-                       add(new GravatarImage("forkSourceAvatar", new PersonIdent("", ""), 20).setVisible(false));\r
-                       Component swatch;\r
-                       if (origin.isBare){\r
-                               swatch = new Label("forkSourceSwatch", "&nbsp;").setEscapeModelStrings(false);\r
-                       } else {\r
-                               swatch = new Label("forkSourceSwatch", "!");\r
-                               WicketUtils.setHtmlTooltip(swatch, getString("gb.workingCopyWarning"));\r
-                       }\r
-                       WicketUtils.setCssBackground(swatch, origin.toString());\r
-                       add(swatch);\r
-                       final boolean showSwatch = GitBlit.getBoolean(Keys.web.repositoryListSwatches, true);\r
-                       swatch.setVisible(showSwatch);\r
-                       \r
-                       String projectName = origin.projectPath;\r
-                       if (StringUtils.isEmpty(projectName)) {\r
-                               projectName = GitBlit.getString(Keys.web.repositoryRootGroupName, "main");\r
-                       }\r
-                       add(new LinkPanel("forkSourceProject", null, projectName, ProjectPage.class, WicketUtils.newProjectParameter(origin.projectPath)));\r
-               }\r
+               final RepositoryModel pageRepository = getRepositoryModel();\r
                \r
-               String source = StringUtils.getLastPathElement(origin.name);\r
-               if (user != null && user.canViewRepository(origin)) {\r
-                       // user can view the origin\r
-                       add(new LinkPanel("forkSource", null, StringUtils.stripDotGit(source), SummaryPage.class, WicketUtils.newRepositoryParameter(origin.name)));\r
-               } else {\r
-                       // user can not view the origin\r
-                       add(new Label("forkSource", StringUtils.stripDotGit(source)));\r
-               }\r
-               \r
-               // superOrigin?\r
-               if (StringUtils.isEmpty(origin.originRepository)) {\r
-                       // origin is root\r
-                       add(new Label("forkSourceOrigin").setVisible(false));\r
-               } else {\r
-                       // origin has an origin\r
-                       RepositoryModel superOrigin = GitBlit.self().getRepositoryModel(origin.originRepository);\r
-                       if (!user.canViewRepository(superOrigin)) {\r
-                               // show superOrigin repository without link\r
-                               Fragment forkFrag = new Fragment("forkSourceOrigin", "originFragment", this);\r
-                               forkFrag.add(new Label("originRepository", StringUtils.stripDotGit(superOrigin.name)));\r
-                               add(forkFrag);\r
-                       } else {\r
-                               // link to superOrigin repository\r
-                               Fragment forkFrag = new Fragment("forkSourceOrigin", "originFragment", this);\r
-                               forkFrag.add(new LinkPanel("originRepository", null, StringUtils.stripDotGit(superOrigin.name), \r
-                                       SummaryPage.class, WicketUtils.newRepositoryParameter(superOrigin.name)));\r
-                               add(forkFrag);\r
-                       }\r
-               }\r
-\r
-               // only display user-accessible forks\r
-               List<RepositoryModel> forks = new ArrayList<RepositoryModel>();\r
-               for (String aFork : list) {\r
-                       RepositoryModel fork = GitBlit.self().getRepositoryModel(user, aFork);\r
-                       if (fork != null) {\r
-                               forks.add(fork);\r
-                       }\r
-               }\r
+               ForkModel root = GitBlit.self().getForkNetwork(pageRepository.name);\r
+               List<FlatFork> network = flatten(root);\r
                \r
-               ListDataProvider<RepositoryModel> forksDp = new ListDataProvider<RepositoryModel>(forks);\r
-               DataView<RepositoryModel> forksList = new DataView<RepositoryModel>("fork", forksDp) {\r
+               ListDataProvider<FlatFork> forksDp = new ListDataProvider<FlatFork>(network);\r
+               DataView<FlatFork> forksList = new DataView<FlatFork>("fork", forksDp) {\r
                        private static final long serialVersionUID = 1L;\r
 \r
-                       public void populateItem(final Item<RepositoryModel> item) {\r
-                               RepositoryModel fork = item.getModelObject();\r
+                       public void populateItem(final Item<FlatFork> item) {\r
+                               FlatFork fork = item.getModelObject();\r
+                               RepositoryModel repository = fork.repository;\r
                                \r
-                               if (fork.isPersonalRepository()) {\r
-                                       UserModel user = GitBlit.self().getUserModel(fork.projectPath.substring(1));\r
+                               if (repository.isPersonalRepository()) {\r
+                                       UserModel user = GitBlit.self().getUserModel(repository.projectPath.substring(1));\r
                                        PersonIdent ident = new PersonIdent(user.getDisplayName(), user.emailAddress);\r
                                        item.add(new GravatarImage("anAvatar", ident, 20));\r
-                                       item.add(new LinkPanel("aProject", null, user.getDisplayName(), UserPage.class, WicketUtils.newUsernameParameter(user.username)));\r
+                                       if (pageRepository.equals(repository)) {\r
+                                               // do not link to self\r
+                                               item.add(new Label("aProject", user.getDisplayName()));\r
+                                       } else {\r
+                                               item.add(new LinkPanel("aProject", null, user.getDisplayName(), UserPage.class, WicketUtils.newUsernameParameter(user.username)));\r
+                                       }\r
                                } else {\r
-                                       PersonIdent ident = new PersonIdent(fork.name, fork.name);\r
-                                       item.add(new GravatarImage("anAvatar", ident, 20));\r
-                                       item.add(new LinkPanel("aProject", null, fork.projectPath, ProjectPage.class, WicketUtils.newProjectParameter(fork.projectPath)));\r
+                                       Component swatch;\r
+                                       if (repository.isBare){\r
+                                               swatch = new Label("anAvatar", "&nbsp;").setEscapeModelStrings(false);\r
+                                       } else {\r
+                                               swatch = new Label("anAvatar", "!");\r
+                                               WicketUtils.setHtmlTooltip(swatch, getString("gb.workingCopyWarning"));\r
+                                       }\r
+                                       WicketUtils.setCssClass(swatch,  "repositorySwatch");\r
+                                       WicketUtils.setCssBackground(swatch, repository.toString());\r
+                                       item.add(swatch);\r
+                                       String projectName = repository.projectPath;\r
+                                       if (StringUtils.isEmpty(projectName)) {\r
+                                               projectName = GitBlit.getString(Keys.web.repositoryRootGroupName, "main");\r
+                                       }\r
+                                       if (pageRepository.equals(repository)) {\r
+                                               // do not link to self\r
+                                               item.add(new Label("aProject", projectName));\r
+                                       } else {\r
+                                               item.add(new LinkPanel("aProject", null, projectName, ProjectPage.class, WicketUtils.newProjectParameter(projectName)));\r
+                                       }\r
                                }\r
                                \r
-                               String repo = StringUtils.getLastPathElement(fork.name);\r
-                               item.add(new LinkPanel("aFork", null, StringUtils.stripDotGit(repo), SummaryPage.class, WicketUtils.newRepositoryParameter(fork.name)));\r
+                               String repo = StringUtils.getLastPathElement(repository.name);\r
+                               UserModel user = GitBlitWebSession.get().getUser();\r
+                               if (user == null) {\r
+                                       user = UserModel.ANONYMOUS;\r
+                               }\r
+                               if (user.canViewRepository(repository)) {\r
+                                       if (pageRepository.equals(repository)) {\r
+                                               // do not link to self\r
+                                               item.add(new Label("aFork", StringUtils.stripDotGit(repo)));\r
+                                       } else {\r
+                                               item.add(new LinkPanel("aFork", null, StringUtils.stripDotGit(repo), SummaryPage.class, WicketUtils.newRepositoryParameter(repository.name)));\r
+                                       }\r
+                                       item.add(WicketUtils.createDateLabel("lastChange", repository.lastChange, getTimeZone(), getTimeUtils()));\r
+                               } else {\r
+                                       item.add(new Label("aFork", repo));\r
+                                       item.add(new Label("lastChange").setVisible(false));\r
+                               }\r
                                \r
-                               if (ArrayUtils.isEmpty(fork.forks)) {\r
-                                       // repository is a leaf\r
-                                       Component icon = new Label("anIcon", "<i class=\"icon-leaf\" ></i>").setEscapeModelStrings(false);\r
-                                       WicketUtils.setHtmlTooltip(icon, MessageFormat.format(getString("gb.noForks"), fork.name));\r
-                                       item.add(icon);\r
+                               WicketUtils.setCssStyle(item, "margin-left:" + (32*fork.level) + "px;");\r
+                               if (fork.level == 0) {\r
+                                       WicketUtils.setCssClass(item, "forkSource");\r
                                } else {\r
-                                       // show forks link\r
-                                       item.add(new LinkPanel("anIcon", null, "(" + getString("gb.forks") + ")", ForksPage.class, WicketUtils.newRepositoryParameter(fork.name)));\r
+                                       WicketUtils.setCssClass(item,  "forkEntry");\r
                                }\r
                        }\r
                };\r
                \r
                add(forksList);\r
-\r
        }\r
 \r
        @Override\r
        protected String getPageName() {\r
                return getString("gb.forks");\r
        }\r
+       \r
+       protected List<FlatFork> flatten(ForkModel root) {\r
+               List<FlatFork> list = new ArrayList<FlatFork>();\r
+               list.addAll(flatten(root, 0));\r
+               return list;\r
+       }\r
+       \r
+       protected List<FlatFork> flatten(ForkModel node, int level) {\r
+               List<FlatFork> list = new ArrayList<FlatFork>();\r
+               list.add(new FlatFork(node.repository, level));\r
+               if (!node.isLeaf()) {\r
+                       for (ForkModel fork : node.forks) {\r
+                               list.addAll(flatten(fork, level + 1));\r
+                       }\r
+               }\r
+               return list;\r
+       }\r
+       \r
+       private class FlatFork implements Serializable {\r
+               \r
+               private static final long serialVersionUID = 1L;\r
+\r
+               public final RepositoryModel repository;\r
+               public final int level;\r
+               \r
+               public FlatFork(RepositoryModel repository, int level) {\r
+                       this.repository = repository;\r
+                       this.level = level;\r
+               }\r
+       }\r
 }\r