Mercurial > jhg
comparison src/org/tmatesoft/hg/repo/ext/MqManager.java @ 480:f3fab7a20841
Refactor LineReader utility as stanalone class to facilitate reuse
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Tue, 17 Jul 2012 22:14:21 +0200 |
parents | 0e34b8f3946a |
children | b3c16d1aede0 |
comparison
equal
deleted
inserted
replaced
479:59b7c817bc4d | 480:f3fab7a20841 |
---|---|
16 */ | 16 */ |
17 package org.tmatesoft.hg.repo.ext; | 17 package org.tmatesoft.hg.repo.ext; |
18 | 18 |
19 import static org.tmatesoft.hg.util.LogFacility.Severity.Warn; | 19 import static org.tmatesoft.hg.util.LogFacility.Severity.Warn; |
20 | 20 |
21 import java.io.BufferedReader; | |
22 import java.io.File; | 21 import java.io.File; |
23 import java.io.FileReader; | |
24 import java.io.IOException; | 22 import java.io.IOException; |
25 import java.util.ArrayList; | 23 import java.util.ArrayList; |
26 import java.util.Collection; | |
27 import java.util.Collections; | 24 import java.util.Collections; |
28 import java.util.HashMap; | 25 import java.util.HashMap; |
29 import java.util.LinkedList; | 26 import java.util.LinkedList; |
30 import java.util.List; | 27 import java.util.List; |
31 import java.util.Map; | 28 import java.util.Map; |
32 | 29 |
33 import org.tmatesoft.hg.core.Nodeid; | 30 import org.tmatesoft.hg.core.Nodeid; |
31 import org.tmatesoft.hg.internal.LineReader; | |
34 import org.tmatesoft.hg.repo.HgInternals; | 32 import org.tmatesoft.hg.repo.HgInternals; |
35 import org.tmatesoft.hg.repo.HgInvalidControlFileException; | 33 import org.tmatesoft.hg.repo.HgInvalidControlFileException; |
36 import org.tmatesoft.hg.repo.HgInvalidFileException; | 34 import org.tmatesoft.hg.repo.HgInvalidFileException; |
37 import org.tmatesoft.hg.repo.HgRepository; | 35 import org.tmatesoft.hg.repo.HgRepository; |
38 import org.tmatesoft.hg.util.LogFacility; | 36 import org.tmatesoft.hg.util.LogFacility; |
69 final LogFacility log = HgInternals.getContext(repo).getLog(); | 67 final LogFacility log = HgInternals.getContext(repo).getLog(); |
70 try { | 68 try { |
71 File queues = new File(repoDir, "patches.queues"); | 69 File queues = new File(repoDir, "patches.queues"); |
72 if (queues.isFile()) { | 70 if (queues.isFile()) { |
73 LineReader lr = new LineReader(queues, log).trimLines(true).skipEmpty(true); | 71 LineReader lr = new LineReader(queues, log).trimLines(true).skipEmpty(true); |
74 lr.read(new SimpleLineCollector(), queueNames = new LinkedList<String>()); | 72 lr.read(new LineReader.SimpleLineCollector(), queueNames = new LinkedList<String>()); |
75 } | 73 } |
76 final String queueLocation; // path under .hg to patch queue information (status, series and diff files) | 74 final String queueLocation; // path under .hg to patch queue information (status, series and diff files) |
77 File activeQueueFile = new File(repoDir, "patches.queue"); | 75 File activeQueueFile = new File(repoDir, "patches.queue"); |
78 // file is there only if it's not default queue ('patches') that is active | 76 // file is there only if it's not default queue ('patches') that is active |
79 if (activeQueueFile.isFile()) { | 77 if (activeQueueFile.isFile()) { |
80 ArrayList<String> contents = new ArrayList<String>(); | 78 ArrayList<String> contents = new ArrayList<String>(); |
81 new LineReader(activeQueueFile, log).read(new SimpleLineCollector(), contents); | 79 new LineReader(activeQueueFile, log).read(new LineReader.SimpleLineCollector(), contents); |
82 if (contents.isEmpty()) { | 80 if (contents.isEmpty()) { |
83 log.dump(getClass(), Warn, "File %s with active queue name is empty", activeQueueFile.getName()); | 81 log.dump(getClass(), Warn, "File %s with active queue name is empty", activeQueueFile.getName()); |
84 activeQueue = PATCHES_DIR; | 82 activeQueue = PATCHES_DIR; |
85 queueLocation = PATCHES_DIR + '/'; | 83 queueLocation = PATCHES_DIR + '/'; |
86 } else { | 84 } else { |
102 } | 100 } |
103 }; | 101 }; |
104 final File fileStatus = new File(repoDir, queueLocation + "status"); | 102 final File fileStatus = new File(repoDir, queueLocation + "status"); |
105 final File fileSeries = new File(repoDir, queueLocation + "series"); | 103 final File fileSeries = new File(repoDir, queueLocation + "series"); |
106 if (fileStatus.isFile()) { | 104 if (fileStatus.isFile()) { |
107 new LineReader(fileStatus, log).read(new LineConsumer<List<PatchRecord>>() { | 105 new LineReader(fileStatus, log).read(new LineReader.LineConsumer<List<PatchRecord>>() { |
108 | 106 |
109 public boolean consume(String line, List<PatchRecord> result) throws IOException { | 107 public boolean consume(String line, List<PatchRecord> result) throws IOException { |
110 int sep = line.indexOf(':'); | 108 int sep = line.indexOf(':'); |
111 if (sep == -1) { | 109 if (sep == -1) { |
112 log.dump(MqManager.class, Warn, "Bad line in %s:%s", fileStatus.getPath(), line); | 110 log.dump(MqManager.class, Warn, "Bad line in %s:%s", fileStatus.getPath(), line); |
123 final Map<String,PatchRecord> name2patch = new HashMap<String, PatchRecord>(); | 121 final Map<String,PatchRecord> name2patch = new HashMap<String, PatchRecord>(); |
124 for (PatchRecord pr : applied) { | 122 for (PatchRecord pr : applied) { |
125 name2patch.put(pr.getName(), pr); | 123 name2patch.put(pr.getName(), pr); |
126 } | 124 } |
127 LinkedList<String> knownPatchNames = new LinkedList<String>(); | 125 LinkedList<String> knownPatchNames = new LinkedList<String>(); |
128 new LineReader(fileSeries, log).read(new SimpleLineCollector(), knownPatchNames); | 126 new LineReader(fileSeries, log).read(new LineReader.SimpleLineCollector(), knownPatchNames); |
129 // XXX read other queues? | 127 // XXX read other queues? |
130 allKnown = new ArrayList<PatchRecord>(knownPatchNames.size()); | 128 allKnown = new ArrayList<PatchRecord>(knownPatchNames.size()); |
131 for (String name : knownPatchNames) { | 129 for (String name : knownPatchNames) { |
132 PatchRecord pr = name2patch.get(name); | 130 PatchRecord pr = name2patch.get(name); |
133 if (pr == null) { | 131 if (pr == null) { |
138 } | 136 } |
139 } catch (HgInvalidFileException ex) { | 137 } catch (HgInvalidFileException ex) { |
140 HgInvalidControlFileException th = new HgInvalidControlFileException(ex.getMessage(), ex.getCause(), ex.getFile()); | 138 HgInvalidControlFileException th = new HgInvalidControlFileException(ex.getMessage(), ex.getCause(), ex.getFile()); |
141 th.setStackTrace(ex.getStackTrace()); | 139 th.setStackTrace(ex.getStackTrace()); |
142 throw th; | 140 throw th; |
143 } | |
144 } | |
145 | |
146 static class SimpleLineCollector implements LineConsumer<Collection<String>> { | |
147 | |
148 public boolean consume(String line, Collection<String> result) throws IOException { | |
149 result.add(line); | |
150 return true; | |
151 } | 141 } |
152 } | 142 } |
153 | 143 |
154 /** | 144 /** |
155 * Number of patches not yet applied | 145 * Number of patches not yet applied |
244 String fmt = "mq.PatchRecord[name:%s; %spath:%s]"; | 234 String fmt = "mq.PatchRecord[name:%s; %spath:%s]"; |
245 String ni = nodeid != null ? String.format("applied as: %s; ", nodeid.shortNotation()) : ""; | 235 String ni = nodeid != null ? String.format("applied as: %s; ", nodeid.shortNotation()) : ""; |
246 return String.format(fmt, name, ni, location); | 236 return String.format(fmt, name, ni, location); |
247 } | 237 } |
248 } | 238 } |
249 | |
250 // TODO refine API and extract into separate classes | |
251 | |
252 interface LineConsumer<T> { | |
253 // boolean begin(File f, T paramObj) throws IOException; | |
254 boolean consume(String line, T paramObj) throws IOException; | |
255 // boolean end(File f, T paramObj) throws IOException; | |
256 } | |
257 | |
258 class LineReader { | |
259 | |
260 private final File file; | |
261 private final LogFacility log; | |
262 private boolean trimLines = true; | |
263 private boolean skipEmpty = true; | |
264 private String ignoreThatStars = null; | |
265 | |
266 LineReader(File f, LogFacility logFacility) { | |
267 file = f; | |
268 log = logFacility; | |
269 } | |
270 | |
271 /** | |
272 * default: <code>true</code> | |
273 * <code>false</code> to return line as is | |
274 */ | |
275 LineReader trimLines(boolean trim) { | |
276 trimLines = trim; | |
277 return this; | |
278 } | |
279 | |
280 /** | |
281 * default: <code>true</code> | |
282 * <code>false</code> to pass empty lines to consumer | |
283 */ | |
284 LineReader skipEmpty(boolean skip) { | |
285 skipEmpty = skip; | |
286 return this; | |
287 } | |
288 | |
289 /** | |
290 * default: doesn't skip any line. | |
291 * set e.g. to "#" or "//" to skip lines that start with such prefix | |
292 */ | |
293 LineReader ignoreLineComments(String lineStart) { | |
294 ignoreThatStars = lineStart; | |
295 return this; | |
296 } | |
297 | |
298 <T> void read(LineConsumer<T> consumer, T paramObj) throws HgInvalidFileException { | |
299 BufferedReader statusFileReader = null; | |
300 try { | |
301 // consumer.begin(file, paramObj); | |
302 statusFileReader = new BufferedReader(new FileReader(file)); | |
303 String line; | |
304 boolean ok = true; | |
305 while (ok && (line = statusFileReader.readLine()) != null) { | |
306 if (trimLines) { | |
307 line = line.trim(); | |
308 } | |
309 if (ignoreThatStars != null && line.startsWith(ignoreThatStars)) { | |
310 continue; | |
311 } | |
312 if (!skipEmpty || line.length() > 0) { | |
313 ok = consumer.consume(line, paramObj); | |
314 } | |
315 } | |
316 } catch (IOException ex) { | |
317 throw new HgInvalidFileException(ex.getMessage(), ex, file); | |
318 } finally { | |
319 try { | |
320 statusFileReader.close(); | |
321 } catch (IOException ex) { | |
322 log.dump(MqManager.class, Warn, ex, null); | |
323 } | |
324 // try { | |
325 // consumer.end(file, paramObj); | |
326 // } catch (IOException ex) { | |
327 // log.warn(MqManager.class, ex, null); | |
328 // } | |
329 } | |
330 } | |
331 } | |
332 } | 239 } |