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 if (line != null) {
141
142
143 line.setAction(Action.COMMENT);
144
145 line.setComment(commentString);
146 }
147 }
148 } catch (Exception e) {
149
150 line = null;
151 } finally {
152 if (line == null)
153 line = new RebaseTodoLine(commentString);
154 r.add(line);
155 }
156 }
157
158
159
160
161
162
163
164
165
166
167
168 private static int nextParsableToken(byte[] buf, int tokenBegin, int lineEnd) {
169 while (tokenBegin <= lineEnd
170 && (buf[tokenBegin] == ' ' || buf[tokenBegin] == '\t' || buf[tokenBegin] == '\r'))
171 tokenBegin++;
172 if (tokenBegin > lineEnd)
173 return -1;
174 return tokenBegin;
175 }
176
177 private static RebaseTodoLine parseLine(byte[] buf, int tokenBegin,
178 int lineEnd) {
179 RebaseTodoLine.Action action = null;
180 AbbreviatedObjectId commit = null;
181
182 int nextSpace = RawParseUtils.next(buf, tokenBegin, ' ');
183 int tokenCount = 0;
184 while (tokenCount < 3 && nextSpace < lineEnd) {
185 switch (tokenCount) {
186 case 0:
187 String actionToken = new String(buf, tokenBegin,
188 nextSpace - tokenBegin - 1, UTF_8);
189 tokenBegin = nextSpace;
190 action = RebaseTodoLine.Action.parse(actionToken);
191 if (action == null)
192 return null;
193 break;
194 case 1:
195 nextSpace = RawParseUtils.next(buf, tokenBegin, ' ');
196 String commitToken = new String(buf, tokenBegin,
197 nextSpace - tokenBegin - 1, UTF_8);
198 tokenBegin = nextSpace;
199 commit = AbbreviatedObjectId.fromString(commitToken);
200 break;
201 case 2:
202 return new RebaseTodoLine(action, commit,
203 RawParseUtils.decode(buf, tokenBegin, 1 + lineEnd));
204 }
205 tokenCount++;
206 }
207 if (tokenCount == 2)
208 return new RebaseTodoLine(action, commit, "");
209 return null;
210 }
211
212
213
214
215
216
217
218
219
220
221
222
223
224 public void writeRebaseTodoFile(String path, List<RebaseTodoLine> steps,
225 boolean append) throws IOException {
226 try (OutputStream fw = new BufferedOutputStream(new FileOutputStream(
227 new File(repo.getDirectory(), path), append))) {
228 StringBuilder sb = new StringBuilder();
229 for (RebaseTodoLine step : steps) {
230 sb.setLength(0);
231 if (RebaseTodoLine.Action.COMMENT.equals(step.action))
232 sb.append(step.getComment());
233 else {
234 sb.append(step.getAction().toToken());
235 sb.append(" ");
236 sb.append(step.getCommit().name());
237 sb.append(" ");
238 sb.append(step.getShortMessage().trim());
239 }
240 sb.append('\n');
241 fw.write(Constants.encode(sb.toString()));
242 }
243 }
244 }
245 }