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.statcvs.util;
24
25 /**
26 * Utility class containing various methods related to CVS logfile parsing
27 *
28 * @author Richard Cyganiak <rcyg@gmx.de>
29 * @version $Id: CvsLogUtils.java,v 1.5 2008/04/02 11:22:15 benoitx Exp $
30 */
31 public class CvsLogUtils {
32
33 /**
34 * <p>Determines if a file is in the attic by comparing the location of
35 * the RCS file and the working file.</p>
36 *
37 * <p>The RCS file is the file containing the version history.
38 * It is located in the CVSROOT directory of the repository.
39 * It's name ends in ",v". The filename is absoulte.</p>
40 *
41 * <p>The working filename is the actual filename relative to the
42 * root of the checked-out module.</p>
43 *
44 * <p>A file is said to be in the attic if and only if it is dead
45 * on the main branch. If a file is in the attic, it's RCS file is
46 * moved to a subdirectory called "Attic". This method checks if
47 * the RCS file is in the "Attic" subdirectory.
48 *
49 * @param rcsFilename a version-controlled file's RCS filename
50 * @param workingFilename a version-controlled file's working filename
51 * @return <tt>true</tt> if the file is in the attic
52 */
53 public static boolean isInAttic(final String rcsFilename, final String workingFilename) {
54 final int lastDelim = workingFilename.lastIndexOf("/");
55 final String filename = workingFilename.substring(lastDelim + 1, workingFilename.length());
56
57 final int rcsPathLength = rcsFilename.length() - filename.length() - 2;
58 final String rcsPath = rcsFilename.substring(0, rcsPathLength);
59 return rcsPath.endsWith("/Attic/");
60 }
61
62 /**
63 * Returns <code>true</code> if this revision is part of the main branch,
64 * and <code>false</code> if it is part of a side branch. Revisions
65 * like 1.1 and 5.212 are on the main branch, 1.1.1.1 and 1.4.2.13 and
66 * 1.4.2.13.4.1 are on side branches.
67 * @param revisionNumber the revision's number, for example "1.1"
68 * @return <code>true</code> if this revision is part of the main branch.
69 */
70 public static boolean isOnMainBranch(final String revisionNumber) {
71 int index = 0;
72 int dotCount = 0;
73 while (revisionNumber.indexOf('.', index) != -1) {
74 index = revisionNumber.indexOf('.', index) + 1;
75 dotCount++;
76 }
77 return (dotCount == 1);
78 }
79
80 /**
81 * Determines the module name by comparing the RCS filename and
82 * the working filename.
83 * @param rcsFilename a version-controlled file's RCS filename
84 * @param workingFilename a version-controlled file's working filename
85 * @return the module name
86 */
87 public static String getModuleName(final String rcsFilename, final String workingFilename) {
88 int localLenght = workingFilename.length() + ",v".length();
89 if (CvsLogUtils.isInAttic(rcsFilename, workingFilename)) {
90 localLenght += "/Attic".length();
91 }
92 final String cvsroot = rcsFilename.substring(0, rcsFilename.length() - localLenght - 1);
93 final int lastSlash = cvsroot.lastIndexOf("/");
94 if (lastSlash == -1) {
95 return "";
96 }
97 return cvsroot.substring(lastSlash + 1);
98 }
99
100 /**
101 * Returns <tt>true</tt> if files with a given keyword substitution
102 * should be treated as binary files. That is, they should be assumed
103 * to be 0 lines of code. Possible values are the same as for the -kXXX
104 * option of CVS (for example, kv, kvl, b).
105 * @param kws the keyword substitution, as of CVS option -kXXX
106 * @return <tt>true</tt> if this is a binary keyword substitution
107 * @throws IllegalArgumentException if <tt>kws</tt> is not a known keyword substitution
108 */
109 public static boolean isBinaryKeywordSubst(final String kws) {
110 if ("kv".equals(kws)) {
111 return false;
112 }
113 if ("kvl".equals(kws)) {
114 return false;
115 }
116 if ("k".equals(kws)) {
117 return false;
118 }
119 if ("o".equals(kws)) {
120 return false;
121 }
122 if ("b".equals(kws)) {
123 return true;
124 }
125 if ("v".equals(kws)) {
126 return false;
127 }
128 if ("u".equals(kws)) {
129 return false;
130 }
131 throw new IllegalArgumentException("unknown keyword substitution: " + kws);
132 }
133 }