001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.maven.scm.provider.hg; 020 021import java.io.File; 022 023import org.apache.maven.scm.ScmException; 024import org.apache.maven.scm.ScmFileStatus; 025import org.apache.maven.scm.provider.hg.command.HgCommandConstants; 026import org.apache.maven.scm.provider.hg.command.HgConsumer; 027import org.codehaus.plexus.util.cli.Commandline; 028 029/** 030 * Check hg installation. 031 * 032 * @author <a href="mailto:thurner.rupert@ymono.net">thurner rupert</a> 033 * @author <a href="mailto:ryan@darksleep.com">ryan daum</a> 034 */ 035public class HgConfig { 036 // Minimum version for the Hg SCM 037 private static final String HG_REQ = "0.9.2"; 038 039 // The string which indicates the beginning of the Mercurial line 040 private static final String HG_VERSION_TAG = "Mercurial Distributed SCM (version "; 041 042 // URL to download mercurial from 043 private static final String HG_INSTALL_URL = "'http://www.selenic.com/mercurial/wiki/index.cgi/Download'"; 044 045 // Configuration to check with default values (not installed) 046 private HgVersionConsumer hgVersion = new HgVersionConsumer(null); 047 048 HgConfig(File workingDir) { 049 try { 050 hgVersion = getHgVersion(workingDir); 051 } catch (ScmException e) { 052 // Ignore - is not installed. 053 // This is already recorded thus we do not generate more info. 054 } 055 } 056 057 /** 058 * @return true if one can run basic hg commands 059 */ 060 private boolean isInstalled() { 061 return hgVersion.isVersionOk(HG_REQ); 062 } 063 064 /** 065 * @return true if all modules for hg are installed 066 */ 067 private boolean isComplete() { 068 return isInstalled(); 069 } 070 071 // Consumer to find the Mercurial version 072 public static HgVersionConsumer getHgVersion(File workingDir) throws ScmException { 073 String[] versionCmd = new String[] {HgCommandConstants.VERSION}; 074 HgVersionConsumer consumer = new HgVersionConsumer(HG_VERSION_TAG); 075 Commandline cmd = HgUtils.buildCmd(workingDir, versionCmd); 076 077 // Execute command 078 HgUtils.executeCmd(consumer, cmd); 079 080 // Return result 081 return consumer; 082 } 083 084 /** 085 * Iterate through two dot-notation version strings, normalize them to the same length, then 086 * do alphabetic comparison. 087 * 088 * @param version1 089 * @param version2 090 * @return true if version2 is greater than version1 091 */ 092 private static boolean compareVersion(String version1, String version2) { 093 int l1, l2; 094 String v1, v2; 095 096 v1 = version1; 097 v2 = version2; 098 l1 = version1.length(); 099 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}