diff options
author | James Moger <james.moger@gitblit.com> | 2011-05-24 17:39:38 -0400 |
---|---|---|
committer | James Moger <james.moger@gitblit.com> | 2011-05-24 17:39:38 -0400 |
commit | 9197d340db81a245193dff1ecb44889b8e0dfe31 (patch) | |
tree | e866bea3c64fd6714ed141c551c67e52fc2f1ad8 /src/com | |
parent | 8a2e9c363346ef5bf48c8eba09cb8afa46fabeeb (diff) | |
download | gitblit-9197d340db81a245193dff1ecb44889b8e0dfe31.tar.gz gitblit-9197d340db81a245193dff1ecb44889b8e0dfe31.zip |
Download zip feature.
Diffstat (limited to 'src/com')
-rw-r--r-- | src/com/gitblit/Constants.java | 4 | ||||
-rw-r--r-- | src/com/gitblit/DownloadZipServlet.java | 100 | ||||
-rw-r--r-- | src/com/gitblit/GitBlitServer.java | 7 | ||||
-rw-r--r-- | src/com/gitblit/tests/JGitUtilsTest.java | 23 | ||||
-rw-r--r-- | src/com/gitblit/utils/JGitUtils.java | 52 | ||||
-rw-r--r-- | src/com/gitblit/wicket/GitBlitWebApp.properties | 3 | ||||
-rw-r--r-- | src/com/gitblit/wicket/pages/CommitPage.html | 7 | ||||
-rw-r--r-- | src/com/gitblit/wicket/pages/CommitPage.java | 6 | ||||
-rw-r--r-- | src/com/gitblit/wicket/pages/TreePage.html | 4 | ||||
-rw-r--r-- | src/com/gitblit/wicket/pages/TreePage.java | 6 | ||||
-rw-r--r-- | src/com/gitblit/wicket/resources/gitblit.css | 8 |
11 files changed, 211 insertions, 9 deletions
diff --git a/src/com/gitblit/Constants.java b/src/com/gitblit/Constants.java index 46f32084..b84ab7da 100644 --- a/src/com/gitblit/Constants.java +++ b/src/com/gitblit/Constants.java @@ -17,6 +17,10 @@ public class Constants { public final static String ADMIN_ROLE = "#admin";
public final static String PROPERTIES_FILE = "gitblit.properties";
+
+ public final static String GIT_SERVLET_PATH = "/git/";
+
+ public final static String ZIP_SERVLET_PATH = "/zip/";
public static enum AccessRestrictionType {
NONE, PUSH, CLONE, VIEW;
diff --git a/src/com/gitblit/DownloadZipServlet.java b/src/com/gitblit/DownloadZipServlet.java new file mode 100644 index 00000000..87fda907 --- /dev/null +++ b/src/com/gitblit/DownloadZipServlet.java @@ -0,0 +1,100 @@ +package com.gitblit;
+
+import java.util.Date;
+
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.gitblit.Constants.AccessRestrictionType;
+import com.gitblit.utils.JGitUtils;
+import com.gitblit.utils.StringUtils;
+import com.gitblit.wicket.models.RepositoryModel;
+
+public class DownloadZipServlet extends HttpServlet {
+
+ public static String asLink(String baseURL, String repository, String objectId, String path) {
+ return baseURL + (baseURL.endsWith("/") ? "" : "/") + "zip?r=" + repository + (path == null ? "" : ("&p=" + path)) + (objectId == null ? "" : ("&h=" + objectId));
+ }
+
+ private static final long serialVersionUID = 1L;
+
+ private final static Logger logger = LoggerFactory.getLogger(DownloadZipServlet.class);
+
+ public DownloadZipServlet() {
+ super();
+ }
+
+ @Override
+ protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, java.io.IOException {
+ processRequest(request, response);
+ }
+
+ @Override
+ protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, java.io.IOException {
+ processRequest(request, response);
+ }
+
+ private void processRequest(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, java.io.IOException {
+ if (!GitBlit.self().settings().getBoolean(Keys.web.allowZipDownloads, true)) {
+ logger.warn("Zip downloads are disabled");
+ response.sendError(HttpServletResponse.SC_FORBIDDEN);
+ return;
+
+ }
+ String repository = request.getParameter("r");
+ String basePath = request.getParameter("p");
+ String objectId = request.getParameter("h");
+
+ try {
+ String name = repository;
+ if (name.indexOf('/') > -1) {
+ name = name.substring(name.lastIndexOf('/') + 1);
+ }
+
+ // check roles first
+ boolean authorized = request.isUserInRole(Constants.ADMIN_ROLE);
+ authorized |= request.isUserInRole(repository);
+
+ if (!authorized) {
+ RepositoryModel model = GitBlit.self().getRepositoryModel(repository);
+ if (model.accessRestriction.atLeast(AccessRestrictionType.VIEW)) {
+ logger.warn("Unauthorized access via zip servlet for " + model.name);
+ response.sendError(HttpServletResponse.SC_FORBIDDEN);
+ return;
+ }
+ }
+ if (!StringUtils.isEmpty(basePath)) {
+ name += "-" + basePath.replace('/', '_');
+ }
+ if (!StringUtils.isEmpty(objectId)) {
+ name += "-" + objectId;
+ }
+
+ Repository r = GitBlit.self().getRepository(repository);
+ RevCommit commit = JGitUtils.getCommit(r, objectId);
+ Date date = JGitUtils.getCommitDate(commit);
+ String contentType = "application/octet-stream";
+ response.setContentType(contentType + "; charset=" + response.getCharacterEncoding());
+ // response.setContentLength(attachment.getFileSize());
+ response.setHeader("Content-Disposition", "attachment; filename=\"" + name + ".zip" + "\"");
+ response.setDateHeader("Last-Modified", date.getTime());
+ response.setHeader("Cache-Control", "no-cache");
+ response.setHeader("Pragma", "no-cache");
+ response.setDateHeader("Expires", 0);
+
+ try {
+ JGitUtils.zip(r, basePath, objectId, response.getOutputStream());
+ response.flushBuffer();
+ } catch (Throwable t) {
+ logger.error("Failed to write attachment to client", t);
+ }
+ } catch (Throwable t) {
+ logger.error("Failed to write attachment to client", t);
+ }
+ }
+}
diff --git a/src/com/gitblit/GitBlitServer.java b/src/com/gitblit/GitBlitServer.java index e9e44637..a7b15385 100644 --- a/src/com/gitblit/GitBlitServer.java +++ b/src/com/gitblit/GitBlitServer.java @@ -211,10 +211,13 @@ public class GitBlitServer { wicketFilter.setInitParameter(WicketFilter.FILTER_MAPPING_PARAM, wicketPathSpec);
wicketFilter.setInitParameter(WicketFilter.IGNORE_PATHS_PARAM, "git/");
rootContext.addFilter(wicketFilter, wicketPathSpec, FilterMapping.DEFAULT);
-
+
+ // Zip Servlet
+ rootContext.addServlet(DownloadZipServlet.class, Constants.ZIP_SERVLET_PATH + "*");
+
// Git Servlet
ServletHolder gitServlet = null;
- String gitServletPathSpec = "/git/*";
+ String gitServletPathSpec = Constants.GIT_SERVLET_PATH + "*";
if (fileSettings.getBoolean(Keys.git.enableGitServlet, true)) {
gitServlet = rootContext.addServlet(GitBlitServlet.class, gitServletPathSpec);
gitServlet.setInitParameter("base-path", params.repositoriesFolder);
diff --git a/src/com/gitblit/tests/JGitUtilsTest.java b/src/com/gitblit/tests/JGitUtilsTest.java index 196058c5..11b77127 100644 --- a/src/com/gitblit/tests/JGitUtilsTest.java +++ b/src/com/gitblit/tests/JGitUtilsTest.java @@ -1,6 +1,7 @@ package com.gitblit.tests;
import java.io.File;
+import java.io.FileOutputStream;
import java.util.Date;
import java.util.List;
@@ -103,5 +104,27 @@ public class JGitUtilsTest extends TestCase { r.close();
System.out.println(diff);
}
+
+ public void testZip() throws Exception {
+ Repository r = new FileRepository(new File(repositoriesFolder, "gitblit.git/" + Constants.DOT_GIT));
+ FileOutputStream fos = null;
+ try {
+ File zipFile = new File("c:/output.zip");
+ zipFile.delete();
+ fos = new FileOutputStream(zipFile);
+ if (JGitUtils.zip(r, "src", Constants.HEAD, fos)) {
+ System.out.println("zip = " + zipFile.length() + " bytes");
+ } else {
+ System.err.println("failed to generate zip file?!");
+ }
+ } finally {
+ if (fos != null) {
+ try {
+ fos.close();
+ } catch (Throwable t) {
+ }
+ }
+ }
+ }
}
diff --git a/src/com/gitblit/utils/JGitUtils.java b/src/com/gitblit/utils/JGitUtils.java index c9c13c56..b153c0c6 100644 --- a/src/com/gitblit/utils/JGitUtils.java +++ b/src/com/gitblit/utils/JGitUtils.java @@ -4,6 +4,7 @@ import java.io.ByteArrayOutputStream; import java.io.File;
import java.io.IOException;
import java.io.InputStream;
+import java.io.OutputStream;
import java.nio.charset.Charset;
import java.text.DateFormat;
import java.text.ParseException;
@@ -17,6 +18,8 @@ import java.util.List; import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.diff.DiffEntry;
@@ -808,10 +811,57 @@ public class JGitUtils { return null;
}
+ public static boolean zip(Repository r, String basePath, String objectId, OutputStream os) throws Exception {
+ RevCommit commit = getCommit(r, objectId);
+ if (commit == null) {
+ return false;
+ }
+ final RevWalk rw = new RevWalk(r);
+ final TreeWalk walk = new TreeWalk(r);
+ try {
+ walk.addTree(commit.getTree());
+ ZipOutputStream zos = new ZipOutputStream(os);
+ zos.setComment("Generated by Git:Blit");
+ if (basePath != null && basePath.length() > 0) {
+ PathFilter f = PathFilter.create(basePath);
+ walk.setFilter(f);
+ }
+ walk.setRecursive(true);
+ while (walk.next()) {
+ ZipEntry entry = new ZipEntry(walk.getPathString());
+ entry.setSize(walk.getObjectReader().getObjectSize(walk.getObjectId(0), Constants.OBJ_BLOB));
+ entry.setComment(commit.getName());
+ zos.putNextEntry(entry);
+
+ ObjectId entid = walk.getObjectId(0);
+ FileMode entmode = walk.getFileMode(0);
+ RevBlob blob = (RevBlob) rw.lookupAny(entid, entmode.getObjectType());
+ rw.parseBody(blob);
+
+ ObjectLoader ldr = r.open(blob.getId(), Constants.OBJ_BLOB);
+ byte[] tmp = new byte[4096];
+ InputStream in = ldr.openStream();
+ int n;
+ while ((n = in.read(tmp)) > 0) {
+ zos.write(tmp, 0, n);
+ }
+ in.close();
+ }
+ zos.finish();
+ return true;
+ } catch (IOException e) {
+ LOGGER.error("Failed to zip files from commit " + commit.getName(), e);
+ } finally {
+ walk.release();
+ rw.dispose();
+ }
+ return false;
+ }
+
public static List<Metric> getDateMetrics(Repository r) {
Metric total = new Metric("TOTAL");
final Map<String, Metric> metricMap = new HashMap<String, Metric>();
-
+
if (hasCommits(r)) {
final List<RefModel> tags = getTags(r, -1);
final Map<ObjectId, RefModel> tagMap = new HashMap<ObjectId, RefModel>();
diff --git a/src/com/gitblit/wicket/GitBlitWebApp.properties b/src/com/gitblit/wicket/GitBlitWebApp.properties index b6dbc117..0c4c350f 100644 --- a/src/com/gitblit/wicket/GitBlitWebApp.properties +++ b/src/com/gitblit/wicket/GitBlitWebApp.properties @@ -92,4 +92,5 @@ gb.showRemoteBranchesDescription = show remote branches gb.canAdminDescription = can administer Git:Blit server
gb.permittedUsers = permitted users
gb.isFrozen = is frozen
-gb.isFrozenDescription = deny push operations
\ No newline at end of file +gb.isFrozenDescription = deny push operations
+gb.zip = zip
\ No newline at end of file diff --git a/src/com/gitblit/wicket/pages/CommitPage.html b/src/com/gitblit/wicket/pages/CommitPage.html index 059d77e4..1b5fffed 100644 --- a/src/com/gitblit/wicket/pages/CommitPage.html +++ b/src/com/gitblit/wicket/pages/CommitPage.html @@ -23,7 +23,12 @@ <tr><th><wicket:message key="gb.committer">committer</wicket:message></th><td><span class="sha1" wicket:id="commitCommitter">[committer]</span></td></tr>
<tr><th></th><td><span class="sha1" wicket:id="commitCommitterDate">[commit date]</span></td></tr>
<tr><th><wicket:message key="gb.commit">commit</wicket:message></th><td><span class="sha1" wicket:id="commitId">[commit id]</span></td></tr>
- <tr><th><wicket:message key="gb.tree">tree</wicket:message></th><td><span class="sha1" wicket:id="commitTree">[commit tree]</span></td></tr>
+ <tr><th><wicket:message key="gb.tree">tree</wicket:message></th>
+ <td><span class="sha1" wicket:id="commitTree">[commit tree]</span>
+ <span class="link">
+ <a wicket:id="treeLink"><wicket:message key="gb.tree"></wicket:message></a> | <a wicket:id="zipLink"><wicket:message key="gb.zip"></wicket:message></a>
+ </span>
+ </td></tr>
<tr><th valign="top"><wicket:message key="gb.parent">parent</wicket:message></th>
<td>
<span wicket:id="commitParents">
diff --git a/src/com/gitblit/wicket/pages/CommitPage.java b/src/com/gitblit/wicket/pages/CommitPage.java index 5396e821..c3c3fa96 100644 --- a/src/com/gitblit/wicket/pages/CommitPage.java +++ b/src/com/gitblit/wicket/pages/CommitPage.java @@ -6,6 +6,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.repeater.Item;
import org.apache.wicket.markup.repeater.data.DataView;
import org.apache.wicket.markup.repeater.data.ListDataProvider;
@@ -13,6 +14,9 @@ import org.apache.wicket.model.StringResourceModel; import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
+import com.gitblit.DownloadZipServlet;
+import com.gitblit.GitBlit;
+import com.gitblit.Keys;
import com.gitblit.utils.JGitUtils;
import com.gitblit.utils.JGitUtils.SearchType;
import com.gitblit.wicket.LinkPanel;
@@ -62,6 +66,8 @@ public class CommitPage extends RepositoryPage { add(new Label("commitId", c.getName()));
add(new LinkPanel("commitTree", "list", c.getTree().getName(), TreePage.class, newCommitParameter()));
+ add(new BookmarkablePageLink<Void>("treeLink", TreePage.class, newCommitParameter()));
+ add(new ExternalLink("zipLink", DownloadZipServlet.asLink(getRequest().getRelativePathPrefixToContextRoot(), repositoryName, objectId, null)).setVisible(GitBlit.self().settings().getBoolean(Keys.web.allowZipDownloads, true)));
// Parent Commits
ListDataProvider<String> parentsDp = new ListDataProvider<String>(parents);
diff --git a/src/com/gitblit/wicket/pages/TreePage.html b/src/com/gitblit/wicket/pages/TreePage.html index 35eac299..8d706ee2 100644 --- a/src/com/gitblit/wicket/pages/TreePage.html +++ b/src/com/gitblit/wicket/pages/TreePage.html @@ -9,7 +9,7 @@ <!-- blob nav links -->
<div class="page_nav2">
- <a wicket:id="historyLink"><wicket:message key="gb.history"></wicket:message></a> | <a wicket:id="headLink"><wicket:message key="gb.head"></wicket:message></a>
+ <a wicket:id="historyLink"><wicket:message key="gb.history"></wicket:message></a> | <a wicket:id="headLink"><wicket:message key="gb.head"></wicket:message></a> | <a wicket:id="zipLink"><wicket:message key="gb.zip"></wicket:message></a>
</div>
<!-- commit header -->
@@ -32,7 +32,7 @@ <!-- tree links -->
<wicket:fragment wicket:id="treeLinks">
<span class="link">
- <a wicket:id="tree"><wicket:message key="gb.tree"></wicket:message></a> | <a wicket:id="history"><wicket:message key="gb.history"></wicket:message></a>
+ <a wicket:id="tree"><wicket:message key="gb.tree"></wicket:message></a> | <a wicket:id="history"><wicket:message key="gb.history"></wicket:message></a> | <a wicket:id="zip"><wicket:message key="gb.zip"></wicket:message></a>
</span>
</wicket:fragment>
diff --git a/src/com/gitblit/wicket/pages/TreePage.java b/src/com/gitblit/wicket/pages/TreePage.java index ea5bd530..e385fab0 100644 --- a/src/com/gitblit/wicket/pages/TreePage.java +++ b/src/com/gitblit/wicket/pages/TreePage.java @@ -5,6 +5,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;
@@ -13,6 +14,9 @@ import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
+import com.gitblit.DownloadZipServlet;
+import com.gitblit.GitBlit;
+import com.gitblit.Keys;
import com.gitblit.utils.ByteFormat;
import com.gitblit.utils.JGitUtils;
import com.gitblit.wicket.LinkPanel;
@@ -36,6 +40,7 @@ public class TreePage extends RepositoryPage { // tree page links
add(new BookmarkablePageLink<Void>("historyLink", HistoryPage.class, WicketUtils.newPathParameter(repositoryName, objectId, path)));
add(new BookmarkablePageLink<Void>("headLink", TreePage.class, WicketUtils.newPathParameter(repositoryName, Constants.HEAD, path)));
+ add(new ExternalLink("zipLink", DownloadZipServlet.asLink(getRequest().getRelativePathPrefixToContextRoot(), repositoryName, objectId, path)).setVisible(GitBlit.self().settings().getBoolean(Keys.web.allowZipDownloads, true)));
add(new CommitHeaderPanel("commitHeader", repositoryName, commit));
@@ -73,6 +78,7 @@ public class TreePage extends RepositoryPage { Fragment links = new Fragment("pathLinks", "treeLinks", this);
links.add(new BookmarkablePageLink<Void>("tree", TreePage.class, WicketUtils.newPathParameter(repositoryName, entry.commitId, entry.path)));
links.add(new BookmarkablePageLink<Void>("history", HistoryPage.class, WicketUtils.newPathParameter(repositoryName, entry.commitId, entry.path)));
+ links.add(new ExternalLink("zip", DownloadZipServlet.asLink(getRequest().getRelativePathPrefixToContextRoot(), repositoryName, objectId, entry.path)).setVisible(GitBlit.self().settings().getBoolean(Keys.web.allowZipDownloads, true)));
item.add(links);
} else {
// blob link
diff --git a/src/com/gitblit/wicket/resources/gitblit.css b/src/com/gitblit/wicket/resources/gitblit.css index 4a971a6f..64484d27 100644 --- a/src/com/gitblit/wicket/resources/gitblit.css +++ b/src/com/gitblit/wicket/resources/gitblit.css @@ -114,15 +114,19 @@ span.empty { color: #008000;
}
+span.link {
+ color: #888;
+}
+
span.link, span.link a {
font-family: sans-serif;
- font-size: 11px;
+ font-size: 11px;
}
span.link em, div.link span em {
font-style: normal;
font-family: sans-serif;
- font-size: 11px;
+ font-size: 11px;
}
div.page_header {
|