001    package org.apache.maven.scm.provider.hg;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     * http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    import org.apache.maven.scm.ScmException;
023    import org.apache.maven.scm.ScmFileStatus;
024    import org.apache.maven.scm.log.DefaultLog;
025    import org.apache.maven.scm.provider.hg.command.HgCommandConstants;
026    import org.apache.maven.scm.provider.hg.command.HgConsumer;
027    import org.codehaus.plexus.util.cli.Commandline;
028    
029    import java.io.File;
030    
031    /**
032     * Check hg installation.
033     *
034     * @author <a href="mailto:thurner.rupert@ymono.net">thurner rupert</a>
035     * @author <a href="mailto:ryan@darksleep.com">ryan daum</a>
036     * @version $Id: HgConfig.java 686566 2008-08-16 21:52:46Z olamy $
037     */
038    public class HgConfig
039    {
040        //Minimum version for the Hg SCM
041        private static final String HG_REQ = "0.9.2";
042    
043        // The string which indicates the beginning of the Mercurial line
044        private static final String HG_VERSION_TAG = "ercurial Distributed SCM (version ";
045    
046        // URL to download mercurial from
047        private static final String HG_INSTALL_URL = "'http://www.selenic.com/mercurial/wiki/index.cgi/Download'";
048    
049        //Configuration to check with default values (not installed)
050        private HgVersionConsumer hgVersion = new HgVersionConsumer( null );
051    
052        HgConfig( File workingDir )
053        {
054            try
055            {
056                hgVersion = getHgVersion( workingDir );
057            }
058            catch ( ScmException e )
059            {
060                //Ignore -  is not installed.
061                //This is already recorded thus we do not generate more info.
062            }
063    
064        }
065    
066        /**
067         * @return True if one can run basic hg commands
068         */
069        private boolean isInstalled()
070        {
071            return hgVersion.isVersionOk( HG_REQ );
072        }
073    
074        /**
075         * @return True if all modules for hg are installed.
076         */
077        private boolean isComplete()
078        {
079            return isInstalled();
080        }
081    
082        // Consumer to find the Mercurial version
083        public static HgVersionConsumer getHgVersion( File workingDir )
084            throws ScmException
085        {
086            String[] versionCmd = new String[]{HgCommandConstants.VERSION};
087            HgVersionConsumer consumer = new HgVersionConsumer( HG_VERSION_TAG );
088            Commandline cmd = HgUtils.buildCmd( workingDir, versionCmd );
089    
090            // Execute command
091            HgUtils.executeCmd( consumer, cmd );
092    
093            // Return result
094            return consumer;
095        }
096    
097    
098        /**
099         * Iterate through two dot-notation version strings, normalize them to the same length, then
100         * do alphabetic comparison
101         *
102         * @param version1
103         * @param version2
104         * @return true if version2 is greater than version1
105         */
106        private static boolean compareVersion( String version1, String version2 )
107        {
108            int l1, l2;
109            String v1, v2;
110    
111            v1 = version1;
112            v2 = version2;
113            l1 = version1.length();
114            l2 = version2.length();
115    
116            if ( l1 > l2 )
117            {
118                for ( int x = l2; x >= l1; x-- )
119                {
120                    v2 += ' ';
121                }
122            }
123            if ( l2 > l1 )
124            {
125                for ( int x = l1; x <= l2; x++ )
126                {
127                    v1 += ' ';
128                }
129            }
130    
131            return v2.compareTo( v1 ) >= 0;
132        }
133    
134    
135        /**
136         * Get version of the executable.
137         * Version is resolved by splitting the line starting with the version tag and finding
138         * the second last word.
139         */
140        private static class HgVersionConsumer
141            extends HgConsumer
142        {
143    
144            private String versionStr = "NA";
145    
146            private String versionTag;
147    
148            HgVersionConsumer( String versionTag )
149            {
150                super( new DefaultLog() );
151                this.versionTag = versionTag;
152            }
153    
154            public void doConsume( ScmFileStatus status, String line )
155            {
156                if ( line.startsWith( versionTag ) )
157                {
158                    String[] elements = line.split( " " );
159                    versionStr = elements[elements.length - 1].split( "\\)" )[0];
160                }
161            }
162    
163            String getVersion()
164            {
165                return versionStr;
166            }
167    
168            boolean isVersionOk( String version )
169            {
170                // build one number out of the whole version #
171    
172                return compareVersion( version, versionStr );
173            }
174        }
175    
176        private String getInstalledStr()
177        {
178            if ( isComplete() )
179            {
180                return "valid and complete.";
181            }
182            return ( isInstalled() ? "incomplete. " : "invalid. " ) + "Consult " + HG_INSTALL_URL;
183        }
184    
185        public String toString( File workingDir )
186        {
187            boolean hgOk = hgVersion.isVersionOk( HG_REQ );
188            return "\n  Your Hg installation seems to be " + getInstalledStr() + "\n    Hg version: "
189                + hgVersion.getVersion() + ( hgOk ? " (OK)" : " (May be INVALID)" ) + "\n";
190        }
191    }