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