]> source.dussan.org Git - gitblit.git/commitdiff
Partially merged url panel with optional support for app clone urls
authorJames Moger <james.moger@gitblit.com>
Fri, 3 May 2013 23:27:25 +0000 (19:27 -0400)
committerJames Moger <james.moger@gitblit.com>
Fri, 3 May 2013 23:27:25 +0000 (19:27 -0400)
14 files changed:
releases.moxie
src/main/distrib/data/gitblit.properties
src/main/java/com/gitblit/GitBlitServer.java
src/main/java/com/gitblit/wicket/GitBlitWebApp.properties
src/main/java/com/gitblit/wicket/pages/BasePage.java
src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage.java
src/main/java/com/gitblit/wicket/pages/SummaryPage.html
src/main/java/com/gitblit/wicket/pages/SummaryPage.java
src/main/java/com/gitblit/wicket/panels/BasePanel.java
src/main/java/com/gitblit/wicket/panels/ProjectRepositoryPanel.java
src/main/java/com/gitblit/wicket/panels/RepositoryUrlPanel.html
src/main/java/com/gitblit/wicket/panels/RepositoryUrlPanel.java
src/main/java/com/gitblit/wicket/panels/SparkleShareInvitePanel.html [deleted file]
src/main/java/com/gitblit/wicket/panels/SparkleShareInvitePanel.java [deleted file]

index 7c0ec8f4896f99d29e5031fe66a1bc16c47f212e..53aef4bcbd6a937fa77c397ef7beb42191cb9fc6 100644 (file)
@@ -26,6 +26,7 @@ r17: {
         - Use standard ServletRequestWrapper instead of custom wrapper (issue 224)\r
 \r
        changes:\r
+        - Improved the repository url display.  This display now indicates your repository access permission, per-protocol.\r
         - Improve Gerrit change ref decoration in the refs panel (issue 206)\r
         - Disable Gson's pretty printing which has a huge performance gain\r
         - Properly set application/json content-type on api calls\r
@@ -33,7 +34,8 @@ r17: {
         - Updated Japanese translation\r
         \r
     additions: \r
-        - Added GO http/https connector thread pool size setting
+        - Added 3rd-party app clone links for SourceTree and SparkleShare\r
+        - Added GO http/https connector thread pool size setting\r
         - Added a server setting to force a particular translation/Locale for all sessions\r
         - Added smart Git Daemon serving.  If enabled, git:// access will be offered for any repository which permits anonymous access.  If the repository permits anonymous cloning, anonymous git:// clone will be permitted while anonmymous git:// pushes will be rejected.
         - Option to automatically tag branch tips on each push with an incremental revision number\r
@@ -81,8 +83,9 @@ r17: {
        - { name: 'git.daemonBindInterface', defaultValue: 'localhost' }\r
        - { name: 'git.daemonPort', defaultValue: 0 }\r
     - { name: 'git.defaultIncrementalPushTagPrefix', defaultValue: 'r' }\r
+       - { name: 'web.allowAppCloneLinks', defaultValue: true }\r
        - { name: 'web.forceDefaultLocale', defaultValue: ' ' }\r
-       - { name: 'server.nioThreadPoolSize', defaultValue: 50 }
+       - { name: 'server.nioThreadPoolSize', defaultValue: 50 }\r
 }\r
 \r
 #\r
index 43185f57c677eb49acbef90756372982da32b167..bfdc3e8b2ffe032ce74d5209a08a298a162bdb1a 100644 (file)
@@ -766,6 +766,11 @@ web.forwardSlashCharacter = /
 # SINCE 0.5.0\r
 web.otherUrls = \r
 \r
+# Should app-specific clone links be displayed for SourceTree, SparkleShare, etc?\r
+#\r
+# SINCE 1.3.0\r
+web.allowAppCloneLinks = true\r
+\r
 # Choose how to present the repositories list.\r
 #   grouped = group nested/subfolder repositories together (no sorting)\r
 #   flat = flat list of repositories (sorting allowed)\r
@@ -1250,13 +1255,13 @@ server.tempFolder = ${baseFolder}/temp
 # RESTART REQUIRED\r
 server.useNio = true\r
 \r
-# If using Jetty NIO connectors, specify the maximum number of concurrent
-# http/https worker threads to allow.
-#
-# SINCE 1.3.0
-# RESTART REQUIRED
-server.nioThreadPoolSize = 50
-
+# If using Jetty NIO connectors, specify the maximum number of concurrent\r
+# http/https worker threads to allow. \r
+#\r
+# SINCE 1.3.0\r
+# RESTART REQUIRED\r
+server.nioThreadPoolSize = 50\r
+\r
 # Context path for the GO application.  You might want to change the context\r
 # path if running Gitblit behind a proxy layer such as mod_proxy.\r
 #\r
index a41b8a2c0ab5bcef74e54151780e121480437beb..2c558be7f48ca4b124523887ffb318ad4abfbb34 100644 (file)
@@ -203,7 +203,7 @@ public class GitBlitServer {
 \r
                // conditionally configure the http connector\r
                if (params.port > 0) {\r
-                       Connector httpConnector = createConnector(params.useNIO, settings.getInteger(Keys.server.nioThreadPoolSize, 50), params.port);
+                       Connector httpConnector = createConnector(params.useNIO, settings.getInteger(Keys.server.nioThreadPoolSize, 50), params.port);\r
                        String bindInterface = settings.getString(Keys.server.httpBindInterface, null);\r
                        if (!StringUtils.isEmpty(bindInterface)) {\r
                                logger.warn(MessageFormat.format("Binding connector on port {0,number,0} to {1}",\r
@@ -262,7 +262,7 @@ public class GitBlitServer {
 \r
                        if (serverKeyStore.exists()) {                  \r
                                Connector secureConnector = createSSLConnector(params.alias, serverKeyStore, serverTrustStore, params.storePassword,\r
-                                               caRevocationList, params.useNIO, settings.getInteger(Keys.server.nioThreadPoolSize, 50), params.securePort, params.requireClientCertificates);
+                                               caRevocationList, params.useNIO, settings.getInteger(Keys.server.nioThreadPoolSize, 50), params.securePort, params.requireClientCertificates);\r
                                String bindInterface = settings.getString(Keys.server.httpsBindInterface, null);\r
                                if (!StringUtils.isEmpty(bindInterface)) {\r
                                        logger.warn(MessageFormat.format(\r
@@ -410,16 +410,16 @@ public class GitBlitServer {
         * \r
         * @param useNIO\r
         * @param port\r
-        * @param maxThreads
+        * @param maxThreads\r
         * @return an http connector\r
         */\r
-       private Connector createConnector(boolean useNIO, int port, int maxThreads) {
+       private Connector createConnector(boolean useNIO, int port, int maxThreads) {\r
                Connector connector;\r
                if (useNIO) {\r
                        logger.info("Setting up NIO SelectChannelConnector on port " + port);\r
                        SelectChannelConnector nioconn = new SelectChannelConnector();\r
                        nioconn.setSoLingerTime(-1);\r
-                       nioconn.setThreadPool(new QueuedThreadPool(maxThreads));
+                       nioconn.setThreadPool(new QueuedThreadPool(maxThreads));\r
                        connector = nioconn;\r
                } else {\r
                        logger.info("Setting up SocketConnector on port " + port);\r
@@ -444,13 +444,13 @@ public class GitBlitServer {
         * @param storePassword\r
         * @param caRevocationList\r
         * @param useNIO\r
-        * @param nioThreadPoolSize
+        * @param nioThreadPoolSize\r
         * @param port\r
         * @param requireClientCertificates\r
         * @return an https connector\r
         */\r
        private Connector createSSLConnector(String certAlias, File keyStore, File clientTrustStore,\r
-                       String storePassword, File caRevocationList, boolean useNIO,  int nioThreadPoolSize, int port,
+                       String storePassword, File caRevocationList, boolean useNIO,  int nioThreadPoolSize, int port,\r
                        boolean requireClientCertificates) {\r
                GitblitSslContextFactory factory = new GitblitSslContextFactory(certAlias,\r
                                keyStore, clientTrustStore, storePassword, caRevocationList);\r
@@ -464,7 +464,7 @@ public class GitBlitServer {
                        } else {\r
                                factory.setWantClientAuth(true);\r
                        }\r
-                       ssl.setThreadPool(new QueuedThreadPool(nioThreadPoolSize));
+                       ssl.setThreadPool(new QueuedThreadPool(nioThreadPoolSize));\r
                        connector = ssl;\r
                } else {\r
                        logger.info("Setting up NIO SslSocketConnector on port " + port);\r
index 049cc4089de5853195083ea274bd63583e6a17e5..4752e99d3cdf404df0eac9d57ab046a96b02133d 100644 (file)
@@ -452,4 +452,7 @@ gb.incrementalPushTagMessage = Auto-tagged [{0}] branch on push
 gb.externalPermissions = {0} access permissions for {1} are externally maintained\r
 gb.viewAccess = You do not have Gitblit read or write access\r
 gb.yourProtocolPermissionIs = Your {0} access permission for {1} is {2}\r
-gb.sparkleshareInvite = SparkleShare invite
\ No newline at end of file
+gb.cloneWithSparkleShare = clone with SparkleShare\u2122\r
+gb.cloneWithSourceTree = clone with SourceTree\u2122\r
+gb.cloneWithGitHub = clone with GitHub\u2122 for {0}\r
+gb.cloneWithSmartGit = clone with SmartGit\u2122
\ No newline at end of file
index b3b0767bbf8b880f47182252c8154f92d2aae9be..19fa7493e4aa73f619b701f9393d21a1549f8d50 100644 (file)
@@ -57,7 +57,6 @@ import com.gitblit.Constants.AuthorizationControl;
 import com.gitblit.Constants.FederationStrategy;\r
 import com.gitblit.GitBlit;\r
 import com.gitblit.Keys;\r
-import com.gitblit.SparkleShareInviteServlet;\r
 import com.gitblit.models.ProjectModel;\r
 import com.gitblit.models.RepositoryModel;\r
 import com.gitblit.models.TeamModel;\r
@@ -313,32 +312,6 @@ public abstract class BasePage extends SessionPage {
                }\r
        }\r
 \r
-       protected String getSparkleShareInviteUrl(RepositoryModel repository) {\r
-               if (repository.isBare && repository.isSparkleshared()) {\r
-                       UserModel user = GitBlitWebSession.get().getUser();\r
-                       if (user == null) {\r
-                               user = UserModel.ANONYMOUS;\r
-                       }\r
-                       String username = null;\r
-                       if (UserModel.ANONYMOUS != user) {\r
-                               username = user.username;\r
-                       }\r
-                       if (GitBlit.getBoolean(Keys.git.enableGitServlet, true) || (GitBlit.getInteger(Keys.git.daemonPort, 0) > 0)) {\r
-                               // Gitblit as server\r
-                               // ensure user can rewind\r
-                               if (user.canRewindRef(repository)) {\r
-                                       String baseURL = WicketUtils.getGitblitURL(RequestCycle.get().getRequest());\r
-                                       return SparkleShareInviteServlet.asLink(baseURL, repository.name, username);\r
-                               }\r
-                       } else {\r
-                               // Gitblit as viewer, assume RW+ permission\r
-                               String baseURL = WicketUtils.getGitblitURL(RequestCycle.get().getRequest());\r
-                               return SparkleShareInviteServlet.asLink(baseURL, repository.name, username);\r
-                       }\r
-               }\r
-               return null;\r
-       }\r
-\r
        protected List<ProjectModel> getProjectModels() {\r
                final UserModel user = GitBlitWebSession.get().getUser();\r
                List<ProjectModel> projects = GitBlit.self().getProjectModels(user, true);\r
index a2264c44d48206d275b59a74aa09e4462c17b0a1..f7e8848917e10b2d6a44a09b8bc14e420f3df146 100644 (file)
 package com.gitblit.wicket.pages;\r
 \r
 import java.text.MessageFormat;\r
-import java.util.ArrayList;\r
-import java.util.List;\r
 \r
 import org.apache.wicket.PageParameters;\r
 import org.apache.wicket.markup.html.basic.Label;\r
 \r
-import com.gitblit.Constants.AccessPermission;\r
 import com.gitblit.GitBlit;\r
-import com.gitblit.Keys;\r
 import com.gitblit.models.RepositoryModel;\r
 import com.gitblit.models.UserModel;\r
-import com.gitblit.utils.ArrayUtils;\r
 import com.gitblit.wicket.GitBlitWebSession;\r
 import com.gitblit.wicket.GitblitRedirectException;\r
 import com.gitblit.wicket.WicketUtils;\r
-import com.gitblit.wicket.panels.DetailedRepositoryUrlPanel;\r
+import com.gitblit.wicket.panels.RepositoryUrlPanel;\r
 \r
 public class EmptyRepositoryPage extends RootPage {\r
 \r
@@ -53,24 +48,17 @@ public class EmptyRepositoryPage extends RootPage {
                \r
                setupPage(repositoryName, getString("gb.emptyRepository"));\r
 \r
-               List<String> repositoryUrls = new ArrayList<String>();\r
-\r
-               if (GitBlit.getBoolean(Keys.git.enableGitServlet, true)) {\r
-                       // add the Gitblit repository url\r
-                       repositoryUrls.add(getRepositoryUrl(repository));\r
-               }\r
                UserModel user = GitBlitWebSession.get().getUser();\r
                if (user == null) {\r
                        user = UserModel.ANONYMOUS;\r
                }\r
-               repositoryUrls.addAll(GitBlit.self().getOtherCloneUrls(repositoryName, UserModel.ANONYMOUS.equals(user) ? "" : user.username));\r
                \r
-               String primaryUrl = ArrayUtils.isEmpty(repositoryUrls) ? "" : repositoryUrls.get(0);\r
-               AccessPermission accessPermission = user.getRepositoryPermission(repository).permission;\r
+               RepositoryUrlPanel urlPanel = new RepositoryUrlPanel("pushurl", false, user, repository, getLocalizer(), this);\r
+               String primaryUrl = urlPanel.getPrimaryUrl();\r
                \r
                add(new Label("repository", repositoryName));\r
-               add(new DetailedRepositoryUrlPanel("pushurl", getLocalizer(), this, repository.name, primaryUrl, accessPermission));\r
-               add(new Label("cloneSyntax", MessageFormat.format("git clone {0}", repositoryUrls.get(0))));\r
+               add(urlPanel);\r
+               add(new Label("cloneSyntax", MessageFormat.format("git clone {0}", primaryUrl)));\r
                add(new Label("remoteSyntax", MessageFormat.format("git remote add gitblit {0}\ngit push gitblit master", primaryUrl)));\r
        }\r
 }\r
index c9bce4017f483f04eb5c37c14f11d5287acda80b..a20ad2f0db4990a93e947a0ed241e87d2b60bcd3 100644 (file)
                                <tr><th><wicket:message key="gb.stats">[stats]</wicket:message></th><td><span wicket:id="branchStats">[branch stats]</span> <span class="link"><a wicket:id="metrics"><wicket:message key="gb.metrics">[metrics]</wicket:message></a></span></td></tr>\r
                                <tr><th style="vertical-align:top;padding-top:4px;"><wicket:message key="gb.repositoryUrl">[URL]</wicket:message>&nbsp;<img style="vertical-align: top;padding-left:3px;" wicket:id="accessRestrictionIcon" /></th>\r
                                    <td style="padding-top:4px;">\r
-                                       <div wicket:id="repositoryPrimaryUrl">[repository primary url]</div>\r
-                                       <div wicket:id="repositoryGitDaemonUrl">[repository git daemon url]</div>\r
+                                       <div wicket:id="repositoryUrlPanel">[repository url panel]</div>\r
                                        <div wicket:id="otherUrls" >\r
                                                <div wicket:id="otherUrl" style="padding-top:10px"></div>\r
                                        </div>\r
-                                       <div wicket:id="repositorySparkleShareInviteUrl">[repository sparkleshare invite url]</div>\r
                                    </td>\r
                                </tr>\r
                        </table>\r
index f092a387e85c941b3c205ea65522d13307e4606c..7588a9332a36f70a42439cbd3d3a4338f24e79a5 100644 (file)
@@ -42,7 +42,6 @@ import org.wicketstuff.googlecharts.LineStyle;
 import org.wicketstuff.googlecharts.MarkerType;\r
 import org.wicketstuff.googlecharts.ShapeMarker;\r
 \r
-import com.gitblit.Constants.AccessPermission;\r
 import com.gitblit.Constants.AccessRestrictionType;\r
 import com.gitblit.GitBlit;\r
 import com.gitblit.Keys;\r
@@ -50,7 +49,6 @@ import com.gitblit.models.Metric;
 import com.gitblit.models.PathModel;\r
 import com.gitblit.models.RepositoryModel;\r
 import com.gitblit.models.UserModel;\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
@@ -60,7 +58,7 @@ import com.gitblit.wicket.panels.BranchesPanel;
 import com.gitblit.wicket.panels.DetailedRepositoryUrlPanel;\r
 import com.gitblit.wicket.panels.LinkPanel;\r
 import com.gitblit.wicket.panels.LogPanel;\r
-import com.gitblit.wicket.panels.SparkleShareInvitePanel;\r
+import com.gitblit.wicket.panels.RepositoryUrlPanel;\r
 import com.gitblit.wicket.panels.TagsPanel;\r
 \r
 public class SummaryPage extends RepositoryPage {\r
@@ -127,11 +125,7 @@ public class SummaryPage extends RepositoryPage {
                add(new BookmarkablePageLink<Void>("metrics", MetricsPage.class,\r
                                WicketUtils.newRepositoryParameter(repositoryName)));\r
 \r
-               List<String> repositoryUrls = new ArrayList<String>();\r
-\r
-               AccessPermission accessPermission = null;\r
                if (GitBlit.getBoolean(Keys.git.enableGitServlet, true)) {                      \r
-                       accessPermission = user.getRepositoryPermission(model).permission;\r
                        AccessRestrictionType accessRestriction = getRepositoryModel().accessRestriction;\r
                        switch (accessRestriction) {\r
                        case NONE:\r
@@ -152,32 +146,14 @@ public class SummaryPage extends RepositoryPage {
                        default:\r
                                add(WicketUtils.newClearPixel("accessRestrictionIcon").setVisible(false));\r
                        }\r
-                       // add the Gitblit repository url\r
-                       repositoryUrls.add(getRepositoryUrl(getRepositoryModel()));\r
                } else {\r
                        add(WicketUtils.newClearPixel("accessRestrictionIcon").setVisible(false));\r
                }\r
-               repositoryUrls.addAll(GitBlit.self().getOtherCloneUrls(repositoryName, UserModel.ANONYMOUS.equals(user) ? "" : user.username));\r
-               \r
-               String primaryUrl = ArrayUtils.isEmpty(repositoryUrls) ? "" : repositoryUrls.remove(0);\r
-               add(new DetailedRepositoryUrlPanel("repositoryPrimaryUrl", getLocalizer(), this, model.name, primaryUrl, accessPermission));\r
-\r
-               Component gitDaemonUrlPanel = createGitDaemonUrlPanel("repositoryGitDaemonUrl", user, model);\r
-               if (!StringUtils.isEmpty(primaryUrl) && gitDaemonUrlPanel instanceof DetailedRepositoryUrlPanel) {\r
-                       WicketUtils.setCssStyle(gitDaemonUrlPanel, "padding-top: 10px");\r
-               }\r
-               add(gitDaemonUrlPanel);\r
                \r
-               String sparkleshareUrl = getSparkleShareInviteUrl(model);\r
-               if (StringUtils.isEmpty(sparkleshareUrl)) {\r
-                       add(new Label("repositorySparkleShareInviteUrl").setVisible(false));\r
-               } else {\r
-                       Component sparklesharePanel = new SparkleShareInvitePanel("repositorySparkleShareInviteUrl", getLocalizer(), this, sparkleshareUrl, accessPermission);\r
-                       WicketUtils.setCssStyle(sparklesharePanel, "padding-top: 10px;");\r
-                       add(sparklesharePanel);\r
-               }\r
-\r
-               ListDataProvider<String> urls = new ListDataProvider<String>(repositoryUrls);\r
+               add(new RepositoryUrlPanel("repositoryUrlPanel", false, user, model, getLocalizer(), this));\r
+                               \r
+               List<String> otherUrls = GitBlit.self().getOtherCloneUrls(repositoryName, UserModel.ANONYMOUS.equals(user) ? "" : user.username);\r
+               ListDataProvider<String> urls = new ListDataProvider<String>(otherUrls);\r
                DataView<String> otherUrlsView = new DataView<String>("otherUrls", urls) {\r
                        private static final long serialVersionUID = 1L;\r
 \r
index ec879178fe6a292dc121ac9f00c4e491bc417b4f..e241a436be85d490c542224e7c4c43429bb10722 100644 (file)
@@ -22,6 +22,7 @@ import org.apache.wicket.AttributeModifier;
 import org.apache.wicket.Component;\r
 import org.apache.wicket.markup.html.panel.Panel;\r
 import org.apache.wicket.model.Model;\r
+import org.apache.wicket.protocol.http.request.WebClientInfo;\r
 \r
 import com.gitblit.Constants;\r
 import com.gitblit.GitBlit;\r
@@ -57,6 +58,19 @@ public abstract class BasePanel extends Panel {
                }\r
                return timeUtils;\r
        }\r
+       \r
+       protected boolean isWindows() {\r
+               return isPlatform("windows");\r
+       }\r
+\r
+       protected boolean isMac() {\r
+               return isPlatform("macintosh");\r
+       }\r
+       \r
+       protected boolean isPlatform(String platform) {\r
+               String ua = ((WebClientInfo) GitBlitWebSession.get().getClientInfo()).getUserAgent();\r
+               return ua.toLowerCase().contains(platform);\r
+       }\r
 \r
        protected void setPersonSearchTooltip(Component component, String value, Constants.SearchType searchType) {\r
                if (searchType.equals(Constants.SearchType.AUTHOR)) {\r
index 822a9b21cc036b3808032bb3b799d428cd5fc1d7..7cce74f7c17fba33c003a21f80f82df1d727efba 100644 (file)
@@ -16,8 +16,6 @@
 package com.gitblit.wicket.panels;\r
 \r
 import java.text.MessageFormat;\r
-import java.util.ArrayList;\r
-import java.util.List;\r
 import java.util.Map;\r
 \r
 import org.apache.wicket.Component;\r
@@ -29,7 +27,6 @@ import org.apache.wicket.markup.html.link.ExternalLink;
 import org.apache.wicket.markup.html.link.Link;\r
 import org.apache.wicket.markup.html.panel.Fragment;\r
 \r
-import com.gitblit.Constants.AccessPermission;\r
 import com.gitblit.Constants.AccessRestrictionType;\r
 import com.gitblit.GitBlit;\r
 import com.gitblit.Keys;\r
@@ -40,7 +37,6 @@ import com.gitblit.utils.ArrayUtils;
 import com.gitblit.utils.StringUtils;\r
 import com.gitblit.wicket.GitBlitWebSession;\r
 import com.gitblit.wicket.WicketUtils;\r
-import com.gitblit.wicket.pages.BasePage;\r
 import com.gitblit.wicket.pages.DocsPage;\r
 import com.gitblit.wicket.pages.EditRepositoryPage;\r
 import com.gitblit.wicket.pages.LogPage;\r
@@ -58,7 +54,6 @@ public class ProjectRepositoryPanel extends BasePanel {
                super(wicketId);\r
 \r
                final boolean showSwatch = GitBlit.getBoolean(Keys.web.repositoryListSwatches, true);\r
-               final boolean gitServlet = GitBlit.getBoolean(Keys.git.enableGitServlet, true);\r
                final boolean showSize = GitBlit.getBoolean(Keys.web.showRepositorySizes, true);\r
 \r
                // repository swatch\r
@@ -217,15 +212,6 @@ public class ProjectRepositoryPanel extends BasePanel {
 \r
                add(new ExternalLink("syndication", SyndicationServlet.asLink("", entry.name, null, 0)));\r
 \r
-               List<String> repositoryUrls = new ArrayList<String>();\r
-               if (gitServlet) {\r
-                       // add the Gitblit repository url\r
-                       repositoryUrls.add(BasePage.getRepositoryUrl(entry));\r
-               }\r
-               repositoryUrls.addAll(GitBlit.self().getOtherCloneUrls(entry.name, UserModel.ANONYMOUS.equals(user) ? "" : user.username));\r
-\r
-               AccessPermission ap = user.getRepositoryPermission(entry).permission;\r
-               String primaryUrl = ArrayUtils.isEmpty(repositoryUrls) ? "" : repositoryUrls.remove(0);\r
-               add(new DetailedRepositoryUrlPanel("repositoryPrimaryUrl",localizer, parent, entry.name, primaryUrl, ap));\r
+               add(new RepositoryUrlPanel("repositoryPrimaryUrl", true, user, entry, localizer, parent));\r
        }\r
 }\r
index d7c76f134bacad47a4dee30e114ee27c0679366f..c32d9d88c6f6b257671f18cf040b3eb39935f6bc 100644 (file)
@@ -5,26 +5,14 @@
       lang="en"> \r
 \r
 <wicket:panel>\r
-       <span wicket:id="repositoryUrl" style="color: blue;">[repository url]</span><span class="hidden-phone hidden-tablet" wicket:id="copyFunction"></span>\r
-    \r
-    <!-- Plain JavaScript manual copy & paste -->\r
-    <wicket:fragment wicket:id="jsPanel">\r
-       <span style="vertical-align:baseline;">\r
-               <img wicket:id="copyIcon" wicket:message="title:gb.copyToClipboard"></img>\r
-       </span>\r
-    </wicket:fragment>\r
-    \r
-    <!-- flash-based button-press copy & paste -->\r
-    <wicket:fragment wicket:id="clippyPanel">\r
-               <object wicket:message="title:gb.copyToClipboard" style="vertical-align:middle;"\r
-                       wicket:id="clippy"\r
-                       width="14" \r
-                       height="14"\r
-                       bgcolor="#ffffff" \r
-                       quality="high"\r
-                       wmode="transparent"\r
-                       scale="noscale"\r
-                       allowScriptAccess="always"></object>\r
-       </wicket:fragment>\r
+       <div wicket:id="repositoryPrimaryUrl">[repository primary url]</div>\r
+       <div style="padding-top: 2px;">\r
+               <span class="link" wicket:id="appCloneLink">\r
+                       <span wicket:id="icon"></span>\r
+                       <span wicket:id="link"></span>\r
+                       <span wicket:id="separator" style="padding: 0px 5px 0px 5px;"></span>\r
+               </span>\r
+       </div>  \r
+       <div wicket:id="repositoryGitDaemonUrl">[repository git daemon url]</div>\r
 </wicket:panel>\r
 </html>
\ No newline at end of file
index 58df028b3a73cf046177c847111c3b266cde0b41..3afb7b157fcc08d453abb5fe36d4f723c0969302 100644 (file)
  */\r
 package com.gitblit.wicket.panels;\r
 \r
+import java.io.Serializable;\r
+import java.text.MessageFormat;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.apache.wicket.Component;\r
+import org.apache.wicket.Localizer;\r
+import org.apache.wicket.RequestCycle;\r
 import org.apache.wicket.markup.html.basic.Label;\r
-import org.apache.wicket.markup.html.image.ContextImage;\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
+import org.apache.wicket.protocol.http.WebRequest;\r
 \r
+import com.gitblit.Constants;\r
+import com.gitblit.Constants.AccessPermission;\r
+import com.gitblit.Constants.AccessRestrictionType;\r
 import com.gitblit.GitBlit;\r
 import com.gitblit.Keys;\r
+import com.gitblit.SparkleShareInviteServlet;\r
+import com.gitblit.models.RepositoryModel;\r
+import com.gitblit.models.UserModel;\r
 import com.gitblit.utils.StringUtils;\r
+import com.gitblit.wicket.GitBlitWebSession;\r
 import com.gitblit.wicket.WicketUtils;\r
 \r
+/**\r
+ * Smart repository url panel which can display multiple Gitblit repository urls\r
+ * and also supports 3rd party app clone links.\r
+ * \r
+ * @author James Moger\r
+ *\r
+ */\r
 public class RepositoryUrlPanel extends BasePanel {\r
 \r
        private static final long serialVersionUID = 1L;\r
+       \r
+       private final String primaryUrl;\r
 \r
-       public RepositoryUrlPanel(String wicketId, String url) {\r
+       public RepositoryUrlPanel(String wicketId, boolean onlyPrimary, UserModel user, \r
+                       RepositoryModel repository, Localizer localizer, Component owner) {\r
                super(wicketId);\r
-               add(new Label("repositoryUrl", url));\r
-               if (GitBlit.getBoolean(Keys.web.allowFlashCopyToClipboard, true)) {\r
-                       // clippy: flash-based copy & paste\r
-                       Fragment fragment = new Fragment("copyFunction", "clippyPanel", this);\r
-                       String baseUrl = WicketUtils.getGitblitURL(getRequest());\r
-                       ShockWaveComponent clippy = new ShockWaveComponent("clippy", baseUrl + "/clippy.swf");\r
-                       clippy.setValue("flashVars", "text=" + StringUtils.encodeURL(url));\r
-                       fragment.add(clippy);\r
-                       add(fragment);\r
+               if (user == null) {\r
+                       user = UserModel.ANONYMOUS;\r
+               }\r
+               List<String> repositoryUrls = new ArrayList<String>();\r
+\r
+               AccessPermission accessPermission = null;\r
+               if (GitBlit.getBoolean(Keys.git.enableGitServlet, true)) {\r
+                       accessPermission = user.getRepositoryPermission(repository).permission;\r
+                       repositoryUrls.add(getRepositoryUrl(repository));\r
+               }\r
+               repositoryUrls.addAll(GitBlit.self().getOtherCloneUrls(repository.name, UserModel.ANONYMOUS.equals(user) ? "" : user.username));\r
+               \r
+               primaryUrl = repositoryUrls.size() == 0 ? "" : repositoryUrls.remove(0);\r
+\r
+               add(new DetailedRepositoryUrlPanel("repositoryPrimaryUrl", localizer, owner, repository.name, primaryUrl, accessPermission));\r
+               \r
+               if (!onlyPrimary) {\r
+                       Component gitDaemonUrlPanel = createGitDaemonUrlPanel("repositoryGitDaemonUrl", user, repository);\r
+                       if (!StringUtils.isEmpty(primaryUrl) && gitDaemonUrlPanel instanceof DetailedRepositoryUrlPanel) {\r
+                               WicketUtils.setCssStyle(gitDaemonUrlPanel, "padding-top: 10px");\r
+                       }\r
+                       add(gitDaemonUrlPanel);\r
                } else {\r
-                       // javascript: manual copy & paste with modal browser prompt dialog\r
-                       Fragment fragment = new Fragment("copyFunction", "jsPanel", this);\r
-                       ContextImage img = WicketUtils.newImage("copyIcon", "clippy.png");\r
-                       img.add(new JavascriptTextPrompt("onclick", "Copy to Clipboard (Ctrl+C, Enter)", url));\r
-                       fragment.add(img);\r
-                       add(fragment);\r
+                       add(new Label("repositoryGitDaemonUrl").setVisible(false));\r
+               }\r
+               \r
+               final List<AppCloneLink> cloneLinks = new ArrayList<AppCloneLink>();\r
+               if (user.canClone(repository) && GitBlit.getBoolean(Keys.web.allowAppCloneLinks, true)) {\r
+                       // universal app clone urls\r
+//                     cloneLinks.add(new AppCloneLink(localizer.getString("gb.cloneWithSmartGit", owner),\r
+//                                     MessageFormat.format("smartgit://cloneRepo/{0}", primaryUrl),\r
+//                                     "Syntevo SmartGit\u2122"));\r
+\r
+                       if (isWindows()) {\r
+                               // Windows client app clone urls\r
+                               cloneLinks.add(new AppCloneLink(localizer.getString("gb.cloneWithSourceTree", owner),\r
+                                               MessageFormat.format("sourcetree://cloneRepo/{0}", primaryUrl),\r
+                                               "Atlassian SourceTree\u2122"));\r
+//                             cloneLinks.add(new AppCloneLink(\r
+//                                             MessageFormat.format(localizer.getString("gb.cloneWithGitHub", owner), "Windows"),\r
+//                                             MessageFormat.format("github-windows://openRepo/{0}", primaryUrl)));\r
+                       } else if (isMac()) {\r
+                               // Mac client app clone urls\r
+                               cloneLinks.add(new AppCloneLink(localizer.getString("gb.cloneWithSourceTree", owner),\r
+                                               MessageFormat.format("sourcetree://cloneRepo/{0}", primaryUrl),\r
+                                               "Atlassian SourceTree\u2122"));\r
+//                             cloneLinks.add(new AppCloneLink(\r
+//                                             MessageFormat.format(localizer.getString("gb.cloneWithGitHub", owner), "Mac"),\r
+//                                             MessageFormat.format("github-mac://openRepo/{0}", primaryUrl)));\r
+                       }\r
+\r
+                       // sparkleshare invite url\r
+                       String sparkleshareUrl = getSparkleShareInviteUrl(user, repository);\r
+                       if (!StringUtils.isEmpty(sparkleshareUrl)) {\r
+                               cloneLinks.add(new AppCloneLink(localizer.getString("gb.cloneWithSparkleShare", owner),\r
+                                               sparkleshareUrl, "SparkleShare \u2122", "icon-star"));\r
+                       }\r
+               }\r
+\r
+               // app clone links\r
+               ListDataProvider<AppCloneLink> appLinks = new ListDataProvider<AppCloneLink>(cloneLinks);\r
+               DataView<AppCloneLink> appCloneLinks = new DataView<AppCloneLink>("appCloneLink", appLinks) {\r
+                       private static final long serialVersionUID = 1L;\r
+                       int count;\r
+                       \r
+                       public void populateItem(final Item<AppCloneLink> item) {\r
+                               final AppCloneLink appLink = item.getModelObject();\r
+                               item.add(new Label("icon", MessageFormat.format("<i class=\"{0}\"></i>", appLink.icon)).setEscapeModelStrings(false));\r
+                               LinkPanel linkPanel = new LinkPanel("link", null, appLink.name, appLink.url);\r
+                               if (!StringUtils.isEmpty(appLink.tooltip)) {\r
+                                       WicketUtils.setHtmlTooltip(linkPanel, appLink.tooltip);\r
+                               }\r
+                               item.add(linkPanel);\r
+                               item.add(new Label("separator", "|").setVisible(count < (cloneLinks.size() - 1)));\r
+                               count++;\r
+                       }\r
+               };\r
+               add(appCloneLinks);\r
+       }\r
+       \r
+       public String getPrimaryUrl() {\r
+               return primaryUrl;\r
+       }\r
+       \r
+       protected String getRepositoryUrl(RepositoryModel repository) {\r
+               StringBuilder sb = new StringBuilder();\r
+               sb.append(WicketUtils.getGitblitURL(RequestCycle.get().getRequest()));\r
+               sb.append(Constants.GIT_PATH);\r
+               sb.append(repository.name);\r
+               \r
+               // inject username into repository url if authentication is required\r
+               if (repository.accessRestriction.exceeds(AccessRestrictionType.NONE)\r
+                               && GitBlitWebSession.get().isLoggedIn()) {\r
+                       String username = GitBlitWebSession.get().getUsername();\r
+                       sb.insert(sb.indexOf("://") + 3, username + "@");\r
+               }\r
+               return sb.toString();\r
+       }\r
+       \r
+       protected Component createGitDaemonUrlPanel(String wicketId, UserModel user, RepositoryModel repository) {\r
+               int gitDaemonPort = GitBlit.getInteger(Keys.git.daemonPort, 0);\r
+               if (gitDaemonPort > 0 && user.canClone(repository)) {\r
+                       String servername = ((WebRequest) getRequest()).getHttpServletRequest().getServerName();\r
+                       String gitDaemonUrl;\r
+                       if (gitDaemonPort == 9418) {\r
+                               // standard port\r
+                               gitDaemonUrl = MessageFormat.format("git://{0}/{1}", servername, repository.name);\r
+                       } else {\r
+                               // non-standard port\r
+                               gitDaemonUrl = MessageFormat.format("git://{0}:{1,number,0}/{2}", servername, gitDaemonPort, repository.name);\r
+                       }\r
+                       \r
+                       AccessPermission gitDaemonPermission = user.getRepositoryPermission(repository).permission;;\r
+                       if (gitDaemonPermission.atLeast(AccessPermission.CLONE)) {\r
+                               if (repository.accessRestriction.atLeast(AccessRestrictionType.CLONE)) {\r
+                                       // can not authenticate clone via anonymous git protocol\r
+                                       gitDaemonPermission = AccessPermission.NONE;\r
+                               } else if (repository.accessRestriction.atLeast(AccessRestrictionType.PUSH)) {\r
+                                       // can not authenticate push via anonymous git protocol\r
+                                       gitDaemonPermission = AccessPermission.CLONE;\r
+                               } else {\r
+                                       // normal user permission\r
+                               }\r
+                       }\r
+                       \r
+                       if (AccessPermission.NONE.equals(gitDaemonPermission)) {\r
+                               // repository prohibits all anonymous access\r
+                               return new Label(wicketId).setVisible(false);\r
+                       } else {\r
+                               // repository allows some form of anonymous access\r
+                               return new DetailedRepositoryUrlPanel(wicketId, getLocalizer(), this, repository.name, gitDaemonUrl, gitDaemonPermission);\r
+                       }\r
+               } else {\r
+                       // git daemon is not running\r
+                       return new Label(wicketId).setVisible(false);\r
+               }\r
+       }\r
+\r
+       protected String getSparkleShareInviteUrl(UserModel user, RepositoryModel repository) {\r
+               if (repository.isBare && repository.isSparkleshared()) {\r
+                       String username = null;\r
+                       if (UserModel.ANONYMOUS != user) {\r
+                               username = user.username;\r
+                       }\r
+                       if (GitBlit.getBoolean(Keys.git.enableGitServlet, true) || (GitBlit.getInteger(Keys.git.daemonPort, 0) > 0)) {\r
+                               // Gitblit as server\r
+                               // ensure user can rewind\r
+                               if (user.canRewindRef(repository)) {\r
+                                       String baseURL = WicketUtils.getGitblitURL(RequestCycle.get().getRequest());\r
+                                       return SparkleShareInviteServlet.asLink(baseURL, repository.name, username);\r
+                               }\r
+                       } else {\r
+                               // Gitblit as viewer, assume RW+ permission\r
+                               String baseURL = WicketUtils.getGitblitURL(RequestCycle.get().getRequest());\r
+                               return SparkleShareInviteServlet.asLink(baseURL, repository.name, username);\r
+                       }\r
+               }\r
+               return null;\r
+       }\r
+       \r
+       static class AppCloneLink implements Serializable {\r
+               \r
+               private static final long serialVersionUID = 1L;\r
+               \r
+               final String name;\r
+               final String url;\r
+               final String tooltip;\r
+               final String icon;\r
+               \r
+               public AppCloneLink(String name, String url, String tooltip) {\r
+                       this(name, url, tooltip, "icon-download");\r
+               }\r
+               \r
+               public AppCloneLink(String name, String url, String tooltip, String icon) {\r
+                       this.name = name;\r
+                       this.url = url;\r
+                       this.tooltip = tooltip;\r
+                       this.icon = icon;\r
                }\r
        }\r
 }\r
diff --git a/src/main/java/com/gitblit/wicket/panels/SparkleShareInvitePanel.html b/src/main/java/com/gitblit/wicket/panels/SparkleShareInvitePanel.html
deleted file mode 100644 (file)
index 483050c..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
-<html xmlns="http://www.w3.org/1999/xhtml"  \r
-      xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd"  \r
-      xml:lang="en"  \r
-      lang="en"> \r
-\r
-<wicket:panel>\r
-       <span class="repositoryUrlContainer">\r
-               <span class="repositoryUrlEndCap">\r
-                       <img wicket:id="sparkleshareIcon"></img>\r
-               </span>\r
-               <span class="repositoryUrl">\r
-                       <a wicket:id="inviteUrl"><wicket:message key="gb.sparkleshareInvite"></wicket:message></a>\r
-               </span>\r
-               <span class="hidden-phone hidden-tablet repositoryUrlEndCap" wicket:id="accessPermission">[access permission]</span>\r
-       </span>\r
-</wicket:panel>\r
-</html>
\ No newline at end of file
diff --git a/src/main/java/com/gitblit/wicket/panels/SparkleShareInvitePanel.java b/src/main/java/com/gitblit/wicket/panels/SparkleShareInvitePanel.java
deleted file mode 100644 (file)
index 5d7aa58..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*\r
- * Copyright 2013 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.wicket.panels;\r
-\r
-import org.apache.wicket.Component;\r
-import org.apache.wicket.Localizer;\r
-import org.apache.wicket.markup.html.basic.Label;\r
-import org.apache.wicket.markup.html.image.ContextImage;\r
-import org.apache.wicket.markup.html.link.ExternalLink;\r
-\r
-import com.gitblit.Constants.AccessPermission;\r
-import com.gitblit.wicket.WicketUtils;\r
-\r
-public class SparkleShareInvitePanel extends BasePanel {\r
-\r
-       private static final long serialVersionUID = 1L;\r
-\r
-       public SparkleShareInvitePanel(String wicketId, Localizer localizer, Component parent, String url, AccessPermission ap) {\r
-               super(wicketId);\r
-               ContextImage star = WicketUtils.newImage("sparkleshareIcon", "star_16x16.png");\r
-               add(star);\r
-               add(new ExternalLink("inviteUrl", url));\r
-               String note = localizer.getString("gb.externalAccess", parent);\r
-               String permission = "";\r
-               if (ap != null) {\r
-                       permission = ap.toString();\r
-                       if (ap.atLeast(AccessPermission.PUSH)) {\r
-                               note = localizer.getString("gb.readWriteAccess", parent);\r
-                       } else if (ap.atLeast(AccessPermission.CLONE)) {\r
-                               note = localizer.getString("gb.readOnlyAccess", parent);\r
-                       } else {\r
-                               note = localizer.getString("gb.viewAccess", parent);\r
-                       }\r
-               }\r
-               Label label = new Label("accessPermission", permission);\r
-               WicketUtils.setHtmlTooltip(label, note);\r
-               add(label);\r
-       }\r
-}\r