Extract a BlameCache interface to allow other implementations Change-Id: I8c00cb8942fb6656233bf66bf69107dc7f6a4cf0
diff --git a/gitiles-servlet/src/main/java/com/google/gitiles/BlameCache.java b/gitiles-servlet/src/main/java/com/google/gitiles/BlameCache.java index 1b3a2d3..cf105ad 100644 --- a/gitiles-servlet/src/main/java/com/google/gitiles/BlameCache.java +++ b/gitiles-servlet/src/main/java/com/google/gitiles/BlameCache.java
@@ -15,14 +15,7 @@ package com.google.gitiles; import com.google.common.base.Objects; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import com.google.common.cache.Weigher; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; -import org.eclipse.jgit.blame.BlameGenerator; import org.eclipse.jgit.blame.BlameResult; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.PersonIdent; @@ -30,23 +23,16 @@ import org.eclipse.jgit.revwalk.RevCommit; import java.io.IOException; -import java.util.Collections; import java.util.List; -import java.util.concurrent.ExecutionException; -/** Cache of blame data, weighted by number of blame regions. */ -public class BlameCache { - public static CacheBuilder<Object, Object> newBuilder() { - return CacheBuilder.newBuilder().maximumWeight(10 << 10); - } - - static class Region { +public interface BlameCache { + public static class Region { private final String sourcePath; private final ObjectId sourceCommit; private final PersonIdent sourceAuthor; private int count; - Region(BlameResult blame, int start) { + public Region(BlameResult blame, int start) { this.sourcePath = blame.getSourcePath(start); RevCommit c = blame.getSourceCommit(start); if (c != null) { @@ -60,23 +46,30 @@ this.count = 1; } - int getCount() { + public Region(String sourcePath, ObjectId sourceCommit, PersonIdent sourceAuthor, int count) { + this.sourcePath = sourcePath; + this.sourceCommit = sourceCommit; + this.sourceAuthor = sourceAuthor; + this.count = count; + } + + public int getCount() { return count; } - String getSourcePath() { + public String getSourcePath() { return sourcePath; } - ObjectId getSourceCommit() { + public ObjectId getSourceCommit() { return sourceCommit; } - PersonIdent getSourceAuthor() { + public PersonIdent getSourceAuthor() { return sourceAuthor; } - private boolean growFrom(BlameResult blame, int i) { + public boolean growFrom(BlameResult blame, int i) { // Don't compare line numbers, so we collapse regions from the same source // but with deleted lines into one. if (Objects.equal(blame.getSourcePath(i), sourcePath) @@ -89,91 +82,5 @@ } } - private static class Key { - private final ObjectId commitId; - private final String path; - private Repository repo; - - private Key(Repository repo, ObjectId commitId, String path) { - this.commitId = commitId; - this.path = path; - this.repo = repo; - } - - @Override - public boolean equals(Object o) { - if (o instanceof Key) { - Key k = (Key) o; - return Objects.equal(commitId, k.commitId) - && Objects.equal(path, k.path); - } - return false; - } - - @Override - public int hashCode() { - return Objects.hashCode(commitId, path); - } - } - - private final LoadingCache<Key, List<BlameCache.Region>> cache; - - public BlameCache() { - this(newBuilder()); - } - - public LoadingCache<?, ?> getCache() { - return cache; - } - - public BlameCache(CacheBuilder<Object, Object> builder) { - this.cache = builder.weigher(new Weigher<Key, List<BlameCache.Region>>() { - @Override - public int weigh(Key key, List<BlameCache.Region> value) { - return value.size(); - } - }).build(new CacheLoader<Key, List<BlameCache.Region>>() { - @Override - public List<BlameCache.Region> load(Key key) throws IOException { - return loadBlame(key); - } - }); - } - - List<BlameCache.Region> get(Repository repo, ObjectId commitId, String path) - throws IOException { - try { - return cache.get(new Key(repo, commitId, path)); - } catch (ExecutionException e) { - throw new IOException(e); - } - } - - private List<BlameCache.Region> loadBlame(Key key) throws IOException { - try { - BlameGenerator gen = new BlameGenerator(key.repo, key.path); - BlameResult blame; - try { - gen.push(null, key.commitId); - blame = gen.computeBlameResult(); - } finally { - gen.release(); - } - if (blame == null) { - return ImmutableList.of(); - } - int lineCount = blame.getResultContents().size(); - blame.discardResultContents(); - - List<BlameCache.Region> regions = Lists.newArrayList(); - for (int i = 0; i < lineCount; i++) { - if (regions.isEmpty() || !regions.get(regions.size() - 1).growFrom(blame, i)) { - regions.add(new BlameCache.Region(blame, i)); - } - } - return Collections.unmodifiableList(regions); - } finally { - key.repo = null; - } - } + public List<Region> get(Repository repo, ObjectId commitId, String path) throws IOException; }
diff --git a/gitiles-servlet/src/main/java/com/google/gitiles/BlameCacheImpl.java b/gitiles-servlet/src/main/java/com/google/gitiles/BlameCacheImpl.java new file mode 100644 index 0000000..d997938 --- /dev/null +++ b/gitiles-servlet/src/main/java/com/google/gitiles/BlameCacheImpl.java
@@ -0,0 +1,137 @@ +// Copyright (C) 2014 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.gitiles; + +import com.google.common.base.Objects; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.cache.Weigher; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; + +import org.eclipse.jgit.blame.BlameGenerator; +import org.eclipse.jgit.blame.BlameResult; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.Repository; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.ExecutionException; + +/** Guava implementation of BlameCache, weighted by number of blame regions. */ +public class BlameCacheImpl implements BlameCache { + public static CacheBuilder<Object, Object> newBuilder() { + return CacheBuilder.newBuilder().maximumWeight(10 << 10); + } + + public static class Key { + private final ObjectId commitId; + private final String path; + private Repository repo; + + public Key(Repository repo, ObjectId commitId, String path) { + this.commitId = commitId; + this.path = path; + this.repo = repo; + } + + public ObjectId getCommitId() { + return commitId; + } + + public String getPath() { + return path; + } + + @Override + public boolean equals(Object o) { + if (o instanceof Key) { + Key k = (Key) o; + return Objects.equal(commitId, k.commitId) + && Objects.equal(path, k.path); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hashCode(commitId, path); + } + } + + private final LoadingCache<Key, List<BlameCache.Region>> cache; + + public BlameCacheImpl() { + this(newBuilder()); + } + + public LoadingCache<?, ?> getCache() { + return cache; + } + + public BlameCacheImpl(CacheBuilder<Object, Object> builder) { + this.cache = builder.weigher(new Weigher<Key, List<BlameCache.Region>>() { + @Override + public int weigh(Key key, List<BlameCache.Region> value) { + return value.size(); + } + }).build(new CacheLoader<Key, List<BlameCache.Region>>() { + @Override + public List<BlameCache.Region> load(Key key) throws IOException { + return loadBlame(key); + } + }); + } + + @Override + public List<BlameCache.Region> get(Repository repo, ObjectId commitId, String path) + throws IOException { + try { + return cache.get(new Key(repo, commitId, path)); + } catch (ExecutionException e) { + throw new IOException(e); + } + } + + private List<BlameCache.Region> loadBlame(Key key) throws IOException { + try { + BlameGenerator gen = new BlameGenerator(key.repo, key.path); + BlameResult blame; + try { + gen.push(null, key.commitId); + blame = gen.computeBlameResult(); + } finally { + gen.release(); + } + if (blame == null) { + return ImmutableList.of(); + } + int lineCount = blame.getResultContents().size(); + blame.discardResultContents(); + + List<BlameCache.Region> regions = Lists.newArrayList(); + for (int i = 0; i < lineCount; i++) { + if (regions.isEmpty() || !regions.get(regions.size() - 1).growFrom(blame, i)) { + regions.add(new BlameCache.Region(blame, i)); + } + } + return Collections.unmodifiableList(regions); + } finally { + key.repo = null; + } + } +}
diff --git a/gitiles-servlet/src/main/java/com/google/gitiles/BlameServlet.java b/gitiles-servlet/src/main/java/com/google/gitiles/BlameServlet.java index 21ce0d5..0383b4f 100644 --- a/gitiles-servlet/src/main/java/com/google/gitiles/BlameServlet.java +++ b/gitiles-servlet/src/main/java/com/google/gitiles/BlameServlet.java
@@ -21,7 +21,6 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; -import com.google.gitiles.BlameCache.Region; import org.eclipse.jgit.errors.IncorrectObjectTypeException; import org.eclipse.jgit.http.server.ServletUtils; @@ -71,7 +70,7 @@ String title = "Blame - " + view.getPathPart(); Map<String, ?> blobData = new BlobSoyData(rw, view).toSoyData(view.getPathPart(), blobId); if (blobData.get("data") != null) { - List<Region> regions = cache.get(repo, commit, view.getPathPart()); + List<BlameCache.Region> regions = cache.get(repo, commit, view.getPathPart()); if (regions.isEmpty()) { res.setStatus(SC_NOT_FOUND); return; @@ -110,7 +109,7 @@ } private static List<Map<String, ?>> toSoyData(GitilesView view, ObjectReader reader, - List<Region> regions, GitDateFormatter df) throws IOException { + List<BlameCache.Region> regions, GitDateFormatter df) throws IOException { Map<ObjectId, String> abbrevShas = Maps.newHashMap(); List<Map<String, ?>> result = Lists.newArrayListWithCapacity(regions.size()); for (BlameCache.Region r : regions) {
diff --git a/gitiles-servlet/src/main/java/com/google/gitiles/GitilesFilter.java b/gitiles-servlet/src/main/java/com/google/gitiles/GitilesFilter.java index b878415..b4e78f6 100644 --- a/gitiles-servlet/src/main/java/com/google/gitiles/GitilesFilter.java +++ b/gitiles-servlet/src/main/java/com/google/gitiles/GitilesFilter.java
@@ -401,9 +401,9 @@ private void setDefaultBlameCache() { if (blameCache == null) { if (config.getSubsections("cache").contains("blame")) { - blameCache = new BlameCache(ConfigUtil.getCacheBuilder(config, "blame")); + blameCache = new BlameCacheImpl(ConfigUtil.getCacheBuilder(config, "blame")); } else { - blameCache = new BlameCache(); + blameCache = new BlameCacheImpl(); } } }