001package org.apache.maven.scm.provider.perforce.command;
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
022import org.apache.maven.scm.log.ScmLogger;
023import org.apache.maven.scm.provider.perforce.PerforceScmProvider;
024import org.apache.maven.scm.provider.perforce.repository.PerforceScmProviderRepository;
025import org.codehaus.plexus.util.IOUtil;
026import org.codehaus.plexus.util.cli.CommandLineException;
027import org.codehaus.plexus.util.cli.Commandline;
028
029import java.io.BufferedReader;
030import java.io.File;
031import java.io.IOException;
032import java.io.InputStreamReader;
033
034/**
035 * Encapsulates the 'p4 where' command which can be very useful in determining
036 * a file's location within the depot.  Use <code>getDepotLocation(String path)</code> to query
037 * the depot location for a particular file.  The data from p4 where looks like this:
038 * <p/>
039 * <pre>
040 * p4 where pom.xml
041 * //depot/modules/fabric/trunk/pom.xml //mikeperham-dt/depot/modules/fabric/trunk/pom.xml
042 * d:\perforce\depot\modules\fabric\trunk\pom.xml
043 * </pre>
044 *
045 * @author mperham
046 * @version $Id: $
047 */
048public class PerforceWhereCommand
049{
050    private ScmLogger logger = null;
051
052    private PerforceScmProviderRepository repo = null;
053
054    public PerforceWhereCommand( ScmLogger log, PerforceScmProviderRepository repos )
055    {
056        logger = log;
057        repo = repos;
058    }
059
060    public String getDepotLocation( File file )
061    {
062        return getDepotLocation( file.getAbsolutePath() );
063    }
064
065    /**
066     * @param filepath an absolute file path
067     * @return the absolute location of the given file within the Perforce repository or null if the file
068     *         does not exist in a mapping within the current clientspec.
069     */
070    public String getDepotLocation( String filepath )
071    {
072        if ( !PerforceScmProvider.isLive() )
073        {
074            return null;
075        }
076
077        InputStreamReader isReader = null;
078        InputStreamReader isReaderErr = null;
079        try
080        {
081            Commandline command = PerforceScmProvider.createP4Command( repo, null );
082            command.createArg().setValue( "where" );
083            command.createArg().setValue( filepath );
084            if ( logger.isDebugEnabled() )
085            {
086                logger.debug( PerforceScmProvider.clean( "Executing: " + command.toString() ) );
087            }
088            Process proc = command.execute();
089            isReader = new InputStreamReader( proc.getInputStream() );
090            isReaderErr = new InputStreamReader( proc.getErrorStream() );
091            BufferedReader br = new BufferedReader( isReader );
092            BufferedReader brErr = new BufferedReader( isReaderErr );
093            String line;
094            String path = null;
095            while ( ( line = br.readLine() ) != null )
096            {
097                if ( line.indexOf( "not in client view" ) != -1 )
098                {
099                    // uh oh, something bad is happening
100                    if ( logger.isErrorEnabled() )
101                    {
102                        logger.error( line );
103                    }
104                    return null;
105                }
106                if ( line.indexOf( "is not under" ) != -1 )
107                {
108                    // uh oh, something bad is happening
109                    if ( logger.isErrorEnabled() )
110                    {
111                        logger.error( line );
112                    }
113                    return null;
114                }
115
116                if ( logger.isDebugEnabled() )
117                {
118                    logger.debug( line );
119                }
120                // verify that "//" appears twice in the line
121                path = line.substring( 0, line.lastIndexOf( "//" ) - 1 );
122            }
123            // Check for errors
124            while ( ( line = brErr.readLine() ) != null )
125            {
126                if ( line.indexOf( "not in client view" ) != -1 )
127                {
128                    // uh oh, something bad is happening
129                    if ( logger.isErrorEnabled() )
130                    {
131                        logger.error( line );
132                    }
133                    return null;
134                }
135                if ( line.indexOf( "is not under" ) != -1 )
136                {
137                    // uh oh, something bad is happening
138                    if ( logger.isErrorEnabled() )
139                    {
140                        logger.error( line );
141                    }
142                    return null;
143                }
144
145                if ( logger.isDebugEnabled() )
146                {
147                    logger.debug( line );
148                }
149            }
150
151            return path;
152        }
153        catch ( CommandLineException e )
154        {
155            if ( logger.isErrorEnabled() )
156            {
157                logger.error( e );
158            }
159            throw new RuntimeException( e.getLocalizedMessage() );
160        }
161        catch ( IOException e )
162        {
163            if ( logger.isErrorEnabled() )
164            {
165                logger.error( e );
166            }
167            throw new RuntimeException( e.getLocalizedMessage() );
168        }
169        finally
170        {
171            IOUtil.close( isReader );
172            IOUtil.close( isReaderErr );
173        }
174    }
175}