Line data Source code
1 : // Copyright (C) 2008 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.entities;
16 :
17 : import static com.google.common.base.Preconditions.checkArgument;
18 :
19 : import com.google.auto.value.AutoValue;
20 : import com.google.common.base.Splitter;
21 : import com.google.common.primitives.Ints;
22 : import com.google.gerrit.common.Nullable;
23 : import com.google.gerrit.common.UsedAt;
24 : import java.util.List;
25 :
26 : /**
27 : * Wrapper class for patch related aspects. Originally, this class represented a single modified
28 : * file in a {@link PatchSet}. It's only kept in its current form as {@link ChangeType} and {@link
29 : * PatchType} are used in diff cache entries for which we would break the serialization if we moved
30 : * the enums somewhere else.
31 : */
32 : public final class Patch {
33 : /** Magical file name which represents the commit message. */
34 : public static final String COMMIT_MSG = "/COMMIT_MSG";
35 :
36 : /** Magical file name which represents the merge list of a merge commit. */
37 : public static final String MERGE_LIST = "/MERGE_LIST";
38 :
39 : /**
40 : * Magical file name which doesn't represent a file. Used specifically for patchset-level
41 : * comments.
42 : */
43 : public static final String PATCHSET_LEVEL = "/PATCHSET_LEVEL";
44 :
45 : /**
46 : * Checks if the given path represents a magic file. A magic file is a generated file that is
47 : * automatically included into changes. It does not exist in the commit of the patch set.
48 : *
49 : * @param path the file path
50 : * @return {@code true} if the path represents a magic file, otherwise {@code false}.
51 : */
52 : public static boolean isMagic(String path) {
53 108 : return COMMIT_MSG.equals(path) || MERGE_LIST.equals(path) || PATCHSET_LEVEL.equals(path);
54 : }
55 :
56 : public static Key key(PatchSet.Id patchSetId, String fileName) {
57 17 : return new AutoValue_Patch_Key(patchSetId, fileName);
58 : }
59 :
60 : @AutoValue
61 17 : public abstract static class Key {
62 : /** Parse a Patch.Key out of a string representation. */
63 : public static Key parse(String str) {
64 1 : List<String> parts = Splitter.on(',').limit(3).splitToList(str);
65 1 : checkKeyFormat(parts.size() == 3, str);
66 1 : Integer changeId = Ints.tryParse(parts.get(0));
67 1 : checkKeyFormat(changeId != null, str);
68 1 : Integer patchSetNum = Ints.tryParse(parts.get(1));
69 1 : checkKeyFormat(patchSetNum != null, str);
70 1 : return key(PatchSet.id(Change.id(changeId), patchSetNum), parts.get(2));
71 : }
72 :
73 : private static void checkKeyFormat(boolean test, String input) {
74 1 : checkArgument(test, "invalid patch key: %s", input);
75 1 : }
76 :
77 : public abstract PatchSet.Id patchSetId();
78 :
79 : public abstract String fileName();
80 : }
81 :
82 : /**
83 : * Type of modification made to the file path. Ordering of values matters (used by diff cache).
84 : */
85 154 : public enum ChangeType implements CodedEnum {
86 : /** Path is being created/introduced by this patch. */
87 154 : ADDED('A'),
88 :
89 : /** Path existed at the source but was moved. */
90 154 : RENAMED('R'),
91 :
92 : /** Path already exists, and has updated content. */
93 154 : MODIFIED('M'),
94 :
95 : /** Path was copied from the source. */
96 154 : COPIED('C'),
97 :
98 : /** Sufficient amount of content changed to claim the file was rewritten. */
99 154 : REWRITE('W'),
100 :
101 : /** Path existed, but is being removed by this patch. */
102 154 : DELETED('D');
103 :
104 : private final char code;
105 :
106 154 : ChangeType(char c) {
107 154 : code = c;
108 154 : }
109 :
110 : @Override
111 : public char getCode() {
112 103 : return code;
113 : }
114 :
115 : @UsedAt(UsedAt.Project.COLLABNET)
116 : @Nullable
117 : public static ChangeType forCode(char c) {
118 0 : for (ChangeType s : ChangeType.values()) {
119 0 : if (s.code == c) {
120 0 : return s;
121 : }
122 : }
123 0 : return null;
124 : }
125 : }
126 :
127 : /** Type of formatting for this patch. */
128 105 : public enum PatchType implements CodedEnum {
129 : /**
130 : * A textual difference between two versions.
131 : *
132 : * <p>A UNIFIED patch can be rendered in multiple ways. Most commonly, it is rendered as a side
133 : * by side display using two columns, left column for the old version, right column for the new
134 : * version. A UNIFIED patch can also be formatted in a number of standard "patch script" styles,
135 : * but typically is formatted in the POSIX standard unified diff format.
136 : *
137 : * <p>Usually Gerrit renders a UNIFIED patch in a PatchScreen.SideBySide view, presenting the
138 : * file in two columns. If the user chooses, a PatchScreen.Unified is also a valid display
139 : * method.
140 : */
141 105 : UNIFIED('U'),
142 :
143 : /**
144 : * Difference of two (or more) binary contents.
145 : *
146 : * <p>A BINARY patch cannot be viewed in a text display, as it represents a change in binary
147 : * content at the associated path, for example, an image file has been replaced with a different
148 : * image.
149 : *
150 : * <p>Gerrit can only render a BINARY file in a PatchScreen.Unified view, as the only
151 : * information it can display is the old and new file content hashes.
152 : */
153 105 : BINARY('B');
154 :
155 : private final char code;
156 :
157 105 : PatchType(char c) {
158 105 : code = c;
159 105 : }
160 :
161 : @Override
162 : public char getCode() {
163 0 : return code;
164 : }
165 : }
166 :
167 : /**
168 : * Constants describing various file modes recognized by GIT. This is the Gerrit entity for {@link
169 : * org.eclipse.jgit.lib.FileMode}.
170 : */
171 94 : public enum FileMode implements CodedEnum {
172 : /** Mode indicating an entry is a tree (aka directory). */
173 94 : TREE('T', 0040000),
174 :
175 : /** Mode indicating an entry is a symbolic link. */
176 94 : SYMLINK('S', 0120000),
177 :
178 : /** Mode indicating an entry is a non-executable file. */
179 94 : REGULAR_FILE('R', 0100644),
180 :
181 : /** Mode indicating an entry is an executable file. */
182 94 : EXECUTABLE_FILE('E', 0100755),
183 :
184 : /** Mode indicating an entry is a submodule commit in another repository. */
185 94 : GITLINK('G', 0160000),
186 :
187 : /** Mode indicating an entry is missing during parallel walks. */
188 94 : MISSING('M', 0000000);
189 :
190 : private final char code;
191 :
192 : private final int mode;
193 :
194 94 : FileMode(char c, int m) {
195 94 : code = c;
196 94 : mode = m;
197 94 : }
198 :
199 : @Override
200 : public char getCode() {
201 0 : return code;
202 : }
203 :
204 : public int getMode() {
205 89 : return mode;
206 : }
207 : }
208 :
209 : private Patch() {}
210 : }
|