/**
* This file is part of git-as-svn. It is subject to the license terms
* in the LICENSE file found in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/gpl-2.0.html. No part of git-as-svn,
* including this file, may be copied, modified, propagated, or distributed
* except according to the terms contained in the LICENSE file.
*/
package svnserver.ext.gitlfs.storage.local;
import com.google.common.io.ByteStreams;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import ru.bozaro.gitlfs.pointer.Constants;
import ru.bozaro.gitlfs.pointer.Pointer;
import svnserver.ext.gitlfs.config.LfsLayout;
import svnserver.ext.gitlfs.storage.LfsReader;
import svnserver.ext.gitlfs.storage.LfsStorage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.GZIPInputStream;
/**
* Local storage writer.
*
* @author Artem V. Navrotskiy <bozaro@users.noreply.github.com>
*/
public class LfsLocalReader implements LfsReader {
@Nullable
private final File dataPath;
@Nullable
private final File gzipPath;
@NotNull
private final Map<String, String> meta;
@Nullable
public static LfsLocalReader create(@NotNull LfsLayout layout, @NotNull File dataRoot, @Nullable File metaRoot, @NotNull String oid) throws IOException {
final Map<String, String> meta;
File dataPath = LfsLocalStorage.getPath(layout, dataRoot, oid, "");
File gzipPath = LfsLocalStorage.getPath(layout, dataRoot, oid, ".gz");
if (metaRoot != null) {
final File metaPath = LfsLocalStorage.getPath(layout, metaRoot, oid, ".meta");
if (metaPath == null || !metaPath.isFile()) {
return null;
}
try (InputStream stream = new FileInputStream(metaPath)) {
meta = Pointer.parsePointer(ByteStreams.toByteArray(stream));
}
if (meta == null) {
throw new IOException("Corrupted meta file: " + metaPath.getAbsolutePath());
}
if (!meta.get(Constants.OID).equals(oid)) {
throw new IOException("Corrupted meta file: " + metaPath.getAbsolutePath() + " - unexpected oid:" + meta.get(Constants.OID));
}
} else {
if (dataPath == null || !dataPath.isFile()) {
return null;
}
gzipPath = null;
meta = new HashMap<>();
meta.put(Constants.OID, oid);
meta.put(Constants.SIZE, Long.toString(dataPath.length()));
}
if (dataPath != null && !dataPath.isFile()) {
dataPath = null;
}
if (gzipPath != null && !gzipPath.isFile()) {
gzipPath = null;
}
if (dataPath == null && gzipPath == null) return null;
return new LfsLocalReader(meta, dataPath, gzipPath);
}
private LfsLocalReader(@NotNull Map<String, String> meta, @Nullable File dataPath, @Nullable File gzipPath) throws IOException {
this.meta = meta;
this.dataPath = dataPath;
this.gzipPath = gzipPath;
}
@NotNull
@Override
public InputStream openStream() throws IOException {
if (dataPath != null) {
return new FileInputStream(dataPath);
}
if (gzipPath != null) {
return new GZIPInputStream(new FileInputStream(gzipPath));
}
throw new IllegalStateException();
}
@Nullable
@Override
public InputStream openGzipStream() throws IOException {
return gzipPath != null ? new FileInputStream(gzipPath) : null;
}
@Override
public long getSize() {
return Long.parseLong(meta.get(Constants.SIZE));
}
@Nullable
@Override
public String getMd5() {
return meta.get(LfsLocalStorage.HASH_MD5);
}
@NotNull
@Override
public String getOid(boolean hashOnly) {
final String oid = meta.get(Constants.OID);
return hashOnly ? oid.substring(LfsStorage.OID_PREFIX.length()) : oid;
}
}