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.lib;
45
46 import java.io.File;
47 import java.io.FileOutputStream;
48 import java.io.IOException;
49 import java.io.OutputStream;
50 import java.util.LinkedList;
51 import java.util.List;
52
53 import org.eclipse.jgit.lib.RebaseTodoLine.Action;
54 import org.eclipse.jgit.util.IO;
55 import org.eclipse.jgit.util.RawParseUtils;
56 import org.eclipse.jgit.util.io.SafeBufferedOutputStream;
57
58
59
60
61
62
63
64 public class RebaseTodoFile {
65 private Repository repo;
66
67
68
69
70 public RebaseTodoFile(Repository repo) {
71 this.repo = repo;
72 }
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87 public List<RebaseTodoLine> readRebaseTodo(String path,
88 boolean includeComments) throws IOException {
89 byte[] buf = IO.readFully(new File(repo.getDirectory(), path));
90 int ptr = 0;
91 int tokenBegin = 0;
92 List<RebaseTodoLine> r = new LinkedList<RebaseTodoLine>();
93 while (ptr < buf.length) {
94 tokenBegin = ptr;
95 ptr = RawParseUtils.nextLF(buf, ptr);
96 int lineStart = tokenBegin;
97 int lineEnd = ptr - 2;
98 if (lineEnd >= 0 && buf[lineEnd] == '\r')
99 lineEnd--;
100
101 if (buf[tokenBegin] == '#') {
102 if (includeComments)
103 parseComments(buf, tokenBegin, r, lineEnd);
104 } else {
105
106 tokenBegin = nextParsableToken(buf, tokenBegin, lineEnd);
107
108
109 if (tokenBegin == -1) {
110 if (includeComments)
111 r.add(new RebaseTodoLine(RawParseUtils.decode(buf,
112 lineStart, 1 + lineEnd)));
113 continue;
114 }
115 RebaseTodoLine line = parseLine(buf, tokenBegin, lineEnd);
116 if (line == null)
117 continue;
118 r.add(line);
119 }
120 }
121 return r;
122 }
123
124 private static void parseComments(byte[] buf, int tokenBegin,
125 List<RebaseTodoLine> r, int lineEnd) {
126 RebaseTodoLine line = null;
127 String commentString = RawParseUtils.decode(buf,
128 tokenBegin, lineEnd + 1);
129 try {
130 int skip = tokenBegin + 1;
131 skip = nextParsableToken(buf, skip, lineEnd);
132 if (skip != -1) {
133
134 line = parseLine(buf, skip, lineEnd);
135
136
137 line.setAction(Action.COMMENT);
138
139 line.setComment(commentString);
140 }
141 } catch (Exception e) {
142
143 line = null;
144 } finally {
145 if (line == null)
146 line = new RebaseTodoLine(commentString);
147 r.add(line);
148 }
149 }
150
151
152
153
154
155
156
157
158
159
160
161 private static int nextParsableToken(byte[] buf, int tokenBegin, int lineEnd) {
162 while (tokenBegin <= lineEnd
163 && (buf[tokenBegin] == ' ' || buf[tokenBegin] == '\t' || buf[tokenBegin] == '\r'))
164 tokenBegin++;
165 if (tokenBegin > lineEnd)
166 return -1;
167 return tokenBegin;
168 }
169
170 private static RebaseTodoLine parseLine(byte[] buf, int tokenBegin,
171 int lineEnd) {
172 RebaseTodoLine.Action action = null;
173 AbbreviatedObjectId commit = null;
174
175 int nextSpace = RawParseUtils.next(buf, tokenBegin, ' ');
176 int tokenCount = 0;
177 while (tokenCount < 3 && nextSpace < lineEnd) {
178 switch (tokenCount) {
179 case 0:
180 String actionToken = new String(buf, tokenBegin, nextSpace
181 - tokenBegin - 1);
182 tokenBegin = nextSpace;
183 action = RebaseTodoLine.Action.parse(actionToken);
184 if (action == null)
185 return null;
186 break;
187 case 1:
188 nextSpace = RawParseUtils.next(buf, tokenBegin, ' ');
189 String commitToken = new String(buf, tokenBegin, nextSpace
190 - tokenBegin - 1);
191 tokenBegin = nextSpace;
192 commit = AbbreviatedObjectId.fromString(commitToken);
193 break;
194 case 2:
195 return new RebaseTodoLine(action, commit, RawParseUtils.decode(
196 buf, tokenBegin, 1 + lineEnd));
197 }
198 tokenCount++;
199 }
200 if (tokenCount == 2)
201 return new RebaseTodoLine(action, commit, "");
202 return null;
203 }
204
205
206
207
208
209
210
211
212
213
214
215
216
217 public void writeRebaseTodoFile(String path, List<RebaseTodoLine> steps,
218 boolean append) throws IOException {
219 OutputStream fw = new SafeBufferedOutputStream(new FileOutputStream(
220 new File(repo.getDirectory(), path), append));
221 try {
222 StringBuilder sb = new StringBuilder();
223 for (RebaseTodoLine step : steps) {
224 sb.setLength(0);
225 if (RebaseTodoLine.Action.COMMENT.equals(step.action))
226 sb.append(step.getComment());
227 else {
228 sb.append(step.getAction().toToken());
229 sb.append(" ");
230 sb.append(step.getCommit().name());
231 sb.append(" ");
232 sb.append(step.getShortMessage().trim());
233 }
234 sb.append('\n');
235 fw.write(Constants.encode(sb.toString()));
236 }
237 } finally {
238 fw.close();
239 }
240 }
241 }