diff --git a/src/main/scala/app/RepositoryViewerController.scala b/src/main/scala/app/RepositoryViewerController.scala index 638478d..9a69662 100644 --- a/src/main/scala/app/RepositoryViewerController.scala +++ b/src/main/scala/app/RepositoryViewerController.scala @@ -11,7 +11,7 @@ import org.eclipse.jgit.lib._ import org.apache.commons.io.FileUtils import org.eclipse.jgit.treewalk._ -import org.eclipse.jgit.api.errors.RefNotFoundException +import java.util.zip.{ZipEntry, ZipOutputStream} class RepositoryViewerController extends RepositoryViewerControllerBase with RepositoryService with AccountService with ReferrerAuthenticator @@ -38,7 +38,7 @@ get("/:owner/:repository")(referrersOnly { fileList(_) }) - + /** * Displays the file list of the specified path and branch. */ @@ -50,7 +50,7 @@ fileList(repository, id, path) } }) - + /** * Displays the commit list of the specified resource. */ @@ -121,7 +121,7 @@ } } }) - + /** * Displays details of the specified commit. */ @@ -139,7 +139,7 @@ } } }) - + /** * Displays branches. */ @@ -166,7 +166,7 @@ */ get("/:owner/:repository/archive/:name")(referrersOnly { repository => val name = params("name") - + if(name.endsWith(".zip")){ val revision = name.replaceFirst("\\.zip$", "") val workDir = getDownloadWorkDir(repository.owner, repository.name, session.getId) @@ -174,26 +174,35 @@ FileUtils.deleteDirectory(workDir) } workDir.mkdirs - - // clone the repository - val cloneDir = new File(workDir, revision) - using(Git.cloneRepository - .setURI(getRepositoryDir(repository.owner, repository.name).toURI.toString) - .setDirectory(cloneDir) - .setBranch(revision) - .call){ git => - // checkout the specified revision - git.checkout.setName(revision).call - } - - // remove .git - FileUtils.deleteDirectory(new File(cloneDir, ".git")) - - // create zip file val zipFile = new File(workDir, (if(revision.length == 40) revision.substring(0, 10) else revision) + ".zip") - FileUtil.createZipFile(zipFile, cloneDir) - + + using(Git.open(getRepositoryDir(repository.owner, repository.name))){ git => + val revCommit = JGitUtil.getRevCommitFromId(git, git.getRepository.resolve(revision)) + using(new TreeWalk(git.getRepository)){ walk => + val reader = walk.getObjectReader + val objectId = new MutableObjectId + + using(new ZipOutputStream(new java.io.FileOutputStream(zipFile))){ out => + walk.addTree(revCommit.getTree) + walk.setRecursive(true) + + while(walk.next){ + val name = walk.getPathString + val mode = walk.getFileMode(0) + if(mode != FileMode.TREE){ + walk.getObjectId(objectId, 0) + val entry = new ZipEntry(name) + val loader = reader.open(objectId) + entry.setSize(loader.getSize) + out.putNextEntry(entry) + loader.copyTo(out) + } + } + } + } + } + contentType = "application/octet-stream" zipFile } else { diff --git a/src/main/scala/util/FileUtil.scala b/src/main/scala/util/FileUtil.scala index 1386a05..0b1a98b 100644 --- a/src/main/scala/util/FileUtil.scala +++ b/src/main/scala/util/FileUtil.scala @@ -1,9 +1,8 @@ package util -import org.apache.commons.io.{IOUtils, FileUtils} +import org.apache.commons.io.FileUtils import java.net.URLConnection import java.io.File -import org.apache.commons.compress.archivers.zip.{ZipArchiveEntry, ZipArchiveOutputStream} import util.ControlUtil._ object FileUtil { @@ -32,23 +31,23 @@ def isText(content: Array[Byte]): Boolean = !content.contains(0) - def createZipFile(dest: File, dir: File): Unit = { - def addDirectoryToZip(out: ZipArchiveOutputStream, dir: File, path: String): Unit = { - dir.listFiles.map { file => - if(file.isFile){ - out.putArchiveEntry(new ZipArchiveEntry(path + "/" + file.getName)) - out.write(FileUtils.readFileToByteArray(file)) - out.closeArchiveEntry - } else if(file.isDirectory){ - addDirectoryToZip(out, file, path + "/" + file.getName) - } - } - } - - using(new ZipArchiveOutputStream(dest)){ out => - addDirectoryToZip(out, dir, dir.getName) - } - } +// def createZipFile(dest: File, dir: File): Unit = { +// def addDirectoryToZip(out: ZipArchiveOutputStream, dir: File, path: String): Unit = { +// dir.listFiles.map { file => +// if(file.isFile){ +// out.putArchiveEntry(new ZipArchiveEntry(path + "/" + file.getName)) +// out.write(FileUtils.readFileToByteArray(file)) +// out.closeArchiveEntry +// } else if(file.isDirectory){ +// addDirectoryToZip(out, file, path + "/" + file.getName) +// } +// } +// } +// +// using(new ZipArchiveOutputStream(dest)){ out => +// addDirectoryToZip(out, dir, dir.getName) +// } +// } def getFileName(path: String): String = defining(path.lastIndexOf('/')){ i => if(i >= 0) path.substring(i + 1) else path