Allow client apps to specify a minimum required access permission
| | |
| | | "title": "Git",
|
| | | "description": "a fast, open-source, distributed VCS",
|
| | | "legal": "released under the GPLv2 open source license",
|
| | | "command": "git clone {0}",
|
| | | "command": "git clone ${repoUrl}",
|
| | | "productUrl": "http://git-scm.com",
|
| | | "icon": "git-black_32x32.png",
|
| | | "isActive": true
|
| | |
| | | "title": "syntevo SmartGit/Hg\u2122",
|
| | | "description": "a Git client for Windows, Mac, & Linux",
|
| | | "legal": "\u00a9 2013 syntevo GmbH. All rights reserved.",
|
| | | "cloneUrl": "smartgit://cloneRepo/{0}",
|
| | | "cloneUrl": "smartgit://cloneRepo/${repoUrl}",
|
| | | "productUrl": "http://www.syntevo.com/smartgithg",
|
| | | "platforms": [ "windows", "macintosh", "linux" ],
|
| | | "icon": "smartgithg_32x32.png",
|
| | |
| | | "title": "Atlassian SourceTree\u2122",
|
| | | "description": "a free Git client for Windows or Mac",
|
| | | "legal": "\u00a9 2013 Atlassian. All rights reserved.",
|
| | | "cloneUrl": "sourcetree://cloneRepo/{0}",
|
| | | "cloneUrl": "sourcetree://cloneRepo/${repoUrl}",
|
| | | "productUrl": "http://sourcetreeapp.com",
|
| | | "platforms": [ "windows", "macintosh" ],
|
| | | "icon": "sourcetree_32x32.png",
|
| | |
| | | "title": "fournova Tower\u2122",
|
| | | "description": "a Git client for Mac",
|
| | | "legal": "\u00a9 2013 fournova Software GmbH. All rights reserved.",
|
| | | "cloneUrl": "gittower://openRepo/{0}",
|
| | | "cloneUrl": "gittower://openRepo/${repoUrl}",
|
| | | "productUrl": "http://www.git-tower.com",
|
| | | "platforms": [ "macintosh" ],
|
| | | "icon": "tower_32x32.png",
|
| | |
| | | "title": "GitHub\u2122 for Macintosh",
|
| | | "description": "a free Git client for Mac OS X",
|
| | | "legal": "\u00a9 2013 GitHub. All rights reserved.",
|
| | | "cloneUrl": "github-mac://openRepo/{0}",
|
| | | "cloneUrl": "github-mac://openRepo/${repoUrl}",
|
| | | "productUrl": "http://mac.github.com",
|
| | | "platforms": [ "macintosh" ],
|
| | | "isActive": false
|
| | |
| | | "title": "GitHub\u2122 for Windows",
|
| | | "description": "a free Git client for Windows",
|
| | | "legal": "\u00a9 2013 GitHub. All rights reserved.",
|
| | | "cloneUrl": "github-windows://openRepo/{0}",
|
| | | "cloneUrl": "github-windows://openRepo/${repoUrl}",
|
| | | "productUrl": "http://windows.github.com",
|
| | | "platforms": [ "windows" ],
|
| | | "isActive": false
|
| | | },
|
| | | {
|
| | | "name": "SparkleShare",
|
| | | "title": "SparkleShare\u2122",
|
| | | "description": "an open source collaboration and sharing tool",
|
| | | "legal": "released under the GPLv3 open source license",
|
| | | "cloneUrl": "sparkleshare://inviteRepo/${baseUrl}/sparkleshare/${repoUrl}.xml",
|
| | | "productUrl": "http://sparkleshare.org",
|
| | | "platforms": [ "windows", "macintosh", "linux" ],
|
| | | "icon": "sparkleshare_32x32.png",
|
| | | "minimumPermission" : "RW+",
|
| | | "isActive": false
|
| | | }
|
| | | ] |
| | |
| | | import com.gitblit.wicket.GitBlitWebSession;
|
| | | import com.gitblit.wicket.WicketUtils;
|
| | | import com.google.gson.Gson;
|
| | | import com.google.gson.GsonBuilder;
|
| | | import com.google.gson.JsonIOException;
|
| | | import com.google.gson.JsonSyntaxException;
|
| | | import com.google.gson.reflect.TypeToken;
|
| | |
| | | Type type = new TypeToken<Collection<GitClientApplication>>() {
|
| | | }.getType();
|
| | | InputStreamReader reader = new InputStreamReader(is);
|
| | | Gson gson = new GsonBuilder().create();
|
| | | Gson gson = JsonUtils.gson(); |
| | | Collection<GitClientApplication> links = gson.fromJson(reader, type);
|
| | | return links;
|
| | | } catch (JsonIOException e) {
|
| | |
| | |
|
| | | import java.io.IOException;
|
| | | import java.text.MessageFormat;
|
| | | import java.util.List;
|
| | |
|
| | | import javax.servlet.ServletException;
|
| | | import javax.servlet.http.HttpServlet;
|
| | | import javax.servlet.http.HttpServletRequest;
|
| | | import javax.servlet.http.HttpServletResponse;
|
| | |
|
| | | import com.gitblit.Constants.AccessRestrictionType;
|
| | | import com.gitblit.models.RepositoryModel;
|
| | | import com.gitblit.models.UserModel;
|
| | | import com.gitblit.utils.StringUtils;
|
| | |
| | |
|
| | | public SparkleShareInviteServlet() {
|
| | | super();
|
| | | }
|
| | | |
| | | /**
|
| | | * Returns an Sparkleshare invite url to this servlet for the repository.
|
| | | * https://github.com/hbons/SparkleShare/wiki/Invites
|
| | | * |
| | | * @param baseURL
|
| | | * @param repository
|
| | | * @param username
|
| | | * @return an url
|
| | | */
|
| | | public static String asLink(String baseURL, String repository, String username) {
|
| | | if (baseURL.length() > 0 && baseURL.charAt(baseURL.length() - 1) == '/') {
|
| | | baseURL = baseURL.substring(0, baseURL.length() - 1);
|
| | | }
|
| | | String url = baseURL + Constants.SPARKLESHARE_INVITE_PATH
|
| | | + ((StringUtils.isEmpty(username) ? "" : (username + "@")))
|
| | | + repository + ".xml";
|
| | | url = url.replace("https://", "sparkleshare://");
|
| | | url = url.replace("http://", "sparkleshare-unsafe://");
|
| | | return url;
|
| | | }
|
| | |
|
| | | @Override
|
| | |
| | | java.io.IOException {
|
| | |
|
| | | // extract repo name from request
|
| | | String path = request.getPathInfo();
|
| | | if (path != null && path.length() > 1) {
|
| | | if (path.charAt(0) == '/') {
|
| | | path = path.substring(1);
|
| | | }
|
| | | }
|
| | | String repoUrl = request.getPathInfo().substring(1);
|
| | |
|
| | | // trim trailing .xml
|
| | | if (path.endsWith(".xml")) {
|
| | | path = path.substring(0, path.length() - 4);
|
| | | if (repoUrl.endsWith(".xml")) {
|
| | | repoUrl = repoUrl.substring(0, repoUrl.length() - 4);
|
| | | }
|
| | |
|
| | | String servletPath = Constants.GIT_PATH;
|
| | | |
| | | int schemeIndex = repoUrl.indexOf("://") + 3;
|
| | | String host = repoUrl.substring(0, repoUrl.indexOf('/', schemeIndex)); |
| | | String path = repoUrl.substring(repoUrl.indexOf(servletPath) + servletPath.length());
|
| | | String username = null;
|
| | | int fetch = path.indexOf('@');
|
| | | if (fetch > -1) {
|
| | | username = path.substring(0, fetch);
|
| | | path = path.substring(fetch + 1);
|
| | | int fetchIndex = repoUrl.indexOf('@');
|
| | | if (fetchIndex > -1) {
|
| | | username = repoUrl.substring(schemeIndex, fetchIndex);
|
| | | }
|
| | | UserModel user;
|
| | | if (StringUtils.isEmpty(username)) {
|
| | |
| | | username = "";
|
| | | }
|
| | |
|
| | | // ensure that the requested repository exists and is sparkleshared
|
| | | // ensure that the requested repository exists
|
| | | RepositoryModel model = GitBlit.self().getRepositoryModel(path);
|
| | | if (model == null) {
|
| | | response.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
| | | response.getWriter().append(MessageFormat.format("Repository \"{0}\" not found!", path));
|
| | | return;
|
| | | } else if (!model.isSparkleshared()) {
|
| | | response.setStatus(HttpServletResponse.SC_FORBIDDEN);
|
| | | response.getWriter().append(MessageFormat.format("Repository \"{0}\" is not sparkleshared!", path));
|
| | | return;
|
| | | }
|
| | |
|
| | | if (GitBlit.getBoolean(Keys.git.enableGitServlet, true)
|
| | | || GitBlit.getInteger(Keys.git.daemonPort, 0) > 0) {
|
| | | // Gitblit as server
|
| | | // determine username for repository url
|
| | | if (model.accessRestriction.exceeds(AccessRestrictionType.NONE)) {
|
| | | if (!user.canRewindRef(model)) {
|
| | | response.setStatus(HttpServletResponse.SC_FORBIDDEN);
|
| | | response.getWriter().append(MessageFormat.format("\"{0}\" does not have RW+ permissions for {1}!", user.username, path));
|
| | | return;
|
| | | }
|
| | | }
|
| | | |
| | | if (model.accessRestriction.exceeds(AccessRestrictionType.NONE)) {
|
| | | username = user.username + "@";
|
| | | } else {
|
| | | username = "";
|
| | | }
|
| | |
|
| | | String serverPort = "";
|
| | | if (request.getScheme().equals("https")) {
|
| | | if (request.getServerPort() != 443) {
|
| | | serverPort = ":" + request.getServerPort();
|
| | | }
|
| | | } else if (request.getScheme().equals("http")) {
|
| | | if (request.getServerPort() != 80) {
|
| | | serverPort = ":" + request.getServerPort();
|
| | | }
|
| | | }
|
| | |
|
| | | // assume http/https serving
|
| | | String scheme = request.getScheme();
|
| | | String servletPath = Constants.GIT_PATH;
|
| | |
|
| | | // try to switch to git://, if git servlet disabled and repo has no restrictions
|
| | | if (!GitBlit.getBoolean(Keys.git.enableGitServlet, true)
|
| | | && (GitBlit.getInteger(Keys.git.daemonPort, 0) > 0)
|
| | | && AccessRestrictionType.NONE == model.accessRestriction) {
|
| | | scheme = "git";
|
| | | servletPath = "/";
|
| | | serverPort = GitBlit.getString(Keys.git.daemonPort, "");
|
| | | }
|
| | |
|
| | | // construct Sparkleshare invite
|
| | | StringBuilder sb = new StringBuilder(); |
| | | sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
|
| | | sb.append("<sparkleshare><invite>\n");
|
| | | sb.append(MessageFormat.format("<address>{0}://{1}{2}{3}{4}</address>\n", scheme, username, request.getServerName(), serverPort, request.getContextPath()));
|
| | | sb.append(MessageFormat.format("<remote_path>{0}{1}</remote_path>\n", servletPath, model.name));
|
| | | if (GitBlit.getInteger(Keys.fanout.port, 0) > 0) {
|
| | | // Gitblit is running it's own fanout service for pubsub notifications
|
| | | sb.append(MessageFormat.format("<announcements_url>tcp://{0}:{1}</announcements_url>\n", request.getServerName(), GitBlit.getString(Keys.fanout.port, "")));
|
| | | }
|
| | | sb.append("</invite></sparkleshare>\n");
|
| | |
|
| | | // write invite to client
|
| | | response.setContentType("application/xml");
|
| | | response.setContentLength(sb.length());
|
| | | response.getWriter().append(sb.toString());
|
| | | } else {
|
| | | // Gitblit as viewer, repository access handled externally so
|
| | | // assume RW+ permission
|
| | | List<String> others = GitBlit.getStrings(Keys.web.otherUrls);
|
| | | if (others.size() == 0) {
|
| | | return;
|
| | | }
|
| | | |
| | | String address = MessageFormat.format(others.get(0), "", username);
|
| | | |
| | | StringBuilder sb = new StringBuilder(); |
| | | sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
|
| | | sb.append("<sparkleshare><invite>\n");
|
| | | |
| | | sb.append(MessageFormat.format("<address>{0}</address>\n", address));
|
| | | sb.append(MessageFormat.format("<remote_path>{0}</remote_path>\n", model.name));
|
| | | if (GitBlit.getInteger(Keys.fanout.port, 0) > 0) {
|
| | | // Gitblit is running it's own fanout service for pubsub notifications
|
| | | sb.append(MessageFormat.format("<announcements_url>tcp://{0}:{1}</announcements_url>\n", request.getServerName(), GitBlit.getString(Keys.fanout.port, "")));
|
| | | }
|
| | | sb.append("</invite></sparkleshare>\n");
|
| | |
|
| | | // write invite to client
|
| | | response.setContentType("application/xml");
|
| | | response.setContentLength(sb.length());
|
| | | response.getWriter().append(sb.toString());
|
| | | StringBuilder sb = new StringBuilder(); |
| | | sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
|
| | | sb.append("<sparkleshare><invite>\n");
|
| | | sb.append(MessageFormat.format("<address>{0}</address>\n", host));
|
| | | sb.append(MessageFormat.format("<remote_path>{0}{1}</remote_path>\n", servletPath, model.name));
|
| | | if (GitBlit.getInteger(Keys.fanout.port, 0) > 0) {
|
| | | // Gitblit is running it's own fanout service for pubsub notifications
|
| | | sb.append(MessageFormat.format("<announcements_url>tcp://{0}:{1}</announcements_url>\n", request.getServerName(), GitBlit.getString(Keys.fanout.port, "")));
|
| | | }
|
| | | sb.append("</invite></sparkleshare>\n");
|
| | |
|
| | | // write invite to client
|
| | | response.setContentType("application/xml");
|
| | | response.setContentLength(sb.length());
|
| | | response.getWriter().append(sb.toString());
|
| | | }
|
| | | }
|
| | |
| | |
|
| | | import java.io.Serializable;
|
| | |
|
| | | import com.gitblit.Constants.AccessPermission;
|
| | | import com.gitblit.utils.ArrayUtils;
|
| | | import com.gitblit.utils.StringUtils;
|
| | |
|
| | |
| | | public String command;
|
| | | public String productUrl;
|
| | | public String[] platforms;
|
| | | public AccessPermission minimumPermission;
|
| | | public boolean isActive;
|
| | |
|
| | | public boolean allowsPlatform(String p) {
|
| | |
| | | <div class="btn-group repositoryUrlContainer">
|
| | | <img style="vertical-align: middle;padding: 0px 0px 1px 3px;" wicket:id="accessRestrictionIcon"></img>
|
| | | <span wicket:id="menu"></span>
|
| | | <span class="repositoryUrl">
|
| | | <div class="repositoryUrl">
|
| | | <span wicket:id="primaryUrl">[repository primary url]</span>
|
| | | <span class="hidden-phone hidden-tablet" wicket:id="copyFunction"></span>
|
| | | </span>
|
| | | </div>
|
| | | <span class="hidden-phone hidden-tablet repositoryUrlRightCap" wicket:id="primaryUrlPermission">[repository primary url permission]</span>
|
| | | </div>
|
| | | </div>
|
| | |
| | | <wicket:fragment wicket:id="applicationMenusFragment">
|
| | | <div class="btn-toolbar" style="margin: 4px 0px 0px 0px;">
|
| | | <div class="btn-group" wicket:id="appMenus">
|
| | | <a class="btn btn-mini btn-appmenu" data-toggle="dropdown" href="#"> |
| | | <span wicket:id="applicationName"></span>
|
| | | <span class="caret"></span>
|
| | | </a>
|
| | | <ul class="dropdown-menu applicationMenu">
|
| | | <li>
|
| | | <div class="applicationHeaderMenuItem">
|
| | | <div style="float:right">
|
| | | <img style="padding-right: 5px;vertical-align: middle;" wicket:id="applicationIcon"></img>
|
| | | </div>
|
| | | <span class="applicationTitle" wicket:id="applicationTitle"></span>
|
| | | </div>
|
| | | </li>
|
| | | <li><div class="applicationHeaderMenuItem"><span wicket:id="applicationDescription"></span></div></li>
|
| | | <li><div class="applicationLegalMenuItem"><span wicket:id="applicationLegal"></span></div></li>
|
| | | |
| | | <li class="divider" style="margin: 5px 1px 0px 1px;clear:both;" ></li>
|
| | | |
| | | <li class="action" wicket:id="actionItems">
|
| | | <span wicket:id="actionItem"></span>
|
| | | </li>
|
| | | </ul>
|
| | | <span wicket:id="appMenu"></span>
|
| | | </div>
|
| | | </div>
|
| | | </wicket:fragment>
|
| | |
|
| | | <wicket:fragment wicket:id="appMenuFragment">
|
| | | <a class="btn btn-mini btn-appmenu" data-toggle="dropdown" href="#"> |
| | | <span wicket:id="applicationName"></span>
|
| | | <span class="caret"></span>
|
| | | </a>
|
| | | <ul class="dropdown-menu applicationMenu">
|
| | | <li>
|
| | | <div class="applicationHeaderMenuItem">
|
| | | <div style="float:right">
|
| | | <img style="padding-right: 5px;vertical-align: middle;" wicket:id="applicationIcon"></img>
|
| | | </div>
|
| | | <span class="applicationTitle" wicket:id="applicationTitle"></span>
|
| | | </div>
|
| | | </li>
|
| | | <li><div class="applicationHeaderMenuItem"><span wicket:id="applicationDescription"></span></div></li>
|
| | | <li><div class="applicationLegalMenuItem"><span wicket:id="applicationLegal"></span></div></li>
|
| | | |
| | | <li class="divider" style="margin: 5px 1px 0px 1px;clear:both;" ></li>
|
| | | |
| | | <li class="action" wicket:id="actionItems">
|
| | | <span wicket:id="actionItem"></span>
|
| | | </li>
|
| | | </ul>
|
| | | </wicket:fragment>
|
| | | |
| | | <wicket:fragment wicket:id="urlProtocolMenuFragment">
|
| | | <a class="" data-toggle="dropdown" href="#">
|
| | | <span class="repositoryUrlLeftCap" wicket:id="menuText">URLs</span>
|
| | |
| | | import com.gitblit.Constants.AccessRestrictionType;
|
| | | import com.gitblit.GitBlit;
|
| | | import com.gitblit.Keys;
|
| | | import com.gitblit.SparkleShareInviteServlet;
|
| | | import com.gitblit.models.GitClientApplication;
|
| | | import com.gitblit.models.RepositoryModel;
|
| | | import com.gitblit.models.RepositoryUrl;
|
| | | import com.gitblit.models.UserModel;
|
| | | import com.gitblit.utils.StringUtils;
|
| | | import com.gitblit.wicket.ExternalImage;
|
| | | import com.gitblit.wicket.GitBlitWebSession;
|
| | | import com.gitblit.wicket.WicketUtils;
|
| | |
|
| | |
| | | return urlPanel;
|
| | | }
|
| | |
|
| | | protected Fragment createApplicationMenus(String wicketId, UserModel user, final RepositoryModel repository, List<RepositoryUrl> repositoryUrls) {
|
| | | protected Fragment createApplicationMenus(String wicketId, UserModel user, final RepositoryModel repository, final List<RepositoryUrl> repositoryUrls) {
|
| | | final List<GitClientApplication> displayedApps = new ArrayList<GitClientApplication>();
|
| | | final String userAgent = ((WebClientInfo) GitBlitWebSession.get().getClientInfo()).getUserAgent();
|
| | |
|
| | |
| | | displayedApps.add(app);
|
| | | }
|
| | | }
|
| | |
|
| | | GitClientApplication sparkleshare = getSparkleShareAppMenu(user, repository);
|
| | | if (sparkleshare != null) {
|
| | | displayedApps.add(sparkleshare);
|
| | | }
|
| | | }
|
| | |
|
| | | final ListDataProvider<RepositoryUrl> urlsDp = new ListDataProvider<RepositoryUrl>(repositoryUrls);
|
| | | final String baseURL = WicketUtils.getGitblitURL(RequestCycle.get().getRequest());
|
| | | ListDataProvider<GitClientApplication> displayedAppsDp = new ListDataProvider<GitClientApplication>(displayedApps);
|
| | | DataView<GitClientApplication> appMenus = new DataView<GitClientApplication>("appMenus", displayedAppsDp) {
|
| | | private static final long serialVersionUID = 1L;
|
| | |
| | | public void populateItem(final Item<GitClientApplication> item) {
|
| | | final GitClientApplication clientApp = item.getModelObject();
|
| | |
|
| | | // filter the urls for the client app
|
| | | List<RepositoryUrl> urls;
|
| | | if (clientApp.minimumPermission == null) {
|
| | | // client app does not specify minimum access permission
|
| | | urls = repositoryUrls;
|
| | | } else {
|
| | | urls = new ArrayList<RepositoryUrl>();
|
| | | for (RepositoryUrl repoUrl : repositoryUrls) {
|
| | | if (repoUrl.permission == null) {
|
| | | // external permissions, assume it is satisfactory
|
| | | urls.add(repoUrl);
|
| | | } else if (repoUrl.permission.atLeast(clientApp.minimumPermission)) {
|
| | | // repo url meets minimum permission requirement
|
| | | urls.add(repoUrl);
|
| | | }
|
| | | }
|
| | | }
|
| | | |
| | | if (urls.size() == 0) {
|
| | | // do not show this app menu because there are no urls
|
| | | item.add(new Label("appMenu").setVisible(false));
|
| | | return;
|
| | | }
|
| | | |
| | | Fragment appMenu = new Fragment("appMenu", "appMenuFragment", this);
|
| | | appMenu.setRenderBodyOnly(true);
|
| | | item.add(appMenu);
|
| | | |
| | | // menu button
|
| | | item.add(new Label("applicationName", clientApp.name));
|
| | | appMenu.add(new Label("applicationName", clientApp.name));
|
| | |
|
| | | // application icon
|
| | | Component img;
|
| | | if (StringUtils.isEmpty(clientApp.icon)) {
|
| | | img = WicketUtils.newClearPixel("applicationIcon").setVisible(false);
|
| | | } else {
|
| | | img = WicketUtils.newImage("applicationIcon", clientApp.icon); |
| | | if (clientApp.icon.contains("://")) {
|
| | | // external image
|
| | | img = new ExternalImage("applicationIcon", clientApp.icon);
|
| | | } else {
|
| | | // context image
|
| | | img = WicketUtils.newImage("applicationIcon", clientApp.icon);
|
| | | }
|
| | | }
|
| | | item.add(img);
|
| | | appMenu.add(img);
|
| | |
|
| | | // application menu title, may be a link
|
| | | if (StringUtils.isEmpty(clientApp.productUrl)) {
|
| | | item.add(new Label("applicationTitle", clientApp.toString()));
|
| | | appMenu.add(new Label("applicationTitle", clientApp.toString()));
|
| | | } else {
|
| | | item.add(new LinkPanel("applicationTitle", null, clientApp.toString(), clientApp.productUrl, true));
|
| | | appMenu.add(new LinkPanel("applicationTitle", null, clientApp.toString(), clientApp.productUrl, true));
|
| | | }
|
| | |
|
| | | // brief application description
|
| | | if (StringUtils.isEmpty(clientApp.description)) {
|
| | | item.add(new Label("applicationDescription").setVisible(false));
|
| | | appMenu.add(new Label("applicationDescription").setVisible(false));
|
| | | } else {
|
| | | item.add(new Label("applicationDescription", clientApp.description));
|
| | | appMenu.add(new Label("applicationDescription", clientApp.description));
|
| | | }
|
| | |
|
| | | // brief application legal info, copyright, license, etc
|
| | | if (StringUtils.isEmpty(clientApp.legal)) {
|
| | | item.add(new Label("applicationLegal").setVisible(false));
|
| | | appMenu.add(new Label("applicationLegal").setVisible(false));
|
| | | } else {
|
| | | item.add(new Label("applicationLegal", clientApp.legal));
|
| | | appMenu.add(new Label("applicationLegal", clientApp.legal));
|
| | | }
|
| | |
|
| | | // a nested repeater for all action items
|
| | | ListDataProvider<RepositoryUrl> urlsDp = new ListDataProvider<RepositoryUrl>(urls);
|
| | | DataView<RepositoryUrl> actionItems = new DataView<RepositoryUrl>("actionItems", urlsDp) {
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | public void populateItem(final Item<RepositoryUrl> repoLinkItem) {
|
| | | RepositoryUrl repoUrl = repoLinkItem.getModelObject();
|
| | | |
| | | Fragment fragment = new Fragment("actionItem", "actionFragment", this);
|
| | | fragment.add(createPermissionBadge("permission", repoUrl));
|
| | |
|
| | | if (!StringUtils.isEmpty(clientApp.cloneUrl)) {
|
| | | // custom registered url
|
| | | String url = MessageFormat.format(clientApp.cloneUrl, repoUrl);
|
| | | String url = substitute(clientApp.cloneUrl, repoUrl.url, baseURL);
|
| | | fragment.add(new LinkPanel("content", "applicationMenuItem", getString("gb.clone") + " " + repoUrl.url, url));
|
| | | repoLinkItem.add(fragment);
|
| | | fragment.add(new Label("copyFunction").setVisible(false));
|
| | | } else if (!StringUtils.isEmpty(clientApp.command)) {
|
| | | // command-line
|
| | | String command = MessageFormat.format(clientApp.command, repoUrl);
|
| | | String command = substitute(clientApp.command, repoUrl.url, baseURL);
|
| | | Label content = new Label("content", command);
|
| | | WicketUtils.setCssClass(content, "commandMenuItem");
|
| | | fragment.add(content);
|
| | |
| | | fragment.add(createCopyFragment(command));
|
| | | }
|
| | | }};
|
| | | item.add(actionItems);
|
| | | appMenu.add(actionItems);
|
| | | }
|
| | | };
|
| | |
|
| | |
| | | return applicationMenus;
|
| | | }
|
| | |
|
| | | protected GitClientApplication getSparkleShareAppMenu(UserModel user, RepositoryModel repository) {
|
| | | String url = null;
|
| | | if (repository.isBare && repository.isSparkleshared()) {
|
| | | String username = null;
|
| | | if (UserModel.ANONYMOUS != user) {
|
| | | username = user.username;
|
| | | }
|
| | | if (isGitblitServingRepositories()) {
|
| | | // Gitblit as server
|
| | | // ensure user can rewind
|
| | | if (user.canRewindRef(repository)) {
|
| | | String baseURL = WicketUtils.getGitblitURL(RequestCycle.get().getRequest());
|
| | | url = SparkleShareInviteServlet.asLink(baseURL, repository.name, username);
|
| | | }
|
| | | } else {
|
| | | // Gitblit as viewer, assume RW+ permission
|
| | | String baseURL = WicketUtils.getGitblitURL(RequestCycle.get().getRequest());
|
| | | url = SparkleShareInviteServlet.asLink(baseURL, repository.name, username);
|
| | | }
|
| | | }
|
| | |
|
| | | // sparkleshare invite url
|
| | | if (!StringUtils.isEmpty(url)) {
|
| | | GitClientApplication app = new GitClientApplication();
|
| | | app.name = "SparkleShare";
|
| | | app.title = "SparkleShare\u2122";
|
| | | app.description = "an open source collaboration and sharing tool";
|
| | | app.legal = "released under the GPLv3 open source license";
|
| | | app.cloneUrl = url;
|
| | | app.platforms = new String [] { "windows", "macintosh", "linux" };
|
| | | app.productUrl = "http://sparkleshare.org";
|
| | | app.icon = "sparkleshare_32x32.png";
|
| | | app.isActive = true;
|
| | | return app;
|
| | | }
|
| | | return null;
|
| | | protected String substitute(String pattern, String repoUrl, String baseUrl) {
|
| | | return pattern.replace("${repoUrl}", repoUrl).replace("${baseUrl}", baseUrl);
|
| | | }
|
| | |
|
| | | protected boolean isGitblitServingRepositories() {
|