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