Line data Source code
1 : // Copyright (C) 2020 The Android Open Source Project 2 : // 3 : // Licensed under the Apache License, Version 2.0 (the "License"); 4 : // you may not use this file except in compliance with the License. 5 : // You may obtain a copy of the License at 6 : // 7 : // http://www.apache.org/licenses/LICENSE-2.0 8 : // 9 : // Unless required by applicable law or agreed to in writing, software 10 : // distributed under the License is distributed on an "AS IS" BASIS, 11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : // See the License for the specific language governing permissions and 13 : // limitations under the License. 14 : 15 : package com.google.gerrit.server.patch.filediff; 16 : 17 : import static com.google.gerrit.server.patch.DiffUtil.stringSize; 18 : 19 : import com.google.auto.value.AutoValue; 20 : import com.google.gerrit.entities.Project; 21 : import com.google.gerrit.entities.Project.NameKey; 22 : import com.google.gerrit.extensions.client.DiffPreferencesInfo; 23 : import com.google.gerrit.extensions.client.DiffPreferencesInfo.Whitespace; 24 : import com.google.gerrit.proto.Protos; 25 : import com.google.gerrit.server.cache.proto.Cache.FileDiffKeyProto; 26 : import com.google.gerrit.server.cache.serialize.CacheSerializer; 27 : import com.google.gerrit.server.cache.serialize.ObjectIdConverter; 28 : import com.google.gerrit.server.patch.gitfilediff.GitFileDiffCacheImpl.DiffAlgorithm; 29 : import org.eclipse.jgit.lib.ObjectId; 30 : 31 : /** Cache key for the {@link FileDiffCache}. */ 32 : @AutoValue 33 105 : public abstract class FileDiffCacheKey { 34 : 35 : /** A specific git project / repository. */ 36 : public abstract Project.NameKey project(); 37 : 38 : /** 39 : * The 20 bytes SHA-1 commit ID of the old commit used in the diff. If set to {@link 40 : * ObjectId#zeroId()}, an empty tree is used for the diff. 41 : */ 42 : public abstract ObjectId oldCommit(); 43 : 44 : /** The 20 bytes SHA-1 commit ID of the new commit used in the diff. */ 45 : public abstract ObjectId newCommit(); 46 : 47 : /** File path identified by its name. */ 48 : public abstract String newFilePath(); 49 : 50 : /** 51 : * Percentage score used to identify a file as a "rename". A special value of -1 means that the 52 : * computation will ignore renames and rename detection will be disabled. 53 : */ 54 : public abstract int renameScore(); 55 : 56 : /** The diff algorithm that should be used in the computation. */ 57 : public abstract DiffAlgorithm diffAlgorithm(); 58 : 59 : public abstract DiffPreferencesInfo.Whitespace whitespace(); 60 : 61 : /** Employ a timeout on the git computation while formatting the file header. */ 62 : public abstract boolean useTimeout(); 63 : 64 : /** Number of bytes that this entity occupies. */ 65 : public int weight() { 66 104 : return stringSize(project().get()) 67 : + 20 * 2 // old and new commits 68 104 : + stringSize(newFilePath()) 69 : + 4 // renameScore 70 : + 4 // diffAlgorithm 71 : + 4 // whitespace 72 : + 1; // useTimeout 73 : } 74 : 75 : public static FileDiffCacheKey.Builder builder() { 76 105 : return new AutoValue_FileDiffCacheKey.Builder(); 77 : } 78 : 79 : public abstract Builder toBuilder(); 80 : 81 : @AutoValue.Builder 82 105 : public abstract static class Builder { 83 : 84 : public abstract FileDiffCacheKey.Builder project(NameKey value); 85 : 86 : public abstract FileDiffCacheKey.Builder oldCommit(ObjectId value); 87 : 88 : public abstract FileDiffCacheKey.Builder newCommit(ObjectId value); 89 : 90 : public abstract FileDiffCacheKey.Builder newFilePath(String value); 91 : 92 : public abstract FileDiffCacheKey.Builder renameScore(int value); 93 : 94 : public FileDiffCacheKey.Builder disableRenameDetection() { 95 0 : renameScore(-1); 96 0 : return this; 97 : } 98 : 99 : public abstract FileDiffCacheKey.Builder diffAlgorithm(DiffAlgorithm value); 100 : 101 : public abstract FileDiffCacheKey.Builder whitespace(Whitespace value); 102 : 103 : public abstract FileDiffCacheKey.Builder useTimeout(boolean value); 104 : 105 : public abstract FileDiffCacheKey build(); 106 : } 107 : 108 153 : public enum Serializer implements CacheSerializer<FileDiffCacheKey> { 109 153 : INSTANCE; 110 : 111 : @Override 112 : public byte[] serialize(FileDiffCacheKey key) { 113 7 : ObjectIdConverter idConverter = ObjectIdConverter.create(); 114 7 : return Protos.toByteArray( 115 7 : FileDiffKeyProto.newBuilder() 116 7 : .setProject(key.project().get()) 117 7 : .setOldCommit(idConverter.toByteString(key.oldCommit())) 118 7 : .setNewCommit(idConverter.toByteString(key.newCommit())) 119 7 : .setFilePath(key.newFilePath()) 120 7 : .setRenameScore(key.renameScore()) 121 7 : .setDiffAlgorithm(key.diffAlgorithm().name()) 122 7 : .setWhitespace(key.whitespace().name()) 123 7 : .setUseTimeout(key.useTimeout()) 124 7 : .build()); 125 : } 126 : 127 : @Override 128 : public FileDiffCacheKey deserialize(byte[] in) { 129 2 : FileDiffKeyProto proto = Protos.parseUnchecked(FileDiffKeyProto.parser(), in); 130 2 : ObjectIdConverter idConverter = ObjectIdConverter.create(); 131 2 : return FileDiffCacheKey.builder() 132 2 : .project(Project.nameKey(proto.getProject())) 133 2 : .oldCommit(idConverter.fromByteString(proto.getOldCommit())) 134 2 : .newCommit(idConverter.fromByteString(proto.getNewCommit())) 135 2 : .newFilePath(proto.getFilePath()) 136 2 : .renameScore(proto.getRenameScore()) 137 2 : .diffAlgorithm(DiffAlgorithm.valueOf(proto.getDiffAlgorithm())) 138 2 : .whitespace(Whitespace.valueOf(proto.getWhitespace())) 139 2 : .useTimeout(proto.getUseTimeout()) 140 2 : .build(); 141 : } 142 : } 143 : }