1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package net.sf.statsvn.input;
24
25 import java.io.BufferedReader;
26 import java.io.FileReader;
27 import java.io.IOException;
28 import java.util.Vector;
29
30 import net.sf.statcvs.input.LogSyntaxException;
31 import net.sf.statcvs.input.NoLineCountException;
32 import net.sf.statcvs.util.FileUtils;
33 import net.sf.statsvn.output.SvnConfigurationOptions;
34 import net.sf.statsvn.util.BinaryDiffException;
35 import net.sf.statsvn.util.ISvnDiffProcessor;
36 import net.sf.statsvn.util.ISvnInfoProcessor;
37 import net.sf.statsvn.util.ISvnProcessor;
38 import net.sf.statsvn.util.ISvnPropgetProcessor;
39 import net.sf.statsvn.util.ISvnVersionProcessor;
40
41 /**
42 * Manages a checked-out repository and provides access to line number counts
43 * for repository files.
44 *
45 * New in StatSVN: Also provides a central point of access to abstract out calls
46 * to the server. Many of the methods here simply redirect to the static
47 * util/SvnXXXUtils classes. Therefore, clients don't have to know where the
48 * information is located, they can simply invoke this class.
49 *
50 * @author Manuel Schulze
51 * @author Steffen Pingel
52 * @author Jason Kealey <jkealey@shade.ca>
53 *
54 * @version $Id: RepositoryFileManager.java 394 2009-08-10 20:08:46Z jkealey $
55 */
56 public class RepositoryFileManager {
57 private final String path;
58
59 /**
60 * Creates a new instance with root at <code>pathName</code>.
61 *
62 * @param pathName
63 * the root of the checked out repository
64 */
65 public RepositoryFileManager(final String pathName) {
66 path = pathName;
67 }
68
69 /**
70 * Converts an absolute path in the repository to a URL, using the
71 * repository URL
72 *
73 * @param absolute
74 * Example: /trunk/statsvn/package.html
75 * @return Example: svn://svn.statsvn.org/statsvn/trunk/statsvn/package.html
76 */
77 public String absolutePathToUrl(final String absolute) {
78 return getInfoProcessor().absolutePathToUrl(absolute);
79 }
80
81 /**
82 * Converts an absolute path in the repository to a path relative to the
83 * working folder root.
84 *
85 * Will return null if absolute path does not start with getModuleName();
86 *
87 * @param absolute
88 * Example (assume getModuleName() returns /trunk/statsvn)
89 * /trunk/statsvn/package.html
90 * @return Example: package.html
91 */
92 public String absoluteToRelativePath(final String stringData) {
93 return getInfoProcessor().absoluteToRelativePath(stringData);
94 }
95
96 /**
97 * Adds a directory to the list of known directories. Used when inferring
98 * implicit actions on deleted paths.
99 *
100 * @param relativePath
101 * the relative path.
102 */
103 public void addDirectory(final String relativePath) {
104 getInfoProcessor().addDirectory(relativePath);
105 }
106
107 /**
108 * Returns true if the file exists in the working copy (according to the svn
109 * metadata, and not file system checks).
110 *
111 * @param relativePath
112 * the path
113 * @return <tt>true</tt> if it exists
114 */
115 public boolean existsInWorkingCopy(final String relativePath) {
116 return getInfoProcessor().existsInWorkingCopy(relativePath);
117 }
118
119 /**
120 * Counts lines on a BufferedReader
121 *
122 * @param reader
123 * the buffered reader
124 * @return the number of lines read
125 * @throws IOException
126 * error reading from reader
127 */
128 protected int getLineCount(final BufferedReader reader) throws IOException {
129 int linecount = 0;
130 while (reader.readLine() != null) {
131 linecount++;
132 }
133 return linecount;
134 }
135
136 /**
137 * Returns line count differences between two revisions of a file.
138 *
139 * @param oldRevNr
140 * old revision number
141 * @param newRevNr
142 * new revision number
143 * @param filename
144 * the filename
145 * @return A int[2] array of [lines added, lines removed] is returned.
146 * @throws IOException
147 * problem parsing the stream
148 * @throws BinaryDiffException
149 * if the error message is due to trying to diff binary files.
150 *
151 */
152 public int[] getLineDiff(final String oldRevNr, final String newRevNr, final String filename) throws IOException, BinaryDiffException {
153
154 return getDiffProcessor().getLineDiff(oldRevNr, newRevNr, filename);
155 }
156
157 /**
158 * Returns line count differences for all files in a particular revision.
159 *
160 * @param newRevNr
161 * new revision number
162 * @return A vector of object[3] array of [filename, int[2](lines added, lines removed), isBinary] is returned.
163 * @throws IOException
164 * problem parsing the stream
165 * @throws BinaryDiffException
166 * if the error message is due to trying to diff binary files.
167 */
168 public Vector getRevisionDiff(final String newRevNr) throws IOException, BinaryDiffException {
169 return getDiffProcessor().getLineDiff(newRevNr);
170 }
171
172 /**
173 * Returns the lines of code for a repository file. (Currently checked out
174 * version)
175 *
176 * @param filename
177 * a file in the repository
178 * @return the lines of code for a repository file
179 * @throws NoLineCountException
180 * when the line count could not be retrieved, for example when
181 * the file was not found.
182 */
183 public int getLinesOfCode(final String filename) throws NoLineCountException {
184 final String absoluteName = FileUtils.getAbsoluteName(this.path, filename);
185 try {
186 final FileReader freader = new FileReader(absoluteName);
187 final BufferedReader reader = new BufferedReader(freader);
188 final int linecount = getLineCount(reader);
189 SvnConfigurationOptions.getTaskLogger().log("line count for '" + absoluteName + "': " + linecount);
190 freader.close();
191 return linecount;
192 } catch (final IOException e) {
193 throw new NoLineCountException("could not get line count for '" + absoluteName + "': " + e);
194 }
195 }
196
197 /**
198 * Assumes #loadInfo(String) has been called. Never ends with /, might be
199 * empty.
200 *
201 * @return The absolute path of the root of the working folder in the
202 * repository.
203 */
204 public String getModuleName() {
205 return getInfoProcessor().getModuleName();
206 }
207
208 /**
209 * Assumes #loadInfo(String) has been called.
210 *
211 * @return The uuid of the repository.
212 */
213 public String getRepositoryUuid() {
214 return getInfoProcessor().getRepositoryUuid();
215 }
216
217 /**
218 * Returns the revision of filename in the local working directory by
219 * reading the svn metadata.
220 *
221 * @param filename
222 * the filename
223 * @return the revision of filename
224 */
225 public String getRevision(final String filename) throws IOException {
226 final String rev = getInfoProcessor().getRevisionNumber(filename);
227 if (rev != null) {
228 return rev;
229 } else if (getInfoProcessor().isDirectory(filename)) {
230 return null;
231 } else {
232 throw new IOException("File " + filename + " has no revision");
233 }
234 }
235
236 /**
237 * Assumes #loadInfo(String) has been called.
238 *
239 * @return the revision number of the root of the working folder
240 * (last checked out revision number)
241 */
242 public String getRootRevisionNumber() {
243 return getInfoProcessor().getRootRevisionNumber();
244 }
245
246 /**
247 * Is the given path a binary file in the <b>working</b> directory?
248 *
249 * @param relativePath
250 * the directory
251 * @return true if it is marked as a binary file
252 */
253 public boolean isBinary(final String relativePath) {
254 return getPropgetProcessor().getBinaryFiles().contains(relativePath);
255 }
256
257 /**
258 * Returns true if the path has been identified as a directory.
259 *
260 * @param relativePath
261 * the path
262 * @return true if it is a known directory.
263 */
264 public boolean isDirectory(final String relativePath) {
265 return getInfoProcessor().isDirectory(relativePath);
266 }
267
268 /**
269 * Initializes our representation of the repository.
270 *
271 * @throws LogSyntaxException
272 * if the svn info --xml is malformed
273 * @throws IOException
274 * if there is an error reading from the stream
275 */
276 public void loadInfo() throws LogSyntaxException, IOException {
277 getInfoProcessor().loadInfo();
278 }
279
280 /**
281 * Converts a relative path in the working folder to a URL, using the
282 * working folder's root URL
283 *
284 * @param relative
285 * Example: src/Messages.java
286 * @return Example:
287 * svn://svn.statsvn.org/statsvn/trunk/statsvn/src/Messages.java
288 *
289 */
290 public String relativePathToUrl(final String relative) {
291 return getInfoProcessor().relativePathToUrl(relative);
292 }
293
294 /**
295 * Converts a relative path in the working folder to an absolute path in the
296 * repository.
297 *
298 * @param relative
299 * Example: src/Messages.java
300 * @return Example: /trunk/statsvn/src/Messages.java
301 *
302 */
303 public String relativeToAbsolutePath(final String relative) {
304 return getInfoProcessor().relativeToAbsolutePath(relative);
305 }
306
307 /**
308 * Converts a url to an absolute path in the repository.
309 *
310 * @param url
311 * Examples: svn://svn.statsvn.org/statsvn/trunk/statsvn,
312 * svn://svn.statsvn.org/statsvn/trunk/statsvn/package.html
313 * @return Example: /trunk/statsvn, /trunk/statsvn/package.html
314 */
315 public String urlToAbsolutePath(final String url) {
316 return getInfoProcessor().urlToAbsolutePath(url);
317 }
318
319 /**
320 * Converts a url to a relative path in the repository.
321 *
322 * @param url
323 * Examples: svn://svn.statsvn.org/statsvn/trunk/statsvn,
324 * svn://svn.statsvn.org/statsvn/trunk/statsvn/package.html
325 * @return Example: ".", package.html
326 */
327 public String urlToRelativePath(final String url) {
328 return getInfoProcessor().urlToRelativePath(url);
329 }
330
331 private ISvnProcessor svnProcessor;
332 public ISvnProcessor getProcessor()
333 {
334 if (svnProcessor==null) svnProcessor = SvnConfigurationOptions.getProcessor();
335 return svnProcessor;
336 }
337
338 protected ISvnDiffProcessor getDiffProcessor()
339 {
340 return getProcessor().getDiffProcessor();
341 }
342
343 protected ISvnInfoProcessor getInfoProcessor()
344 {
345 return getProcessor().getInfoProcessor();
346 }
347 protected ISvnPropgetProcessor getPropgetProcessor()
348 {
349 return getProcessor().getPropgetProcessor();
350 }
351 protected ISvnVersionProcessor getVersionProcessor()
352 {
353 return getProcessor().getVersionProcessor();
354 }
355 }