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