Get correct sizes for lfs files

This commit is contained in:
René Pfeuffer
2019-09-25 08:31:42 +02:00
parent 7e5e45b488
commit 5b4d1d6003
3 changed files with 56 additions and 23 deletions

View File

@@ -42,7 +42,10 @@ import com.google.common.collect.Multimap;
import org.eclipse.jgit.api.FetchCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.attributes.Attribute;
import org.eclipse.jgit.attributes.Attributes;
import org.eclipse.jgit.diff.DiffFormatter;
import org.eclipse.jgit.lfs.LfsPointer;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
@@ -55,6 +58,7 @@ import org.eclipse.jgit.transport.FetchResult;
import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.LfsFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.ContextEntry;
@@ -65,10 +69,12 @@ import sonia.scm.web.GitUserAgentProvider;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import static java.util.Optional.empty;
import static java.util.Optional.of;
//~--- JDK imports ------------------------------------------------------------
@@ -731,6 +737,20 @@ public final class GitUtil
}
}
public static Optional<LfsPointer> getLfsPointer(org.eclipse.jgit.lib.Repository repo, String path, RevCommit commit, TreeWalk treeWalk) throws IOException {
Attributes attributes = LfsFactory.getAttributesForPath(repo, path, commit);
Attribute filter = attributes.get("filter");
if (filter != null && "lfs".equals(filter.getValue())) {
ObjectId blobId = treeWalk.getObjectId(0);
try (InputStream is = repo.open(blobId, Constants.OBJ_BLOB).openStream()) {
return of(LfsPointer.parseLfsPointer(is));
}
} else {
return empty();
}
}
//~--- methods --------------------------------------------------------------
/**

View File

@@ -38,6 +38,7 @@ package sonia.scm.repository.spi;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.eclipse.jgit.lfs.LfsPointer;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
@@ -57,6 +58,8 @@ import sonia.scm.repository.GitSubModuleParser;
import sonia.scm.repository.GitUtil;
import sonia.scm.repository.Repository;
import sonia.scm.repository.SubRepository;
import sonia.scm.store.Blob;
import sonia.scm.store.BlobStore;
import sonia.scm.util.Util;
import sonia.scm.web.lfs.LfsBlobStoreFactory;
@@ -65,6 +68,7 @@ import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import static sonia.scm.ContextEntry.ContextBuilder.entity;
import static sonia.scm.NotFoundException.notFound;
@@ -170,7 +174,7 @@ public class GitBrowseCommand extends AbstractGitCommand
* @throws IOException
*/
private FileObject createFileObject(org.eclipse.jgit.lib.Repository repo,
BrowseCommandRequest request, ObjectId revId, TreeWalk treeWalk)
BrowseCommandRequest request, ObjectId revId, TreeWalk treeWalk)
throws IOException {
FileObject file = new FileObject();
@@ -198,7 +202,6 @@ public class GitBrowseCommand extends AbstractGitCommand
ObjectLoader loader = repo.open(treeWalk.getObjectId(0));
file.setDirectory(loader.getType() == Constants.OBJ_TREE);
file.setLength(loader.getSize());
// don't show message and date for directories to improve performance
if (!file.isDirectory() &&!request.isDisableLastCommit())
@@ -206,6 +209,16 @@ public class GitBrowseCommand extends AbstractGitCommand
logger.trace("fetch last commit for {} at {}", path, revId.getName());
RevCommit commit = getLatestCommit(repo, revId, path);
Optional<LfsPointer> lfsPointer = GitUtil.getLfsPointer(repo, path, commit, treeWalk);
if (lfsPointer.isPresent()) {
BlobStore lfsBlobStore = lfsBlobStoreFactory.getLfsBlobStore(repository);
Blob blob = lfsBlobStore.get(lfsPointer.get().getOid().getName());
file.setLength(blob.getSize());
} else {
file.setLength(loader.getSize());
}
if (commit != null)
{
file.setLastModified(GitUtil.getCommitTime(commit));
@@ -235,7 +248,7 @@ public class GitBrowseCommand extends AbstractGitCommand
* @return
*/
private RevCommit getLatestCommit(org.eclipse.jgit.lib.Repository repo,
ObjectId revId, String path)
ObjectId revId, String path)
{
RevCommit result = null;
RevWalk walk = null;
@@ -342,7 +355,7 @@ public class GitBrowseCommand extends AbstractGitCommand
}
private FileObject findFirstMatch(org.eclipse.jgit.lib.Repository repo,
BrowseCommandRequest request, ObjectId revId, TreeWalk treeWalk) throws IOException {
BrowseCommandRequest request, ObjectId revId, TreeWalk treeWalk) throws IOException {
String[] pathElements = request.getPath().split("/");
int currentDepth = 0;
int limit = pathElements.length;
@@ -367,7 +380,7 @@ public class GitBrowseCommand extends AbstractGitCommand
@SuppressWarnings("unchecked")
private Map<String,
SubRepository> getSubRepositories(org.eclipse.jgit.lib.Repository repo,
ObjectId revision)
ObjectId revision)
throws IOException {
if (logger.isDebugEnabled())
{
@@ -392,7 +405,7 @@ public class GitBrowseCommand extends AbstractGitCommand
}
private SubRepository getSubRepository(org.eclipse.jgit.lib.Repository repo,
ObjectId revId, String path)
ObjectId revId, String path)
throws IOException {
Map<String, SubRepository> subRepositories = subrepositoryCache.get(revId);
@@ -413,7 +426,7 @@ public class GitBrowseCommand extends AbstractGitCommand
}
//~--- fields ---------------------------------------------------------------
/** sub repository cache */
private final Map<ObjectId, Map<String, SubRepository>> subrepositoryCache = Maps.newHashMap();
}

View File

@@ -50,6 +50,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.repository.GitUtil;
import sonia.scm.store.Blob;
import sonia.scm.store.BlobStore;
import sonia.scm.util.IOUtil;
import sonia.scm.util.Util;
import sonia.scm.web.lfs.LfsBlobStoreFactory;
@@ -59,6 +60,7 @@ import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Optional;
import static sonia.scm.ContextEntry.ContextBuilder.entity;
import static sonia.scm.NotFoundException.notFound;
@@ -126,29 +128,27 @@ public class GitCatCommand extends AbstractGitCommand implements CatCommand {
treeWalk.setFilter(PathFilter.create(path));
if (treeWalk.next() && treeWalk.getFileMode(0).getObjectType() == Constants.OBJ_BLOB) {
Attributes attributes = LfsFactory.getAttributesForPath(repo, path, entry);
Attribute filter = attributes.get("filter");
if (filter != null && "lfs".equals(filter.getValue())) {
return loadFromLfsStore(repo, treeWalk, revWalk);
Optional<LfsPointer> lfsPointer = GitUtil.getLfsPointer(repo, path, entry, treeWalk);
if (lfsPointer.isPresent()) {
return loadFromLfsStore(treeWalk, revWalk, lfsPointer.get());
} else {
return loadFromGit(repo, treeWalk, revWalk);
}
ObjectId blobId = treeWalk.getObjectId(0);
ObjectLoader loader = repo.open(blobId);
return new GitObjectLoaderWrapper(loader, treeWalk, revWalk);
} else {
throw notFound(entity("Path", path).in("Revision", revId.getName()).in(repository));
}
}
private Loader loadFromLfsStore(Repository repo, TreeWalk treeWalk, RevWalk revWalk) throws IOException {
private Loader loadFromGit(Repository repo, TreeWalk treeWalk, RevWalk revWalk) throws IOException {
ObjectId blobId = treeWalk.getObjectId(0);
LfsPointer lfsPointer;
try (InputStream is = repo.open(blobId, Constants.OBJ_BLOB).openStream()) {
lfsPointer = LfsPointer.parseLfsPointer(is);
}
Blob blob = lfsBlobStoreFactory.getLfsBlobStore(repository).get(lfsPointer.getOid().getName());
ObjectLoader loader = repo.open(blobId);
return new GitObjectLoaderWrapper(loader, treeWalk, revWalk);
}
private Loader loadFromLfsStore(TreeWalk treeWalk, RevWalk revWalk, LfsPointer lfsPointer) throws IOException {
BlobStore lfsBlobStore = lfsBlobStoreFactory.getLfsBlobStore(repository);
Blob blob = lfsBlobStore.get(lfsPointer.getOid().getName());
GitUtil.release(revWalk);
GitUtil.release(treeWalk);
return new BlobLoader(blob);