/*
* Copyright (c) 1998-2011 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Resin Open Source is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
*
* Free Software Foundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Scott Ferguson
*/
package com.caucho.env.git;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import com.caucho.java.WorkDir;
import com.caucho.util.IoUtil;
import com.caucho.vfs.JarPath;
import com.caucho.vfs.Path;
import com.caucho.vfs.ReadStream;
import com.caucho.vfs.WriteStream;
import com.caucho.vfs.Jar.ZipStreamImpl;
/**
* Tree structure from a jar
*/
public class GitCommitJar {
private static final Logger log
= Logger.getLogger(GitCommitJar.class.getName());
private GitCommitTree _commit = new GitCommitTree();
private JarPath _jar;
private Path _tempJar;
public GitCommitJar(Path jar)
throws IOException
{
if (jar.getScheme().equals("memory")) {
InputStream is = jar.openRead();
try {
init(is);
} finally {
is.close();
}
}
else {
init(jar);
}
}
public GitCommitJar(InputStream is)
throws IOException
{
init(is);
}
private void init(InputStream is)
throws IOException
{
Path dir = WorkDir.getLocalWorkDir();
dir.mkdirs();
Path path = dir.createTempFile("git", "tmp");
try {
WriteStream os = path.openWrite();
os.writeStream(is);
os.close();
init(path);
_tempJar = path;
} catch (IOException e) {
path.remove();
}
}
private void init(Path path)
throws IOException
{
_jar = JarPath.create(path);
HashMap<String,Long> lengthMap = new HashMap<String,Long>();
fillLengthMap(lengthMap, path);
ReadStream is = path.openRead();
fillCommit(lengthMap, is);
_commit.commit();
}
private void fillCommit(HashMap<String,Long> lengthMap, InputStream is)
throws IOException
{
ZipInputStream zin = null;
try {
zin = new ZipInputStream(is);
ZipEntry entry;
while ((entry = zin.getNextEntry()) != null) {
String path = entry.getName();
long length = entry.getSize();
if (entry.isDirectory())
continue;
Long lengthValue = lengthMap.get(path);
if (lengthValue != null)
length = lengthValue;
_commit.addFile(path, 0664, zin, length);
}
} finally {
IoUtil.close(zin);
is.close();
}
}
public String []getCommitList()
{
return _commit.getCommitList();
}
public String getDigest()
{
return _commit.getDigest();
}
public String findPath(String sha1)
{
return _commit.findPath(sha1);
}
private void fillLengthMap(HashMap<String,Long> lengthMap, Path jar)
throws IOException
{
ReadStream is = jar.openRead();
ZipInputStream zin = null;
try {
zin = new ZipInputStream(is);
ZipEntry entry;
while ((entry = zin.getNextEntry()) != null) {
String path = entry.getName();
long length = entry.getSize();
if (entry.isDirectory())
continue;
if (length < 0) {
length = 0;
while (zin.read() >= 0) {
length++;
}
}
lengthMap.put(path, length);
}
} finally {
IoUtil.close(zin);
IoUtil.close(is);
}
}
private long getLength(String path)
throws IOException
{
InputStream is = null;
try {
ZipStreamImpl zipIs = _jar.getJar().openReadImpl(path);
is = new ReadStream(zipIs);
long length = 0;
while (is.read() >= 0) {
length++;
}
return length;
} finally {
IoUtil.close(is);
}
}
public InputStream openFile(String sha1)
throws IOException
{
String path = _commit.findPath(sha1);
if (path.endsWith("/")) {
GitWorkingTree tree = _commit.findTree(path);
return tree.openFile();
}
else {
long size = _jar.getJar().getLength(path);
if (size < 0)
size = getLength(path);
ZipStreamImpl zipIs = _jar.getJar().openReadImpl(path);
ReadStream is = new ReadStream(zipIs);
try {
return GitCommitTree.writeBlob(is, size);
} finally {
is.close();
zipIs.close();
}
}
}
public void close()
{
if (_jar != null)
_jar.closeJar();
if (_tempJar != null) {
try {
_tempJar.remove();
} catch (IOException e) {
log.log(Level.FINER, e.toString(), e);
}
}
}
@Override
public String toString()
{
return (getClass().getSimpleName() + "[]");
}
}