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 package org.eclipse.jgit.api;
44
45 import static org.eclipse.jgit.lib.Constants.R_STASH;
46
47 import java.io.File;
48 import java.io.IOException;
49 import java.nio.file.StandardCopyOption;
50 import java.text.MessageFormat;
51 import java.util.List;
52
53 import org.eclipse.jgit.api.errors.GitAPIException;
54 import org.eclipse.jgit.api.errors.InvalidRefNameException;
55 import org.eclipse.jgit.api.errors.JGitInternalException;
56 import org.eclipse.jgit.api.errors.RefNotFoundException;
57 import org.eclipse.jgit.errors.LockFailedException;
58 import org.eclipse.jgit.internal.JGitText;
59 import org.eclipse.jgit.internal.storage.file.ReflogWriter;
60 import org.eclipse.jgit.lib.ObjectId;
61 import org.eclipse.jgit.lib.Ref;
62 import org.eclipse.jgit.lib.RefUpdate;
63 import org.eclipse.jgit.lib.RefUpdate.Result;
64 import org.eclipse.jgit.lib.ReflogEntry;
65 import org.eclipse.jgit.lib.ReflogReader;
66 import org.eclipse.jgit.lib.Repository;
67 import org.eclipse.jgit.util.FileUtils;
68
69
70
71
72
73
74
75
76 public class StashDropCommand extends GitCommand<ObjectId> {
77
78 private int stashRefEntry;
79
80 private boolean all;
81
82
83
84
85 public StashDropCommand(Repository repo) {
86 super(repo);
87 }
88
89
90
91
92
93
94
95
96
97
98 public StashDropCommand setStashRef(final int stashRef) {
99 if (stashRef < 0)
100 throw new IllegalArgumentException();
101
102 stashRefEntry = stashRef;
103 return this;
104 }
105
106
107
108
109
110
111
112
113
114 public StashDropCommand setAll(final boolean all) {
115 this.all = all;
116 return this;
117 }
118
119 private Ref getRef() throws GitAPIException {
120 try {
121 return repo.getRef(R_STASH);
122 } catch (IOException e) {
123 throw new InvalidRefNameException(MessageFormat.format(
124 JGitText.get().cannotRead, R_STASH), e);
125 }
126 }
127
128 private RefUpdate createRefUpdate(final Ref stashRef) throws IOException {
129 RefUpdate update = repo.updateRef(R_STASH);
130 update.disableRefLog();
131 update.setExpectedOldObjectId(stashRef.getObjectId());
132 update.setForceUpdate(true);
133 return update;
134 }
135
136 private void deleteRef(final Ref stashRef) {
137 try {
138 Result result = createRefUpdate(stashRef).delete();
139 if (Result.FORCED != result)
140 throw new JGitInternalException(MessageFormat.format(
141 JGitText.get().stashDropDeleteRefFailed, result));
142 } catch (IOException e) {
143 throw new JGitInternalException(JGitText.get().stashDropFailed, e);
144 }
145 }
146
147 private void updateRef(Ref stashRef, ObjectId newId) {
148 try {
149 RefUpdate update = createRefUpdate(stashRef);
150 update.setNewObjectId(newId);
151 Result result = update.update();
152 switch (result) {
153 case FORCED:
154 case NEW:
155 case NO_CHANGE:
156 return;
157 default:
158 throw new JGitInternalException(MessageFormat.format(
159 JGitText.get().updatingRefFailed, R_STASH, newId,
160 result));
161 }
162 } catch (IOException e) {
163 throw new JGitInternalException(JGitText.get().stashDropFailed, e);
164 }
165 }
166
167
168
169
170
171
172
173
174 public ObjectId call() throws GitAPIException {
175 checkCallable();
176
177 Ref stashRef = getRef();
178 if (stashRef == null)
179 return null;
180
181 if (all) {
182 deleteRef(stashRef);
183 return null;
184 }
185
186 List<ReflogEntry> entries;
187 try {
188 ReflogReader reader = repo.getReflogReader(R_STASH);
189 if (reader == null) {
190 throw new RefNotFoundException(MessageFormat
191 .format(JGitText.get().refNotResolved, stashRef));
192 }
193 entries = reader.getReverseEntries();
194 } catch (IOException e) {
195 throw new JGitInternalException(JGitText.get().stashDropFailed, e);
196 }
197
198 if (stashRefEntry >= entries.size())
199 throw new JGitInternalException(
200 JGitText.get().stashDropMissingReflog);
201
202 if (entries.size() == 1) {
203 deleteRef(stashRef);
204 return null;
205 }
206
207 ReflogWriter writer = new ReflogWriter(repo, true);
208 String stashLockRef = ReflogWriter.refLockFor(R_STASH);
209 File stashLockFile = writer.logFor(stashLockRef);
210 File stashFile = writer.logFor(R_STASH);
211 if (stashLockFile.exists())
212 throw new JGitInternalException(JGitText.get().stashDropFailed,
213 new LockFailedException(stashFile));
214
215 entries.remove(stashRefEntry);
216 ObjectId entryId = ObjectId.zeroId();
217 try {
218 for (int i = entries.size() - 1; i >= 0; i--) {
219 ReflogEntry entry = entries.get(i);
220 writer.log(stashLockRef, entryId, entry.getNewId(),
221 entry.getWho(), entry.getComment());
222 entryId = entry.getNewId();
223 }
224 try {
225 FileUtils.rename(stashLockFile, stashFile,
226 StandardCopyOption.ATOMIC_MOVE);
227 } catch (IOException e) {
228 throw new JGitInternalException(MessageFormat.format(
229 JGitText.get().renameFileFailed,
230 stashLockFile.getPath(), stashFile.getPath()),
231 e);
232 }
233 } catch (IOException e) {
234 throw new JGitInternalException(JGitText.get().stashDropFailed, e);
235 }
236 updateRef(stashRef, entryId);
237
238 try {
239 Ref newStashRef = repo.getRef(R_STASH);
240 return newStashRef != null ? newStashRef.getObjectId() : null;
241 } catch (IOException e) {
242 throw new InvalidRefNameException(MessageFormat.format(
243 JGitText.get().cannotRead, R_STASH), e);
244 }
245 }
246 }