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