blob: 16b0e6580ca6fa28c16a17e9d677bf44e02c0cca [file] [log] [blame]
// Copyright (C) 2020 The Android Open Source Project
//
// 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.gerrit.server.patch.gitdiff;
import static com.google.gerrit.server.patch.DiffUtil.stringSize;
import com.google.auto.value.AutoValue;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.Project.NameKey;
import com.google.gerrit.proto.Protos;
import com.google.gerrit.server.cache.proto.Cache.GitModifiedFilesKeyProto;
import com.google.gerrit.server.cache.serialize.CacheSerializer;
import com.google.gerrit.server.cache.serialize.ObjectIdConverter;
import com.google.gerrit.server.patch.DiffUtil;
import java.io.IOException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.revwalk.RevWalk;
/** Cache key for the {@link GitModifiedFilesCache}. */
@AutoValue
public abstract class GitModifiedFilesCacheKey {
/** A specific git project / repository. */
public abstract Project.NameKey project();
/**
* The git SHA-1 {@link ObjectId} of the first git tree object for which the diff should be
* computed. If equals to {@link ObjectId#zeroId()}, a null tree is used for the diff scan, and
* {@link #bTree()} is treated as an added tree.
*/
public abstract ObjectId aTree();
/**
* The git SHA-1 {@link ObjectId} of the second git tree object for which the diff should be
* computed.
*/
public abstract ObjectId bTree();
/**
* Percentage score used to identify a file as a rename. This value is only available if {@link
* #renameDetection()} is true. Otherwise, this method will return -1.
*
* <p>This value will be used to set the rename score of {@link
* org.eclipse.jgit.diff.DiffFormatter#getRenameDetector()}.
*/
public abstract int renameScore();
/** Returns true if rename detection was set for this key. */
public boolean renameDetection() {
return renameScore() != -1;
}
public static GitModifiedFilesCacheKey create(
Project.NameKey project, ObjectId aCommit, ObjectId bCommit, int renameScore, RevWalk rw)
throws IOException {
ObjectId aTree = DiffUtil.getTreeId(rw, aCommit);
ObjectId bTree = DiffUtil.getTreeId(rw, bCommit);
return builder().project(project).aTree(aTree).bTree(bTree).renameScore(renameScore).build();
}
public static Builder builder() {
return new AutoValue_GitModifiedFilesCacheKey.Builder();
}
/** Returns the size of the object in bytes */
public int weight() {
return stringSize(project().get())
+ 20 * 2 // old and new tree IDs
+ 4; // rename score
}
@AutoValue.Builder
public abstract static class Builder {
public abstract Builder project(NameKey value);
public abstract Builder aTree(ObjectId value);
public abstract Builder bTree(ObjectId value);
public abstract Builder renameScore(int value);
public Builder disableRenameDetection() {
renameScore(-1);
return this;
}
public abstract GitModifiedFilesCacheKey build();
}
public enum Serializer implements CacheSerializer<GitModifiedFilesCacheKey> {
INSTANCE;
@Override
public byte[] serialize(GitModifiedFilesCacheKey key) {
ObjectIdConverter idConverter = ObjectIdConverter.create();
return Protos.toByteArray(
GitModifiedFilesKeyProto.newBuilder()
.setProject(key.project().get())
.setATree(idConverter.toByteString(key.aTree()))
.setBTree(idConverter.toByteString(key.bTree()))
.setRenameScore(key.renameScore())
.build());
}
@Override
public GitModifiedFilesCacheKey deserialize(byte[] in) {
GitModifiedFilesKeyProto proto = Protos.parseUnchecked(GitModifiedFilesKeyProto.parser(), in);
ObjectIdConverter idConverter = ObjectIdConverter.create();
return GitModifiedFilesCacheKey.builder()
.project(NameKey.parse(proto.getProject()))
.aTree(idConverter.fromByteString(proto.getATree()))
.bTree(idConverter.fromByteString(proto.getBTree()))
.renameScore(proto.getRenameScore())
.build();
}
}
}