From ca31f51855b39a179bdad9bb912da6aeadad866d Mon Sep 17 00:00:00 2001 From: James Moger Date: Wed, 23 Apr 2014 15:41:14 -0400 Subject: Split pages servlet into a raw branch servlet and a gh-pages servlet --- src/main/java/com/gitblit/Constants.java | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/main/java/com/gitblit/Constants.java') diff --git a/src/main/java/com/gitblit/Constants.java b/src/main/java/com/gitblit/Constants.java index af533996..96f13c89 100644 --- a/src/main/java/com/gitblit/Constants.java +++ b/src/main/java/com/gitblit/Constants.java @@ -68,6 +68,8 @@ public class Constants { public static final String SPARKLESHARE_INVITE_PATH = "/sparkleshare/"; + public static final String BRANCH = "/branch/"; + public static final String BRANCH_GRAPH_PATH = "/graph/"; public static final String BORDER = "*****************************************************************"; -- cgit v1.2.3 From ff17f7bac432b4ba8310ba3ea335748a34859d50 Mon Sep 17 00:00:00 2001 From: James Moger Date: Mon, 5 May 2014 09:53:24 -0400 Subject: Replace RawPage with RawServlet --- src/main/java/WEB-INF/web.xml | 30 +- src/main/java/com/gitblit/Constants.java | 2 +- .../java/com/gitblit/servlet/BranchFilter.java | 126 ------ .../java/com/gitblit/servlet/BranchServlet.java | 480 --------------------- src/main/java/com/gitblit/servlet/PagesFilter.java | 2 +- .../java/com/gitblit/servlet/PagesServlet.java | 2 +- src/main/java/com/gitblit/servlet/RawFilter.java | 126 ++++++ src/main/java/com/gitblit/servlet/RawServlet.java | 472 ++++++++++++++++++++ .../java/com/gitblit/wicket/GitBlitWebApp.java | 4 +- .../java/com/gitblit/wicket/MarkupProcessor.java | 11 +- .../java/com/gitblit/wicket/pages/BasePage.java | 4 + .../java/com/gitblit/wicket/pages/BlobPage.java | 12 +- .../com/gitblit/wicket/pages/CommitDiffPage.java | 5 +- .../java/com/gitblit/wicket/pages/CommitPage.java | 5 +- .../java/com/gitblit/wicket/pages/ComparePage.java | 5 +- .../java/com/gitblit/wicket/pages/DocPage.java | 6 +- .../java/com/gitblit/wicket/pages/DocsPage.java | 9 +- .../java/com/gitblit/wicket/pages/TreePage.java | 6 +- .../java/com/gitblit/wicket/panels/TagsPanel.java | 11 +- 19 files changed, 664 insertions(+), 654 deletions(-) delete mode 100644 src/main/java/com/gitblit/servlet/BranchFilter.java delete mode 100644 src/main/java/com/gitblit/servlet/BranchServlet.java create mode 100644 src/main/java/com/gitblit/servlet/RawFilter.java create mode 100644 src/main/java/com/gitblit/servlet/RawServlet.java (limited to 'src/main/java/com/gitblit/Constants.java') diff --git a/src/main/java/WEB-INF/web.xml b/src/main/java/WEB-INF/web.xml index d60992dd..cb483af4 100644 --- a/src/main/java/WEB-INF/web.xml +++ b/src/main/java/WEB-INF/web.xml @@ -134,18 +134,18 @@ - - BranchServlet - com.gitblit.servlet.BranchServlet + RawServlet + com.gitblit.servlet.RawServlet - BranchServlet - /branch/* + RawServlet + /raw/* @@ -280,16 +280,16 @@ - BranchFilter - com.gitblit.servlet.BranchFilter + RawFilter + com.gitblit.servlet.RawFilter - BranchFilter - /branch/* + RawFilter + /raw/* @@ -340,12 +340,12 @@ * FederationServlet * RpcFilter * RpcServlet - * BranchFilter - * BranchServlet + * RawFilter + * RawServlet * PagesFilter * PagesServlet * com.gitblit.Constants.PAGES_PATH --> - r/,git/,pt,feed/,zip/,federation/,rpc/,branch/,pages/,robots.txt,logo.png,graph/,sparkleshare/ + r/,git/,pt,feed/,zip/,federation/,rpc/,raw/,pages/,robots.txt,logo.png,graph/,sparkleshare/ diff --git a/src/main/java/com/gitblit/Constants.java b/src/main/java/com/gitblit/Constants.java index 96f13c89..4b9755f3 100644 --- a/src/main/java/com/gitblit/Constants.java +++ b/src/main/java/com/gitblit/Constants.java @@ -68,7 +68,7 @@ public class Constants { public static final String SPARKLESHARE_INVITE_PATH = "/sparkleshare/"; - public static final String BRANCH = "/branch/"; + public static final String RAW_PATH = "/raw/"; public static final String BRANCH_GRAPH_PATH = "/graph/"; diff --git a/src/main/java/com/gitblit/servlet/BranchFilter.java b/src/main/java/com/gitblit/servlet/BranchFilter.java deleted file mode 100644 index 58b8f433..00000000 --- a/src/main/java/com/gitblit/servlet/BranchFilter.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2012 gitblit.com. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.gitblit.servlet; - -import org.eclipse.jgit.lib.Repository; - -import com.gitblit.Constants.AccessRestrictionType; -import com.gitblit.models.RepositoryModel; -import com.gitblit.models.UserModel; - -/** - * The BranchFilter is an AccessRestrictionFilter which ensures http branch - * requests for a view-restricted repository are authenticated and authorized. - * - * @author James Moger - * - */ -public class BranchFilter extends AccessRestrictionFilter { - - /** - * Extract the repository name from the url. - * - * @param url - * @return repository name - */ - @Override - protected String extractRepositoryName(String url) { - // get the repository name from the url by finding a known url suffix - String repository = ""; - Repository r = null; - int offset = 0; - while (r == null) { - int slash = url.indexOf('/', offset); - if (slash == -1) { - repository = url; - } else { - repository = url.substring(0, slash); - } - r = repositoryManager.getRepository(repository, false); - if (r == null) { - // try again - offset = slash + 1; - } else { - // close the repo - r.close(); - } - if (repository.equals(url)) { - // either only repository in url or no repository found - break; - } - } - return repository; - } - - /** - * Analyze the url and returns the action of the request. - * - * @param cloneUrl - * @return action of the request - */ - @Override - protected String getUrlRequestAction(String suffix) { - return "VIEW"; - } - - /** - * Determine if a non-existing repository can be created using this filter. - * - * @return true if the filter allows repository creation - */ - @Override - protected boolean isCreationAllowed() { - return false; - } - - /** - * Determine if the action may be executed on the repository. - * - * @param repository - * @param action - * @return true if the action may be performed - */ - @Override - protected boolean isActionAllowed(RepositoryModel repository, String action) { - return true; - } - - /** - * Determine if the repository requires authentication. - * - * @param repository - * @param action - * @return true if authentication required - */ - @Override - protected boolean requiresAuthentication(RepositoryModel repository, String action) { - return repository.accessRestriction.atLeast(AccessRestrictionType.VIEW); - } - - /** - * Determine if the user can access the repository and perform the specified - * action. - * - * @param repository - * @param user - * @param action - * @return true if user may execute the action on the repository - */ - @Override - protected boolean canAccess(RepositoryModel repository, UserModel user, String action) { - return user.canView(repository); - } -} diff --git a/src/main/java/com/gitblit/servlet/BranchServlet.java b/src/main/java/com/gitblit/servlet/BranchServlet.java deleted file mode 100644 index 33808961..00000000 --- a/src/main/java/com/gitblit/servlet/BranchServlet.java +++ /dev/null @@ -1,480 +0,0 @@ -/* - * Copyright 2014 gitblit.com. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.gitblit.servlet; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.text.MessageFormat; -import java.text.ParseException; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.tika.Tika; -import org.eclipse.jgit.lib.FileMode; -import org.eclipse.jgit.lib.MutableObjectId; -import org.eclipse.jgit.lib.ObjectLoader; -import org.eclipse.jgit.lib.ObjectReader; -import org.eclipse.jgit.lib.Repository; -import org.eclipse.jgit.revwalk.RevCommit; -import org.eclipse.jgit.revwalk.RevWalk; -import org.eclipse.jgit.treewalk.TreeWalk; -import org.eclipse.jgit.treewalk.filter.PathFilter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.gitblit.Constants; -import com.gitblit.Keys; -import com.gitblit.dagger.DaggerServlet; -import com.gitblit.manager.IRepositoryManager; -import com.gitblit.manager.IRuntimeManager; -import com.gitblit.models.PathModel; -import com.gitblit.utils.ByteFormat; -import com.gitblit.utils.JGitUtils; -import com.gitblit.utils.MarkdownUtils; -import com.gitblit.utils.StringUtils; - -import dagger.ObjectGraph; - -/** - * Serves the content of a branch. - * - * @author James Moger - * - */ -public class BranchServlet extends DaggerServlet { - - private static final long serialVersionUID = 1L; - - private transient Logger logger = LoggerFactory.getLogger(BranchServlet.class); - - private IRuntimeManager runtimeManager; - - private IRepositoryManager repositoryManager; - - @Override - protected void inject(ObjectGraph dagger) { - this.runtimeManager = dagger.get(IRuntimeManager.class); - this.repositoryManager = dagger.get(IRepositoryManager.class); - } - - /** - * Returns an url to this servlet for the specified parameters. - * - * @param baseURL - * @param repository - * @param branch - * @param path - * @return an url - */ - public static String asLink(String baseURL, String repository, String branch, String path) { - if (baseURL.length() > 0 && baseURL.charAt(baseURL.length() - 1) == '/') { - baseURL = baseURL.substring(0, baseURL.length() - 1); - } - String encodedPath = path.replace(' ', '-'); - try { - encodedPath = URLEncoder.encode(encodedPath, "UTF-8"); - } catch (UnsupportedEncodingException e) { - } - return baseURL + Constants.BRANCH + repository + "/" + (branch == null ? "" : (branch + "/" + (path == null ? "" : (encodedPath + "/")))); - } - - protected String getBranch(String repository, HttpServletRequest request) { - String pi = request.getPathInfo(); - String branch = pi.substring(pi.indexOf(repository) + repository.length() + 1); - int fs = branch.indexOf('/'); - if (fs > -1) { - branch = branch.substring(0, fs); - } - return branch; - } - - protected String getPath(String repository, String branch, HttpServletRequest request) { - String base = repository + "/" + branch; - String pi = request.getPathInfo().substring(1); - if (pi.equals(base)) { - return ""; - } - String path = pi.substring(pi.indexOf(base) + base.length() + 1); - if (path.endsWith("/")) { - path = path.substring(0, path.length() - 1); - } - return path; - } - - protected boolean renderIndex() { - return false; - } - - /** - * Retrieves the specified resource from the specified branch of the - * repository. - * - * @param request - * @param response - * @throws javax.servlet.ServletException - * @throws java.io.IOException - */ - private void processRequest(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - String path = request.getPathInfo(); - if (path.toLowerCase().endsWith(".git")) { - // forward to url with trailing / - // this is important for relative pages links - response.sendRedirect(request.getServletPath() + path + "/"); - return; - } - if (path.charAt(0) == '/') { - // strip leading / - path = path.substring(1); - } - - // determine repository and resource from url - String repository = ""; - Repository r = null; - int offset = 0; - while (r == null) { - int slash = path.indexOf('/', offset); - if (slash == -1) { - repository = path; - } else { - repository = path.substring(0, slash); - } - offset += slash; - r = repositoryManager.getRepository(repository, false); - if (repository.equals(path)) { - // either only repository in url or no repository found - break; - } - } - - ServletContext context = request.getSession().getServletContext(); - - try { - if (r == null) { - // repository not found! - String mkd = MessageFormat.format( - "# Error\nSorry, no valid **repository** specified in this url: {0}!", - path); - error(response, mkd); - return; - } - - // identify the branch - String branch = getBranch(repository, request); - if (StringUtils.isEmpty(branch)) { - branch = r.getBranch(); - if (branch == null) { - // no branches found! empty? - String mkd = MessageFormat.format( - "# Error\nSorry, no valid **branch** specified in this url: {0}!", - path); - error(response, mkd); - } else { - // redirect to default branch - String base = request.getRequestURI(); - String url = base + branch + "/"; - response.sendRedirect(url); - } - return; - } - - // identify the requested path - String requestedPath = getPath(repository, branch, request); - - // identify the commit - RevCommit commit = JGitUtils.getCommit(r, branch); - if (commit == null) { - // branch not found! - String mkd = MessageFormat.format( - "# Error\nSorry, the repository {0} does not have a **{1}** branch!", - repository, branch); - error(response, mkd); - return; - } - - - List pathEntries = JGitUtils.getFilesInPath(r, requestedPath, commit); - if (pathEntries.isEmpty()) { - // requested a specific resource - String file = StringUtils.getLastPathElement(requestedPath); - try { - // query Tika for the content type - Tika tika = new Tika(); - String contentType = tika.detect(file); - - if (contentType == null) { - // ask the container for the content type - contentType = context.getMimeType(requestedPath); - - if (contentType == null) { - // still unknown content type, assume binary - contentType = "application/octet-stream"; - } - } - - setContentType(response, contentType); - - if (isTextType(contentType)) { - - // load, interpret, and serve text content as UTF-8 - String [] encodings = runtimeManager.getSettings().getStrings(Keys.web.blobEncodings).toArray(new String[0]); - String content = JGitUtils.getStringContent(r, commit.getTree(), requestedPath, encodings); - - byte [] bytes = content.getBytes(Constants.ENCODING); - response.setContentLength(bytes.length); - ByteArrayInputStream is = new ByteArrayInputStream(bytes); - sendContent(response, JGitUtils.getCommitDate(commit), is); - - } else { - // serve binary content - String filename = StringUtils.getLastPathElement(requestedPath); - try { - String userAgent = request.getHeader("User-Agent"); - if (userAgent != null && userAgent.indexOf("MSIE 5.5") > -1) { - response.setHeader("Content-Disposition", "filename=\"" - + URLEncoder.encode(filename, Constants.ENCODING) + "\""); - } else if (userAgent != null && userAgent.indexOf("MSIE") > -1) { - response.setHeader("Content-Disposition", "attachment; filename=\"" - + URLEncoder.encode(filename, Constants.ENCODING) + "\""); - } else { - response.setHeader("Content-Disposition", "attachment; filename=\"" - + new String(filename.getBytes(Constants.ENCODING), "latin1") + "\""); - } - } - catch (UnsupportedEncodingException e) { - response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\""); - } - - // stream binary content directly from the repository - streamFromRepo(response, r, commit, requestedPath); - } - return; - } catch (Exception e) { - logger.error(null, e); - } - } else { - // path request - if (!request.getPathInfo().endsWith("/")) { - // redirect to trailing '/' url - response.sendRedirect(request.getServletPath() + request.getPathInfo() + "/"); - return; - } - - if (renderIndex()) { - // locate and render an index file - Map names = new TreeMap(); - for (PathModel entry : pathEntries) { - names.put(entry.name.toLowerCase(), entry.name); - } - - List extensions = new ArrayList(); - extensions.add("html"); - extensions.add("htm"); - - String content = null; - for (String ext : extensions) { - String key = "index." + ext; - - if (names.containsKey(key)) { - String fileName = names.get(key); - String fullPath = fileName; - if (!requestedPath.isEmpty()) { - fullPath = requestedPath + "/" + fileName; - } - - String [] encodings = runtimeManager.getSettings().getStrings(Keys.web.blobEncodings).toArray(new String[0]); - String stringContent = JGitUtils.getStringContent(r, commit.getTree(), fullPath, encodings); - if (stringContent == null) { - continue; - } - content = stringContent; - requestedPath = fullPath; - break; - } - } - - response.setContentType("text/html; charset=" + Constants.ENCODING); - byte [] bytes = content.getBytes(Constants.ENCODING); - response.setContentLength(bytes.length); - - ByteArrayInputStream is = new ByteArrayInputStream(bytes); - sendContent(response, JGitUtils.getCommitDate(commit), is); - return; - } - } - - // no content, document list or 404 page - if (pathEntries.isEmpty()) { - // default 404 page - String str = MessageFormat.format( - "# Error\nSorry, the requested resource **{0}** was not found.", - requestedPath); - String content = MarkdownUtils.transformMarkdown(str); - - try { - response.setStatus(HttpServletResponse.SC_NOT_FOUND); - - byte [] bytes = content.getBytes(Constants.ENCODING); - ByteArrayInputStream is = new ByteArrayInputStream(bytes); - sendContent(response, new Date(), is); - return; - } catch (Throwable t) { - logger.error("Failed to write page to client", t); - } - } else { - // - // directory list - // - response.setContentType("text/html"); - response.getWriter().append(""); - response.getWriter().append(""); - response.getWriter().append(""); - response.getWriter().append(""); - response.getWriter().append(""); - String pattern = ""; - final ByteFormat byteFormat = new ByteFormat(); - if (!pathEntries.isEmpty()) { - if (pathEntries.get(0).path.indexOf('/') > -1) { - // we are in a subdirectory, add parent directory link - String pp = URLEncoder.encode(requestedPath, Constants.ENCODING); - pathEntries.add(0, new PathModel("..", pp + "/..", 0, FileMode.TREE.getBits(), null, null)); - } - } - - String basePath = request.getServletPath() + request.getPathInfo(); - if (basePath.charAt(basePath.length() - 1) == '/') { - // strip trailing slash - basePath = basePath.substring(0, basePath.length() - 1); - } - for (PathModel entry : pathEntries) { - String pp = URLEncoder.encode(entry.name, Constants.ENCODING); - response.getWriter().append(MessageFormat.format(pattern, basePath, pp, - JGitUtils.getPermissionsFromMode(entry.mode), byteFormat.format(entry.size))); - } - response.getWriter().append(""); - response.getWriter().append("
pathmodesize
{1}{2}{3}
"); - } - } catch (Throwable t) { - logger.error("Failed to write page to client", t); - } finally { - r.close(); - } - } - - protected boolean isTextType(String contentType) { - if (contentType.startsWith("text/") - || "application/json".equals(contentType) - || "application/xml".equals(contentType)) { - return true; - } - return false; - } - - /** - * Override all text types to be plain text. - * - * @param response - * @param contentType - */ - protected void setContentType(HttpServletResponse response, String contentType) { - if (isTextType(contentType)) { - response.setContentType("text/plain"); - } else { - response.setContentType(contentType); - } - } - - private void streamFromRepo(HttpServletResponse response, Repository repository, - RevCommit commit, String requestedPath) throws IOException { - - response.setDateHeader("Last-Modified", JGitUtils.getCommitDate(commit).getTime()); - response.setHeader("Cache-Control", "public, max-age=3600, must-revalidate"); - - RevWalk rw = new RevWalk(repository); - TreeWalk tw = new TreeWalk(repository); - try { - tw.reset(); - tw.addTree(commit.getTree()); - PathFilter f = PathFilter.create(requestedPath); - tw.setFilter(f); - tw.setRecursive(true); - MutableObjectId id = new MutableObjectId(); - ObjectReader reader = tw.getObjectReader(); - while (tw.next()) { - FileMode mode = tw.getFileMode(0); - if (mode == FileMode.GITLINK || mode == FileMode.TREE) { - continue; - } - tw.getObjectId(id, 0); - - long len = reader.getObjectSize(id, org.eclipse.jgit.lib.Constants.OBJ_BLOB); - response.setIntHeader("Content-Length", (int) len); - ObjectLoader ldr = repository.open(id); - ldr.copyTo(response.getOutputStream()); - } - } finally { - tw.release(); - rw.dispose(); - } - - response.flushBuffer(); - } - - private void sendContent(HttpServletResponse response, Date date, InputStream is) throws ServletException, IOException { - response.setDateHeader("Last-Modified", date.getTime()); - response.setHeader("Cache-Control", "public, max-age=3600, must-revalidate"); - try { - byte[] tmp = new byte[8192]; - int len = 0; - while ((len = is.read(tmp)) > -1) { - response.getOutputStream().write(tmp, 0, len); - } - } finally { - is.close(); - } - response.flushBuffer(); - } - - private void error(HttpServletResponse response, String mkd) throws ServletException, - IOException, ParseException { - String content = MarkdownUtils.transformMarkdown(mkd); - response.setContentType("text/html; charset=" + Constants.ENCODING); - response.getWriter().write(content); - } - - @Override - protected void doPost(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - processRequest(request, response); - } - - @Override - protected void doGet(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - processRequest(request, response); - } -} diff --git a/src/main/java/com/gitblit/servlet/PagesFilter.java b/src/main/java/com/gitblit/servlet/PagesFilter.java index 0535ea06..e07d9b3b 100644 --- a/src/main/java/com/gitblit/servlet/PagesFilter.java +++ b/src/main/java/com/gitblit/servlet/PagesFilter.java @@ -23,7 +23,7 @@ package com.gitblit.servlet; * @author James Moger * */ -public class PagesFilter extends BranchFilter { +public class PagesFilter extends RawFilter { } diff --git a/src/main/java/com/gitblit/servlet/PagesServlet.java b/src/main/java/com/gitblit/servlet/PagesServlet.java index 7919e442..f578f86f 100644 --- a/src/main/java/com/gitblit/servlet/PagesServlet.java +++ b/src/main/java/com/gitblit/servlet/PagesServlet.java @@ -26,7 +26,7 @@ import com.gitblit.Constants; * @author James Moger * */ -public class PagesServlet extends BranchServlet { +public class PagesServlet extends RawServlet { private static final long serialVersionUID = 1L; diff --git a/src/main/java/com/gitblit/servlet/RawFilter.java b/src/main/java/com/gitblit/servlet/RawFilter.java new file mode 100644 index 00000000..34989c98 --- /dev/null +++ b/src/main/java/com/gitblit/servlet/RawFilter.java @@ -0,0 +1,126 @@ +/* + * Copyright 2012 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.servlet; + +import org.eclipse.jgit.lib.Repository; + +import com.gitblit.Constants.AccessRestrictionType; +import com.gitblit.models.RepositoryModel; +import com.gitblit.models.UserModel; + +/** + * The RawFilter is an AccessRestrictionFilter which ensures http branch + * requests for a view-restricted repository are authenticated and authorized. + * + * @author James Moger + * + */ +public class RawFilter extends AccessRestrictionFilter { + + /** + * Extract the repository name from the url. + * + * @param url + * @return repository name + */ + @Override + protected String extractRepositoryName(String url) { + // get the repository name from the url by finding a known url suffix + String repository = ""; + Repository r = null; + int offset = 0; + while (r == null) { + int slash = url.indexOf('/', offset); + if (slash == -1) { + repository = url; + } else { + repository = url.substring(0, slash); + } + r = repositoryManager.getRepository(repository, false); + if (r == null) { + // try again + offset = slash + 1; + } else { + // close the repo + r.close(); + } + if (repository.equals(url)) { + // either only repository in url or no repository found + break; + } + } + return repository; + } + + /** + * Analyze the url and returns the action of the request. + * + * @param cloneUrl + * @return action of the request + */ + @Override + protected String getUrlRequestAction(String suffix) { + return "VIEW"; + } + + /** + * Determine if a non-existing repository can be created using this filter. + * + * @return true if the filter allows repository creation + */ + @Override + protected boolean isCreationAllowed() { + return false; + } + + /** + * Determine if the action may be executed on the repository. + * + * @param repository + * @param action + * @return true if the action may be performed + */ + @Override + protected boolean isActionAllowed(RepositoryModel repository, String action) { + return true; + } + + /** + * Determine if the repository requires authentication. + * + * @param repository + * @param action + * @return true if authentication required + */ + @Override + protected boolean requiresAuthentication(RepositoryModel repository, String action) { + return repository.accessRestriction.atLeast(AccessRestrictionType.VIEW); + } + + /** + * Determine if the user can access the repository and perform the specified + * action. + * + * @param repository + * @param user + * @param action + * @return true if user may execute the action on the repository + */ + @Override + protected boolean canAccess(RepositoryModel repository, UserModel user, String action) { + return user.canView(repository); + } +} diff --git a/src/main/java/com/gitblit/servlet/RawServlet.java b/src/main/java/com/gitblit/servlet/RawServlet.java new file mode 100644 index 00000000..cde7b2e1 --- /dev/null +++ b/src/main/java/com/gitblit/servlet/RawServlet.java @@ -0,0 +1,472 @@ +/* + * Copyright 2014 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.servlet; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.text.MessageFormat; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.tika.Tika; +import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.lib.MutableObjectId; +import org.eclipse.jgit.lib.ObjectLoader; +import org.eclipse.jgit.lib.ObjectReader; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.revwalk.RevWalk; +import org.eclipse.jgit.treewalk.TreeWalk; +import org.eclipse.jgit.treewalk.filter.PathFilter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.gitblit.Constants; +import com.gitblit.Keys; +import com.gitblit.dagger.DaggerServlet; +import com.gitblit.manager.IRepositoryManager; +import com.gitblit.manager.IRuntimeManager; +import com.gitblit.models.PathModel; +import com.gitblit.utils.ByteFormat; +import com.gitblit.utils.JGitUtils; +import com.gitblit.utils.MarkdownUtils; +import com.gitblit.utils.StringUtils; + +import dagger.ObjectGraph; + +/** + * Serves the content of a branch. + * + * @author James Moger + * + */ +public class RawServlet extends DaggerServlet { + + private static final long serialVersionUID = 1L; + + private transient Logger logger = LoggerFactory.getLogger(RawServlet.class); + + private IRuntimeManager runtimeManager; + + private IRepositoryManager repositoryManager; + + @Override + protected void inject(ObjectGraph dagger) { + this.runtimeManager = dagger.get(IRuntimeManager.class); + this.repositoryManager = dagger.get(IRepositoryManager.class); + } + + /** + * Returns an url to this servlet for the specified parameters. + * + * @param baseURL + * @param repository + * @param branch + * @param path + * @return an url + */ + public static String asLink(String baseURL, String repository, String branch, String path) { + if (baseURL.length() > 0 && baseURL.charAt(baseURL.length() - 1) == '/') { + baseURL = baseURL.substring(0, baseURL.length() - 1); + } + String encodedPath = path.replace(' ', '-'); + try { + encodedPath = URLEncoder.encode(encodedPath, "UTF-8"); + } catch (UnsupportedEncodingException e) { + } + return baseURL + Constants.RAW_PATH + repository + "/" + (branch == null ? "" : (branch + "/" + (path == null ? "" : encodedPath))); + } + + protected String getBranch(String repository, HttpServletRequest request) { + String pi = request.getPathInfo(); + String branch = pi.substring(pi.indexOf(repository) + repository.length() + 1); + int fs = branch.indexOf('/'); + if (fs > -1) { + branch = branch.substring(0, fs); + } + return branch; + } + + protected String getPath(String repository, String branch, HttpServletRequest request) { + String base = repository + "/" + branch; + String pi = request.getPathInfo().substring(1); + if (pi.equals(base)) { + return ""; + } + String path = pi.substring(pi.indexOf(base) + base.length() + 1); + if (path.endsWith("/")) { + path = path.substring(0, path.length() - 1); + } + return path; + } + + protected boolean renderIndex() { + return false; + } + + /** + * Retrieves the specified resource from the specified branch of the + * repository. + * + * @param request + * @param response + * @throws javax.servlet.ServletException + * @throws java.io.IOException + */ + private void processRequest(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + String path = request.getPathInfo(); + if (path.toLowerCase().endsWith(".git")) { + // forward to url with trailing / + // this is important for relative pages links + response.sendRedirect(request.getServletPath() + path + "/"); + return; + } + if (path.charAt(0) == '/') { + // strip leading / + path = path.substring(1); + } + + // determine repository and resource from url + String repository = ""; + Repository r = null; + int offset = 0; + while (r == null) { + int slash = path.indexOf('/', offset); + if (slash == -1) { + repository = path; + } else { + repository = path.substring(0, slash); + } + offset += slash; + r = repositoryManager.getRepository(repository, false); + if (repository.equals(path)) { + // either only repository in url or no repository found + break; + } + } + + ServletContext context = request.getSession().getServletContext(); + + try { + if (r == null) { + // repository not found! + String mkd = MessageFormat.format( + "# Error\nSorry, no valid **repository** specified in this url: {0}!", + path); + error(response, mkd); + return; + } + + // identify the branch + String branch = getBranch(repository, request); + if (StringUtils.isEmpty(branch)) { + branch = r.getBranch(); + if (branch == null) { + // no branches found! empty? + String mkd = MessageFormat.format( + "# Error\nSorry, no valid **branch** specified in this url: {0}!", + path); + error(response, mkd); + } else { + // redirect to default branch + String base = request.getRequestURI(); + String url = base + branch + "/"; + response.sendRedirect(url); + } + return; + } + + // identify the requested path + String requestedPath = getPath(repository, branch, request); + + // identify the commit + RevCommit commit = JGitUtils.getCommit(r, branch); + if (commit == null) { + // branch not found! + String mkd = MessageFormat.format( + "# Error\nSorry, the repository {0} does not have a **{1}** branch!", + repository, branch); + error(response, mkd); + return; + } + + + List pathEntries = JGitUtils.getFilesInPath(r, requestedPath, commit); + if (pathEntries.isEmpty()) { + // requested a specific resource + String file = StringUtils.getLastPathElement(requestedPath); + try { + // query Tika for the content type + Tika tika = new Tika(); + String contentType = tika.detect(file); + + if (contentType == null) { + // ask the container for the content type + contentType = context.getMimeType(requestedPath); + + if (contentType == null) { + // still unknown content type, assume binary + contentType = "application/octet-stream"; + } + } + + setContentType(response, contentType); + + if (isTextType(contentType)) { + + // load, interpret, and serve text content as UTF-8 + String [] encodings = runtimeManager.getSettings().getStrings(Keys.web.blobEncodings).toArray(new String[0]); + String content = JGitUtils.getStringContent(r, commit.getTree(), requestedPath, encodings); + + byte [] bytes = content.getBytes(Constants.ENCODING); + response.setContentLength(bytes.length); + ByteArrayInputStream is = new ByteArrayInputStream(bytes); + sendContent(response, JGitUtils.getCommitDate(commit), is); + + } else { + // serve binary content + String filename = StringUtils.getLastPathElement(requestedPath); + try { + String userAgent = request.getHeader("User-Agent"); + if (userAgent != null && userAgent.indexOf("MSIE 5.5") > -1) { + response.setHeader("Content-Disposition", "filename=\"" + + URLEncoder.encode(filename, Constants.ENCODING) + "\""); + } else if (userAgent != null && userAgent.indexOf("MSIE") > -1) { + response.setHeader("Content-Disposition", "attachment; filename=\"" + + URLEncoder.encode(filename, Constants.ENCODING) + "\""); + } else { + response.setHeader("Content-Disposition", "attachment; filename=\"" + + new String(filename.getBytes(Constants.ENCODING), "latin1") + "\""); + } + } + catch (UnsupportedEncodingException e) { + response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\""); + } + + // stream binary content directly from the repository + streamFromRepo(response, r, commit, requestedPath); + } + return; + } catch (Exception e) { + logger.error(null, e); + } + } else { + // path request + if (!request.getPathInfo().endsWith("/")) { + // redirect to trailing '/' url + response.sendRedirect(request.getServletPath() + request.getPathInfo() + "/"); + return; + } + + if (renderIndex()) { + // locate and render an index file + Map names = new TreeMap(); + for (PathModel entry : pathEntries) { + names.put(entry.name.toLowerCase(), entry.name); + } + + List extensions = new ArrayList(); + extensions.add("html"); + extensions.add("htm"); + + String content = null; + for (String ext : extensions) { + String key = "index." + ext; + + if (names.containsKey(key)) { + String fileName = names.get(key); + String fullPath = fileName; + if (!requestedPath.isEmpty()) { + fullPath = requestedPath + "/" + fileName; + } + + String [] encodings = runtimeManager.getSettings().getStrings(Keys.web.blobEncodings).toArray(new String[0]); + String stringContent = JGitUtils.getStringContent(r, commit.getTree(), fullPath, encodings); + if (stringContent == null) { + continue; + } + content = stringContent; + requestedPath = fullPath; + break; + } + } + + response.setContentType("text/html; charset=" + Constants.ENCODING); + byte [] bytes = content.getBytes(Constants.ENCODING); + response.setContentLength(bytes.length); + + ByteArrayInputStream is = new ByteArrayInputStream(bytes); + sendContent(response, JGitUtils.getCommitDate(commit), is); + return; + } + } + + // no content, document list or 404 page + if (pathEntries.isEmpty()) { + // default 404 page + String str = MessageFormat.format( + "# Error\nSorry, the requested resource **{0}** was not found.", + requestedPath); + response.setStatus(HttpServletResponse.SC_NOT_FOUND); + error(response, str); + return; + } else { + // + // directory list + // + response.setContentType("text/html"); + response.getWriter().append(""); + response.getWriter().append(""); + response.getWriter().append(""); + response.getWriter().append(""); + response.getWriter().append(""); + String pattern = ""; + final ByteFormat byteFormat = new ByteFormat(); + if (!pathEntries.isEmpty()) { + if (pathEntries.get(0).path.indexOf('/') > -1) { + // we are in a subdirectory, add parent directory link + String pp = URLEncoder.encode(requestedPath, Constants.ENCODING); + pathEntries.add(0, new PathModel("..", pp + "/..", 0, FileMode.TREE.getBits(), null, null)); + } + } + + String basePath = request.getServletPath() + request.getPathInfo(); + if (basePath.charAt(basePath.length() - 1) == '/') { + // strip trailing slash + basePath = basePath.substring(0, basePath.length() - 1); + } + for (PathModel entry : pathEntries) { + String pp = URLEncoder.encode(entry.name, Constants.ENCODING); + response.getWriter().append(MessageFormat.format(pattern, basePath, pp, + JGitUtils.getPermissionsFromMode(entry.mode), + entry.isFile() ? byteFormat.format(entry.size) : "")); + } + response.getWriter().append(""); + response.getWriter().append("
pathmodesize
{1}{2}{3}
"); + } + } catch (Throwable t) { + logger.error("Failed to write page to client", t); + } finally { + r.close(); + } + } + + protected boolean isTextType(String contentType) { + if (contentType.startsWith("text/") + || "application/json".equals(contentType) + || "application/xml".equals(contentType)) { + return true; + } + return false; + } + + /** + * Override all text types to be plain text. + * + * @param response + * @param contentType + */ + protected void setContentType(HttpServletResponse response, String contentType) { + if (isTextType(contentType)) { + response.setContentType("text/plain"); + } else { + response.setContentType(contentType); + } + } + + private void streamFromRepo(HttpServletResponse response, Repository repository, + RevCommit commit, String requestedPath) throws IOException { + + response.setDateHeader("Last-Modified", JGitUtils.getCommitDate(commit).getTime()); + response.setHeader("Cache-Control", "public, max-age=3600, must-revalidate"); + + RevWalk rw = new RevWalk(repository); + TreeWalk tw = new TreeWalk(repository); + try { + tw.reset(); + tw.addTree(commit.getTree()); + PathFilter f = PathFilter.create(requestedPath); + tw.setFilter(f); + tw.setRecursive(true); + MutableObjectId id = new MutableObjectId(); + ObjectReader reader = tw.getObjectReader(); + while (tw.next()) { + FileMode mode = tw.getFileMode(0); + if (mode == FileMode.GITLINK || mode == FileMode.TREE) { + continue; + } + tw.getObjectId(id, 0); + + long len = reader.getObjectSize(id, org.eclipse.jgit.lib.Constants.OBJ_BLOB); + response.setIntHeader("Content-Length", (int) len); + ObjectLoader ldr = repository.open(id); + ldr.copyTo(response.getOutputStream()); + } + } finally { + tw.release(); + rw.dispose(); + } + + response.flushBuffer(); + } + + private void sendContent(HttpServletResponse response, Date date, InputStream is) throws ServletException, IOException { + response.setDateHeader("Last-Modified", date.getTime()); + response.setHeader("Cache-Control", "public, max-age=3600, must-revalidate"); + try { + byte[] tmp = new byte[8192]; + int len = 0; + while ((len = is.read(tmp)) > -1) { + response.getOutputStream().write(tmp, 0, len); + } + } finally { + is.close(); + } + response.flushBuffer(); + } + + private void error(HttpServletResponse response, String mkd) throws ServletException, + IOException, ParseException { + String content = MarkdownUtils.transformMarkdown(mkd); + response.setContentType("text/html; charset=" + Constants.ENCODING); + response.getWriter().write(content); + } + + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + processRequest(request, response); + } + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + processRequest(request, response); + } +} diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.java b/src/main/java/com/gitblit/wicket/GitBlitWebApp.java index 9f002d2b..dc79af26 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.java +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.java @@ -64,13 +64,13 @@ import com.gitblit.wicket.pages.LogoutPage; import com.gitblit.wicket.pages.LuceneSearchPage; import com.gitblit.wicket.pages.MetricsPage; import com.gitblit.wicket.pages.MyDashboardPage; +import com.gitblit.wicket.pages.MyTicketsPage; import com.gitblit.wicket.pages.NewMilestonePage; import com.gitblit.wicket.pages.NewTicketPage; import com.gitblit.wicket.pages.OverviewPage; import com.gitblit.wicket.pages.PatchPage; import com.gitblit.wicket.pages.ProjectPage; import com.gitblit.wicket.pages.ProjectsPage; -import com.gitblit.wicket.pages.RawPage; import com.gitblit.wicket.pages.ReflogPage; import com.gitblit.wicket.pages.RepositoriesPage; import com.gitblit.wicket.pages.ReviewProposalPage; @@ -81,7 +81,6 @@ import com.gitblit.wicket.pages.TicketsPage; import com.gitblit.wicket.pages.TreePage; import com.gitblit.wicket.pages.UserPage; import com.gitblit.wicket.pages.UsersPage; -import com.gitblit.wicket.pages.MyTicketsPage; public class GitBlitWebApp extends WebApplication { @@ -173,7 +172,6 @@ public class GitBlitWebApp extends WebApplication { mount("/tag", TagPage.class, "r", "h"); mount("/tree", TreePage.class, "r", "h", "f"); mount("/blob", BlobPage.class, "r", "h", "f"); - mount("/raw", RawPage.class, "r", "h", "f"); mount("/blobdiff", BlobDiffPage.class, "r", "h", "f"); mount("/commitdiff", CommitDiffPage.class, "r", "h"); mount("/compare", ComparePage.class, "r", "h"); diff --git a/src/main/java/com/gitblit/wicket/MarkupProcessor.java b/src/main/java/com/gitblit/wicket/MarkupProcessor.java index ff6fbce2..e7681f2c 100644 --- a/src/main/java/com/gitblit/wicket/MarkupProcessor.java +++ b/src/main/java/com/gitblit/wicket/MarkupProcessor.java @@ -56,11 +56,11 @@ import org.slf4j.LoggerFactory; import com.gitblit.IStoredSettings; import com.gitblit.Keys; import com.gitblit.models.PathModel; +import com.gitblit.servlet.RawServlet; import com.gitblit.utils.JGitUtils; import com.gitblit.utils.MarkdownUtils; import com.gitblit.utils.StringUtils; import com.gitblit.wicket.pages.DocPage; -import com.gitblit.wicket.pages.RawPage; import com.google.common.base.Joiner; /** @@ -260,7 +260,8 @@ public class MarkupProcessor { if (imagePath.indexOf("://") == -1) { // relative image String path = doc.getRelativePath(imagePath); - url = getWicketUrl(RawPage.class, repositoryName, commitId, path); + String contextUrl = RequestCycle.get().getRequest().getRelativePathPrefixToContextRoot(); + url = RawServlet.asLink(contextUrl, repositoryName, commitId, path); } else { // absolute image url = imagePath; @@ -312,7 +313,8 @@ public class MarkupProcessor { if (node.url.indexOf("://") == -1) { // repository-relative image link String path = doc.getRelativePath(node.url); - String url = getWicketUrl(RawPage.class, repositoryName, commitId, path); + String contextUrl = RequestCycle.get().getRequest().getRelativePathPrefixToContextRoot(); + String url = RawServlet.asLink(contextUrl, repositoryName, commitId, path); return new Rendering(url, text); } // absolute image link @@ -325,7 +327,8 @@ public class MarkupProcessor { if (url.indexOf("://") == -1) { // repository-relative image link String path = doc.getRelativePath(url); - String wurl = getWicketUrl(RawPage.class, repositoryName, commitId, path); + String contextUrl = RequestCycle.get().getRequest().getRelativePathPrefixToContextRoot(); + String wurl = RawServlet.asLink(contextUrl, repositoryName, commitId, path); rendering = new Rendering(wurl, alt); } else { // absolute image link diff --git a/src/main/java/com/gitblit/wicket/pages/BasePage.java b/src/main/java/com/gitblit/wicket/pages/BasePage.java index 7d3d3a24..49710397 100644 --- a/src/main/java/com/gitblit/wicket/pages/BasePage.java +++ b/src/main/java/com/gitblit/wicket/pages/BasePage.java @@ -98,6 +98,10 @@ public abstract class BasePage extends SessionPage { } } + protected String getContextUrl() { + return getRequest().getRelativePathPrefixToContextRoot(); + } + protected String getCanonicalUrl() { return getCanonicalUrl(getClass(), getPageParameters()); } diff --git a/src/main/java/com/gitblit/wicket/pages/BlobPage.java b/src/main/java/com/gitblit/wicket/pages/BlobPage.java index 299d8dbc..f3d0bc92 100644 --- a/src/main/java/com/gitblit/wicket/pages/BlobPage.java +++ b/src/main/java/com/gitblit/wicket/pages/BlobPage.java @@ -24,10 +24,12 @@ import org.apache.wicket.PageParameters; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.image.Image; import org.apache.wicket.markup.html.link.BookmarkablePageLink; +import org.apache.wicket.markup.html.link.ExternalLink; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevCommit; import com.gitblit.Keys; +import com.gitblit.servlet.RawServlet; import com.gitblit.utils.JGitUtils; import com.gitblit.utils.StringUtils; import com.gitblit.wicket.CacheControl; @@ -57,8 +59,8 @@ public class BlobPage extends RepositoryPage { WicketUtils.newPathParameter(repositoryName, objectId, blobPath)) .setEnabled(false)); add(new BookmarkablePageLink("historyLink", HistoryPage.class).setEnabled(false)); - add(new BookmarkablePageLink("rawLink", RawPage.class, - WicketUtils.newPathParameter(repositoryName, objectId, blobPath))); + String rawUrl = RawServlet.asLink(getContextUrl(), repositoryName, objectId, blobPath); + add(new ExternalLink("rawLink", rawUrl)); add(new CommitHeaderPanel("commitHeader", objectId)); add(new PathBreadcrumbsPanel("breadcrumbs", repositoryName, blobPath, objectId)); Component c = new Label("blobText", JGitUtils.getStringContent(r, objectId, encodings)); @@ -87,8 +89,8 @@ public class BlobPage extends RepositoryPage { WicketUtils.newPathParameter(repositoryName, objectId, blobPath))); add(new BookmarkablePageLink("historyLink", HistoryPage.class, WicketUtils.newPathParameter(repositoryName, objectId, blobPath))); - add(new BookmarkablePageLink("rawLink", RawPage.class, - WicketUtils.newPathParameter(repositoryName, objectId, blobPath))); + String rawUrl = RawServlet.asLink(getContextUrl(), repositoryName, objectId, blobPath); + add(new ExternalLink("rawLink", rawUrl)); add(new CommitHeaderPanel("commitHeader", repositoryName, commit)); @@ -115,7 +117,7 @@ public class BlobPage extends RepositoryPage { case 2: // image blobs add(new Label("blobText").setVisible(false)); - add(new ExternalImage("blobImage", urlFor(RawPage.class, WicketUtils.newPathParameter(repositoryName, objectId, blobPath)).toString())); + add(new ExternalImage("blobImage", rawUrl)); break; case 3: // binary blobs diff --git a/src/main/java/com/gitblit/wicket/pages/CommitDiffPage.java b/src/main/java/com/gitblit/wicket/pages/CommitDiffPage.java index 7f2a8a61..71a5ea67 100644 --- a/src/main/java/com/gitblit/wicket/pages/CommitDiffPage.java +++ b/src/main/java/com/gitblit/wicket/pages/CommitDiffPage.java @@ -34,6 +34,7 @@ import com.gitblit.Constants; import com.gitblit.models.GitNote; import com.gitblit.models.PathModel.PathChangeModel; import com.gitblit.models.SubmoduleModel; +import com.gitblit.servlet.RawServlet; import com.gitblit.utils.DiffUtils; import com.gitblit.utils.DiffUtils.DiffOutput; import com.gitblit.utils.DiffUtils.DiffOutputType; @@ -170,8 +171,8 @@ public class CommitDiffPage extends RepositoryPage { item.add(new BookmarkablePageLink("view", BlobPage.class, WicketUtils .newPathParameter(repositoryName, entry.commitId, entry.path)) .setEnabled(!entry.changeType.equals(ChangeType.DELETE))); - item.add(new BookmarkablePageLink("raw", RawPage.class, WicketUtils - .newPathParameter(repositoryName, entry.commitId, entry.path)) + String rawUrl = RawServlet.asLink(getContextUrl(), repositoryName, entry.commitId, entry.path); + item.add(new ExternalLink("raw", rawUrl) .setEnabled(!entry.changeType.equals(ChangeType.DELETE))); item.add(new BookmarkablePageLink("blame", BlamePage.class, WicketUtils .newPathParameter(repositoryName, entry.commitId, entry.path)) diff --git a/src/main/java/com/gitblit/wicket/pages/CommitPage.java b/src/main/java/com/gitblit/wicket/pages/CommitPage.java index 8bc98489..6fadec5b 100644 --- a/src/main/java/com/gitblit/wicket/pages/CommitPage.java +++ b/src/main/java/com/gitblit/wicket/pages/CommitPage.java @@ -35,6 +35,7 @@ import com.gitblit.Constants; import com.gitblit.models.GitNote; import com.gitblit.models.PathModel.PathChangeModel; import com.gitblit.models.SubmoduleModel; +import com.gitblit.servlet.RawServlet; import com.gitblit.utils.JGitUtils; import com.gitblit.wicket.CacheControl; import com.gitblit.wicket.CacheControl.LastModified; @@ -222,8 +223,8 @@ public class CommitPage extends RepositoryPage { item.add(new BookmarkablePageLink("view", BlobPage.class, WicketUtils .newPathParameter(repositoryName, entry.commitId, entry.path)) .setEnabled(!entry.changeType.equals(ChangeType.DELETE))); - item.add(new BookmarkablePageLink("raw", RawPage.class, WicketUtils - .newPathParameter(repositoryName, entry.commitId, entry.path)) + String rawUrl = RawServlet.asLink(getContextUrl(), repositoryName, entry.commitId, entry.path); + item.add(new ExternalLink("raw", rawUrl) .setEnabled(!entry.changeType.equals(ChangeType.DELETE))); item.add(new BookmarkablePageLink("blame", BlamePage.class, WicketUtils .newPathParameter(repositoryName, entry.commitId, entry.path)) diff --git a/src/main/java/com/gitblit/wicket/pages/ComparePage.java b/src/main/java/com/gitblit/wicket/pages/ComparePage.java index 2024bf17..1ec66133 100644 --- a/src/main/java/com/gitblit/wicket/pages/ComparePage.java +++ b/src/main/java/com/gitblit/wicket/pages/ComparePage.java @@ -41,6 +41,7 @@ import com.gitblit.models.PathModel.PathChangeModel; import com.gitblit.models.RefModel; import com.gitblit.models.RepositoryModel; import com.gitblit.models.SubmoduleModel; +import com.gitblit.servlet.RawServlet; import com.gitblit.utils.DiffUtils; import com.gitblit.utils.DiffUtils.DiffOutput; import com.gitblit.utils.DiffUtils.DiffOutputType; @@ -184,8 +185,8 @@ public class ComparePage extends RepositoryPage { item.add(new BookmarkablePageLink("view", BlobPage.class, WicketUtils .newPathParameter(repositoryName, endId, entry.path)) .setEnabled(!entry.changeType.equals(ChangeType.DELETE))); - item.add(new BookmarkablePageLink("raw", RawPage.class, WicketUtils - .newPathParameter(repositoryName, endId, entry.path)) + String rawUrl = RawServlet.asLink(getContextUrl(), repositoryName, endId, entry.path); + item.add(new ExternalLink("raw", rawUrl) .setEnabled(!entry.changeType.equals(ChangeType.DELETE))); item.add(new BookmarkablePageLink("blame", BlamePage.class, WicketUtils .newPathParameter(repositoryName, endId, entry.path)) diff --git a/src/main/java/com/gitblit/wicket/pages/DocPage.java b/src/main/java/com/gitblit/wicket/pages/DocPage.java index bf99978c..c06d8065 100644 --- a/src/main/java/com/gitblit/wicket/pages/DocPage.java +++ b/src/main/java/com/gitblit/wicket/pages/DocPage.java @@ -20,10 +20,12 @@ import java.util.List; import org.apache.wicket.PageParameters; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.link.BookmarkablePageLink; +import org.apache.wicket.markup.html.link.ExternalLink; import org.apache.wicket.markup.html.panel.Fragment; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevCommit; +import com.gitblit.servlet.RawServlet; import com.gitblit.utils.BugtraqProcessor; import com.gitblit.utils.JGitUtils; import com.gitblit.utils.StringUtils; @@ -87,8 +89,8 @@ public class DocPage extends RepositoryPage { WicketUtils.newPathParameter(repositoryName, objectId, documentPath))); fragment.add(new BookmarkablePageLink("historyLink", HistoryPage.class, WicketUtils.newPathParameter(repositoryName, objectId, documentPath))); - fragment.add(new BookmarkablePageLink("rawLink", RawPage.class, WicketUtils.newPathParameter( - repositoryName, objectId, documentPath))); + String rawUrl = RawServlet.asLink(getContextUrl(), repositoryName, objectId, documentPath); + fragment.add(new ExternalLink("rawLink", rawUrl)); fragment.add(new Label("content", markupDoc.html).setEscapeModelStrings(false)); add(fragment); diff --git a/src/main/java/com/gitblit/wicket/pages/DocsPage.java b/src/main/java/com/gitblit/wicket/pages/DocsPage.java index 907dd6e2..fc56ee07 100644 --- a/src/main/java/com/gitblit/wicket/pages/DocsPage.java +++ b/src/main/java/com/gitblit/wicket/pages/DocsPage.java @@ -31,6 +31,7 @@ import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevCommit; import com.gitblit.models.PathModel; +import com.gitblit.servlet.RawServlet; import com.gitblit.utils.ByteFormat; import com.gitblit.utils.JGitUtils; import com.gitblit.utils.StringUtils; @@ -103,8 +104,8 @@ public class DocsPage extends RepositoryPage { WicketUtils.newPathParameter(repositoryName, commitId, doc.documentPath))); item.add(new BookmarkablePageLink("historyLink", HistoryPage.class, WicketUtils.newPathParameter(repositoryName, commitId, doc.documentPath))); - item.add(new BookmarkablePageLink("rawLink", RawPage.class, WicketUtils.newPathParameter( - repositoryName, commitId, doc.documentPath))); + String rawUrl = RawServlet.asLink(getContextUrl(), repositoryName, commitId, doc.documentPath); + item.add(new ExternalLink("rawLink", rawUrl)); // document content String file = StringUtils.getLastPathElement(doc.documentPath); @@ -145,8 +146,8 @@ public class DocsPage extends RepositoryPage { // links item.add(new BookmarkablePageLink("view", DocPage.class, WicketUtils .newPathParameter(repositoryName, id, entry.path))); - item.add(new BookmarkablePageLink("raw", RawPage.class, WicketUtils - .newPathParameter(repositoryName, id, entry.path))); + String rawUrl = RawServlet.asLink(getContextUrl(), repositoryName, id, entry.path); + item.add(new ExternalLink("raw", rawUrl)); item.add(new BookmarkablePageLink("blame", BlamePage.class, WicketUtils .newPathParameter(repositoryName, id, entry.path))); item.add(new BookmarkablePageLink("history", HistoryPage.class, WicketUtils diff --git a/src/main/java/com/gitblit/wicket/pages/TreePage.java b/src/main/java/com/gitblit/wicket/pages/TreePage.java index d6bf1fe1..722b824f 100644 --- a/src/main/java/com/gitblit/wicket/pages/TreePage.java +++ b/src/main/java/com/gitblit/wicket/pages/TreePage.java @@ -20,6 +20,7 @@ import java.util.List; import org.apache.wicket.PageParameters; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.link.BookmarkablePageLink; +import org.apache.wicket.markup.html.link.ExternalLink; import org.apache.wicket.markup.html.panel.Fragment; import org.apache.wicket.markup.repeater.Item; import org.apache.wicket.markup.repeater.data.DataView; @@ -30,6 +31,7 @@ import org.eclipse.jgit.revwalk.RevCommit; import com.gitblit.models.PathModel; import com.gitblit.models.SubmoduleModel; +import com.gitblit.servlet.RawServlet; import com.gitblit.utils.ByteFormat; import com.gitblit.utils.JGitUtils; import com.gitblit.wicket.CacheControl; @@ -162,8 +164,8 @@ public class TreePage extends RepositoryPage { links.add(new BookmarkablePageLink("view", BlobPage.class, WicketUtils.newPathParameter(repositoryName, id, path))); - links.add(new BookmarkablePageLink("raw", RawPage.class, WicketUtils - .newPathParameter(repositoryName, id, path))); + String rawUrl = RawServlet.asLink(getContextUrl(), repositoryName, id, path); + links.add(new ExternalLink("raw", rawUrl)); links.add(new BookmarkablePageLink("blame", BlamePage.class, WicketUtils.newPathParameter(repositoryName, id, path))); diff --git a/src/main/java/com/gitblit/wicket/panels/TagsPanel.java b/src/main/java/com/gitblit/wicket/panels/TagsPanel.java index 9f3987be..f1f82739 100644 --- a/src/main/java/com/gitblit/wicket/panels/TagsPanel.java +++ b/src/main/java/com/gitblit/wicket/panels/TagsPanel.java @@ -17,9 +17,11 @@ package com.gitblit.wicket.panels; import java.util.List; +import org.apache.wicket.RequestCycle; import org.apache.wicket.markup.html.WebPage; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.link.BookmarkablePageLink; +import org.apache.wicket.markup.html.link.ExternalLink; import org.apache.wicket.markup.html.panel.Fragment; import org.apache.wicket.markup.repeater.Item; import org.apache.wicket.markup.repeater.data.DataView; @@ -29,13 +31,13 @@ import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Repository; import com.gitblit.models.RefModel; +import com.gitblit.servlet.RawServlet; import com.gitblit.utils.JGitUtils; import com.gitblit.utils.StringUtils; import com.gitblit.wicket.WicketUtils; import com.gitblit.wicket.pages.BlobPage; import com.gitblit.wicket.pages.CommitPage; import com.gitblit.wicket.pages.LogPage; -import com.gitblit.wicket.pages.RawPage; import com.gitblit.wicket.pages.TagPage; import com.gitblit.wicket.pages.TagsPage; import com.gitblit.wicket.pages.TreePage; @@ -113,9 +115,10 @@ public class TagsPanel extends BasePanel { .newObjectParameter(repositoryName, entry.getReferencedObjectId() .getName()))); - fragment.add(new BookmarkablePageLink("raw", RawPage.class, WicketUtils - .newObjectParameter(repositoryName, entry.getReferencedObjectId() - .getName()))); + String contextUrl = RequestCycle.get().getRequest().getRelativePathPrefixToContextRoot(); + String rawUrl = RawServlet.asLink(contextUrl, repositoryName, entry.displayName, + entry.getReferencedObjectId().getName()); + fragment.add(new ExternalLink("raw", rawUrl)); item.add(fragment); } else { // TODO Tree Tag Object -- cgit v1.2.3 From 03d5ee0bcc4b9d7b6814d7212d19d1126638810d Mon Sep 17 00:00:00 2001 From: manisha Date: Fri, 21 Mar 2014 14:27:02 +0530 Subject: Implement FORK RPC request type --- src/main/java/com/gitblit/Constants.java | 2 +- .../models/UserRepositoryCompositeModel.java | 47 ++ src/main/java/com/gitblit/servlet/RpcServlet.java | 689 +++++++++++---------- src/main/java/com/gitblit/utils/RpcUtils.java | 31 +- src/test/config/test-users.conf | 1 - src/test/java/com/gitblit/tests/RpcTests.java | 6 + src/test/java/com/gitblit/tests/Test.java | 11 + 7 files changed, 435 insertions(+), 352 deletions(-) create mode 100644 src/main/java/com/gitblit/models/UserRepositoryCompositeModel.java create mode 100644 src/test/java/com/gitblit/tests/Test.java (limited to 'src/main/java/com/gitblit/Constants.java') diff --git a/src/main/java/com/gitblit/Constants.java b/src/main/java/com/gitblit/Constants.java index a5e76a51..cbbc0cac 100644 --- a/src/main/java/com/gitblit/Constants.java +++ b/src/main/java/com/gitblit/Constants.java @@ -353,7 +353,7 @@ public class Constants { // Order is important here. anything above LIST_SETTINGS requires // administrator privileges and web.allowRpcManagement. CLEAR_REPOSITORY_CACHE, REINDEX_TICKETS, GET_PROTOCOL, LIST_REPOSITORIES, LIST_BRANCHES, GET_USER, LIST_SETTINGS, - CREATE_REPOSITORY, EDIT_REPOSITORY, DELETE_REPOSITORY, + CREATE_REPOSITORY, FORK_REPOSITORY, EDIT_REPOSITORY, DELETE_REPOSITORY, LIST_USERS, CREATE_USER, EDIT_USER, DELETE_USER, LIST_TEAMS, CREATE_TEAM, EDIT_TEAM, DELETE_TEAM, LIST_REPOSITORY_MEMBERS, SET_REPOSITORY_MEMBERS, LIST_REPOSITORY_TEAMS, SET_REPOSITORY_TEAMS, diff --git a/src/main/java/com/gitblit/models/UserRepositoryCompositeModel.java b/src/main/java/com/gitblit/models/UserRepositoryCompositeModel.java new file mode 100644 index 00000000..122bb3ba --- /dev/null +++ b/src/main/java/com/gitblit/models/UserRepositoryCompositeModel.java @@ -0,0 +1,47 @@ +package com.gitblit.models; + +/* + * Copyright 2011 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import com.gitblit.utils.StringUtils; + +import java.io.Serializable; + +public class UserRepositoryCompositeModel implements Serializable { + + private static final long serialVersionUID = 1L; + + public UserModel userModel; + public RepositoryModel repositoryModel; + + public UserModel getUserModel() { + return userModel; + } + + public void setUserModel(UserModel userModel) { + this.userModel = userModel; + } + + public RepositoryModel getRepositoryModel() { + return repositoryModel; + } + + public void setRepositoryModel(RepositoryModel repositoryModel) { + this.repositoryModel = repositoryModel; + } + +} \ No newline at end of file diff --git a/src/main/java/com/gitblit/servlet/RpcServlet.java b/src/main/java/com/gitblit/servlet/RpcServlet.java index 2d59ebd7..80c50714 100644 --- a/src/main/java/com/gitblit/servlet/RpcServlet.java +++ b/src/main/java/com/gitblit/servlet/RpcServlet.java @@ -27,6 +27,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import com.gitblit.models.*; import org.eclipse.jgit.lib.Repository; import com.gitblit.Constants; @@ -35,12 +36,6 @@ import com.gitblit.GitBlitException; import com.gitblit.IStoredSettings; import com.gitblit.Keys; import com.gitblit.manager.IGitblit; -import com.gitblit.models.RefModel; -import com.gitblit.models.RegistrantAccessPermission; -import com.gitblit.models.RepositoryModel; -import com.gitblit.models.ServerSettings; -import com.gitblit.models.TeamModel; -import com.gitblit.models.UserModel; import com.gitblit.utils.DeepCopier; import com.gitblit.utils.HttpUtils; import com.gitblit.utils.JGitUtils; @@ -53,352 +48,368 @@ import dagger.ObjectGraph; * Handles remote procedure calls. * * @author James Moger - * */ public class RpcServlet extends JsonServlet { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; + + public static final int PROTOCOL_VERSION = 7; - public static final int PROTOCOL_VERSION = 7; + private IStoredSettings settings; - private IStoredSettings settings; + private IGitblit gitblit; - private IGitblit gitblit; + @Override + protected void inject(ObjectGraph dagger) { + this.settings = dagger.get(IStoredSettings.class); + this.gitblit = dagger.get(IGitblit.class); + } - @Override - protected void inject(ObjectGraph dagger) { - this.settings = dagger.get(IStoredSettings.class); - this.gitblit = dagger.get(IGitblit.class); - } + /** + * Processes an rpc request. + * + * @param request + * @param response + * @throws javax.servlet.ServletException + * @throws java.io.IOException + */ + @Override + protected void processRequest(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + RpcRequest reqType = RpcRequest.fromName(request.getParameter("req")); + String objectName = request.getParameter("name"); + logger.info(MessageFormat.format("Rpc {0} request from {1}", reqType, + request.getRemoteAddr())); - /** - * Processes an rpc request. - * - * @param request - * @param response - * @throws javax.servlet.ServletException - * @throws java.io.IOException - */ - @Override - protected void processRequest(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - RpcRequest reqType = RpcRequest.fromName(request.getParameter("req")); - String objectName = request.getParameter("name"); - logger.info(MessageFormat.format("Rpc {0} request from {1}", reqType, - request.getRemoteAddr())); + UserModel user = (UserModel) request.getUserPrincipal(); - UserModel user = (UserModel) request.getUserPrincipal(); + boolean allowManagement = user != null && user.canAdmin() + && settings.getBoolean(Keys.web.enableRpcManagement, false); - boolean allowManagement = user != null && user.canAdmin() - && settings.getBoolean(Keys.web.enableRpcManagement, false); + boolean allowAdmin = user != null && user.canAdmin() + && settings.getBoolean(Keys.web.enableRpcAdministration, false); - boolean allowAdmin = user != null && user.canAdmin() - && settings.getBoolean(Keys.web.enableRpcAdministration, false); + Object result = null; + if (RpcRequest.GET_PROTOCOL.equals(reqType)) { + // Return the protocol version + result = PROTOCOL_VERSION; + } else if (RpcRequest.LIST_REPOSITORIES.equals(reqType)) { + // Determine the Gitblit clone url + String gitblitUrl = settings.getString(Keys.web.canonicalUrl, null); + if (StringUtils.isEmpty(gitblitUrl)) { + gitblitUrl = HttpUtils.getGitblitURL(request); + } + StringBuilder sb = new StringBuilder(); + sb.append(gitblitUrl); + sb.append(Constants.R_PATH); + sb.append("{0}"); + String cloneUrl = sb.toString(); - Object result = null; - if (RpcRequest.GET_PROTOCOL.equals(reqType)) { - // Return the protocol version - result = PROTOCOL_VERSION; - } else if (RpcRequest.LIST_REPOSITORIES.equals(reqType)) { - // Determine the Gitblit clone url - String gitblitUrl = settings.getString(Keys.web.canonicalUrl, null); - if (StringUtils.isEmpty(gitblitUrl)) { - gitblitUrl = HttpUtils.getGitblitURL(request); - } - StringBuilder sb = new StringBuilder(); - sb.append(gitblitUrl); - sb.append(Constants.R_PATH); - sb.append("{0}"); - String cloneUrl = sb.toString(); + // list repositories + List list = gitblit.getRepositoryModels(user); + Map repositories = new HashMap(); + for (RepositoryModel model : list) { + String url = MessageFormat.format(cloneUrl, model.name); + repositories.put(url, model); + } + result = repositories; + } else if (RpcRequest.LIST_BRANCHES.equals(reqType)) { + // list all local branches in all repositories accessible to user + Map> localBranches = new HashMap>(); + List models = gitblit.getRepositoryModels(user); + for (RepositoryModel model : models) { + if (!model.hasCommits) { + // skip empty repository + continue; + } + if (model.isCollectingGarbage) { + // skip garbage collecting repository + logger.warn(MessageFormat.format("Temporarily excluding {0} from RPC, busy collecting garbage", model.name)); + continue; + } + // get local branches + Repository repository = gitblit.getRepository(model.name); + List refs = JGitUtils.getLocalBranches(repository, false, -1); + if (model.showRemoteBranches) { + // add remote branches if repository displays them + refs.addAll(JGitUtils.getRemoteBranches(repository, false, -1)); + } + if (refs.size() > 0) { + List branches = new ArrayList(); + for (RefModel ref : refs) { + branches.add(ref.getName()); + } + localBranches.put(model.name, branches); + } + repository.close(); + } + result = localBranches; + } else if (RpcRequest.GET_USER.equals(reqType)) { + if (StringUtils.isEmpty(objectName)) { + if (UserModel.ANONYMOUS.equals(user)) { + response.sendError(forbiddenCode); + } else { + // return the current user, reset credentials + UserModel requestedUser = DeepCopier.copy(user); + result = requestedUser; + } + } else { + if (user.canAdmin() || objectName.equals(user.username)) { + // return the specified user + UserModel requestedUser = gitblit.getUserModel(objectName); + if (requestedUser == null) { + response.setStatus(failureCode); + } else { + result = requestedUser; + } + } else { + response.sendError(forbiddenCode); + } + } + } else if (RpcRequest.LIST_USERS.equals(reqType)) { + // list users + List names = gitblit.getAllUsernames(); + List users = new ArrayList(); + for (String name : names) { + users.add(gitblit.getUserModel(name)); + } + result = users; + } else if (RpcRequest.LIST_TEAMS.equals(reqType)) { + // list teams + List names = gitblit.getAllTeamNames(); + List teams = new ArrayList(); + for (String name : names) { + teams.add(gitblit.getTeamModel(name)); + } + result = teams; + } else if (RpcRequest.CREATE_REPOSITORY.equals(reqType)) { + // create repository + RepositoryModel model = deserialize(request, response, RepositoryModel.class); + try { + gitblit.updateRepositoryModel(model.name, model, true); + } catch (GitBlitException e) { + response.setStatus(failureCode); + } + } else if (RpcRequest.FORK_REPOSITORY.equals(reqType)) { + // fork repository + UserRepositoryCompositeModel userRepositoryCompositeModel = deserialize(request, response, + UserRepositoryCompositeModel.class); + RepositoryModel repoModel = userRepositoryCompositeModel.getRepositoryModel(); + UserModel userModel = userRepositoryCompositeModel.getUserModel(); + try { + if (repoModel != null && userModel != null) { + gitblit.fork(repoModel, userModel); + } else { + System.out.println("Non existing user model or repo model"); + response.setStatus(failureCode); + } - // list repositories - List list = gitblit.getRepositoryModels(user); - Map repositories = new HashMap(); - for (RepositoryModel model : list) { - String url = MessageFormat.format(cloneUrl, model.name); - repositories.put(url, model); - } - result = repositories; - } else if (RpcRequest.LIST_BRANCHES.equals(reqType)) { - // list all local branches in all repositories accessible to user - Map> localBranches = new HashMap>(); - List models = gitblit.getRepositoryModels(user); - for (RepositoryModel model : models) { - if (!model.hasCommits) { - // skip empty repository - continue; - } - if (model.isCollectingGarbage) { - // skip garbage collecting repository - logger.warn(MessageFormat.format("Temporarily excluding {0} from RPC, busy collecting garbage", model.name)); - continue; - } - // get local branches - Repository repository = gitblit.getRepository(model.name); - List refs = JGitUtils.getLocalBranches(repository, false, -1); - if (model.showRemoteBranches) { - // add remote branches if repository displays them - refs.addAll(JGitUtils.getRemoteBranches(repository, false, -1)); - } - if (refs.size() > 0) { - List branches = new ArrayList(); - for (RefModel ref : refs) { - branches.add(ref.getName()); - } - localBranches.put(model.name, branches); - } - repository.close(); - } - result = localBranches; - } else if (RpcRequest.GET_USER.equals(reqType)) { - if (StringUtils.isEmpty(objectName)) { - if (UserModel.ANONYMOUS.equals(user)) { - response.sendError(forbiddenCode); - } else { - // return the current user, reset credentials - UserModel requestedUser = DeepCopier.copy(user); - result = requestedUser; - } - } else { - if (user.canAdmin() || objectName.equals(user.username)) { - // return the specified user - UserModel requestedUser = gitblit.getUserModel(objectName); - if (requestedUser == null) { - response.setStatus(failureCode); - } else { - result = requestedUser; - } - } else { - response.sendError(forbiddenCode); - } - } - } else if (RpcRequest.LIST_USERS.equals(reqType)) { - // list users - List names = gitblit.getAllUsernames(); - List users = new ArrayList(); - for (String name : names) { - users.add(gitblit.getUserModel(name)); - } - result = users; - } else if (RpcRequest.LIST_TEAMS.equals(reqType)) { - // list teams - List names = gitblit.getAllTeamNames(); - List teams = new ArrayList(); - for (String name : names) { - teams.add(gitblit.getTeamModel(name)); - } - result = teams; - } else if (RpcRequest.CREATE_REPOSITORY.equals(reqType)) { - // create repository - RepositoryModel model = deserialize(request, response, RepositoryModel.class); - try { - gitblit.updateRepositoryModel(model.name, model, true); - } catch (GitBlitException e) { - response.setStatus(failureCode); - } - } else if (RpcRequest.EDIT_REPOSITORY.equals(reqType)) { - // edit repository - RepositoryModel model = deserialize(request, response, RepositoryModel.class); - // name specifies original repository name in event of rename - String repoName = objectName; - if (repoName == null) { - repoName = model.name; - } - try { - gitblit.updateRepositoryModel(repoName, model, false); - } catch (GitBlitException e) { - response.setStatus(failureCode); - } - } else if (RpcRequest.DELETE_REPOSITORY.equals(reqType)) { - // delete repository - RepositoryModel model = deserialize(request, response, RepositoryModel.class); - gitblit.deleteRepositoryModel(model); - } else if (RpcRequest.CREATE_USER.equals(reqType)) { - // create user - UserModel model = deserialize(request, response, UserModel.class); - try { - gitblit.addUser(model); - } catch (GitBlitException e) { - response.setStatus(failureCode); - } - } else if (RpcRequest.EDIT_USER.equals(reqType)) { - // edit user - UserModel model = deserialize(request, response, UserModel.class); - // name parameter specifies original user name in event of rename - String username = objectName; - if (username == null) { - username = model.username; - } - try { - gitblit.reviseUser(username, model); - } catch (GitBlitException e) { - response.setStatus(failureCode); - } - } else if (RpcRequest.DELETE_USER.equals(reqType)) { - // delete user - UserModel model = deserialize(request, response, UserModel.class); - if (!gitblit.deleteUser(model.username)) { - response.setStatus(failureCode); - } - } else if (RpcRequest.CREATE_TEAM.equals(reqType)) { - // create team - TeamModel model = deserialize(request, response, TeamModel.class); - try { - gitblit.addTeam(model); - } catch (GitBlitException e) { - response.setStatus(failureCode); - } - } else if (RpcRequest.EDIT_TEAM.equals(reqType)) { - // edit team - TeamModel model = deserialize(request, response, TeamModel.class); - // name parameter specifies original team name in event of rename - String teamname = objectName; - if (teamname == null) { - teamname = model.name; - } - try { - gitblit.reviseTeam(teamname, model); - } catch (GitBlitException e) { - response.setStatus(failureCode); - } - } else if (RpcRequest.DELETE_TEAM.equals(reqType)) { - // delete team - TeamModel model = deserialize(request, response, TeamModel.class); - if (!gitblit.deleteTeam(model.name)) { - response.setStatus(failureCode); - } - } else if (RpcRequest.LIST_REPOSITORY_MEMBERS.equals(reqType)) { - // get repository members - RepositoryModel model = gitblit.getRepositoryModel(objectName); - result = gitblit.getRepositoryUsers(model); - } else if (RpcRequest.SET_REPOSITORY_MEMBERS.equals(reqType)) { - // rejected since 1.2.0 - response.setStatus(failureCode); - } else if (RpcRequest.LIST_REPOSITORY_MEMBER_PERMISSIONS.equals(reqType)) { - // get repository member permissions - RepositoryModel model = gitblit.getRepositoryModel(objectName); - result = gitblit.getUserAccessPermissions(model); - } else if (RpcRequest.SET_REPOSITORY_MEMBER_PERMISSIONS.equals(reqType)) { - // set the repository permissions for the specified users - RepositoryModel model = gitblit.getRepositoryModel(objectName); - Collection permissions = deserialize(request, response, RpcUtils.REGISTRANT_PERMISSIONS_TYPE); - result = gitblit.setUserAccessPermissions(model, permissions); - } else if (RpcRequest.LIST_REPOSITORY_TEAMS.equals(reqType)) { - // get repository teams - RepositoryModel model = gitblit.getRepositoryModel(objectName); - result = gitblit.getRepositoryTeams(model); - } else if (RpcRequest.SET_REPOSITORY_TEAMS.equals(reqType)) { - // rejected since 1.2.0 - response.setStatus(failureCode); - } else if (RpcRequest.LIST_REPOSITORY_TEAM_PERMISSIONS.equals(reqType)) { - // get repository team permissions - RepositoryModel model = gitblit.getRepositoryModel(objectName); - result = gitblit.getTeamAccessPermissions(model); - } else if (RpcRequest.SET_REPOSITORY_TEAM_PERMISSIONS.equals(reqType)) { - // set the repository permissions for the specified teams - RepositoryModel model = gitblit.getRepositoryModel(objectName); - Collection permissions = deserialize(request, response, RpcUtils.REGISTRANT_PERMISSIONS_TYPE); - result = gitblit.setTeamAccessPermissions(model, permissions); - } else if (RpcRequest.LIST_FEDERATION_REGISTRATIONS.equals(reqType)) { - // return the list of federation registrations - if (allowAdmin) { - result = gitblit.getFederationRegistrations(); - } else { - response.sendError(notAllowedCode); - } - } else if (RpcRequest.LIST_FEDERATION_RESULTS.equals(reqType)) { - // return the list of federation result registrations - if (allowAdmin && gitblit.canFederate()) { - result = gitblit.getFederationResultRegistrations(); - } else { - response.sendError(notAllowedCode); - } - } else if (RpcRequest.LIST_FEDERATION_PROPOSALS.equals(reqType)) { - // return the list of federation proposals - if (allowAdmin && gitblit.canFederate()) { - result = gitblit.getPendingFederationProposals(); - } else { - response.sendError(notAllowedCode); - } - } else if (RpcRequest.LIST_FEDERATION_SETS.equals(reqType)) { - // return the list of federation sets - if (allowAdmin && gitblit.canFederate()) { - String gitblitUrl = settings.getString(Keys.web.canonicalUrl, null); - if (StringUtils.isEmpty(gitblitUrl)) { - gitblitUrl = HttpUtils.getGitblitURL(request); - } - result = gitblit.getFederationSets(gitblitUrl); - } else { - response.sendError(notAllowedCode); - } - } else if (RpcRequest.LIST_SETTINGS.equals(reqType)) { - // return the server's settings - ServerSettings serverSettings = gitblit.getSettingsModel(); - if (allowAdmin) { - // return all settings - result = serverSettings; - } else { - // anonymous users get a few settings to allow browser launching - List keys = new ArrayList(); - keys.add(Keys.web.siteName); - keys.add(Keys.web.mountParameters); - keys.add(Keys.web.syndicationEntries); + } catch (GitBlitException e) { + response.setStatus(failureCode); + } + } else if (RpcRequest.EDIT_REPOSITORY.equals(reqType)) { + // edit repository + RepositoryModel model = deserialize(request, response, RepositoryModel.class); + // name specifies original repository name in event of rename + String repoName = objectName; + if (repoName == null) { + repoName = model.name; + } + try { + gitblit.updateRepositoryModel(repoName, model, false); + } catch (GitBlitException e) { + response.setStatus(failureCode); + } + } else if (RpcRequest.DELETE_REPOSITORY.equals(reqType)) { + // delete repository + RepositoryModel model = deserialize(request, response, RepositoryModel.class); + gitblit.deleteRepositoryModel(model); + } else if (RpcRequest.CREATE_USER.equals(reqType)) { + // create user + UserModel model = deserialize(request, response, UserModel.class); + try { + gitblit.addUser(model); + } catch (GitBlitException e) { + response.setStatus(failureCode); + } + } else if (RpcRequest.EDIT_USER.equals(reqType)) { + // edit user + UserModel model = deserialize(request, response, UserModel.class); + // name parameter specifies original user name in event of rename + String username = objectName; + if (username == null) { + username = model.username; + } + try { + gitblit.reviseUser(username, model); + } catch (GitBlitException e) { + response.setStatus(failureCode); + } + } else if (RpcRequest.DELETE_USER.equals(reqType)) { + // delete user + UserModel model = deserialize(request, response, UserModel.class); + if (!gitblit.deleteUser(model.username)) { + response.setStatus(failureCode); + } + } else if (RpcRequest.CREATE_TEAM.equals(reqType)) { + // create team + TeamModel model = deserialize(request, response, TeamModel.class); + try { + gitblit.addTeam(model); + } catch (GitBlitException e) { + response.setStatus(failureCode); + } + } else if (RpcRequest.EDIT_TEAM.equals(reqType)) { + // edit team + TeamModel model = deserialize(request, response, TeamModel.class); + // name parameter specifies original team name in event of rename + String teamname = objectName; + if (teamname == null) { + teamname = model.name; + } + try { + gitblit.reviseTeam(teamname, model); + } catch (GitBlitException e) { + response.setStatus(failureCode); + } + } else if (RpcRequest.DELETE_TEAM.equals(reqType)) { + // delete team + TeamModel model = deserialize(request, response, TeamModel.class); + if (!gitblit.deleteTeam(model.name)) { + response.setStatus(failureCode); + } + } else if (RpcRequest.LIST_REPOSITORY_MEMBERS.equals(reqType)) { + // get repository members + RepositoryModel model = gitblit.getRepositoryModel(objectName); + result = gitblit.getRepositoryUsers(model); + } else if (RpcRequest.SET_REPOSITORY_MEMBERS.equals(reqType)) { + // rejected since 1.2.0 + response.setStatus(failureCode); + } else if (RpcRequest.LIST_REPOSITORY_MEMBER_PERMISSIONS.equals(reqType)) { + // get repository member permissions + RepositoryModel model = gitblit.getRepositoryModel(objectName); + result = gitblit.getUserAccessPermissions(model); + } else if (RpcRequest.SET_REPOSITORY_MEMBER_PERMISSIONS.equals(reqType)) { + // set the repository permissions for the specified users + RepositoryModel model = gitblit.getRepositoryModel(objectName); + Collection permissions = deserialize(request, response, RpcUtils.REGISTRANT_PERMISSIONS_TYPE); + result = gitblit.setUserAccessPermissions(model, permissions); + } else if (RpcRequest.LIST_REPOSITORY_TEAMS.equals(reqType)) { + // get repository teams + RepositoryModel model = gitblit.getRepositoryModel(objectName); + result = gitblit.getRepositoryTeams(model); + } else if (RpcRequest.SET_REPOSITORY_TEAMS.equals(reqType)) { + // rejected since 1.2.0 + response.setStatus(failureCode); + } else if (RpcRequest.LIST_REPOSITORY_TEAM_PERMISSIONS.equals(reqType)) { + // get repository team permissions + RepositoryModel model = gitblit.getRepositoryModel(objectName); + result = gitblit.getTeamAccessPermissions(model); + } else if (RpcRequest.SET_REPOSITORY_TEAM_PERMISSIONS.equals(reqType)) { + // set the repository permissions for the specified teams + RepositoryModel model = gitblit.getRepositoryModel(objectName); + Collection permissions = deserialize(request, response, RpcUtils.REGISTRANT_PERMISSIONS_TYPE); + result = gitblit.setTeamAccessPermissions(model, permissions); + } else if (RpcRequest.LIST_FEDERATION_REGISTRATIONS.equals(reqType)) { + // return the list of federation registrations + if (allowAdmin) { + result = gitblit.getFederationRegistrations(); + } else { + response.sendError(notAllowedCode); + } + } else if (RpcRequest.LIST_FEDERATION_RESULTS.equals(reqType)) { + // return the list of federation result registrations + if (allowAdmin && gitblit.canFederate()) { + result = gitblit.getFederationResultRegistrations(); + } else { + response.sendError(notAllowedCode); + } + } else if (RpcRequest.LIST_FEDERATION_PROPOSALS.equals(reqType)) { + // return the list of federation proposals + if (allowAdmin && gitblit.canFederate()) { + result = gitblit.getPendingFederationProposals(); + } else { + response.sendError(notAllowedCode); + } + } else if (RpcRequest.LIST_FEDERATION_SETS.equals(reqType)) { + // return the list of federation sets + if (allowAdmin && gitblit.canFederate()) { + String gitblitUrl = settings.getString(Keys.web.canonicalUrl, null); + if (StringUtils.isEmpty(gitblitUrl)) { + gitblitUrl = HttpUtils.getGitblitURL(request); + } + result = gitblit.getFederationSets(gitblitUrl); + } else { + response.sendError(notAllowedCode); + } + } else if (RpcRequest.LIST_SETTINGS.equals(reqType)) { + // return the server's settings + ServerSettings serverSettings = gitblit.getSettingsModel(); + if (allowAdmin) { + // return all settings + result = serverSettings; + } else { + // anonymous users get a few settings to allow browser launching + List keys = new ArrayList(); + keys.add(Keys.web.siteName); + keys.add(Keys.web.mountParameters); + keys.add(Keys.web.syndicationEntries); - if (allowManagement) { - // keys necessary for repository and/or user management - keys.add(Keys.realm.minPasswordLength); - keys.add(Keys.realm.passwordStorage); - keys.add(Keys.federation.sets); - } - // build the settings - ServerSettings managementSettings = new ServerSettings(); - for (String key : keys) { - managementSettings.add(serverSettings.get(key)); - } - if (allowManagement) { - managementSettings.pushScripts = serverSettings.pushScripts; - } - result = managementSettings; - } - } else if (RpcRequest.EDIT_SETTINGS.equals(reqType)) { - // update settings on the server - if (allowAdmin) { - Map map = deserialize(request, response, - RpcUtils.SETTINGS_TYPE); - gitblit.updateSettings(map); - } else { - response.sendError(notAllowedCode); - } - } else if (RpcRequest.LIST_STATUS.equals(reqType)) { - // return the server's status information - if (allowAdmin) { - result = gitblit.getStatus(); - } else { - response.sendError(notAllowedCode); - } - } else if (RpcRequest.CLEAR_REPOSITORY_CACHE.equals(reqType)) { - // clear the repository list cache - if (allowManagement) { - gitblit.resetRepositoryListCache(); - } else { - response.sendError(notAllowedCode); - } - } else if (RpcRequest.REINDEX_TICKETS.equals(reqType)) { - if (allowManagement) { - if (StringUtils.isEmpty(objectName)) { - // reindex all tickets - gitblit.getTicketService().reindex(); - } else { - // reindex tickets in a specific repository - RepositoryModel model = gitblit.getRepositoryModel(objectName); - gitblit.getTicketService().reindex(model); - } - } else { - response.sendError(notAllowedCode); - } - } + if (allowManagement) { + // keys necessary for repository and/or user management + keys.add(Keys.realm.minPasswordLength); + keys.add(Keys.realm.passwordStorage); + keys.add(Keys.federation.sets); + } + // build the settings + ServerSettings managementSettings = new ServerSettings(); + for (String key : keys) { + managementSettings.add(serverSettings.get(key)); + } + if (allowManagement) { + managementSettings.pushScripts = serverSettings.pushScripts; + } + result = managementSettings; + } + } else if (RpcRequest.EDIT_SETTINGS.equals(reqType)) { + // update settings on the server + if (allowAdmin) { + Map map = deserialize(request, response, + RpcUtils.SETTINGS_TYPE); + gitblit.updateSettings(map); + } else { + response.sendError(notAllowedCode); + } + } else if (RpcRequest.LIST_STATUS.equals(reqType)) { + // return the server's status information + if (allowAdmin) { + result = gitblit.getStatus(); + } else { + response.sendError(notAllowedCode); + } + } else if (RpcRequest.CLEAR_REPOSITORY_CACHE.equals(reqType)) { + // clear the repository list cache + if (allowManagement) { + gitblit.resetRepositoryListCache(); + } else { + response.sendError(notAllowedCode); + } + } else if (RpcRequest.REINDEX_TICKETS.equals(reqType)) { + if (allowManagement) { + if (StringUtils.isEmpty(objectName)) { + // reindex all tickets + gitblit.getTicketService().reindex(); + } else { + // reindex tickets in a specific repository + RepositoryModel model = gitblit.getRepositoryModel(objectName); + gitblit.getTicketService().reindex(model); + } + } else { + response.sendError(notAllowedCode); + } + } - // send the result of the request - serialize(response, result); - } + // send the result of the request + serialize(response, result); + } } diff --git a/src/main/java/com/gitblit/utils/RpcUtils.java b/src/main/java/com/gitblit/utils/RpcUtils.java index 5e577fb6..904461c8 100644 --- a/src/main/java/com/gitblit/utils/RpcUtils.java +++ b/src/main/java/com/gitblit/utils/RpcUtils.java @@ -25,16 +25,7 @@ import java.util.Map; import com.gitblit.Constants; import com.gitblit.Constants.RpcRequest; import com.gitblit.GitBlitException.UnknownRequestException; -import com.gitblit.models.FederationModel; -import com.gitblit.models.FederationProposal; -import com.gitblit.models.FederationSet; -import com.gitblit.models.FeedModel; -import com.gitblit.models.RegistrantAccessPermission; -import com.gitblit.models.RepositoryModel; -import com.gitblit.models.ServerSettings; -import com.gitblit.models.ServerStatus; -import com.gitblit.models.TeamModel; -import com.gitblit.models.UserModel; +import com.gitblit.models.*; import com.google.gson.reflect.TypeToken; /** @@ -203,7 +194,25 @@ public class RpcUtils { } - /** + /** + * Create a fork of an already existing repo + * + * @param repository + * @param user + + * @return true if the action succeeded + * @throws IOException + */ + public static boolean forkRpository(RepositoryModel repository, UserModel user, String serverUrl, + String account, char[] password) throws IOException { + UserRepositoryCompositeModel userRepositoryCompositeModel = new UserRepositoryCompositeModel(); + userRepositoryCompositeModel.setRepositoryModel(repository); + userRepositoryCompositeModel.setUserModel(user); + return doAction(RpcRequest.FORK_REPOSITORY, null, userRepositoryCompositeModel, serverUrl, account, password); + } + + + /** * Send a revised version of the repository model to the Gitblit server. * * @param repository diff --git a/src/test/config/test-users.conf b/src/test/config/test-users.conf index 1d01f846..4e00903b 100644 --- a/src/test/config/test-users.conf +++ b/src/test/config/test-users.conf @@ -6,7 +6,6 @@ role = "#notfederated" [user "sampleuser"] password = sampleuser - cookie = 6e07ed42149fc166206319faffdfba2e2ec82e43 accountType = LOCAL role = "#none" [team "admins"] diff --git a/src/test/java/com/gitblit/tests/RpcTests.java b/src/test/java/com/gitblit/tests/RpcTests.java index ced1a130..943153de 100644 --- a/src/test/java/com/gitblit/tests/RpcTests.java +++ b/src/test/java/com/gitblit/tests/RpcTests.java @@ -191,6 +191,12 @@ public class RpcTests extends GitblitUnitTest { assertEquals(AccessRestrictionType.VIEW, retrievedRepository.accessRestriction); assertEquals(AuthorizationControl.AUTHENTICATED, retrievedRepository.authorizationControl); + //fork repo + UserModel userModel = new UserModel("garbageUser"); + assertTrue("Failed to create Fork Repository!", + RpcUtils.forkRpository(model, userModel, url, account, password.toCharArray())); + + // rename and change access restriciton String originalName = model.name; model.name = "garbagerepo2.git"; diff --git a/src/test/java/com/gitblit/tests/Test.java b/src/test/java/com/gitblit/tests/Test.java new file mode 100644 index 00000000..275c6b4c --- /dev/null +++ b/src/test/java/com/gitblit/tests/Test.java @@ -0,0 +1,11 @@ +package com.gitblit.tests; + +/** + * Created with IntelliJ IDEA. + * User: manisha + * Date: 3/21/14 + * Time: 12:03 PM + * To change this template use File | Settings | File Templates. + */ +public @interface Test { +} -- cgit v1.2.3 From 813a1fab72a462bdd9387ac3f137055853a69710 Mon Sep 17 00:00:00 2001 From: James Moger Date: Thu, 8 May 2014 11:11:04 -0400 Subject: Revise, complete, and fully test the FORK rpc --- releases.moxie | 6 +- src/main/java/com/gitblit/Constants.java | 7 ++- .../models/UserRepositoryCompositeModel.java | 47 --------------- src/main/java/com/gitblit/servlet/RpcServlet.java | 50 ++++++++++------ src/main/java/com/gitblit/utils/RpcUtils.java | 21 ++++--- src/site/rpc.mkd | 8 ++- src/test/config/test-users.conf | 1 + src/test/java/com/gitblit/tests/RpcTests.java | 69 ++++++++++++++++++++-- src/test/java/com/gitblit/tests/Test.java | 11 ---- 9 files changed, 122 insertions(+), 98 deletions(-) delete mode 100644 src/main/java/com/gitblit/models/UserRepositoryCompositeModel.java delete mode 100644 src/test/java/com/gitblit/tests/Test.java (limited to 'src/main/java/com/gitblit/Constants.java') diff --git a/releases.moxie b/releases.moxie index aac46f0c..228fc7e6 100644 --- a/releases.moxie +++ b/releases.moxie @@ -11,9 +11,11 @@ r24: { security: ~ fixes: ~ changes: ~ - additions: ~ + additions: + - Add FORK_REPOSITORY RPC request type (issue-371, pr-161, ticket-65) dependencyChanges: ~ - contributors: ~ + contributors: + - Manisha Gayathri } # diff --git a/src/main/java/com/gitblit/Constants.java b/src/main/java/com/gitblit/Constants.java index cbbc0cac..c8ce83c1 100644 --- a/src/main/java/com/gitblit/Constants.java +++ b/src/main/java/com/gitblit/Constants.java @@ -350,10 +350,11 @@ public class Constants { * a client. */ public static enum RpcRequest { - // Order is important here. anything above LIST_SETTINGS requires + // Order is important here. anything after LIST_SETTINGS requires // administrator privileges and web.allowRpcManagement. - CLEAR_REPOSITORY_CACHE, REINDEX_TICKETS, GET_PROTOCOL, LIST_REPOSITORIES, LIST_BRANCHES, GET_USER, LIST_SETTINGS, - CREATE_REPOSITORY, FORK_REPOSITORY, EDIT_REPOSITORY, DELETE_REPOSITORY, + CLEAR_REPOSITORY_CACHE, REINDEX_TICKETS, GET_PROTOCOL, LIST_REPOSITORIES, LIST_BRANCHES, GET_USER, + FORK_REPOSITORY, LIST_SETTINGS, + CREATE_REPOSITORY, EDIT_REPOSITORY, DELETE_REPOSITORY, LIST_USERS, CREATE_USER, EDIT_USER, DELETE_USER, LIST_TEAMS, CREATE_TEAM, EDIT_TEAM, DELETE_TEAM, LIST_REPOSITORY_MEMBERS, SET_REPOSITORY_MEMBERS, LIST_REPOSITORY_TEAMS, SET_REPOSITORY_TEAMS, diff --git a/src/main/java/com/gitblit/models/UserRepositoryCompositeModel.java b/src/main/java/com/gitblit/models/UserRepositoryCompositeModel.java deleted file mode 100644 index 122bb3ba..00000000 --- a/src/main/java/com/gitblit/models/UserRepositoryCompositeModel.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.gitblit.models; - -/* - * Copyright 2011 gitblit.com. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -import com.gitblit.utils.StringUtils; - -import java.io.Serializable; - -public class UserRepositoryCompositeModel implements Serializable { - - private static final long serialVersionUID = 1L; - - public UserModel userModel; - public RepositoryModel repositoryModel; - - public UserModel getUserModel() { - return userModel; - } - - public void setUserModel(UserModel userModel) { - this.userModel = userModel; - } - - public RepositoryModel getRepositoryModel() { - return repositoryModel; - } - - public void setRepositoryModel(RepositoryModel repositoryModel) { - this.repositoryModel = repositoryModel; - } - -} \ No newline at end of file diff --git a/src/main/java/com/gitblit/servlet/RpcServlet.java b/src/main/java/com/gitblit/servlet/RpcServlet.java index 80c50714..b3016ad6 100644 --- a/src/main/java/com/gitblit/servlet/RpcServlet.java +++ b/src/main/java/com/gitblit/servlet/RpcServlet.java @@ -27,7 +27,6 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import com.gitblit.models.*; import org.eclipse.jgit.lib.Repository; import com.gitblit.Constants; @@ -36,6 +35,12 @@ import com.gitblit.GitBlitException; import com.gitblit.IStoredSettings; import com.gitblit.Keys; import com.gitblit.manager.IGitblit; +import com.gitblit.models.RefModel; +import com.gitblit.models.RegistrantAccessPermission; +import com.gitblit.models.RepositoryModel; +import com.gitblit.models.ServerSettings; +import com.gitblit.models.TeamModel; +import com.gitblit.models.UserModel; import com.gitblit.utils.DeepCopier; import com.gitblit.utils.HttpUtils; import com.gitblit.utils.JGitUtils; @@ -53,7 +58,7 @@ public class RpcServlet extends JsonServlet { private static final long serialVersionUID = 1L; - public static final int PROTOCOL_VERSION = 7; + public static final int PROTOCOL_VERSION = 8; private IStoredSettings settings; @@ -191,22 +196,31 @@ public class RpcServlet extends JsonServlet { response.setStatus(failureCode); } } else if (RpcRequest.FORK_REPOSITORY.equals(reqType)) { - // fork repository - UserRepositoryCompositeModel userRepositoryCompositeModel = deserialize(request, response, - UserRepositoryCompositeModel.class); - RepositoryModel repoModel = userRepositoryCompositeModel.getRepositoryModel(); - UserModel userModel = userRepositoryCompositeModel.getUserModel(); - try { - if (repoModel != null && userModel != null) { - gitblit.fork(repoModel, userModel); - } else { - System.out.println("Non existing user model or repo model"); - response.setStatus(failureCode); - } - - } catch (GitBlitException e) { - response.setStatus(failureCode); - } + // fork repository + RepositoryModel origin = gitblit.getRepositoryModel(objectName); + if (origin == null) { + // failed to find repository, error is logged by the repository manager + response.setStatus(failureCode); + } else { + if (user == null || !user.canFork(origin)) { + logger.error("User {} is not permitted to fork '{}'!", + user == null ? "anonymous" : user.username, objectName); + response.setStatus(failureCode); + } else { + try { + // fork the origin + RepositoryModel fork = gitblit.fork(origin, user); + if (fork == null) { + logger.error("Failed to fork repository '{}'!", objectName); + response.setStatus(failureCode); + } else { + logger.info("User {} has forked '{}'!", user.username, objectName); + } + } catch (GitBlitException e) { + response.setStatus(failureCode); + } + } + } } else if (RpcRequest.EDIT_REPOSITORY.equals(reqType)) { // edit repository RepositoryModel model = deserialize(request, response, RepositoryModel.class); diff --git a/src/main/java/com/gitblit/utils/RpcUtils.java b/src/main/java/com/gitblit/utils/RpcUtils.java index 904461c8..82202154 100644 --- a/src/main/java/com/gitblit/utils/RpcUtils.java +++ b/src/main/java/com/gitblit/utils/RpcUtils.java @@ -25,7 +25,16 @@ import java.util.Map; import com.gitblit.Constants; import com.gitblit.Constants.RpcRequest; import com.gitblit.GitBlitException.UnknownRequestException; -import com.gitblit.models.*; +import com.gitblit.models.FederationModel; +import com.gitblit.models.FederationProposal; +import com.gitblit.models.FederationSet; +import com.gitblit.models.FeedModel; +import com.gitblit.models.RegistrantAccessPermission; +import com.gitblit.models.RepositoryModel; +import com.gitblit.models.ServerSettings; +import com.gitblit.models.ServerStatus; +import com.gitblit.models.TeamModel; +import com.gitblit.models.UserModel; import com.google.gson.reflect.TypeToken; /** @@ -195,20 +204,16 @@ public class RpcUtils { } /** - * Create a fork of an already existing repo + * Create a fork of a repository. * * @param repository - * @param user * @return true if the action succeeded * @throws IOException */ - public static boolean forkRpository(RepositoryModel repository, UserModel user, String serverUrl, + public static boolean forkRepository(RepositoryModel repository, String serverUrl, String account, char[] password) throws IOException { - UserRepositoryCompositeModel userRepositoryCompositeModel = new UserRepositoryCompositeModel(); - userRepositoryCompositeModel.setRepositoryModel(repository); - userRepositoryCompositeModel.setUserModel(user); - return doAction(RpcRequest.FORK_REPOSITORY, null, userRepositoryCompositeModel, serverUrl, account, password); + return doAction(RpcRequest.FORK_REPOSITORY, repository.name, null, serverUrl, account, password); } diff --git a/src/site/rpc.mkd b/src/site/rpc.mkd index b86fd9ad..2e502e2c 100644 --- a/src/site/rpc.mkd +++ b/src/site/rpc.mkd @@ -57,9 +57,10 @@ The Gitblit API includes methods for retrieving and interpreting RSS feeds. The Gitblit v0.8.02 Gitblit v0.9.0 - v1.0.03 Gitblit v1.1.04 -Gitblit v1.2.0+5 -Gitblit v1.3.1+6 -Gitblit v1.4.0+7 +Gitblit v1.2.05 +Gitblit v1.3.16 +Gitblit v1.4.07 +Gitblit v1.6.08 @@ -81,6 +82,7 @@ Use *SET_REPOSITORY_TEAM_PERMISSIONS* instead. LIST_BRANCHES--1-Map<String, List<String>> LIST_SETTINGS--1-ServerSettings (basic keys) GET_USERuser name-6-UserModel +FORK_REPOSITORYrepository name-8-- web.enableRpcManagement=true CREATE_REPOSITORYrepository nameadmin1RepositoryModel- EDIT_REPOSITORYrepository nameadmin1RepositoryModel- diff --git a/src/test/config/test-users.conf b/src/test/config/test-users.conf index 4e00903b..1d01f846 100644 --- a/src/test/config/test-users.conf +++ b/src/test/config/test-users.conf @@ -6,6 +6,7 @@ role = "#notfederated" [user "sampleuser"] password = sampleuser + cookie = 6e07ed42149fc166206319faffdfba2e2ec82e43 accountType = LOCAL role = "#none" [team "admins"] diff --git a/src/test/java/com/gitblit/tests/RpcTests.java b/src/test/java/com/gitblit/tests/RpcTests.java index 943153de..51b4671b 100644 --- a/src/test/java/com/gitblit/tests/RpcTests.java +++ b/src/test/java/com/gitblit/tests/RpcTests.java @@ -191,12 +191,6 @@ public class RpcTests extends GitblitUnitTest { assertEquals(AccessRestrictionType.VIEW, retrievedRepository.accessRestriction); assertEquals(AuthorizationControl.AUTHENTICATED, retrievedRepository.authorizationControl); - //fork repo - UserModel userModel = new UserModel("garbageUser"); - assertTrue("Failed to create Fork Repository!", - RpcUtils.forkRpository(model, userModel, url, account, password.toCharArray())); - - // rename and change access restriciton String originalName = model.name; model.name = "garbagerepo2.git"; @@ -403,4 +397,67 @@ public class RpcTests extends GitblitUnitTest { assertNotNull(branches); assertTrue(branches.size() > 0); } + + @Test + public void testFork() throws Exception { + // test forking by an administrator + // admins are all-powerful and can fork the unforakable :) + testFork(account, password, true, true); + testFork(account, password, false, true); + + // test forking by a permitted normal user + UserModel forkUser = new UserModel("forkuser"); + forkUser.password = forkUser.username; + forkUser.canFork = true; + RpcUtils.deleteUser(forkUser, url, account, password.toCharArray()); + RpcUtils.createUser(forkUser, url, account, password.toCharArray()); + testFork(forkUser.username, forkUser.password, true, true); + testFork(forkUser.username, forkUser.password, false, false); + RpcUtils.deleteUser(forkUser, url, account, password.toCharArray()); + + // test forking by a non-permitted normal user + UserModel noForkUser = new UserModel("noforkuser"); + noForkUser.password = noForkUser.username; + noForkUser.canFork = false; + RpcUtils.deleteUser(noForkUser, url, account, password.toCharArray()); + RpcUtils.createUser(noForkUser, url, account, password.toCharArray()); + testFork(forkUser.username, forkUser.password, true, false); + testFork(forkUser.username, forkUser.password, false, false); + RpcUtils.deleteUser(noForkUser, url, account, password.toCharArray()); + } + + private void testFork(String forkAcct, String forkAcctPassword, boolean allowForks, boolean expectSuccess) throws Exception { + // test does not exist + RepositoryModel dne = new RepositoryModel(); + dne.name = "doesNotExist.git"; + assertFalse(String.format("Successfully forked %s!", dne.name), + RpcUtils.forkRepository(dne, url, forkAcct, forkAcctPassword.toCharArray())); + + // delete any previous fork + RepositoryModel fork = findRepository(String.format("~%s/helloworld.git", forkAcct)); + if (fork != null) { + RpcUtils.deleteRepository(fork, url, account, password.toCharArray()); + } + + // update the origin to allow forks or not + RepositoryModel origin = findRepository("helloworld.git"); + origin.allowForks = allowForks; + RpcUtils.updateRepository(origin.name, origin, url, account, password.toCharArray()); + + // fork the repository + if (expectSuccess) { + assertTrue(String.format("Failed to fork %s!", origin.name), + RpcUtils.forkRepository(origin, url, forkAcct, forkAcctPassword.toCharArray())); + } else { + assertFalse(String.format("Successfully forked %s!", origin.name), + RpcUtils.forkRepository(origin, url, forkAcct, forkAcctPassword.toCharArray())); + } + + // attempt another fork + assertFalse(String.format("Successfully forked %s!", origin.name), + RpcUtils.forkRepository(origin, url, forkAcct, forkAcctPassword.toCharArray())); + + // delete the fork repository + RpcUtils.deleteRepository(fork, url, account, password.toCharArray()); + } } diff --git a/src/test/java/com/gitblit/tests/Test.java b/src/test/java/com/gitblit/tests/Test.java deleted file mode 100644 index 275c6b4c..00000000 --- a/src/test/java/com/gitblit/tests/Test.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.gitblit.tests; - -/** - * Created with IntelliJ IDEA. - * User: manisha - * Date: 3/21/14 - * Time: 12:03 PM - * To change this template use File | Settings | File Templates. - */ -public @interface Test { -} -- cgit v1.2.3 From f76fee63ed9cb3a30d3c0c092d860b1cb93a481b Mon Sep 17 00:00:00 2001 From: Gerard Smyth Date: Tue, 1 Apr 2014 12:29:01 +0100 Subject: Updated the SyndicationServlet to provide an additional option to return details of the tags in the repository instead of the commits. This uses a new 'ot' request parameter to indicate the object type of the content to return, which can be ither TAG or COMMIT. If this is not provided, then COMMIT is assumed to maintain backwards compatability. If tags are returned, then the paging parameters, 'l' and 'pg' are still supported, but searching options are currently ignored. --- src/main/java/com/gitblit/Constants.java | 21 ++++ .../com/gitblit/servlet/SyndicationServlet.java | 135 ++++++++++++++------- src/main/java/com/gitblit/utils/JGitUtils.java | 48 +++++++- 3 files changed, 159 insertions(+), 45 deletions(-) (limited to 'src/main/java/com/gitblit/Constants.java') diff --git a/src/main/java/com/gitblit/Constants.java b/src/main/java/com/gitblit/Constants.java index c8ce83c1..2007c0a8 100644 --- a/src/main/java/com/gitblit/Constants.java +++ b/src/main/java/com/gitblit/Constants.java @@ -402,6 +402,27 @@ public class Constants { } } + /** + * Enumeration of the feed content object types. + */ + public static enum FeedContentObjectType { + COMMIT, TAG; + + public static FeedContentObjectType forName(String name) { + for (FeedContentObjectType type : values()) { + if (type.name().equalsIgnoreCase(name)) { + return type; + } + } + return COMMIT; + } + + @Override + public String toString() { + return name().toLowerCase(); + } + } + /** * The types of objects that can be indexed and queried. */ diff --git a/src/main/java/com/gitblit/servlet/SyndicationServlet.java b/src/main/java/com/gitblit/servlet/SyndicationServlet.java index 24def995..9650ee3a 100644 --- a/src/main/java/com/gitblit/servlet/SyndicationServlet.java +++ b/src/main/java/com/gitblit/servlet/SyndicationServlet.java @@ -163,6 +163,15 @@ public class SyndicationServlet extends DaggerServlet { searchType = type; } } + + Constants.FeedContentObjectType objectType = Constants.FeedContentObjectType.COMMIT; + if (!StringUtils.isEmpty(request.getParameter("ot"))) { + Constants.FeedContentObjectType type = Constants.FeedContentObjectType.forName(request.getParameter("ot")); + if (type != null) { + objectType = type; + } + } + int length = settings.getInteger(Keys.web.syndicationEntries, 25); if (StringUtils.isEmpty(objectId)) { objectId = org.eclipse.jgit.lib.Constants.HEAD; @@ -214,14 +223,7 @@ public class SyndicationServlet extends DaggerServlet { boolean mountParameters = settings.getBoolean(Keys.web.mountParameters, true); - String urlPattern; - if (mountParameters) { - // mounted parameters - urlPattern = "{0}/commit/{1}/{2}"; - } else { - // parameterized parameters - urlPattern = "{0}/commit/?r={1}&h={2}"; - } + String gitblitUrl = settings.getString(Keys.web.canonicalUrl, null); if (StringUtils.isEmpty(gitblitUrl)) { gitblitUrl = HttpUtils.getGitblitURL(request); @@ -247,47 +249,92 @@ public class SyndicationServlet extends DaggerServlet { feedDescription = model.description; } - List commits; - if (StringUtils.isEmpty(searchString)) { - // standard log/history lookup - commits = JGitUtils.getRevLog(repository, objectId, offset, length); + if (objectType == Constants.FeedContentObjectType.TAG) { + + String urlPattern; + if (mountParameters) { + // mounted parameters + urlPattern = "{0}/tag/{1}/{2}"; + } else { + // parameterized parameters + urlPattern = "{0}/tag/?r={1}&h={2}"; + } + + List tags = JGitUtils.getTags(repository, false, length, offset); + + for (RefModel tag : tags) { + FeedEntryModel entry = new FeedEntryModel(); + entry.title = tag.getName(); + entry.author = tag.getAuthorIdent().getName(); + entry.link = MessageFormat.format(urlPattern, gitblitUrl, + StringUtils.encodeURL(model.name.replace('/', fsc)), tag.getObjectId().getName()); + entry.published = tag.getDate(); + entry.contentType = "text/html"; + entry.content = tag.getFullMessage(); + entry.repository = model.name; + entry.branch = objectId; + + entry.tags = new ArrayList(); + + // add tag id and referenced commit id + entry.tags.add("tag:" + tag.getObjectId().getName()); + entry.tags.add("commit:" + tag.getReferencedObjectId().getName()); + + entries.add(entry); + } } else { - // repository search - commits = JGitUtils.searchRevlogs(repository, objectId, searchString, searchType, - offset, length); - } - Map> allRefs = JGitUtils.getAllRefs(repository, model.showRemoteBranches); - BugtraqProcessor processor = new BugtraqProcessor(settings); - - // convert RevCommit to SyndicatedEntryModel - for (RevCommit commit : commits) { - FeedEntryModel entry = new FeedEntryModel(); - entry.title = commit.getShortMessage(); - entry.author = commit.getAuthorIdent().getName(); - entry.link = MessageFormat.format(urlPattern, gitblitUrl, - StringUtils.encodeURL(model.name.replace('/', fsc)), commit.getName()); - entry.published = commit.getCommitterIdent().getWhen(); - entry.contentType = "text/html"; - String message = processor.processCommitMessage(repository, model, commit.getFullMessage()); - entry.content = message; - entry.repository = model.name; - entry.branch = objectId; - entry.tags = new ArrayList(); - - // add commit id and parent commit ids - entry.tags.add("commit:" + commit.getName()); - for (RevCommit parent : commit.getParents()) { - entry.tags.add("parent:" + parent.getName()); + + String urlPattern; + if (mountParameters) { + // mounted parameters + urlPattern = "{0}/commit/{1}/{2}"; + } else { + // parameterized parameters + urlPattern = "{0}/commit/?r={1}&h={2}"; } - // add refs to tabs list - List refs = allRefs.get(commit.getId()); - if (refs != null && refs.size() > 0) { - for (RefModel ref : refs) { - entry.tags.add("ref:" + ref.getName()); + List commits; + if (StringUtils.isEmpty(searchString)) { + // standard log/history lookup + commits = JGitUtils.getRevLog(repository, objectId, offset, length); + } else { + // repository search + commits = JGitUtils.searchRevlogs(repository, objectId, searchString, searchType, + offset, length); + } + Map> allRefs = JGitUtils.getAllRefs(repository, model.showRemoteBranches); + BugtraqProcessor processor = new BugtraqProcessor(settings); + + // convert RevCommit to SyndicatedEntryModel + for (RevCommit commit : commits) { + FeedEntryModel entry = new FeedEntryModel(); + entry.title = commit.getShortMessage(); + entry.author = commit.getAuthorIdent().getName(); + entry.link = MessageFormat.format(urlPattern, gitblitUrl, + StringUtils.encodeURL(model.name.replace('/', fsc)), commit.getName()); + entry.published = commit.getCommitterIdent().getWhen(); + entry.contentType = "text/html"; + String message = processor.processCommitMessage(repository, model, commit.getFullMessage()); + entry.content = message; + entry.repository = model.name; + entry.branch = objectId; + entry.tags = new ArrayList(); + + // add commit id and parent commit ids + entry.tags.add("commit:" + commit.getName()); + for (RevCommit parent : commit.getParents()) { + entry.tags.add("parent:" + parent.getName()); + } + + // add refs to tabs list + List refs = allRefs.get(commit.getId()); + if (refs != null && refs.size() > 0) { + for (RefModel ref : refs) { + entry.tags.add("ref:" + ref.getName()); + } } + entries.add(entry); } - entries.add(entry); } } diff --git a/src/main/java/com/gitblit/utils/JGitUtils.java b/src/main/java/com/gitblit/utils/JGitUtils.java index 190872a7..da51ea98 100644 --- a/src/main/java/com/gitblit/utils/JGitUtils.java +++ b/src/main/java/com/gitblit/utils/JGitUtils.java @@ -1667,6 +1667,24 @@ public class JGitUtils { return getRefs(repository, Constants.R_TAGS, fullName, maxCount); } + /** + * Returns the list of tags in the repository. If repository does not exist + * or is empty, an empty list is returned. + * + * @param repository + * @param fullName + * if true, /refs/tags/yadayadayada is returned. If false, + * yadayadayada is returned. + * @param maxCount + * if < 0, all tags are returned + * @param offset + * if maxCount provided sets the starting point of the records to return + * @return list of tags + */ + public static List getTags(Repository repository, boolean fullName, int maxCount, int offset) { + return getRefs(repository, Constants.R_TAGS, fullName, maxCount, offset); + } + /** * Returns the list of local branches in the repository. If repository does * not exist or is empty, an empty list is returned. @@ -1748,6 +1766,27 @@ public class JGitUtils { */ private static List getRefs(Repository repository, String refs, boolean fullName, int maxCount) { + return getRefs(repository, refs, fullName, maxCount, 0); + } + + /** + * Returns a list of references in the repository matching "refs". If the + * repository is null or empty, an empty list is returned. + * + * @param repository + * @param refs + * if unspecified, all refs are returned + * @param fullName + * if true, /refs/something/yadayadayada is returned. If false, + * yadayadayada is returned. + * @param maxCount + * if < 0, all references are returned + * @param offset + * if maxCount provided sets the starting point of the records to return + * @return list of references + */ + private static List getRefs(Repository repository, String refs, boolean fullName, + int maxCount, int offset) { List list = new ArrayList(); if (maxCount == 0) { return list; @@ -1771,7 +1810,14 @@ public class JGitUtils { Collections.sort(list); Collections.reverse(list); if (maxCount > 0 && list.size() > maxCount) { - list = new ArrayList(list.subList(0, maxCount)); + if (offset < 0) { + offset = 0; + } + int endIndex = offset + maxCount; + if (endIndex > list.size()) { + endIndex = list.size(); + } + list = new ArrayList(list.subList(offset, endIndex)); } } catch (IOException e) { error(e, repository, "{0} failed to retrieve {1}", refs); -- cgit v1.2.3 From 9ff0c16b05cb0eb7c3cc63eda763b0f75d84853c Mon Sep 17 00:00:00 2001 From: James Moger Date: Thu, 8 May 2014 13:09:08 -0400 Subject: Change enum name and unit test RSS tag queries --- releases.moxie | 2 + src/main/java/com/gitblit/Constants.java | 6 +-- .../com/gitblit/servlet/SyndicationServlet.java | 6 +-- .../java/com/gitblit/utils/SyndicationUtils.java | 57 ++++++++++++++++++++++ src/site/rpc.mkd | 1 + .../com/gitblit/tests/SyndicationUtilsTest.java | 36 +++++++++++++- 6 files changed, 101 insertions(+), 7 deletions(-) (limited to 'src/main/java/com/gitblit/Constants.java') diff --git a/releases.moxie b/releases.moxie index 228fc7e6..96a0ae91 100644 --- a/releases.moxie +++ b/releases.moxie @@ -13,9 +13,11 @@ r24: { changes: ~ additions: - Add FORK_REPOSITORY RPC request type (issue-371, pr-161, ticket-65) + - Add object type (ot) parameter for RSS queries to retrieve tag details (pr-165, ticket-66) dependencyChanges: ~ contributors: - Manisha Gayathri + - Gerard Smyth } # diff --git a/src/main/java/com/gitblit/Constants.java b/src/main/java/com/gitblit/Constants.java index 2007c0a8..95eb944a 100644 --- a/src/main/java/com/gitblit/Constants.java +++ b/src/main/java/com/gitblit/Constants.java @@ -405,11 +405,11 @@ public class Constants { /** * Enumeration of the feed content object types. */ - public static enum FeedContentObjectType { + public static enum FeedObjectType { COMMIT, TAG; - public static FeedContentObjectType forName(String name) { - for (FeedContentObjectType type : values()) { + public static FeedObjectType forName(String name) { + for (FeedObjectType type : values()) { if (type.name().equalsIgnoreCase(name)) { return type; } diff --git a/src/main/java/com/gitblit/servlet/SyndicationServlet.java b/src/main/java/com/gitblit/servlet/SyndicationServlet.java index 9650ee3a..631df781 100644 --- a/src/main/java/com/gitblit/servlet/SyndicationServlet.java +++ b/src/main/java/com/gitblit/servlet/SyndicationServlet.java @@ -164,9 +164,9 @@ public class SyndicationServlet extends DaggerServlet { } } - Constants.FeedContentObjectType objectType = Constants.FeedContentObjectType.COMMIT; + Constants.FeedObjectType objectType = Constants.FeedObjectType.COMMIT; if (!StringUtils.isEmpty(request.getParameter("ot"))) { - Constants.FeedContentObjectType type = Constants.FeedContentObjectType.forName(request.getParameter("ot")); + Constants.FeedObjectType type = Constants.FeedObjectType.forName(request.getParameter("ot")); if (type != null) { objectType = type; } @@ -249,7 +249,7 @@ public class SyndicationServlet extends DaggerServlet { feedDescription = model.description; } - if (objectType == Constants.FeedContentObjectType.TAG) { + if (objectType == Constants.FeedObjectType.TAG) { String urlPattern; if (mountParameters) { diff --git a/src/main/java/com/gitblit/utils/SyndicationUtils.java b/src/main/java/com/gitblit/utils/SyndicationUtils.java index 2ee1cf69..93e9321a 100644 --- a/src/main/java/com/gitblit/utils/SyndicationUtils.java +++ b/src/main/java/com/gitblit/utils/SyndicationUtils.java @@ -25,6 +25,7 @@ import java.util.ArrayList; import java.util.List; import com.gitblit.Constants; +import com.gitblit.Constants.FeedObjectType; import com.gitblit.GitBlitException; import com.gitblit.models.FeedEntryModel; import com.sun.syndication.feed.synd.SyndCategory; @@ -137,6 +138,59 @@ public class SyndicationUtils { */ public static List readFeed(String url, String repository, String branch, int numberOfEntries, int page, String username, char[] password) throws IOException { + return readFeed(url, repository, branch, FeedObjectType.COMMIT, numberOfEntries, + page, username, password); + } + + /** + * Reads tags from the specified repository. + * + * @param url + * the url of the Gitblit server + * @param repository + * the repository name + * @param branch + * the branch name (optional) + * @param numberOfEntries + * the number of entries to retrieve. if <= 0 the server default + * is used. + * @param page + * 0-indexed. used to paginate the results. + * @param username + * @param password + * @return a list of SyndicationModel entries + * @throws {@link IOException} + */ + public static List readTags(String url, String repository, + int numberOfEntries, int page, String username, char[] password) throws IOException { + return readFeed(url, repository, null, FeedObjectType.TAG, numberOfEntries, + page, username, password); + } + + /** + * Reads a Gitblit RSS feed. + * + * @param url + * the url of the Gitblit server + * @param repository + * the repository name + * @param branch + * the branch name (optional) + * @param objectType + * the object type to return (optional, COMMIT assummed) + * @param numberOfEntries + * the number of entries to retrieve. if <= 0 the server default + * is used. + * @param page + * 0-indexed. used to paginate the results. + * @param username + * @param password + * @return a list of SyndicationModel entries + * @throws {@link IOException} + */ + private static List readFeed(String url, String repository, String branch, + FeedObjectType objectType, int numberOfEntries, int page, String username, + char[] password) throws IOException { // build feed url List parameters = new ArrayList(); if (numberOfEntries > 0) { @@ -148,6 +202,9 @@ public class SyndicationUtils { if (!StringUtils.isEmpty(branch)) { parameters.add("h=" + branch); } + if (objectType != null) { + parameters.add("ot=" + objectType.name()); + } return readFeed(url, parameters, repository, branch, username, password); } diff --git a/src/site/rpc.mkd b/src/site/rpc.mkd index 2e502e2c..302084fb 100644 --- a/src/site/rpc.mkd +++ b/src/site/rpc.mkd @@ -32,6 +32,7 @@ The Gitblit API includes methods for retrieving and interpreting RSS feeds. The url parameterdefaultdescription standard query repositoryrequiredrepository name is part of the url (see examples below) +ot=optional
default: COMMITobject type to return in results. COMMIT or TAG h=optional
default: HEADstarting branch, ref, or commit id l=optional
default: web.syndicationEntriesmaximum return count pg=optional
default: 0page number for paging
(offset into history = pagenumber*maximum return count) diff --git a/src/test/java/com/gitblit/tests/SyndicationUtilsTest.java b/src/test/java/com/gitblit/tests/SyndicationUtilsTest.java index d206bbdb..b4bb044f 100644 --- a/src/test/java/com/gitblit/tests/SyndicationUtilsTest.java +++ b/src/test/java/com/gitblit/tests/SyndicationUtilsTest.java @@ -21,7 +21,10 @@ import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; +import org.junit.AfterClass; +import org.junit.BeforeClass; import org.junit.Test; import com.gitblit.Constants.SearchType; @@ -30,6 +33,20 @@ import com.gitblit.utils.SyndicationUtils; public class SyndicationUtilsTest extends GitblitUnitTest { + private static final AtomicBoolean started = new AtomicBoolean(false); + + @BeforeClass + public static void startGitblit() throws Exception { + started.set(GitBlitSuite.startGitblit()); + } + + @AfterClass + public static void stopGitblit() throws Exception { + if (started.get()) { + GitBlitSuite.stopGitblit(); + } + } + @Test public void testSyndication() throws Exception { List entries = new ArrayList(); @@ -60,7 +77,7 @@ public class SyndicationUtilsTest extends GitblitUnitTest { } @Test - public void testFeedRead() throws Exception { + public void testFeedReadCommits() throws Exception { Set links = new HashSet(); for (int i = 0; i < 2; i++) { List feed = SyndicationUtils.readFeed(GitBlitSuite.url, "ticgit.git", @@ -76,6 +93,23 @@ public class SyndicationUtilsTest extends GitblitUnitTest { assertEquals("Feed pagination failed", 10, links.size()); } + @Test + public void testFeedReadTags() throws Exception { + Set links = new HashSet(); + for (int i = 0; i < 2; i++) { + List feed = SyndicationUtils.readTags(GitBlitSuite.url, "test/gitective.git", + 5, i, GitBlitSuite.account, GitBlitSuite.password.toCharArray()); + assertTrue(feed != null); + assertTrue(feed.size() > 0); + assertEquals(5, feed.size()); + for (FeedEntryModel entry : feed) { + links.add(entry.link); + } + } + // confirm we have 10 unique tags + assertEquals("Feed pagination failed", 10, links.size()); + } + @Test public void testSearchFeedRead() throws Exception { List feed = SyndicationUtils -- cgit v1.2.3 From 0047fbba99b804d268a66ed7504a568596de6168 Mon Sep 17 00:00:00 2001 From: James Moger Date: Tue, 27 May 2014 18:13:30 -0400 Subject: Simplified repository creation with a NewRepositoryPage --- .gitmodules | 3 + build.xml | 6 + releases.moxie | 2 + src/main/distrib/data/gitblit.properties | 5 + src/main/distrib/data/gitignore | 1 + src/main/java/com/gitblit/Constants.java | 8 + .../java/com/gitblit/servlet/GitblitContext.java | 16 + .../java/com/gitblit/wicket/GitBlitWebApp.java | 10 + .../com/gitblit/wicket/GitBlitWebApp.properties | 17 +- .../gitblit/wicket/pages/EditRepositoryPage.java | 16 +- .../gitblit/wicket/pages/NewRepositoryPage.html | 98 ++++ .../gitblit/wicket/pages/NewRepositoryPage.java | 493 +++++++++++++++++++++ .../java/com/gitblit/wicket/pages/RootPage.java | 2 +- .../java/com/gitblit/wicket/pages/UserPage.java | 4 +- .../wicket/panels/FilterableRepositoryList.java | 3 +- .../gitblit/wicket/panels/RepositoriesPanel.java | 5 +- 16 files changed, 674 insertions(+), 15 deletions(-) create mode 100644 .gitmodules create mode 160000 src/main/distrib/data/gitignore create mode 100644 src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html create mode 100644 src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java (limited to 'src/main/java/com/gitblit/Constants.java') diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..01eaa2c8 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "src/main/distrib/data/gitignore"] + path = src/main/distrib/data/gitignore + url = https://github.com/github/gitignore.git diff --git a/build.xml b/build.xml index f45c4ca9..be6f1dd2 100644 --- a/build.xml +++ b/build.xml @@ -919,6 +919,12 @@ + + + + + + diff --git a/releases.moxie b/releases.moxie index 4332238d..5aa207fa 100644 --- a/releases.moxie +++ b/releases.moxie @@ -36,6 +36,7 @@ r24: { - Add FORK_REPOSITORY RPC request type (issue-371, pr-161, ticket-65) - Add object type (ot) parameter for RSS queries to retrieve tag details (pr-165, ticket-66) - Add setting to allow STARTTLS without requiring SMTPS (pr-183) + - Simplified repository creation, offer simple README generation, and insertion of a pre-defined .gitignore file (ticket-76) - Added an extension point for monitoring onStartup and onShutdown (ticket-79) - Tag server-side merges when incremental push tags are enabled (issue-432, ticket-85) - Add setting to control default thread pool size for miscellaneous background tasks (ticket-92) @@ -55,6 +56,7 @@ r24: { - { name: 'web.allowDeletingNonEmptyRepositories', defaultValue: 'true' } - { name: 'mail.starttls', defaultValue: 'false' } - { name: 'execution.defaultThreadPoolSize', defaultValue: '1' } + - { name: 'git.gitignoreFolder', defaultValue: '${baseFolder}/gitignore' } } # diff --git a/src/main/distrib/data/gitblit.properties b/src/main/distrib/data/gitblit.properties index 6f55a3eb..d5623cd5 100644 --- a/src/main/distrib/data/gitblit.properties +++ b/src/main/distrib/data/gitblit.properties @@ -271,6 +271,11 @@ git.defaultIncrementalPushTagPrefix = r # SINCE 1.4.0 git.createRepositoriesShared = false +# Directory for gitignore templates used during repository creation. +# +# SINCE 1.6.0 +git.gitignoreFolder = ${baseFolder}/gitignore + # Enable JGit-based garbage collection. (!!EXPERIMENTAL!!) # # USE AT YOUR OWN RISK! diff --git a/src/main/distrib/data/gitignore b/src/main/distrib/data/gitignore new file mode 160000 index 00000000..097db81c --- /dev/null +++ b/src/main/distrib/data/gitignore @@ -0,0 +1 @@ +Subproject commit 097db81c08b138dea7cb031eb18eeb16afe44bdf diff --git a/src/main/java/com/gitblit/Constants.java b/src/main/java/com/gitblit/Constants.java index 95eb944a..3e307537 100644 --- a/src/main/java/com/gitblit/Constants.java +++ b/src/main/java/com/gitblit/Constants.java @@ -122,6 +122,14 @@ public class Constants { public static final String R_TICKETS_PATCHSETS = "refs/tickets/"; + public static final String R_MASTER = "refs/heads/master"; + + public static final String MASTER = "master"; + + public static final String R_DEVELOP = "refs/heads/develop"; + + public static final String DEVELOP = "develop"; + public static String getVersion() { String v = Constants.class.getPackage().getImplementationVersion(); if (v == null) { diff --git a/src/main/java/com/gitblit/servlet/GitblitContext.java b/src/main/java/com/gitblit/servlet/GitblitContext.java index 110e553c..50f22d5a 100644 --- a/src/main/java/com/gitblit/servlet/GitblitContext.java +++ b/src/main/java/com/gitblit/servlet/GitblitContext.java @@ -372,6 +372,22 @@ public class GitblitContext extends DaggerContext { } } + // Copy the included gitignore files to the configured gitignore folder + String gitignorePath = webxmlSettings.getString(Keys.git.gitignoreFolder, "gitignore"); + File localGitignores = com.gitblit.utils.FileUtils.resolveParameter(Constants.baseFolder$, base, gitignorePath); + if (!localGitignores.exists()) { + File warGitignores = new File(contextFolder, "/WEB-INF/data/gitignore"); + if (!warGitignores.equals(localGitignores)) { + try { + com.gitblit.utils.FileUtils.copy(localGitignores, warGitignores.listFiles()); + } catch (IOException e) { + logger.error(MessageFormat.format( + "Failed to copy included .gitignore files from {0} to {1}", + warGitignores, localGitignores)); + } + } + } + // merge the WebXmlSettings into the runtime settings (for backwards-compatibilty) runtimeSettings.merge(webxmlSettings); diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.java b/src/main/java/com/gitblit/wicket/GitBlitWebApp.java index 7291d039..f63ff3d9 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.java +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.java @@ -57,6 +57,7 @@ import com.gitblit.wicket.pages.ComparePage; import com.gitblit.wicket.pages.DocPage; import com.gitblit.wicket.pages.DocsPage; import com.gitblit.wicket.pages.EditMilestonePage; +import com.gitblit.wicket.pages.EditRepositoryPage; import com.gitblit.wicket.pages.EditTicketPage; import com.gitblit.wicket.pages.ExportTicketPage; import com.gitblit.wicket.pages.FederationRegistrationPage; @@ -71,6 +72,7 @@ import com.gitblit.wicket.pages.MetricsPage; import com.gitblit.wicket.pages.MyDashboardPage; import com.gitblit.wicket.pages.MyTicketsPage; import com.gitblit.wicket.pages.NewMilestonePage; +import com.gitblit.wicket.pages.NewRepositoryPage; import com.gitblit.wicket.pages.NewTicketPage; import com.gitblit.wicket.pages.OverviewPage; import com.gitblit.wicket.pages.PatchPage; @@ -92,6 +94,8 @@ public class GitBlitWebApp extends WebApplication implements GitblitWicketApp { private final Class homePageClass = MyDashboardPage.class; + private final Class newRepositoryPageClass = NewRepositoryPage.class; + private final Map cacheablePages = new HashMap(); private final IStoredSettings settings; @@ -207,6 +211,8 @@ public class GitBlitWebApp extends WebApplication implements GitblitWicketApp { mount("/proposal", ReviewProposalPage.class, "t"); mount("/registration", FederationRegistrationPage.class, "u", "n"); + mount("/new", NewRepositoryPage.class); + mount("/edit", EditRepositoryPage.class, "r"); mount("/activity", ActivityPage.class, "r", "h"); mount("/lucene", LuceneSearchPage.class); mount("/project", ProjectPage.class, "p"); @@ -262,6 +268,10 @@ public class GitBlitWebApp extends WebApplication implements GitblitWicketApp { return homePageClass; } + public Class getNewRepositoryPage() { + return newRepositoryPageClass; + } + /* (non-Javadoc) * @see com.gitblit.wicket.Webapp#isCacheablePage(java.lang.String) */ diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties index 12430ade..ac589558 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties @@ -685,4 +685,19 @@ gb.closedMilestones = closed milestones gb.administration = administration gb.plugins = plugins gb.extensions = extensions - +gb.anonymous = Anonymous +gb.anonymousRepoDescription = Anyone can see, clone, and push to this repository. +gb.public = Public +gb.publicRepoDescription = Anyone can see and clone this repository. You choose who can push. +gb.protected = Protected +gb.protectedRepoDescription = Anyone can see this repository. You choose who can clone and push. +gb.private = Private +gb.privateRepoDescription = You choose who can see, clone, and push to this repository. +gb.initialCommit = Initial Commit +gb.initialCommitDescription = This will allow you to git clone this repository immediately. Skip this step if you have already run git init locally. +gb.initWithReadme = Include a README +gb.initWithReadmeDescription = This will generate a simple README document for your repository. +gb.initWithGitignore = Include a .gitignore file +gb.initWithGitignoreDescription = This will insert a config file that instructs your Git clients to ignore files or directories that match defined patterns. +gb.initWithGitflow = Include a .gitflow file +gb.initWithGitflowDescription = This will generate a config file which guides Git clients in setting up Gitflow branches. \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java index 412c0ecc..c18cd514 100644 --- a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java +++ b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java @@ -429,11 +429,7 @@ public class EditRepositoryPage extends RootSubPage { return; } setRedirect(false); - if (isCreate) { - setResponsePage(RepositoriesPage.class); - } else { - setResponsePage(SummaryPage.class, WicketUtils.newRepositoryParameter(repositoryModel.name)); - } + setResponsePage(SummaryPage.class, WicketUtils.newRepositoryParameter(repositoryModel.name)); } }; @@ -632,7 +628,15 @@ public class EditRepositoryPage extends RootSubPage { if (canDelete) { if (app().repositories().deleteRepositoryModel(latestModel)) { info(MessageFormat.format(getString("gb.repositoryDeleted"), latestModel)); - setResponsePage(RepositoriesPage.class); + if (latestModel.isPersonalRepository()) { + // redirect to user's profile page + String prefix = app().settings().getString(Keys.git.userRepositoryPrefix, "~"); + String username = latestModel.projectPath.substring(prefix.length()); + setResponsePage(UserPage.class, WicketUtils.newUsernameParameter(username)); + } else { + // redirect to server repositories page + setResponsePage(RepositoriesPage.class); + } } else { error(MessageFormat.format(getString("gb.repositoryDeleteFailed"), latestModel)); } diff --git a/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html new file mode 100644 index 00000000..e9f12027 --- /dev/null +++ b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html @@ -0,0 +1,98 @@ + + + + + +
+
+
+ + + + + + + + + + + + + + +
/  
+ +
+
+ +
+ +
+ + +
+
+ + +
+
+
+ +
+
+
+ +
+ +

+
+

+
+ +
+
+ +
+
+
+

+
+
+ +
+ +
+ +
+
+ +

+
+
+ +
+
+ +
+
+
+

+

+
+
+ + + + + \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java new file mode 100644 index 00000000..b0cc3e95 --- /dev/null +++ b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java @@ -0,0 +1,493 @@ +/* + * Copyright 2014 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.wicket.pages; + +import java.io.File; +import java.io.IOException; +import java.io.Serializable; +import java.io.UnsupportedEncodingException; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; +import org.apache.wicket.behavior.SimpleAttributeModifier; +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.html.form.Button; +import org.apache.wicket.markup.html.form.CheckBox; +import org.apache.wicket.markup.html.form.DropDownChoice; +import org.apache.wicket.markup.html.form.Form; +import org.apache.wicket.markup.html.form.Radio; +import org.apache.wicket.markup.html.form.RadioGroup; +import org.apache.wicket.markup.html.form.TextField; +import org.apache.wicket.markup.html.list.ListItem; +import org.apache.wicket.markup.html.list.ListView; +import org.apache.wicket.model.CompoundPropertyModel; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.Model; +import org.eclipse.jgit.dircache.DirCache; +import org.eclipse.jgit.dircache.DirCacheBuilder; +import org.eclipse.jgit.dircache.DirCacheEntry; +import org.eclipse.jgit.lib.CommitBuilder; +import org.eclipse.jgit.lib.Config; +import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.ObjectInserter; +import org.eclipse.jgit.lib.PersonIdent; +import org.eclipse.jgit.lib.RefUpdate; +import org.eclipse.jgit.lib.RefUpdate.Result; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.revwalk.RevWalk; + +import com.gitblit.Constants; +import com.gitblit.Constants.AccessRestrictionType; +import com.gitblit.Constants.AuthorizationControl; +import com.gitblit.GitBlitException; +import com.gitblit.Keys; +import com.gitblit.models.RepositoryModel; +import com.gitblit.models.UserModel; +import com.gitblit.utils.ArrayUtils; +import com.gitblit.utils.FileUtils; +import com.gitblit.utils.StringUtils; +import com.gitblit.wicket.GitBlitWebSession; +import com.gitblit.wicket.WicketUtils; + +public class NewRepositoryPage extends RootSubPage { + + private final RepositoryModel repositoryModel; + private RadioGroup permissionGroup; + private IModel addReadmeModel; + private Model gitignoreModel; + private IModel addGitflowModel; + private IModel addGitignoreModel; + + public NewRepositoryPage() { + // create constructor + super(); + repositoryModel = new RepositoryModel(); + + setupPage(getString("gb.newRepository"), ""); + + setStatelessHint(false); + setOutputMarkupId(true); + } + + @Override + protected boolean requiresPageMap() { + return true; + } + + @Override + protected Class getRootNavPageClass() { + return RepositoriesPage.class; + } + + @Override + protected void onInitialize() { + super.onInitialize(); + + CompoundPropertyModel rModel = new CompoundPropertyModel<>(repositoryModel); + Form form = new Form("editForm", rModel) { + + private static final long serialVersionUID = 1L; + + @Override + protected void onSubmit() { + + // confirm a repository name was entered + if (StringUtils.isEmpty(repositoryModel.name)) { + error(getString("gb.pleaseSetRepositoryName")); + return; + } + + String project = repositoryModel.projectPath; + String fullName = (project + "/" + repositoryModel.name).trim(); + fullName = fullName.replace('\\', '/'); + fullName = fullName.replace("//", "/"); + if (fullName.charAt(0) == '/') { + fullName = fullName.substring(1); + } + if (fullName.endsWith("/")) { + fullName = fullName.substring(0, fullName.length() - 1); + } + + try { + if (fullName.contains("../")) { + error(getString("gb.illegalRelativeSlash")); + return; + } + if (fullName.contains("/../")) { + error(getString("gb.illegalRelativeSlash")); + return; + } + + // confirm valid characters in repository name + Character c = StringUtils.findInvalidCharacter(fullName); + if (c != null) { + error(MessageFormat.format(getString("gb.illegalCharacterRepositoryName"), + c)); + return; + } + + repositoryModel.name = fullName; + repositoryModel.projectPath = null; + + Permission permisison = permissionGroup.getModelObject(); + repositoryModel.accessRestriction = permisison.type; + repositoryModel.authorizationControl = AuthorizationControl.NAMED; + + repositoryModel.owners = new ArrayList(); + repositoryModel.owners.add(GitBlitWebSession.get().getUsername()); + + // setup branch defaults + boolean useGitFlow = addGitflowModel.getObject(); + + repositoryModel.HEAD = Constants.R_MASTER; + repositoryModel.mergeTo = Constants.MASTER; + if (useGitFlow) { + // tickets normally merge to develop unless they are hotfixes + repositoryModel.mergeTo = Constants.DEVELOP; + } + + repositoryModel.allowForks = app().settings().getBoolean(Keys.web.allowForking, true); + + // optionally generate an initial commit + boolean addReadme = addReadmeModel.getObject(); + String gitignore = null; + boolean addGitignore = addGitignoreModel.getObject(); + if (addGitignore) { + gitignore = gitignoreModel.getObject(); + if (StringUtils.isEmpty(gitignore)) { + throw new GitBlitException("Please select a .gitignore file"); + } + } + + // init the repository + app().gitblit().updateRepositoryModel(repositoryModel.name, repositoryModel, true); + + // optionally create an initial commit + initialCommit(repositoryModel, addReadme, gitignore, useGitFlow); + + } catch (GitBlitException e) { + error(e.getMessage()); + + // restore project and name fields on error condition + repositoryModel.projectPath = StringUtils.getFirstPathElement(fullName); + if (!StringUtils.isEmpty(repositoryModel.projectPath)) { + repositoryModel.name = fullName.substring(repositoryModel.projectPath.length() + 1); + } + return; + } + setRedirect(true); + setResponsePage(SummaryPage.class, WicketUtils.newRepositoryParameter(fullName)); + } + }; + + GitBlitWebSession session = GitBlitWebSession.get(); + UserModel user = session.getUser(); + + // build project list for repository destination + String defaultProject = null; + List projects = new ArrayList(); + + if (user.canAdmin()) { + String main = app().settings().getString(Keys.web.repositoryRootGroupName, "main"); + projects.add(main); + defaultProject = main; + } + + if (user.canCreate()) { + projects.add(user.getPersonalPath()); + if (defaultProject == null) { + // only prefer personal namespace if default is not already set + defaultProject = user.getPersonalPath(); + } + } + + repositoryModel.projectPath = defaultProject; + + // do not let the browser pre-populate these fields + form.add(new SimpleAttributeModifier("autocomplete", "off")); + + form.add(new DropDownChoice("projectPath", projects)); + form.add(new TextField("name")); + form.add(new TextField("description")); + + Permission anonymousPermission = new Permission(getString("gb.anonymous"), getString("gb.anonymousRepoDescription"), "blank.png", AccessRestrictionType.NONE); + Permission publicPermission = new Permission(getString("gb.public"), getString("gb.publicRepoDescription"), "lock_go_16x16.png", AccessRestrictionType.PUSH); + Permission protectedPermission = new Permission(getString("gb.protected"), getString("gb.protectedRepoDescription"), "lock_pull_16x16.png", AccessRestrictionType.CLONE); + Permission privatePermission = new Permission(getString("gb.private"), getString("gb.privateRepoDescription"), "shield_16x16.png", AccessRestrictionType.VIEW); + + List permissions = new ArrayList(); + if (app().settings().getBoolean(Keys.git.allowAnonymousPushes, false)) { + permissions.add(anonymousPermission); + } + permissions.add(publicPermission); + permissions.add(protectedPermission); + permissions.add(privatePermission); + + // determine default permission selection + AccessRestrictionType defaultRestriction = AccessRestrictionType.fromName( + app().settings().getString(Keys.git.defaultAccessRestriction, AccessRestrictionType.PUSH.name())); + if (AccessRestrictionType.NONE == defaultRestriction) { + defaultRestriction = AccessRestrictionType.PUSH; + } + + Permission defaultPermission = publicPermission; + for (Permission permission : permissions) { + if (permission.type == defaultRestriction) { + defaultPermission = permission; + } + } + + permissionGroup = new RadioGroup<>("permissionsGroup", new Model(defaultPermission)); + form.add(permissionGroup); + + ListView permissionsList = new ListView("permissions", permissions) { + + private static final long serialVersionUID = 1L; + + @Override + protected void populateItem(ListItem item) { + Permission p = item.getModelObject(); + item.add(new Radio("radio", item.getModel())); + item.add(WicketUtils.newImage("image", p.image)); + item.add(new Label("name", p.name)); + item.add(new Label("description", p.description)); + } + }; + permissionGroup.add(permissionsList); + + // + // initial commit options + // + + // add README + addReadmeModel = Model.of(false); + form.add(new CheckBox("addReadme", addReadmeModel)); + + // add .gitignore + File gitignoreDir = app().runtime().getFileOrFolder(Keys.git.gitignoreFolder, "${baseFolder}/gitignore"); + File [] files = gitignoreDir.listFiles(); + if (files == null) { + files = new File[0]; + } + List gitignores = new ArrayList(); + for (File file : files) { + if (file.isFile() && file.getName().endsWith(".gitignore")) { + gitignores.add(StringUtils.stripFileExtension(file.getName())); + } + } + Collections.sort(gitignores); + gitignoreModel = Model.of(""); + final DropDownChoice gitignoreChoice = new DropDownChoice("gitignore", gitignoreModel, gitignores); + gitignoreChoice.setOutputMarkupId(true); + form.add(gitignoreChoice.setEnabled(false)); + + addGitignoreModel = Model.of(false); + final CheckBox gitignoreCheckbox = new CheckBox("addGitignore", addGitignoreModel); + form.add(gitignoreCheckbox); + + gitignoreCheckbox.add(new AjaxFormComponentUpdatingBehavior("onchange") { + + private static final long serialVersionUID = 1L; + + @Override + protected void onUpdate(AjaxRequestTarget target) { + gitignoreChoice.setEnabled(addGitignoreModel.getObject()); + target.addComponent(gitignoreChoice); + } + }); + + // TODO add .gitflow + addGitflowModel = Model.of(false); + form.add(new CheckBox("addGitflow", addGitflowModel)); + + form.add(new Button("create")); + + add(form); + } + + /** + * Prepare the initial commit for the repository. + * + * @param repository + * @param addReadme + * @param gitignore + * @param addGitFlow + * @return true if an initial commit was created + */ + protected boolean initialCommit(RepositoryModel repository, boolean addReadme, String gitignore, + boolean addGitFlow) { + boolean initialCommit = addReadme || !StringUtils.isEmpty(gitignore) || addGitFlow; + if (!initialCommit) { + return false; + } + + // build an initial commit + boolean success = false; + Repository db = app().repositories().getRepository(repositoryModel.name); + ObjectInserter odi = db.newObjectInserter(); + try { + + UserModel user = GitBlitWebSession.get().getUser(); + PersonIdent author = new PersonIdent(user.getDisplayName(), user.emailAddress); + + DirCache newIndex = DirCache.newInCore(); + DirCacheBuilder indexBuilder = newIndex.builder(); + + if (addReadme) { + // insert a README + String title = StringUtils.stripDotGit(StringUtils.getLastPathElement(repositoryModel.name)); + String description = repositoryModel.description == null ? "" : repositoryModel.description; + String readme = String.format("## %s\n\n%s\n\n", title, description); + byte [] bytes = readme.getBytes(Constants.ENCODING); + + DirCacheEntry entry = new DirCacheEntry("README.md"); + entry.setLength(bytes.length); + entry.setLastModified(System.currentTimeMillis()); + entry.setFileMode(FileMode.REGULAR_FILE); + entry.setObjectId(odi.insert(org.eclipse.jgit.lib.Constants.OBJ_BLOB, bytes)); + + indexBuilder.add(entry); + } + + if (!StringUtils.isEmpty(gitignore)) { + // insert a .gitignore file + File dir = app().runtime().getFileOrFolder(Keys.git.gitignoreFolder, "${baseFolder}/gitignore"); + File file = new File(dir, gitignore + ".gitignore"); + if (file.exists() && file.length() > 0) { + byte [] bytes = FileUtils.readContent(file); + if (!ArrayUtils.isEmpty(bytes)) { + DirCacheEntry entry = new DirCacheEntry(".gitignore"); + entry.setLength(bytes.length); + entry.setLastModified(System.currentTimeMillis()); + entry.setFileMode(FileMode.REGULAR_FILE); + entry.setObjectId(odi.insert(org.eclipse.jgit.lib.Constants.OBJ_BLOB, bytes)); + + indexBuilder.add(entry); + } + } + } + + if (addGitFlow) { + // insert a .gitflow file + Config config = new Config(); + config.setString("gitflow", null, "masterBranch", Constants.MASTER); + config.setString("gitflow", null, "developBranch", Constants.DEVELOP); + config.setString("gitflow", null, "featureBranchPrefix", "feature/"); + config.setString("gitflow", null, "releaseBranchPrefix", "release/"); + config.setString("gitflow", null, "hotfixBranchPrefix", "hotfix/"); + config.setString("gitflow", null, "supportBranchPrefix", "support/"); + config.setString("gitflow", null, "versionTagPrefix", ""); + + byte [] bytes = config.toText().getBytes(Constants.ENCODING); + + DirCacheEntry entry = new DirCacheEntry(".gitflow"); + entry.setLength(bytes.length); + entry.setLastModified(System.currentTimeMillis()); + entry.setFileMode(FileMode.REGULAR_FILE); + entry.setObjectId(odi.insert(org.eclipse.jgit.lib.Constants.OBJ_BLOB, bytes)); + + indexBuilder.add(entry); + } + + indexBuilder.finish(); + + if (newIndex.getEntryCount() == 0) { + // nothing to commit + return false; + } + + ObjectId treeId = newIndex.writeTree(odi); + + // Create a commit object + CommitBuilder commit = new CommitBuilder(); + commit.setAuthor(author); + commit.setCommitter(author); + commit.setEncoding(Constants.ENCODING); + commit.setMessage("Initial commit"); + commit.setTreeId(treeId); + + // Insert the commit into the repository + ObjectId commitId = odi.insert(commit); + odi.flush(); + + // set the branch refs + RevWalk revWalk = new RevWalk(db); + try { + // set the master branch + RevCommit revCommit = revWalk.parseCommit(commitId); + RefUpdate masterRef = db.updateRef(Constants.R_MASTER); + masterRef.setNewObjectId(commitId); + masterRef.setRefLogMessage("commit: " + revCommit.getShortMessage(), false); + Result masterRC = masterRef.update(); + switch (masterRC) { + case NEW: + success = true; + break; + default: + success = false; + } + + if (addGitFlow) { + // set the develop branch for git-flow + RefUpdate developRef = db.updateRef(Constants.R_DEVELOP); + developRef.setNewObjectId(commitId); + developRef.setRefLogMessage("commit: " + revCommit.getShortMessage(), false); + Result developRC = developRef.update(); + switch (developRC) { + case NEW: + success = true; + break; + default: + success = false; + } + } + } finally { + revWalk.release(); + } + } catch (UnsupportedEncodingException e) { + logger().error(null, e); + } catch (IOException e) { + logger().error(null, e); + } finally { + odi.release(); + db.close(); + } + return success; + } + + private static class Permission implements Serializable { + + private static final long serialVersionUID = 1L; + + final String name; + final String description; + final String image; + final AccessRestrictionType type; + + Permission(String name, String description, String img, AccessRestrictionType type) { + this.name = name; + this.description = description; + this.image = img; + this.type = type; + } + } +} diff --git a/src/main/java/com/gitblit/wicket/pages/RootPage.java b/src/main/java/com/gitblit/wicket/pages/RootPage.java index a2f3a497..b1c3639d 100644 --- a/src/main/java/com/gitblit/wicket/pages/RootPage.java +++ b/src/main/java/com/gitblit/wicket/pages/RootPage.java @@ -607,7 +607,7 @@ public abstract class RootPage extends BasePage { List standardItems = new ArrayList(); standardItems.add(new MenuDivider()); if (user.canAdmin() || user.canCreate()) { - standardItems.add(new PageLinkMenuItem("gb.newRepository", EditRepositoryPage.class)); + standardItems.add(new PageLinkMenuItem("gb.newRepository", app().getNewRepositoryPage())); } standardItems.add(new PageLinkMenuItem("gb.myProfile", UserPage.class, WicketUtils.newUsernameParameter(user.username))); diff --git a/src/main/java/com/gitblit/wicket/pages/UserPage.java b/src/main/java/com/gitblit/wicket/pages/UserPage.java index 6cb791eb..29b49b33 100644 --- a/src/main/java/com/gitblit/wicket/pages/UserPage.java +++ b/src/main/java/com/gitblit/wicket/pages/UserPage.java @@ -30,8 +30,8 @@ import org.eclipse.jgit.lib.PersonIdent; import com.gitblit.Keys; import com.gitblit.models.Menu.ParameterMenuItem; -import com.gitblit.models.NavLink.DropDownPageMenuNavLink; import com.gitblit.models.NavLink; +import com.gitblit.models.NavLink.DropDownPageMenuNavLink; import com.gitblit.models.ProjectModel; import com.gitblit.models.RepositoryModel; import com.gitblit.models.UserModel; @@ -95,7 +95,7 @@ public class UserPage extends RootPage { UserModel sessionUser = GitBlitWebSession.get().getUser(); if (sessionUser != null && user.canCreate() && sessionUser.equals(user)) { // user can create personal repositories - add(new BookmarkablePageLink("newRepository", EditRepositoryPage.class)); + add(new BookmarkablePageLink("newRepository", app().getNewRepositoryPage())); } else { add(new Label("newRepository").setVisible(false)); } diff --git a/src/main/java/com/gitblit/wicket/panels/FilterableRepositoryList.java b/src/main/java/com/gitblit/wicket/panels/FilterableRepositoryList.java index 45b0bab1..4433b043 100644 --- a/src/main/java/com/gitblit/wicket/panels/FilterableRepositoryList.java +++ b/src/main/java/com/gitblit/wicket/panels/FilterableRepositoryList.java @@ -33,7 +33,6 @@ import com.gitblit.utils.StringUtils; import com.gitblit.wicket.WicketUtils; import com.gitblit.wicket.freemarker.FreemarkerPanel; import com.gitblit.wicket.ng.NgController; -import com.gitblit.wicket.pages.EditRepositoryPage; /** * A client-side filterable rich repository list which uses Freemarker, Wicket, @@ -98,7 +97,7 @@ public class FilterableRepositoryList extends BasePanel { } if (allowCreate) { - panel.add(new LinkPanel(ngList + "Button", "btn btn-mini", getString("gb.newRepository"), EditRepositoryPage.class)); + panel.add(new LinkPanel(ngList + "Button", "btn btn-mini", getString("gb.newRepository"), app().getNewRepositoryPage())); } else { panel.add(new Label(ngList + "Button").setVisible(false)); } diff --git a/src/main/java/com/gitblit/wicket/panels/RepositoriesPanel.java b/src/main/java/com/gitblit/wicket/panels/RepositoriesPanel.java index dd208e23..8573e1a6 100644 --- a/src/main/java/com/gitblit/wicket/panels/RepositoriesPanel.java +++ b/src/main/java/com/gitblit/wicket/panels/RepositoriesPanel.java @@ -51,7 +51,6 @@ import com.gitblit.utils.StringUtils; import com.gitblit.wicket.GitBlitWebSession; import com.gitblit.wicket.WicketUtils; import com.gitblit.wicket.pages.BasePage; -import com.gitblit.wicket.pages.EditRepositoryPage; import com.gitblit.wicket.pages.ProjectPage; import com.gitblit.wicket.pages.RepositoriesPage; import com.gitblit.wicket.pages.SummaryPage; @@ -87,12 +86,12 @@ public class RepositoriesPanel extends BasePanel { setResponsePage(RepositoriesPage.class); } }.setVisible(app().settings().getBoolean(Keys.git.cacheRepositoryList, true))); - managementLinks.add(new BookmarkablePageLink("newRepository", EditRepositoryPage.class)); + managementLinks.add(new BookmarkablePageLink("newRepository", app().getNewRepositoryPage())); add(managementLinks); } else if (showManagement && user != null && user.canCreate()) { // user can create personal repositories managementLinks = new Fragment("managementPanel", "personalLinks", this); - managementLinks.add(new BookmarkablePageLink("newRepository", EditRepositoryPage.class)); + managementLinks.add(new BookmarkablePageLink("newRepository", app().getNewRepositoryPage())); add(managementLinks); } else { // user has no management permissions -- cgit v1.2.3