1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 package org.eclipse.jgit.internal.storage.reftree;
45
46 import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
47 import static org.eclipse.jgit.lib.Constants.encode;
48 import static org.eclipse.jgit.lib.FileMode.TYPE_GITLINK;
49 import static org.eclipse.jgit.lib.FileMode.TYPE_SYMLINK;
50 import static org.eclipse.jgit.lib.Ref.Storage.NETWORK;
51 import static org.eclipse.jgit.transport.ReceiveCommand.Result.NOT_ATTEMPTED;
52 import static org.eclipse.jgit.transport.ReceiveCommand.Result.REJECTED_OTHER_REASON;
53
54 import java.io.IOException;
55
56 import org.eclipse.jgit.annotations.Nullable;
57 import org.eclipse.jgit.dircache.DirCacheEntry;
58 import org.eclipse.jgit.errors.MissingObjectException;
59 import org.eclipse.jgit.internal.JGitText;
60 import org.eclipse.jgit.lib.ObjectId;
61 import org.eclipse.jgit.lib.ObjectIdRef;
62 import org.eclipse.jgit.lib.ObjectInserter;
63 import org.eclipse.jgit.lib.Ref;
64 import org.eclipse.jgit.lib.SymbolicRef;
65 import org.eclipse.jgit.revwalk.RevObject;
66 import org.eclipse.jgit.revwalk.RevTag;
67 import org.eclipse.jgit.revwalk.RevWalk;
68 import org.eclipse.jgit.transport.ReceiveCommand;
69 import org.eclipse.jgit.transport.ReceiveCommand.Result;
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87 public class Command {
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103 public static void abort(Iterable<Command> commands, @Nullable String why) {
104 if (why == null || why.isEmpty()) {
105 why = JGitText.get().transactionAborted;
106 }
107 for (Command c : commands) {
108 if (c.getResult() == NOT_ATTEMPTED) {
109 c.setResult(REJECTED_OTHER_REASON, why);
110 why = JGitText.get().transactionAborted;
111 }
112 }
113 }
114
115 private final Ref oldRef;
116 private final Ref newRef;
117 private final ReceiveCommand cmd;
118 private Result result;
119
120
121
122
123
124
125
126
127
128
129
130
131 public Command(@Nullable Ref oldRef, @Nullable Ref newRef) {
132 this.oldRef = oldRef;
133 this.newRef = newRef;
134 this.cmd = null;
135 this.result = NOT_ATTEMPTED;
136
137 if (oldRef == null && newRef == null) {
138 throw new IllegalArgumentException();
139 }
140 if (newRef != null && !newRef.isPeeled() && !newRef.isSymbolic()) {
141 throw new IllegalArgumentException();
142 }
143 if (oldRef != null && newRef != null
144 && !oldRef.getName().equals(newRef.getName())) {
145 throw new IllegalArgumentException();
146 }
147 }
148
149
150
151
152
153
154
155
156
157
158
159
160
161 public Command(RevWalk rw, ReceiveCommand cmd)
162 throws MissingObjectException, IOException {
163 this.oldRef = toRef(rw, cmd.getOldId(), cmd.getOldSymref(),
164 cmd.getRefName(), false);
165 this.newRef = toRef(rw, cmd.getNewId(), cmd.getNewSymref(),
166 cmd.getRefName(), true);
167 this.cmd = cmd;
168 }
169
170 static Ref toRef(RevWalk rw, ObjectId id, @Nullable String target,
171 String name, boolean mustExist)
172 throws MissingObjectException, IOException {
173 if (target != null) {
174 return new SymbolicRef(name,
175 new ObjectIdRef.Unpeeled(NETWORK, target, id));
176 } else if (ObjectId.zeroId().equals(id)) {
177 return null;
178 }
179
180 try {
181 RevObject o = rw.parseAny(id);
182 if (o instanceof RevTag) {
183 RevObject p = rw.peel(o);
184 return new ObjectIdRef.PeeledTag(NETWORK, name, id, p.copy());
185 }
186 return new ObjectIdRef.PeeledNonTag(NETWORK, name, id);
187 } catch (MissingObjectException e) {
188 if (mustExist) {
189 throw e;
190 }
191 return new ObjectIdRef.Unpeeled(NETWORK, name, id);
192 }
193 }
194
195
196
197
198
199
200 public String getRefName() {
201 if (cmd != null) {
202 return cmd.getRefName();
203 } else if (newRef != null) {
204 return newRef.getName();
205 }
206 return oldRef.getName();
207 }
208
209
210
211
212
213
214
215 public void setResult(Result result) {
216 setResult(result, null);
217 }
218
219
220
221
222
223
224
225
226
227 public void setResult(Result result, @Nullable String why) {
228 if (cmd != null) {
229 cmd.setResult(result, why);
230 } else {
231 this.result = result;
232 }
233 }
234
235
236
237
238
239
240 public Result getResult() {
241 return cmd != null ? cmd.getResult() : result;
242 }
243
244
245
246
247
248
249 @Nullable
250 public String getMessage() {
251 return cmd != null ? cmd.getMessage() : null;
252 }
253
254
255
256
257
258
259 @Nullable
260 public Ref getOldRef() {
261 return oldRef;
262 }
263
264
265
266
267
268
269 @Nullable
270 public Ref getNewRef() {
271 return newRef;
272 }
273
274
275 @Override
276 public String toString() {
277 StringBuilder s = new StringBuilder();
278 append(s, oldRef, "CREATE");
279 s.append(' ');
280 append(s, newRef, "DELETE");
281 s.append(' ').append(getRefName());
282 s.append(' ').append(getResult());
283 if (getMessage() != null) {
284 s.append(' ').append(getMessage());
285 }
286 return s.toString();
287 }
288
289 private static void append(StringBuilder s, Ref r, String nullName) {
290 if (r == null) {
291 s.append(nullName);
292 } else if (r.isSymbolic()) {
293 s.append(r.getTarget().getName());
294 } else {
295 ObjectId id = r.getObjectId();
296 if (id != null) {
297 s.append(id.name());
298 }
299 }
300 }
301
302
303
304
305
306
307
308
309
310 boolean checkRef(@Nullable DirCacheEntry entry) {
311 if (entry != null && entry.getRawMode() == 0) {
312 entry = null;
313 }
314 return check(entry, oldRef) || check(entry, newRef);
315 }
316
317 private static boolean check(@Nullable DirCacheEntry cur,
318 @Nullable Ref exp) {
319 if (cur == null) {
320
321 return exp == null;
322 } else if (exp == null) {
323
324 return false;
325 }
326
327 if (exp.isSymbolic()) {
328 String dst = exp.getTarget().getName();
329 return cur.getRawMode() == TYPE_SYMLINK
330 && cur.getObjectId().equals(symref(dst));
331 }
332
333 return cur.getRawMode() == TYPE_GITLINK
334 && cur.getObjectId().equals(exp.getObjectId());
335 }
336
337 static ObjectId symref(String s) {
338 @SuppressWarnings("resource")
339 ObjectInserter.Formatter fmt = new ObjectInserter.Formatter();
340 return fmt.idFor(OBJ_BLOB, encode(s));
341 }
342 }