001package org.apache.maven.scm.provider.hg.command.branch;
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.Iterator;
025import java.util.List;
026
027import org.apache.maven.scm.ScmBranchParameters;
028import org.apache.maven.scm.ScmException;
029import org.apache.maven.scm.ScmFile;
030import org.apache.maven.scm.ScmFileSet;
031import org.apache.maven.scm.ScmFileStatus;
032import org.apache.maven.scm.ScmResult;
033import org.apache.maven.scm.command.Command;
034import org.apache.maven.scm.command.branch.AbstractBranchCommand;
035import org.apache.maven.scm.command.branch.BranchScmResult;
036import org.apache.maven.scm.provider.ScmProviderRepository;
037import org.apache.maven.scm.provider.hg.HgUtils;
038import org.apache.maven.scm.provider.hg.command.HgCommandConstants;
039import org.apache.maven.scm.provider.hg.command.HgConsumer;
040import org.apache.maven.scm.provider.hg.command.inventory.HgListConsumer;
041import org.apache.maven.scm.provider.hg.repository.HgScmProviderRepository;
042import org.codehaus.plexus.util.StringUtils;
043
044/**
045 * Branch. Mercurial has weird branches. After a branch is created, it must be committed to the server, otherwise
046 * the branch does not exist (yet) in the repository.
047 *
048 * @author Henning Schmiedehausen
049 *
050 */
051public class HgBranchCommand
052    extends AbstractBranchCommand
053    implements Command
054{
055
056    protected ScmResult executeBranchCommand( ScmProviderRepository scmProviderRepository, ScmFileSet fileSet, String branch,
057                                           String message )
058        throws ScmException
059    {
060        return executeBranchCommand( scmProviderRepository, fileSet, branch, new ScmBranchParameters( message ) );
061    }
062
063    /**
064     * {@inheritDoc}
065     */
066    protected ScmResult executeBranchCommand( ScmProviderRepository scmProviderRepository, ScmFileSet fileSet, String branch,
067                                           ScmBranchParameters scmBranchParameters )
068        throws ScmException
069    {
070
071        if ( StringUtils.isBlank( branch ) )
072        {
073            throw new ScmException( "branch must be specified" );
074        }
075
076        if ( !fileSet.getFileList().isEmpty() )
077        {
078            throw new ScmException( "This provider doesn't support branchging subsets of a directory" );
079        }
080
081        File workingDir = fileSet.getBasedir();
082
083        // build the command
084        String[] branchCmd =
085            new String[]{ HgCommandConstants.BRANCH_CMD, branch };
086
087        // keep the command about in string form for reporting
088        ;
089        HgConsumer branchConsumer = new HgConsumer( getLogger() ) {
090            public void doConsume( ScmFileStatus status, String trimmedLine )
091            {
092            }
093        };
094
095        ScmResult result = HgUtils.execute( branchConsumer, getLogger(), workingDir, branchCmd );
096        HgScmProviderRepository repository = (HgScmProviderRepository) scmProviderRepository;
097
098        if ( !result.isSuccess() )
099        {
100            throw new ScmException( "Error while executing command " + joinCmd( branchCmd ) );
101        }
102
103        // First commit.
104        String[] commitCmd = new String[]{ HgCommandConstants.COMMIT_CMD, HgCommandConstants.MESSAGE_OPTION, scmBranchParameters.getMessage() };
105
106
107        result = HgUtils.execute( new HgConsumer( getLogger() ), getLogger(), workingDir, commitCmd );
108
109        if ( !result.isSuccess() )
110        {
111            throw new ScmException( "Error while executing command " + joinCmd( commitCmd ) );
112        }
113
114        // now push, if we should.
115
116        if ( repository.isPushChanges() )
117        {
118            if ( !repository.getURI().equals( fileSet.getBasedir().getAbsolutePath() ) )
119            {
120
121                String[] pushCmd = new String[] {
122                    HgCommandConstants.PUSH_CMD,
123                    HgCommandConstants.NEW_BRANCH_OPTION,
124                    repository.getURI()
125                };
126
127                result = HgUtils.execute( new HgConsumer( getLogger() ), getLogger(), fileSet.getBasedir(), pushCmd );
128
129                if ( !result.isSuccess() )
130                {
131                    throw new ScmException( "Error while executing command " + joinCmd( pushCmd ) );
132                }
133            }
134        }
135
136        // do an inventory to return the files branched (all of them)
137        String[] listCmd = new String[]{ HgCommandConstants.INVENTORY_CMD };
138        HgListConsumer listconsumer = new HgListConsumer( getLogger() );
139
140        result = HgUtils.execute( listconsumer, getLogger(), fileSet.getBasedir(), listCmd );
141
142        if ( !result.isSuccess() )
143        {
144            throw new ScmException( "Error while executing command " + joinCmd(listCmd) );
145        }
146
147        List<ScmFile> files = listconsumer.getFiles();
148        List<ScmFile> fileList = new ArrayList<ScmFile>();
149        for ( Iterator<ScmFile> i = files.iterator(); i.hasNext(); )
150        {
151            ScmFile f = i.next();
152
153            fileList.add( new ScmFile( f.getPath(), ScmFileStatus.TAGGED ) );
154        }
155
156        return new BranchScmResult( fileList, result );
157    }
158
159    private String joinCmd( String[] cmd )
160    {
161        StringBuilder result = new StringBuilder();
162        for ( int i = 0; i < cmd.length; i++ )
163        {
164            String s = cmd[i];
165            result.append( s );
166            if ( i < cmd.length - 1 )
167            {
168                result.append( " " );
169            }
170        }
171        return result.toString();
172    }
173}