]> source.dussan.org Git - gitblit.git/commitdiff
Support for gh-pages branch serving as /pages/repo.git
authorJames Moger <james.moger@gitblit.com>
Tue, 10 Jan 2012 01:49:34 +0000 (20:49 -0500)
committerJames Moger <james.moger@gitblit.com>
Tue, 10 Jan 2012 01:49:34 +0000 (20:49 -0500)
14 files changed:
docs/01_features.mkd
docs/04_releases.mkd
src/WEB-INF/web.xml
src/com/gitblit/GitBlit.java
src/com/gitblit/PagesFilter.java [new file with mode: 0644]
src/com/gitblit/PagesServlet.java [new file with mode: 0644]
src/com/gitblit/utils/ArrayUtils.java
src/com/gitblit/utils/JGitUtils.java
src/com/gitblit/wicket/GitBlitWebApp.properties
src/com/gitblit/wicket/PageRegistration.java
src/com/gitblit/wicket/pages/RepositoryPage.java
src/com/gitblit/wicket/panels/LinkPanel.java
src/com/gitblit/wicket/panels/NavigationPanel.java
tests/com/gitblit/tests/GitBlitSuite.java

index a5856a1ca419a5bef0673bcb2361ae87e5d48f21..7eb9e645eb40875217f2dc9f5e6bbbdaa2486dc3 100644 (file)
@@ -19,6 +19,7 @@
 - Repository Owners may edit repositories through the web UI\r
 - Gravatar integration\r
 - Git-notes display support\r
+- gh-pages display support (Jekyll is not supported)\r
 - Branch metrics (uses Google Charts)\r
 - HEAD and Branch RSS feeds\r
 - Blame annotations view\r
index c142f5f43aab717ca1408c61f50a3cd06ebcf6f8..89211cc73d263fb577069377a6b441c03fb733dc 100644 (file)
@@ -33,6 +33,8 @@ The original `users.properties` file and it's corresponding implementation are *
    **New:** *web.allowFlashCopyToClipboard = true*\r
 - JavaScript-based 3-step (click, ctrl+c, enter) *copy to clipboard* of the primary repository url in the event that you do not want to use Flash on your installation\r
 - Empty repositories now link to an *empty repository* page which gives some direction to the user for the next step in using Gitblit.  This page displays the primary push/clone url of the repository and gives sample syntax for the git command-line client. (issue 31)\r
+- automatic *gh-pages* branch serving (Jekyll is not supported)  \r
+Gitblit does not checkout your gh-pages branch to a temporary filesystem, all page and resource requests are live through the repository\r
 - Gitblit Express bundle to get started running Gitblit on RedHat's OpenShift cloud <span class="label warning">BETA</span>\r
 \r
 #### changes\r
index afe4552dd45ae754478b9e88e48172235997a1a6..eef49d4925f4791f57983d2cae1c983dff03297c 100644 (file)
                <servlet-name>RpcServlet</servlet-name>\r
                <url-pattern>/rpc/*</url-pattern>\r
        </servlet-mapping>      \r
+\r
+\r
+       <!-- Pages Servlet\r
+                <url-pattern> MUST match: \r
+                       * PagesFilter\r
+                       * com.gitblit.Constants.PAGES_PATH\r
+                       * Wicket Filter ignorePaths parameter -->\r
+       <servlet>\r
+               <servlet-name>PagesServlet</servlet-name>\r
+               <servlet-class>com.gitblit.PagesServlet</servlet-class>\r
+       </servlet>\r
+       <servlet-mapping>\r
+               <servlet-name>PagesServlet</servlet-name>               \r
+               <url-pattern>/pages/*</url-pattern>\r
+       </servlet-mapping>      \r
        \r
-       \r
+\r
        <!-- Git Access Restriction Filter\r
                 <url-pattern> MUST match: \r
                        * GitServlet\r
                <url-pattern>/rpc/*</url-pattern>\r
        </filter-mapping>\r
 \r
-               \r
+\r
+       <!-- Pges Restriction Filter\r
+                <url-pattern> MUST match: \r
+                       * PagesServlet\r
+                       * com.gitblit.Constants.PAGES_PATH\r
+                       * Wicket Filter ignorePaths parameter -->\r
+       <filter>\r
+               <filter-name>PagesFilter</filter-name>\r
+               <filter-class>com.gitblit.PagesFilter</filter-class>\r
+       </filter>\r
+       <filter-mapping>\r
+               <filter-name>PagesFilter</filter-name>\r
+               <url-pattern>/pages/*</url-pattern>\r
+       </filter-mapping>\r
+\r
+\r
        <!-- Wicket Filter -->\r
     <filter>\r
         <filter-name>wicketFilter</filter-name>\r
                * com.gitblit.Constants.ZIP_PATH\r
                * FederationServlet <url-pattern>\r
                * RpcFilter <url-pattern>\r
-               * RpcServlet <url-pattern> -->\r
-            <param-value>git/,feed/,zip/,federation/,rpc/</param-value>\r
+               * RpcServlet <url-pattern>\r
+               * PagesFilter <url-pattern>\r
+               * PagesServlet <url-pattern>\r
+               * com.gitblit.Constants.PAGES_PATH -->\r
+            <param-value>git/,feed/,zip/,federation/,rpc/,pages/</param-value>\r
         </init-param>\r
     </filter>\r
     <filter-mapping>\r
index ce3e16d6d68f8af29e8a2c4dcc1861656e3534d7..2448f7aee2e0dd4a481efc158a28a0f27d988f1d 100644 (file)
@@ -653,21 +653,38 @@ public class GitBlit implements ServletContextListener {
         * @return repository or null\r
         */\r
        public Repository getRepository(String repositoryName) {\r
+               return getRepository(repositoryName, true);\r
+       }\r
+\r
+       /**\r
+        * Returns the JGit repository for the specified name.\r
+        * \r
+        * @param repositoryName\r
+        * @param logError\r
+        * @return repository or null\r
+        */\r
+       public Repository getRepository(String repositoryName, boolean logError) {\r
                Repository r = null;\r
                try {\r
                        r = repositoryResolver.open(null, repositoryName);\r
                } catch (RepositoryNotFoundException e) {\r
                        r = null;\r
-                       logger.error("GitBlit.getRepository(String) failed to find "\r
-                                       + new File(repositoriesFolder, repositoryName).getAbsolutePath());\r
+                       if (logError) {\r
+                               logger.error("GitBlit.getRepository(String) failed to find "\r
+                                               + new File(repositoriesFolder, repositoryName).getAbsolutePath());\r
+                       }\r
                } catch (ServiceNotAuthorizedException e) {\r
                        r = null;\r
-                       logger.error("GitBlit.getRepository(String) failed to find "\r
-                                       + new File(repositoriesFolder, repositoryName).getAbsolutePath(), e);\r
+                       if (logError) {\r
+                               logger.error("GitBlit.getRepository(String) failed to find "\r
+                                               + new File(repositoriesFolder, repositoryName).getAbsolutePath(), e);\r
+                       }\r
                } catch (ServiceNotEnabledException e) {\r
                        r = null;\r
-                       logger.error("GitBlit.getRepository(String) failed to find "\r
-                                       + new File(repositoriesFolder, repositoryName).getAbsolutePath(), e);\r
+                       if (logError) {\r
+                               logger.error("GitBlit.getRepository(String) failed to find "\r
+                                               + new File(repositoriesFolder, repositoryName).getAbsolutePath(), e);\r
+                       }\r
                }\r
                return r;\r
        }\r
diff --git a/src/com/gitblit/PagesFilter.java b/src/com/gitblit/PagesFilter.java
new file mode 100644 (file)
index 0000000..87fef0d
--- /dev/null
@@ -0,0 +1,103 @@
+/*\r
+ * Copyright 2012 gitblit.com.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package com.gitblit;\r
+\r
+import org.eclipse.jgit.lib.Repository;\r
+\r
+import com.gitblit.Constants.AccessRestrictionType;\r
+import com.gitblit.models.RepositoryModel;\r
+import com.gitblit.models.UserModel;\r
+\r
+/**\r
+ * The PagesFilter is an AccessRestrictionFilter which ensures the gh-pages\r
+ * requests for a view-restricted repository are authenticated and authorized.\r
+ * \r
+ * @author James Moger\r
+ * \r
+ */\r
+public class PagesFilter extends AccessRestrictionFilter {\r
+\r
+       /**\r
+        * Extract the repository name from the url.\r
+        * \r
+        * @param url\r
+        * @return repository name\r
+        */\r
+       @Override\r
+       protected String extractRepositoryName(String url) {            \r
+               // get the repository name from the url by finding a known url suffix\r
+               String repository = "";         \r
+               Repository r = null;\r
+               int offset = 0;\r
+               while (r == null) {\r
+                       int slash = url.indexOf('/', offset);\r
+                       if (slash == -1) {\r
+                               repository = url;\r
+                       } else {\r
+                               repository = url.substring(0, slash);\r
+                       }\r
+                       r = GitBlit.self().getRepository(repository, false);\r
+                       if (r == null) {\r
+                               // try again\r
+                               offset = slash + 1;     \r
+                       } else {\r
+                               // close the repo\r
+                               r.close();\r
+                       }                       \r
+                       if (repository.equals(url)) {\r
+                               // either only repository in url or no repository found\r
+                               break;\r
+                       }\r
+               }\r
+               return repository;\r
+       }\r
+\r
+       /**\r
+        * Analyze the url and returns the action of the request.\r
+        * \r
+        * @param url\r
+        * @return action of the request\r
+        */\r
+       @Override\r
+       protected String getUrlRequestAction(String suffix) {\r
+               return "VIEW";\r
+       }\r
+\r
+       /**\r
+        * Determine if the repository requires authentication.\r
+        * \r
+        * @param repository\r
+        * @return true if authentication required\r
+        */\r
+       @Override\r
+       protected boolean requiresAuthentication(RepositoryModel repository) {\r
+               return repository.accessRestriction.atLeast(AccessRestrictionType.VIEW);\r
+       }\r
+\r
+       /**\r
+        * Determine if the user can access the repository and perform the specified\r
+        * action.\r
+        * \r
+        * @param repository\r
+        * @param user\r
+        * @param action\r
+        * @return true if user may execute the action on the repository\r
+        */\r
+       @Override\r
+       protected boolean canAccess(RepositoryModel repository, UserModel user, String action) {                \r
+               return user.canAccessRepository(repository);\r
+       }\r
+}\r
diff --git a/src/com/gitblit/PagesServlet.java b/src/com/gitblit/PagesServlet.java
new file mode 100644 (file)
index 0000000..58d67b0
--- /dev/null
@@ -0,0 +1,227 @@
+/*\r
+ * Copyright 2012 gitblit.com.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package com.gitblit;\r
+\r
+import java.io.IOException;\r
+import java.text.MessageFormat;\r
+import java.text.ParseException;\r
+\r
+import javax.servlet.ServletContext;\r
+import javax.servlet.ServletException;\r
+import javax.servlet.http.HttpServlet;\r
+import javax.servlet.http.HttpServletRequest;\r
+import javax.servlet.http.HttpServletResponse;\r
+\r
+import org.eclipse.jgit.lib.Repository;\r
+import org.eclipse.jgit.revwalk.RevCommit;\r
+import org.eclipse.jgit.revwalk.RevTree;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+\r
+import com.gitblit.models.RefModel;\r
+import com.gitblit.utils.ArrayUtils;\r
+import com.gitblit.utils.JGitUtils;\r
+import com.gitblit.utils.MarkdownUtils;\r
+import com.gitblit.utils.StringUtils;\r
+\r
+/**\r
+ * Serves the content of a gh-pages branch.\r
+ * \r
+ * @author James Moger\r
+ * \r
+ */\r
+public class PagesServlet extends HttpServlet {\r
+\r
+       private static final long serialVersionUID = 1L;\r
+\r
+       private transient Logger logger = LoggerFactory.getLogger(PagesServlet.class);\r
+\r
+       public PagesServlet() {\r
+               super();\r
+       }\r
+\r
+       /**\r
+        * Returns an url to this servlet for the specified parameters.\r
+        * \r
+        * @param baseURL\r
+        * @param repository\r
+        * @param path\r
+        * @return an url\r
+        */\r
+       public static String asLink(String baseURL, String repository, String path) {\r
+               if (baseURL.length() > 0 && baseURL.charAt(baseURL.length() - 1) == '/') {\r
+                       baseURL = baseURL.substring(0, baseURL.length() - 1);\r
+               }\r
+               return baseURL + Constants.PAGES + repository + "/" + (path == null ? "" : ("/" + path));\r
+       }\r
+\r
+       /**\r
+        * Retrieves the specified resource from the gh-pages branch of the\r
+        * repository.\r
+        * \r
+        * @param request\r
+        * @param response\r
+        * @throws javax.servlet.ServletException\r
+        * @throws java.io.IOException\r
+        */\r
+       private void processRequest(HttpServletRequest request, HttpServletResponse response)\r
+                       throws ServletException, IOException {\r
+               String path = request.getPathInfo();\r
+               if (path.toLowerCase().endsWith(".git")) {\r
+                       // forward to url with trailing /\r
+                       // this is important for relative pages links\r
+                       response.sendRedirect(request.getServletPath() + path + "/");\r
+                       return;\r
+               }\r
+               if (path.charAt(0) == '/') {\r
+                       // strip leading /\r
+                       path = path.substring(1);\r
+               }\r
+\r
+               // determine repository and resource from url\r
+               String repository = "";\r
+               String resource = "";\r
+               Repository r = null;\r
+               int offset = 0;\r
+               while (r == null) {\r
+                       int slash = path.indexOf('/', offset);\r
+                       if (slash == -1) {\r
+                               repository = path;\r
+                       } else {\r
+                               repository = path.substring(0, slash);\r
+                       }\r
+                       r = GitBlit.self().getRepository(repository, false);\r
+                       offset = slash + 1;\r
+                       if (offset > 0) {\r
+                               resource = path.substring(offset);\r
+                       }\r
+                       if (repository.equals(path)) {\r
+                               // either only repository in url or no repository found\r
+                               break;\r
+                       }\r
+               }\r
+\r
+               ServletContext context = request.getSession().getServletContext();\r
+\r
+               try {\r
+                       if (r == null) {\r
+                               // repository not found!\r
+                               String mkd = MessageFormat.format(\r
+                                               "# Error\nSorry, no valid **repository** specified in this url: {0}!",\r
+                                               repository);\r
+                               error(response, mkd);\r
+                               return;\r
+                       }\r
+\r
+                       // retrieve the content from the repository\r
+                       RefModel pages = JGitUtils.getPagesBranch(r);\r
+                       RevCommit commit = JGitUtils.getCommit(r, pages.getObjectId().getName());\r
+\r
+                       if (commit == null) {\r
+                               // branch not found!\r
+                               String mkd = MessageFormat.format(\r
+                                               "# Error\nSorry, the repository {0} does not have a **gh-pages** branch!",\r
+                                               repository);\r
+                               error(response, mkd);\r
+                               r.close();\r
+                               return;\r
+                       }\r
+                       response.setDateHeader("Last-Modified", JGitUtils.getCommitDate(commit).getTime());\r
+\r
+                       RevTree tree = commit.getTree();\r
+                       byte[] content = null;\r
+                       if (StringUtils.isEmpty(resource)) {\r
+                               // find resource\r
+                               String[] files = { "index.html", "index.htm", "index.mkd" };\r
+                               for (String file : files) {\r
+                                       content = JGitUtils.getStringContent(r, tree, file)\r
+                                                       .getBytes(Constants.ENCODING);\r
+                                       if (content != null) {\r
+                                               resource = file;\r
+                                               // assume text/html unless the servlet container\r
+                                               // overrides\r
+                                               response.setContentType("text/html; charset=" + Constants.ENCODING);\r
+                                               break;\r
+                                       }\r
+                               }\r
+                       } else {\r
+                               // specific resource\r
+                               String contentType = context.getMimeType(resource);\r
+                               if (contentType.startsWith("text")) {\r
+                                       content = JGitUtils.getStringContent(r, tree, resource).getBytes(\r
+                                                       Constants.ENCODING);\r
+                               } else {\r
+                                       content = JGitUtils.getByteContent(r, tree, resource);\r
+                               }\r
+                               response.setContentType(contentType);\r
+                       }\r
+\r
+                       // no content, try custom 404 page\r
+                       if (ArrayUtils.isEmpty(content)) {\r
+                               content = JGitUtils.getStringContent(r, tree, "404.html").getBytes(\r
+                                               Constants.ENCODING);\r
+                               // still no content\r
+                               if (ArrayUtils.isEmpty(content)) {\r
+                                       content = (MessageFormat.format(\r
+                                                       "# Error\nSorry, the requested resource **{0}** was not found.",\r
+                                                       resource)).getBytes(Constants.ENCODING);\r
+                                       resource = "404.mkd";\r
+                               }\r
+                       }\r
+\r
+                       // check to see if we should transform markdown files\r
+                       for (String ext : GitBlit.getStrings(Keys.web.markdownExtensions)) {\r
+                               if (resource.endsWith(ext)) {\r
+                                       String mkd = new String(content, Constants.ENCODING);\r
+                                       content = MarkdownUtils.transformMarkdown(mkd).getBytes(Constants.ENCODING);\r
+                                       break;\r
+                               }\r
+                       }\r
+\r
+                       try {\r
+                               // output the content\r
+                               response.getOutputStream().write(content);\r
+                               response.flushBuffer();\r
+                       } catch (Throwable t) {\r
+                               logger.error("Failed to write page to client", t);\r
+                       }\r
+\r
+                       // close the repository\r
+                       r.close();\r
+               } catch (Throwable t) {\r
+                       logger.error("Failed to write page to client", t);\r
+               }\r
+       }\r
+\r
+       private void error(HttpServletResponse response, String mkd) throws ServletException,\r
+                       IOException, ParseException {\r
+               String content = MarkdownUtils.transformMarkdown(mkd);\r
+               response.setContentType("text/html; charset=" + Constants.ENCODING);\r
+               response.getWriter().write(content);\r
+       }\r
+\r
+       @Override\r
+       protected void doPost(HttpServletRequest request, HttpServletResponse response)\r
+                       throws ServletException, IOException {\r
+               processRequest(request, response);\r
+       }\r
+\r
+       @Override\r
+       protected void doGet(HttpServletRequest request, HttpServletResponse response)\r
+                       throws ServletException, IOException {\r
+               processRequest(request, response);\r
+       }\r
+}\r
index 635d27ab4c1f6821be3d87d68f1b421e2acdc46a..d0322b6b7751bff3fc4296b89ab477eefbff3b31 100644 (file)
@@ -26,6 +26,10 @@ import java.util.Collection;
  */\r
 public class ArrayUtils {\r
 \r
+       public static boolean isEmpty(byte [] array) {\r
+               return array == null || array.length == 0;\r
+       }\r
+       \r
        public static boolean isEmpty(Object [] array) {\r
                return array == null || array.length == 0;\r
        }\r
index d694ee289819b2b184a60895f4a8d34bfd5a6fc2..ae53c942e0c71ae2388574cb7dbb0362fde77e78 100644 (file)
@@ -1283,6 +1283,39 @@ public class JGitUtils {
                return list;\r
        }\r
 \r
+       /**\r
+        * Returns a RefModel for the gh-pages branch in the repository. If the\r
+        * branch can not be found, null is returned.\r
+        * \r
+        * @param repository\r
+        * @return a refmodel for the gh-pages branch or null\r
+        */\r
+       public static RefModel getPagesBranch(Repository repository) {\r
+               RefModel ghPages = null;\r
+               try {\r
+                       // search for gh-pages branch in local heads\r
+                       for (RefModel ref : JGitUtils.getLocalBranches(repository, false, -1)) {\r
+                               if (ref.displayName.endsWith("gh-pages")) {\r
+                                       ghPages = ref;\r
+                                       break;\r
+                               }\r
+                       }\r
+\r
+                       // search for gh-pages branch in remote heads\r
+                       if (ghPages == null) {\r
+                               for (RefModel ref : JGitUtils.getRemoteBranches(repository, false, -1)) {\r
+                                       if (ref.displayName.endsWith("gh-pages")) {\r
+                                               ghPages = ref;\r
+                                               break;\r
+                                       }\r
+                               }\r
+                       }\r
+               } catch (Throwable t) {\r
+                       LOGGER.error("Failed to find gh-pages branch!", t);\r
+               }\r
+               return ghPages;\r
+       }\r
+\r
        /**\r
         * Returns the list of notes entered about the commit from the refs/notes\r
         * namespace. If the repository does not exist or is empty, an empty list is\r
index 2abc5479eaa1ef9516c4a99f34c0519449914f58..713fee701b64696ef4077b8d0df15391cfb4ca20 100644 (file)
@@ -208,4 +208,5 @@ gb.accessPermissionsForUserDescription = set team memberships or grant access to
 gb.accessPermissionsForTeamDescription = set team members and grant access to specific restricted repositories\r
 gb.federationRepositoryDescription = share this repository with other Gitblit servers\r
 gb.hookScriptsDescription = run Groovy scripts on pushes to this Gitblit server\r
-gb.reset = reset
\ No newline at end of file
+gb.reset = reset\r
+gb.pages = pages
\ No newline at end of file
index fe76a85fc1b93fb5772be9d77b636447148effe0..e8eeabae816fa49b61b91b08418fd05555cd7d98 100644 (file)
@@ -48,6 +48,24 @@ public class PageRegistration implements Serializable {
                this.params = params;\r
        }\r
 \r
+       /**\r
+        * Represents a page link to a non-Wicket page. Might be external.\r
+        * \r
+        * @author James Moger\r
+        * \r
+        */\r
+       public static class OtherPageLink extends PageRegistration {\r
+\r
+               private static final long serialVersionUID = 1L;\r
+\r
+               public final String url;\r
+\r
+               public OtherPageLink(String translationKey, String url) {\r
+                       super(translationKey, null);\r
+                       this.url = url;\r
+               }\r
+       }\r
+\r
        /**\r
         * Represents a DropDownMenu for the topbar\r
         * \r
index c84ccb0671904b0466e5002f38db54fdd7028e17..5f544012274281e8cbfca096eab8699c93ac9f8b 100644 (file)
@@ -41,6 +41,7 @@ import org.eclipse.jgit.revwalk.RevCommit;
 import com.gitblit.Constants;\r
 import com.gitblit.GitBlit;\r
 import com.gitblit.Keys;\r
+import com.gitblit.PagesServlet;\r
 import com.gitblit.SyndicationServlet;\r
 import com.gitblit.models.RepositoryModel;\r
 import com.gitblit.utils.JGitUtils;\r
@@ -48,6 +49,7 @@ import com.gitblit.utils.StringUtils;
 import com.gitblit.utils.TicgitUtils;\r
 import com.gitblit.wicket.GitBlitWebSession;\r
 import com.gitblit.wicket.PageRegistration;\r
+import com.gitblit.wicket.PageRegistration.OtherPageLink;\r
 import com.gitblit.wicket.WicketUtils;\r
 import com.gitblit.wicket.panels.LinkPanel;\r
 import com.gitblit.wicket.panels.NavigationPanel;\r
@@ -123,6 +125,12 @@ public abstract class RepositoryPage extends BasePage {
                if (model.useDocs) {\r
                        pages.put("docs", new PageRegistration("gb.docs", DocsPage.class, params));\r
                }\r
+               if (JGitUtils.getPagesBranch(r) != null) {\r
+                       OtherPageLink pagesLink = new OtherPageLink("gb.pages", PagesServlet.asLink(\r
+                                       getRequest().getRelativePathPrefixToContextRoot(), repositoryName, null));\r
+                       pages.put("pages", pagesLink);\r
+               }\r
+\r
                // Conditionally add edit link\r
                final boolean showAdmin;\r
                if (GitBlit.getBoolean(Keys.web.authenticateAdminPages, true)) {\r
@@ -141,9 +149,9 @@ public abstract class RepositoryPage extends BasePage {
        }\r
 \r
        @Override\r
-       protected void setupPage(String repositoryName, String pageName) {              \r
-               add(new LinkPanel("repositoryName", null, StringUtils.stripDotGit(repositoryName), SummaryPage.class,\r
-                               WicketUtils.newRepositoryParameter(repositoryName)));\r
+       protected void setupPage(String repositoryName, String pageName) {\r
+               add(new LinkPanel("repositoryName", null, StringUtils.stripDotGit(repositoryName),\r
+                               SummaryPage.class, WicketUtils.newRepositoryParameter(repositoryName)));\r
                add(new Label("pageName", pageName));\r
 \r
                super.setupPage(repositoryName, pageName);\r
@@ -245,7 +253,8 @@ public abstract class RepositoryPage extends BasePage {
                }\r
        }\r
 \r
-       protected void setPersonSearchTooltip(Component component, String value, Constants.SearchType searchType) {\r
+       protected void setPersonSearchTooltip(Component component, String value,\r
+                       Constants.SearchType searchType) {\r
                if (searchType.equals(Constants.SearchType.AUTHOR)) {\r
                        WicketUtils.setHtmlTooltip(component, getString("gb.searchForAuthor") + " " + value);\r
                } else if (searchType.equals(Constants.SearchType.COMMITTER)) {\r
@@ -302,13 +311,14 @@ public abstract class RepositoryPage extends BasePage {
 \r
                private final IModel<String> searchBoxModel = new Model<String>("");\r
 \r
-               private final IModel<Constants.SearchType> searchTypeModel = new Model<Constants.SearchType>(Constants.SearchType.COMMIT);\r
+               private final IModel<Constants.SearchType> searchTypeModel = new Model<Constants.SearchType>(\r
+                               Constants.SearchType.COMMIT);\r
 \r
                public SearchForm(String id, String repositoryName) {\r
                        super(id);\r
                        this.repositoryName = repositoryName;\r
-                       DropDownChoice<Constants.SearchType> searchType = new DropDownChoice<Constants.SearchType>("searchType",\r
-                                       Arrays.asList(Constants.SearchType.values()));\r
+                       DropDownChoice<Constants.SearchType> searchType = new DropDownChoice<Constants.SearchType>(\r
+                                       "searchType", Arrays.asList(Constants.SearchType.values()));\r
                        searchType.setModel(searchTypeModel);\r
                        add(searchType.setVisible(GitBlit.getBoolean(Keys.web.showSearchTypeSelection, false)));\r
                        TextField<String> searchBox = new TextField<String>("searchBox", searchBoxModel);\r
index 2872d4bf3bc0dd4a8a24e63f738ca96e9e1aff41..16b8cd46aa40d4c65d7b86487a4f192ea94d0991 100644 (file)
@@ -20,6 +20,7 @@ import org.apache.wicket.behavior.SimpleAttributeModifier;
 import org.apache.wicket.markup.html.WebPage;\r
 import org.apache.wicket.markup.html.basic.Label;\r
 import org.apache.wicket.markup.html.link.BookmarkablePageLink;\r
+import org.apache.wicket.markup.html.link.ExternalLink;\r
 import org.apache.wicket.markup.html.link.Link;\r
 import org.apache.wicket.markup.html.panel.Panel;\r
 import org.apache.wicket.model.IModel;\r
@@ -71,4 +72,23 @@ public class LinkPanel extends Panel {
                add(link);\r
        }\r
 \r
+       public LinkPanel(String wicketId, String linkCssClass, String label, String href) {\r
+               this(wicketId, linkCssClass, label, href, false);\r
+       }\r
+\r
+       public LinkPanel(String wicketId, String linkCssClass, String label, String href,\r
+                       boolean newWindow) {\r
+               super(wicketId);\r
+               this.labelModel = new Model<String>(label);\r
+               ExternalLink link = new ExternalLink("link", href);\r
+               if (newWindow) {\r
+                       link.add(new SimpleAttributeModifier("target", "_blank"));\r
+               }\r
+               if (linkCssClass != null) {\r
+                       link.add(new SimpleAttributeModifier("class", linkCssClass));\r
+               }\r
+               link.add(new Label("label", labelModel));\r
+               add(link);\r
+       }\r
+\r
 }\r
index 018bbb2fa4c9981dc0e71cc716faad5098cc46c1..57c82e80aacf1a60eed94ed282f589b4a29749e8 100644 (file)
@@ -25,6 +25,7 @@ import org.apache.wicket.markup.repeater.data.ListDataProvider;
 \r
 import com.gitblit.wicket.PageRegistration;\r
 import com.gitblit.wicket.PageRegistration.DropDownMenuRegistration;\r
+import com.gitblit.wicket.PageRegistration.OtherPageLink;\r
 import com.gitblit.wicket.WicketUtils;\r
 import com.gitblit.wicket.pages.BasePage;\r
 \r
@@ -43,7 +44,12 @@ public class NavigationPanel extends Panel {
 \r
                        public void populateItem(final Item<PageRegistration> item) {\r
                                PageRegistration entry = item.getModelObject();\r
-                               if (entry instanceof DropDownMenuRegistration) {\r
+                               if (entry instanceof OtherPageLink) {\r
+                                       // other link\r
+                                       OtherPageLink link = (OtherPageLink) entry;\r
+                                       Component c = new LinkPanel("link", null, getString(entry.translationKey), link.url);\r
+                                       item.add(c);\r
+                               } else if (entry instanceof DropDownMenuRegistration) {\r
                                        // drop down menu\r
                                        DropDownMenuRegistration reg = (DropDownMenuRegistration) entry;\r
                                        Component c = new DropDownMenu("link", getString(entry.translationKey), reg);\r
index f697c17894904377d517b39c90189d71c37ecb28..71947e14a71bd3df74f808caca9921411810aae5 100644 (file)
@@ -82,6 +82,14 @@ public class GitBlitSuite {
                return new FileRepository(new File(REPOSITORIES, "test/bluez-gnome.git"));\r
        }\r
 \r
+       public static Repository getAmbitionRepository() throws Exception {\r
+               return new FileRepository(new File(REPOSITORIES, "test/ambition.git"));\r
+       }\r
+\r
+       public static Repository getTheoreticalPhysicsRepository() throws Exception {\r
+               return new FileRepository(new File(REPOSITORIES, "test/theoretical-physics.git"));\r
+       }\r
+\r
        public static boolean startGitblit() throws Exception {\r
                if (started.get()) {\r
                        // already started\r
@@ -123,7 +131,9 @@ public class GitBlitSuite {
                                        "https://git.kernel.org/pub/scm/bluetooth/bluez-gnome.git");\r
                        cloneOrFetch("test/jgit.git", "https://github.com/eclipse/jgit.git");\r
                        cloneOrFetch("test/helloworld.git", "https://github.com/git/hello-world.git");\r
-\r
+                       cloneOrFetch("test/ambition.git", "https://github.com/defunkt/ambition.git");\r
+                       cloneOrFetch("test/theoretical-physics.git", "https://github.com/certik/theoretical-physics.git");\r
+                       \r
                        enableTickets("ticgit.git");\r
                        enableDocs("ticgit.git");\r
                        showRemoteBranches("ticgit.git");\r