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