comparison src/org/tmatesoft/hg/core/HgManifestCommand.java @ 131:aa1629f36482

Renamed .core classes to start with Hg prefix
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Wed, 16 Feb 2011 20:47:56 +0100
parents src/org/tmatesoft/hg/core/RepositoryTreeWalker.java@4f509f5bc8cb
children 6778075cd2b4
comparison
equal deleted inserted replaced
130:7567f4a42fe5 131:aa1629f36482
1 /*
2 * Copyright (c) 2011 TMate Software Ltd
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * For information on how to redistribute this software under
14 * the terms of a license other than GNU General Public License
15 * contact TMate Software at support@hg4j.com
16 */
17 package org.tmatesoft.hg.core;
18
19 import static org.tmatesoft.hg.repo.HgRepository.TIP;
20
21 import java.util.ConcurrentModificationException;
22 import java.util.LinkedHashMap;
23 import java.util.LinkedList;
24 import java.util.List;
25
26 import org.tmatesoft.hg.core.HgLogCommand.FileRevision;
27 import org.tmatesoft.hg.repo.HgManifest;
28 import org.tmatesoft.hg.repo.HgRepository;
29 import org.tmatesoft.hg.util.PathPool;
30
31
32 /**
33 * Gives access to list of files in each revision (Mercurial manifest information), 'hg manifest' counterpart.
34 *
35 * @author Artem Tikhomirov
36 * @author TMate Software Ltd.
37 */
38 public class HgManifestCommand {
39
40 private final HgRepository repo;
41 private Path.Matcher matcher;
42 private int startRev = 0, endRev = TIP;
43 private Handler visitor;
44 private boolean needDirs = false;
45
46 private final Mediator mediator = new Mediator();
47
48 public HgManifestCommand(HgRepository hgRepo) {
49 repo = hgRepo;
50 }
51
52 public HgManifestCommand range(int rev1, int rev2) {
53 // if manifest range is different from that of changelog, need conversion utils (external?)
54 throw HgRepository.notImplemented();
55 }
56
57 public HgManifestCommand revision(int rev) {
58 startRev = endRev = rev;
59 return this;
60 }
61
62 public HgManifestCommand dirs(boolean include) {
63 // XXX whether directories with directories only are include or not
64 // now lists only directories with files
65 needDirs = include;
66 return this;
67 }
68
69 /**
70 * Limit manifest walk to a subset of files.
71 * @param pathMatcher - filter, pass <code>null</code> to clear.
72 * @return <code>this</code> instance for convenience
73 */
74 public HgManifestCommand match(Path.Matcher pathMatcher) {
75 matcher = pathMatcher;
76 return this;
77 }
78
79 public void walk(Handler handler) {
80 if (handler == null) {
81 throw new IllegalArgumentException();
82 }
83 if (visitor != null) {
84 throw new ConcurrentModificationException();
85 }
86 try {
87 visitor = handler;
88 mediator.start();
89 repo.getManifest().walk(startRev, endRev, mediator);
90 } finally {
91 mediator.done();
92 visitor = null;
93 }
94 }
95
96 /**
97 * Callback to walk file/directory tree of a revision
98 */
99 public interface Handler {
100 void begin(Nodeid manifestRevision);
101 void dir(Path p); // optionally invoked (if walker was configured to spit out directories) prior to any files from this dir and subdirs
102 void file(FileRevision fileRevision); // XXX allow to check p is invalid (df.exists())
103 void end(Nodeid manifestRevision);
104 }
105
106 // I'd rather let RepositoryTreeWalker implement HgManifest.Inspector directly, but this pollutes API alot
107 private class Mediator implements HgManifest.Inspector {
108 private PathPool pathPool;
109 private List<FileRevision> manifestContent;
110 private Nodeid manifestNodeid;
111
112 public void start() {
113 pathPool = new PathPool(repo.getPathHelper());
114 }
115
116 public void done() {
117 manifestContent = null;
118 pathPool = null;
119 }
120
121 public boolean begin(int revision, Nodeid nid) {
122 if (needDirs && manifestContent == null) {
123 manifestContent = new LinkedList<FileRevision>();
124 }
125 visitor.begin(manifestNodeid = nid);
126 return true;
127 }
128 public boolean end(int revision) {
129 if (needDirs) {
130 LinkedHashMap<Path, LinkedList<FileRevision>> breakDown = new LinkedHashMap<Path, LinkedList<FileRevision>>();
131 for (FileRevision fr : manifestContent) {
132 Path filePath = fr.getPath();
133 Path dirPath = pathPool.parent(filePath);
134 LinkedList<FileRevision> revs = breakDown.get(dirPath);
135 if (revs == null) {
136 revs = new LinkedList<FileRevision>();
137 breakDown.put(dirPath, revs);
138 }
139 revs.addLast(fr);
140 }
141 for (Path dir : breakDown.keySet()) {
142 visitor.dir(dir);
143 for (FileRevision fr : breakDown.get(dir)) {
144 visitor.file(fr);
145 }
146 }
147 manifestContent.clear();
148 }
149 visitor.end(manifestNodeid);
150 manifestNodeid = null;
151 return true;
152 }
153 public boolean next(Nodeid nid, String fname, String flags) {
154 Path p = pathPool.path(fname);
155 if (matcher != null && !matcher.accept(p)) {
156 return true;
157 }
158 FileRevision fr = new FileRevision(repo, nid, p);
159 if (needDirs) {
160 manifestContent.add(fr);
161 } else {
162 visitor.file(fr);
163 }
164 return true;
165 }
166 }
167 }