001package org.apache.maven.scm.provider.git;
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 java.io.File;
023import java.util.ArrayList;
024import java.util.List;
025
026import org.apache.maven.scm.CommandParameters;
027import org.apache.maven.scm.ScmException;
028import org.apache.maven.scm.ScmFileSet;
029import org.apache.maven.scm.ScmResult;
030import org.apache.maven.scm.command.add.AddScmResult;
031import org.apache.maven.scm.command.blame.BlameScmResult;
032import org.apache.maven.scm.command.branch.BranchScmResult;
033import org.apache.maven.scm.command.changelog.ChangeLogScmResult;
034import org.apache.maven.scm.command.checkin.CheckInScmResult;
035import org.apache.maven.scm.command.checkout.CheckOutScmResult;
036import org.apache.maven.scm.command.diff.DiffScmResult;
037import org.apache.maven.scm.command.export.ExportScmResult;
038import org.apache.maven.scm.command.info.InfoScmResult;
039import org.apache.maven.scm.command.remoteinfo.RemoteInfoScmResult;
040import org.apache.maven.scm.command.remove.RemoveScmResult;
041import org.apache.maven.scm.command.status.StatusScmResult;
042import org.apache.maven.scm.command.tag.TagScmResult;
043import org.apache.maven.scm.command.update.UpdateScmResult;
044import org.apache.maven.scm.provider.AbstractScmProvider;
045import org.apache.maven.scm.provider.ScmProviderRepository;
046import org.apache.maven.scm.provider.git.command.GitCommand;
047import org.apache.maven.scm.provider.git.repository.GitScmProviderRepository;
048import org.apache.maven.scm.repository.ScmRepositoryException;
049import org.apache.maven.scm.repository.UnknownRepositoryStructure;
050
051/**
052 * SCM Provider for git
053 *
054 *
055 * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
056 *
057 */
058public abstract class AbstractGitScmProvider
059    extends AbstractScmProvider
060{
061
062    // ----------------------------------------------------------------------
063    //
064    // ----------------------------------------------------------------------
065
066    /**
067     * Internal class
068     */
069    private static class ScmUrlParserResult
070    {
071        private List<String> messages = new ArrayList<String>();
072
073        private ScmProviderRepository repository;
074    }
075
076    // ----------------------------------------------------------------------
077    // ScmProvider Implementation
078    // ----------------------------------------------------------------------
079
080    /** {@inheritDoc} */
081    public String getScmSpecificFilename()
082    {
083        return ".git";
084    }
085
086    /** {@inheritDoc} */
087    public ScmProviderRepository makeProviderScmRepository( String scmSpecificUrl, char delimiter )
088        throws ScmRepositoryException
089    {
090        try
091        {
092            ScmUrlParserResult result = parseScmUrl( scmSpecificUrl, delimiter );
093
094            if ( result.messages.size() > 0 )
095            {
096                throw new ScmRepositoryException( "The scm url " + scmSpecificUrl + " is invalid.", result.messages );
097            }
098
099            return result.repository;
100        }
101        catch ( ScmException e )
102        {
103            // XXX We should allow throwing of SCMException.
104            throw new ScmRepositoryException( "Error creating the scm repository", e );
105        }
106    }
107
108    /** {@inheritDoc} */
109    public ScmProviderRepository makeProviderScmRepository( File path )
110        throws ScmRepositoryException, UnknownRepositoryStructure
111    {
112        if ( path == null )
113        {
114            throw new NullPointerException( "Path argument is null" );
115        }
116
117        if ( !path.isDirectory() )
118        {
119            throw new ScmRepositoryException( path.getAbsolutePath() + " isn't a valid directory." );
120        }
121
122        if ( !new File( path, ".git" ).exists() )
123        {
124            throw new ScmRepositoryException( path.getAbsolutePath() + " isn't a git checkout directory." );
125        }
126
127        try
128        {
129            return makeProviderScmRepository( getRepositoryURL( path ), ':' );
130        }
131        catch ( ScmException e )
132        {
133            // XXX We should allow throwing of SCMException.
134            throw new ScmRepositoryException( "Error creating the scm repository", e );
135        }
136    }
137
138    protected abstract String getRepositoryURL( File path )
139        throws ScmException;
140
141    /** {@inheritDoc} */
142    public List<String> validateScmUrl( String scmSpecificUrl, char delimiter )
143    {
144        List<String> messages = new ArrayList<String>();
145        try
146        {
147            makeProviderScmRepository( scmSpecificUrl, delimiter );
148        }
149        catch ( ScmRepositoryException e )
150        {
151            messages = e.getValidationMessages();
152        }
153        return messages;
154    }
155
156    /** {@inheritDoc} */
157    public String getScmType()
158    {
159        return "git";
160    }
161
162    // ----------------------------------------------------------------------
163    //
164    // ----------------------------------------------------------------------
165
166    /**
167     * The git-submodule(1) command is available since Git 1.5.3, so modules will
168     * be activated in a later stage
169     */
170    private ScmUrlParserResult parseScmUrl( String scmSpecificUrl, char delimiter )
171        throws ScmException
172    {
173        ScmUrlParserResult result = new ScmUrlParserResult();
174
175        result.repository = new GitScmProviderRepository( scmSpecificUrl );
176
177        return result;
178    }
179
180    protected abstract GitCommand getAddCommand();
181
182    /** {@inheritDoc} */
183    public AddScmResult add( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters )
184        throws ScmException
185    {
186        return (AddScmResult) executeCommand( getAddCommand(), repository, fileSet, parameters );
187    }
188
189    protected abstract GitCommand getBranchCommand();
190
191    /** {@inheritDoc} */
192    protected BranchScmResult branch( ScmProviderRepository repository, ScmFileSet fileSet,
193                                      CommandParameters parameters )
194        throws ScmException
195    {
196        return (BranchScmResult) executeCommand( getBranchCommand(), repository, fileSet, parameters );
197    }
198
199    protected abstract GitCommand getChangeLogCommand();
200
201    /** {@inheritDoc} */
202    public ChangeLogScmResult changelog( ScmProviderRepository repository, ScmFileSet fileSet,
203                                         CommandParameters parameters )
204        throws ScmException
205    {
206        return (ChangeLogScmResult) executeCommand( getChangeLogCommand(), repository, fileSet, parameters );
207    }
208
209    protected abstract GitCommand getCheckInCommand();
210
211    /** {@inheritDoc} */
212    public CheckInScmResult checkin( ScmProviderRepository repository, ScmFileSet fileSet,
213                                     CommandParameters parameters )
214        throws ScmException
215    {
216        return (CheckInScmResult) executeCommand( getCheckInCommand(), repository, fileSet, parameters );
217    }
218
219    protected abstract GitCommand getCheckOutCommand();
220
221    /** {@inheritDoc} */
222    public CheckOutScmResult checkout( ScmProviderRepository repository, ScmFileSet fileSet,
223                                       CommandParameters parameters )
224        throws ScmException
225    {
226        return (CheckOutScmResult) executeCommand( getCheckOutCommand(), repository, fileSet, parameters );
227    }
228
229    protected abstract GitCommand getDiffCommand();
230
231    /** {@inheritDoc} */
232    public DiffScmResult diff( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters )
233        throws ScmException
234    {
235        return (DiffScmResult) executeCommand( getDiffCommand(), repository, fileSet, parameters );
236    }
237
238    protected abstract GitCommand getExportCommand();
239
240    /** {@inheritDoc} */
241    protected ExportScmResult export( ScmProviderRepository repository, ScmFileSet fileSet,
242                                      CommandParameters parameters )
243        throws ScmException
244    {
245        return (ExportScmResult) executeCommand( getExportCommand(), repository, fileSet, parameters );
246    }
247
248    protected abstract GitCommand getRemoveCommand();
249
250    /** {@inheritDoc} */
251    public RemoveScmResult remove( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters )
252        throws ScmException
253    {
254        return (RemoveScmResult) executeCommand( getRemoveCommand(), repository, fileSet, parameters );
255    }
256
257    protected abstract GitCommand getStatusCommand();
258
259    /** {@inheritDoc} */
260    public StatusScmResult status( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters )
261        throws ScmException
262    {
263        return (StatusScmResult) executeCommand( getStatusCommand(), repository, fileSet, parameters );
264    }
265
266    protected abstract GitCommand getTagCommand();
267
268    /** {@inheritDoc} */
269    public TagScmResult tag( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters )
270        throws ScmException
271    {
272        return (TagScmResult) executeCommand( getTagCommand(), repository, fileSet, parameters );
273    }
274
275    protected abstract GitCommand getUpdateCommand();
276
277    /** {@inheritDoc} */
278    public UpdateScmResult update( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters )
279        throws ScmException
280    {
281        return (UpdateScmResult) executeCommand( getUpdateCommand(), repository, fileSet, parameters );
282    }
283
284    protected ScmResult executeCommand( GitCommand command, ScmProviderRepository repository, ScmFileSet fileSet,
285                                        CommandParameters parameters )
286        throws ScmException
287    {
288        command.setLogger( getLogger() );
289
290        return command.execute( repository, fileSet, parameters );
291    }
292
293    protected abstract GitCommand getInfoCommand();
294
295    public InfoScmResult info( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters )
296        throws ScmException
297    {
298        GitCommand cmd = getInfoCommand();
299
300        return (InfoScmResult) executeCommand( cmd, repository, fileSet, parameters );
301    }
302
303    /** {@inheritDoc} */
304    protected BlameScmResult blame( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters )
305        throws ScmException
306    {
307        GitCommand cmd = getBlameCommand();
308
309        return (BlameScmResult) executeCommand( cmd, repository, fileSet, parameters );
310    }
311
312    protected abstract GitCommand getBlameCommand();
313
314    /** {@inheritDoc} */
315    public RemoteInfoScmResult remoteInfo( ScmProviderRepository repository, ScmFileSet fileSet,
316                                           CommandParameters parameters )
317        throws ScmException
318    {
319        GitCommand cmd = getRemoteInfoCommand();
320
321        return (RemoteInfoScmResult) executeCommand( cmd, repository, fileSet, parameters );
322    }
323
324    protected abstract GitCommand getRemoteInfoCommand();
325
326}