View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.scm.provider.hg;
20  
21  import java.io.File;
22  
23  import org.apache.maven.scm.ScmException;
24  import org.apache.maven.scm.ScmFileStatus;
25  import org.apache.maven.scm.provider.hg.command.HgCommandConstants;
26  import org.apache.maven.scm.provider.hg.command.HgConsumer;
27  import org.codehaus.plexus.util.cli.Commandline;
28  
29  /**
30   * Check hg installation.
31   *
32   * @author <a href="mailto:thurner.rupert@ymono.net">thurner rupert</a>
33   * @author <a href="mailto:ryan@darksleep.com">ryan daum</a>
34   *
35   */
36  public class HgConfig {
37      // Minimum version for the Hg SCM
38      private static final String HG_REQ = "0.9.2";
39  
40      // The string which indicates the beginning of the Mercurial line
41      private static final String HG_VERSION_TAG = "Mercurial Distributed SCM (version ";
42  
43      // URL to download mercurial from
44      private static final String HG_INSTALL_URL = "'http://www.selenic.com/mercurial/wiki/index.cgi/Download'";
45  
46      // Configuration to check with default values (not installed)
47      private HgVersionConsumer hgVersion = new HgVersionConsumer(null);
48  
49      HgConfig(File workingDir) {
50          try {
51              hgVersion = getHgVersion(workingDir);
52          } catch (ScmException e) {
53              // Ignore -  is not installed.
54              // This is already recorded thus we do not generate more info.
55          }
56      }
57  
58      /**
59       * @return True if one can run basic hg commands
60       */
61      private boolean isInstalled() {
62          return hgVersion.isVersionOk(HG_REQ);
63      }
64  
65      /**
66       * @return True if all modules for hg are installed.
67       */
68      private boolean isComplete() {
69          return isInstalled();
70      }
71  
72      // Consumer to find the Mercurial version
73      public static HgVersionConsumer getHgVersion(File workingDir) throws ScmException {
74          String[] versionCmd = new String[] {HgCommandConstants.VERSION};
75          HgVersionConsumer consumer = new HgVersionConsumer(HG_VERSION_TAG);
76          Commandline cmd = HgUtils.buildCmd(workingDir, versionCmd);
77  
78          // Execute command
79          HgUtils.executeCmd(consumer, cmd);
80  
81          // Return result
82          return consumer;
83      }
84  
85      /**
86       * Iterate through two dot-notation version strings, normalize them to the same length, then
87       * do alphabetic comparison
88       *
89       * @param version1
90       * @param version2
91       * @return true if version2 is greater than version1
92       */
93      private static boolean compareVersion(String version1, String version2) {
94          int l1, l2;
95          String v1, v2;
96  
97          v1 = version1;
98          v2 = version2;
99          l1 = version1.length();
100         l2 = version2.length();
101 
102         if (l1 > l2) {
103             for (int x = l2; x >= l1; x--) {
104                 v2 += ' ';
105             }
106         }
107         if (l2 > l1) {
108             for (int x = l1; x <= l2; x++) {
109                 v1 += ' ';
110             }
111         }
112 
113         return v2.compareTo(v1) >= 0;
114     }
115 
116     /**
117      * Get version of the executable.
118      * Version is resolved by splitting the line starting with the version tag and finding
119      * the second last word.
120      */
121     private static class HgVersionConsumer extends HgConsumer {
122 
123         private String versionStr = "NA";
124 
125         private String versionTag;
126 
127         HgVersionConsumer(String versionTag) {
128             this.versionTag = versionTag;
129         }
130 
131         public void doConsume(ScmFileStatus status, String line) {
132             if (line.startsWith(versionTag)) {
133                 String[] elements = line.split(" ");
134                 versionStr = elements[elements.length - 1].split("\\)")[0];
135             }
136         }
137 
138         String getVersion() {
139             return versionStr;
140         }
141 
142         boolean isVersionOk(String version) {
143             // build one number out of the whole version #
144 
145             return compareVersion(version, versionStr);
146         }
147     }
148 
149     private String getInstalledStr() {
150         if (isComplete()) {
151             return "valid and complete.";
152         }
153         return (isInstalled() ? "incomplete. " : "invalid. ") + "Consult " + HG_INSTALL_URL;
154     }
155 
156     public String toString(File workingDir) {
157         boolean hgOk = hgVersion.isVersionOk(HG_REQ);
158         return "\n  Your Hg installation seems to be " + getInstalledStr() + "\n    Hg version: "
159                 + hgVersion.getVersion() + (hgOk ? " (OK)" : " (May be INVALID)") + "\n";
160     }
161 }