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  public class HgConfig {
36      // Minimum version for the Hg SCM
37      private static final String HG_REQ = "0.9.2";
38  
39      // The string which indicates the beginning of the Mercurial line
40      private static final String HG_VERSION_TAG = "Mercurial Distributed SCM (version ";
41  
42      // URL to download mercurial from
43      private static final String HG_INSTALL_URL = "'http://www.selenic.com/mercurial/wiki/index.cgi/Download'";
44  
45      // Configuration to check with default values (not installed)
46      private HgVersionConsumer hgVersion = new HgVersionConsumer(null);
47  
48      HgConfig(File workingDir) {
49          try {
50              hgVersion = getHgVersion(workingDir);
51          } catch (ScmException e) {
52              // Ignore -  is not installed.
53              // This is already recorded thus we do not generate more info.
54          }
55      }
56  
57      /**
58       * @return true if one can run basic hg commands
59       */
60      private boolean isInstalled() {
61          return hgVersion.isVersionOk(HG_REQ);
62      }
63  
64      /**
65       * @return true if all modules for hg are installed
66       */
67      private boolean isComplete() {
68          return isInstalled();
69      }
70  
71      // Consumer to find the Mercurial version
72      public static HgVersionConsumer getHgVersion(File workingDir) throws ScmException {
73          String[] versionCmd = new String[] {HgCommandConstants.VERSION};
74          HgVersionConsumer consumer = new HgVersionConsumer(HG_VERSION_TAG);
75          Commandline cmd = HgUtils.buildCmd(workingDir, versionCmd);
76  
77          // Execute command
78          HgUtils.executeCmd(consumer, cmd);
79  
80          // Return result
81          return consumer;
82      }
83  
84      /**
85       * Iterate through two dot-notation version strings, normalize them to the same length, then
86       * do alphabetic comparison.
87       *
88       * @param version1
89       * @param version2
90       * @return true if version2 is greater than version1
91       */
92      private static boolean compareVersion(String version1, String version2) {
93          int l1, l2;
94          String v1, v2;
95  
96          v1 = version1;
97          v2 = version2;
98          l1 = version1.length();
99          l2 = version2.length();
100 
101         if (l1 > l2) {
102             for (int x = l2; x >= l1; x--) {
103                 v2 += ' ';
104             }
105         }
106         if (l2 > l1) {
107             for (int x = l1; x <= l2; x++) {
108                 v1 += ' ';
109             }
110         }
111 
112         return v2.compareTo(v1) >= 0;
113     }
114 
115     /**
116      * Get version of the executable.
117      * Version is resolved by splitting the line starting with the version tag and finding
118      * the second last word.
119      */
120     private static class HgVersionConsumer extends HgConsumer {
121 
122         private String versionStr = "NA";
123 
124         private String versionTag;
125 
126         HgVersionConsumer(String versionTag) {
127             this.versionTag = versionTag;
128         }
129 
130         public void doConsume(ScmFileStatus status, String line) {
131             if (line.startsWith(versionTag)) {
132                 String[] elements = line.split(" ");
133                 versionStr = elements[elements.length - 1].split("\\)")[0];
134             }
135         }
136 
137         String getVersion() {
138             return versionStr;
139         }
140 
141         boolean isVersionOk(String version) {
142             // build one number out of the whole version #
143 
144             return compareVersion(version, versionStr);
145         }
146     }
147 
148     private String getInstalledStr() {
149         if (isComplete()) {
150             return "valid and complete.";
151         }
152         return (isInstalled() ? "incomplete. " : "invalid. ") + "Consult " + HG_INSTALL_URL;
153     }
154 
155     public String toString(File workingDir) {
156         boolean hgOk = hgVersion.isVersionOk(HG_REQ);
157         return "\n  Your Hg installation seems to be " + getInstalledStr() + "\n    Hg version: "
158                 + hgVersion.getVersion() + (hgOk ? " (OK)" : " (May be INVALID)") + "\n";
159     }
160 }