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.revwalk.RevObject;
65 import org.eclipse.jgit.revwalk.RevTag;
66 import org.eclipse.jgit.revwalk.RevWalk;
67 import org.eclipse.jgit.transport.ReceiveCommand;
68 import org.eclipse.jgit.transport.ReceiveCommand.Result;
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83 public class Command {
84
85
86
87
88
89
90
91
92
93
94
95
96 public static void abort(Iterable<Command> commands, @Nullable String why) {
97 if (why == null || why.isEmpty()) {
98 why = JGitText.get().transactionAborted;
99 }
100 for (Command c : commands) {
101 if (c.getResult() == NOT_ATTEMPTED) {
102 c.setResult(REJECTED_OTHER_REASON, why);
103 why = JGitText.get().transactionAborted;
104 }
105 }
106 }
107
108 private final Ref oldRef;
109 private final Ref newRef;
110 private final ReceiveCommand cmd;
111 private Result result;
112
113
114
115
116
117
118
119
120
121
122
123
124 public Command(@Nullable Ref oldRef, @Nullable Ref newRef) {
125 this.oldRef = oldRef;
126 this.newRef = newRef;
127 this.cmd = null;
128 this.result = NOT_ATTEMPTED;
129
130 if (oldRef == null && newRef == null) {
131 throw new IllegalArgumentException();
132 }
133 if (newRef != null && !newRef.isPeeled() && !newRef.isSymbolic()) {
134 throw new IllegalArgumentException();
135 }
136 if (oldRef != null && newRef != null
137 && !oldRef.getName().equals(newRef.getName())) {
138 throw new IllegalArgumentException();
139 }
140 }
141
142
143
144
145
146
147
148
149
150
151
152
153
154 public Command(RevWalk rw, ReceiveCommand cmd)
155 throws MissingObjectException, IOException {
156 this.oldRef = toRef(rw, cmd.getOldId(), cmd.getRefName(), false);
157 this.newRef = toRef(rw, cmd.getNewId(), cmd.getRefName(), true);
158 this.cmd = cmd;
159 }
160
161 static Ref toRef(RevWalk rw, ObjectId id, String name,
162 boolean mustExist) throws MissingObjectException, IOException {
163 if (ObjectId.zeroId().equals(id)) {
164 return null;
165 }
166
167 try {
168 RevObject o = rw.parseAny(id);
169 if (o instanceof RevTag) {
170 RevObject p = rw.peel(o);
171 return new ObjectIdRef.PeeledTag(NETWORK, name, id, p.copy());
172 }
173 return new ObjectIdRef.PeeledNonTag(NETWORK, name, id);
174 } catch (MissingObjectException e) {
175 if (mustExist) {
176 throw e;
177 }
178 return new ObjectIdRef.Unpeeled(NETWORK, name, id);
179 }
180 }
181
182
183 public String getRefName() {
184 if (cmd != null) {
185 return cmd.getRefName();
186 } else if (newRef != null) {
187 return newRef.getName();
188 }
189 return oldRef.getName();
190 }
191
192
193
194
195
196
197
198 public void setResult(Result result) {
199 setResult(result, null);
200 }
201
202
203
204
205
206
207
208
209
210 public void setResult(Result result, @Nullable String why) {
211 if (cmd != null) {
212 cmd.setResult(result, why);
213 } else {
214 this.result = result;
215 }
216 }
217
218
219 public Result getResult() {
220 return cmd != null ? cmd.getResult() : result;
221 }
222
223
224 @Nullable
225 public String getMessage() {
226 return cmd != null ? cmd.getMessage() : null;
227 }
228
229
230
231
232
233
234 @Nullable
235 public Ref getOldRef() {
236 return oldRef;
237 }
238
239
240
241
242
243
244 @Nullable
245 public Ref getNewRef() {
246 return newRef;
247 }
248
249 @Override
250 public String toString() {
251 StringBuilder s = new StringBuilder();
252 append(s, oldRef, "CREATE");
253 s.append(' ');
254 append(s, newRef, "DELETE");
255 s.append(' ').append(getRefName());
256 s.append(' ').append(getResult());
257 if (getMessage() != null) {
258 s.append(' ').append(getMessage());
259 }
260 return s.toString();
261 }
262
263 private static void append(StringBuilder s, Ref r, String nullName) {
264 if (r == null) {
265 s.append(nullName);
266 } else if (r.isSymbolic()) {
267 s.append(r.getTarget().getName());
268 } else {
269 ObjectId id = r.getObjectId();
270 if (id != null) {
271 s.append(id.name());
272 }
273 }
274 }
275
276
277
278
279
280
281
282
283
284 boolean checkRef(@Nullable DirCacheEntry entry) {
285 if (entry != null && entry.getRawMode() == 0) {
286 entry = null;
287 }
288 return check(entry, oldRef) || check(entry, newRef);
289 }
290
291 private static boolean check(@Nullable DirCacheEntry cur,
292 @Nullable Ref exp) {
293 if (cur == null) {
294
295 return exp == null;
296 } else if (exp == null) {
297
298 return false;
299 }
300
301 if (exp.isSymbolic()) {
302 String dst = exp.getTarget().getName();
303 return cur.getRawMode() == TYPE_SYMLINK
304 && cur.getObjectId().equals(symref(dst));
305 }
306
307 return cur.getRawMode() == TYPE_GITLINK
308 && cur.getObjectId().equals(exp.getObjectId());
309 }
310
311 static ObjectId symref(String s) {
312 @SuppressWarnings("resource")
313 ObjectInserter.Formatter fmt = new ObjectInserter.Formatter();
314 return fmt.idFor(OBJ_BLOB, encode(s));
315 }
316 }