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