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.gitfilediff; 16 : 17 : import static com.google.gerrit.server.patch.DiffUtil.stringSize; 18 : 19 : import com.google.auto.value.AutoValue; 20 : import com.google.common.base.Converter; 21 : import com.google.common.base.Enums; 22 : import com.google.gerrit.entities.Project; 23 : import com.google.gerrit.entities.Project.NameKey; 24 : import com.google.gerrit.extensions.client.DiffPreferencesInfo; 25 : import com.google.gerrit.extensions.client.DiffPreferencesInfo.Whitespace; 26 : import com.google.gerrit.proto.Protos; 27 : import com.google.gerrit.server.cache.proto.Cache.GitFileDiffKeyProto; 28 : import com.google.gerrit.server.cache.serialize.CacheSerializer; 29 : import com.google.gerrit.server.cache.serialize.ObjectIdConverter; 30 : import com.google.gerrit.server.patch.gitfilediff.GitFileDiffCacheImpl.DiffAlgorithm; 31 : import org.eclipse.jgit.lib.ObjectId; 32 : 33 : @AutoValue 34 94 : public abstract class GitFileDiffCacheKey { 35 : 36 : /** A specific git project / repository. */ 37 : public abstract Project.NameKey project(); 38 : 39 : /** 40 : * The old 20 bytes SHA-1 git tree ID used in the git tree diff. If equals to {@link 41 : * ObjectId#zeroId()}, a null tree is used for the diff scan, and {@link #newTree()} ()} is 42 : * treated as an added tree. 43 : */ 44 : public abstract ObjectId oldTree(); 45 : 46 : /** The new 20 bytes SHA-1 git tree ID used in the git tree diff */ 47 : public abstract ObjectId newTree(); 48 : 49 : /** File name in the tree identified by {@link #newTree()} */ 50 : public abstract String newFilePath(); 51 : 52 : /** 53 : * Percentage score used to identify a file as a "rename". A special value of -1 means that the 54 : * computation will ignore renames and rename detection will be disabled. 55 : */ 56 : public abstract int renameScore(); 57 : 58 : public abstract DiffAlgorithm diffAlgorithm(); 59 : 60 : public abstract DiffPreferencesInfo.Whitespace whitespace(); 61 : 62 : /** Employ a timeout on the git computation while formatting the file header. */ 63 : public abstract boolean useTimeout(); 64 : 65 : public int weight() { 66 93 : return stringSize(project().get()) 67 : + 20 * 2 // oldTree and newTree 68 93 : + stringSize(newFilePath()) 69 : + 4 // renameScore 70 : + 4 // diffAlgorithm 71 : + 4 // whitespace 72 : + 1; // useTimeout 73 : } 74 : 75 : public static Builder builder() { 76 94 : return new AutoValue_GitFileDiffCacheKey.Builder(); 77 : } 78 : 79 : @AutoValue.Builder 80 94 : public abstract static class Builder { 81 : 82 : public abstract Builder project(NameKey value); 83 : 84 : public abstract Builder oldTree(ObjectId value); 85 : 86 : public abstract Builder newTree(ObjectId value); 87 : 88 : public abstract Builder newFilePath(String value); 89 : 90 : public abstract Builder renameScore(Integer value); 91 : 92 : public Builder disableRenameDetection() { 93 0 : renameScore(-1); 94 0 : return this; 95 : } 96 : 97 : public abstract Builder diffAlgorithm(DiffAlgorithm value); 98 : 99 : public abstract Builder whitespace(Whitespace value); 100 : 101 : public abstract Builder useTimeout(boolean value); 102 : 103 : public abstract GitFileDiffCacheKey build(); 104 : } 105 : 106 153 : public enum Serializer implements CacheSerializer<GitFileDiffCacheKey> { 107 153 : INSTANCE; 108 : 109 153 : private static final Converter<String, DiffAlgorithm> DIFF_ALGORITHM_CONVERTER = 110 153 : Enums.stringConverter(DiffAlgorithm.class); 111 : 112 153 : private static final Converter<String, Whitespace> WHITESPACE_CONVERTER = 113 153 : Enums.stringConverter(Whitespace.class); 114 : 115 : @Override 116 : public byte[] serialize(GitFileDiffCacheKey key) { 117 5 : ObjectIdConverter idConverter = ObjectIdConverter.create(); 118 5 : return Protos.toByteArray( 119 5 : GitFileDiffKeyProto.newBuilder() 120 5 : .setProject(key.project().get()) 121 5 : .setATree(idConverter.toByteString(key.oldTree())) 122 5 : .setBTree(idConverter.toByteString(key.newTree())) 123 5 : .setFilePath(key.newFilePath()) 124 5 : .setRenameScore(key.renameScore()) 125 5 : .setDiffAlgorithm(DIFF_ALGORITHM_CONVERTER.reverse().convert(key.diffAlgorithm())) 126 5 : .setWhitepsace(WHITESPACE_CONVERTER.reverse().convert(key.whitespace())) 127 5 : .setUseTimeout(key.useTimeout()) 128 5 : .build()); 129 : } 130 : 131 : @Override 132 : public GitFileDiffCacheKey deserialize(byte[] in) { 133 1 : GitFileDiffKeyProto proto = Protos.parseUnchecked(GitFileDiffKeyProto.parser(), in); 134 1 : ObjectIdConverter idConverter = ObjectIdConverter.create(); 135 1 : return GitFileDiffCacheKey.builder() 136 1 : .project(Project.nameKey(proto.getProject())) 137 1 : .oldTree(idConverter.fromByteString(proto.getATree())) 138 1 : .newTree(idConverter.fromByteString(proto.getBTree())) 139 1 : .newFilePath(proto.getFilePath()) 140 1 : .renameScore(proto.getRenameScore()) 141 1 : .diffAlgorithm(DIFF_ALGORITHM_CONVERTER.convert(proto.getDiffAlgorithm())) 142 1 : .whitespace(WHITESPACE_CONVERTER.convert(proto.getWhitepsace())) 143 1 : .useTimeout(proto.getUseTimeout()) 144 1 : .build(); 145 : } 146 : } 147 : }