001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.maven.scm.provider.hg.command.branch;
020
021import java.io.File;
022import java.util.ArrayList;
023import java.util.List;
024
025import org.apache.commons.lang3.StringUtils;
026import org.apache.maven.scm.ScmBranchParameters;
027import org.apache.maven.scm.ScmException;
028import org.apache.maven.scm.ScmFile;
029import org.apache.maven.scm.ScmFileSet;
030import org.apache.maven.scm.ScmFileStatus;
031import org.apache.maven.scm.ScmResult;
032import org.apache.maven.scm.command.Command;
033import org.apache.maven.scm.command.branch.AbstractBranchCommand;
034import org.apache.maven.scm.command.branch.BranchScmResult;
035import org.apache.maven.scm.provider.ScmProviderRepository;
036import org.apache.maven.scm.provider.hg.HgUtils;
037import org.apache.maven.scm.provider.hg.command.HgCommandConstants;
038import org.apache.maven.scm.provider.hg.command.HgConsumer;
039import org.apache.maven.scm.provider.hg.command.inventory.HgListConsumer;
040import org.apache.maven.scm.provider.hg.repository.HgScmProviderRepository;
041
042/**
043 * Branch. Mercurial has weird branches. After a branch is created, it must be committed to the server, otherwise
044 * the branch does not exist (yet) in the repository.
045 *
046 * @author Henning Schmiedehausen
047 *
048 */
049public class HgBranchCommand extends AbstractBranchCommand implements Command {
050
051    protected ScmResult executeBranchCommand(
052            ScmProviderRepository scmProviderRepository, ScmFileSet fileSet, String branch, String message)
053            throws ScmException {
054        return executeBranchCommand(scmProviderRepository, fileSet, branch, new ScmBranchParameters(message));
055    }
056
057    /**
058     * {@inheritDoc}
059     */
060    protected ScmResult executeBranchCommand(
061            ScmProviderRepository scmProviderRepository,
062            ScmFileSet fileSet,
063            String branch,
064            ScmBranchParameters scmBranchParameters)
065            throws ScmException {
066
067        if (StringUtils.isBlank(branch)) {
068            throw new ScmException("branch must be specified");
069        }
070
071        if (!fileSet.getFileList().isEmpty()) {
072            throw new ScmException("This provider doesn't support branchging subsets of a directory");
073        }
074
075        File workingDir = fileSet.getBasedir();
076
077        // build the command
078        String[] branchCmd = new String[] {HgCommandConstants.BRANCH_CMD, branch};
079
080        // keep the command about in string form for reporting
081        HgConsumer branchConsumer = new HgConsumer() {
082            public void doConsume(ScmFileStatus status, String trimmedLine) {
083                // noop
084            }
085        };
086
087        ScmResult result = HgUtils.execute(branchConsumer, workingDir, branchCmd);
088        HgScmProviderRepository repository = (HgScmProviderRepository) scmProviderRepository;
089
090        if (!result.isSuccess()) {
091            throw new ScmException("Error while executing command " + joinCmd(branchCmd));
092        }
093
094        // First commit.
095        String[] commitCmd = new String[] {
096            HgCommandConstants.COMMIT_CMD, HgCommandConstants.MESSAGE_OPTION, scmBranchParameters.getMessage()
097        };
098
099        result = HgUtils.execute(new HgConsumer(), workingDir, commitCmd);
100
101        if (!result.isSuccess()) {
102            throw new ScmException("Error while executing command " + joinCmd(commitCmd));
103        }
104
105        // now push, if we should.
106
107        if (repository.isPushChanges()) {
108            if (!repository.getURI().equals(fileSet.getBasedir().getAbsolutePath())) {
109
110                String[] pushCmd = new String[] {
111                    HgCommandConstants.PUSH_CMD, HgCommandConstants.NEW_BRANCH_OPTION, repository.getURI()
112                };
113
114                result = HgUtils.execute(new HgConsumer(), fileSet.getBasedir(), pushCmd);
115
116                if (!result.isSuccess()) {
117                    throw new ScmException("Error while executing command " + joinCmd(pushCmd));
118                }
119            }
120        }
121
122        // do an inventory to return the files branched (all of them)
123        String[] listCmd = new String[] {HgCommandConstants.INVENTORY_CMD};
124        HgListConsumer listconsumer = new HgListConsumer();
125
126        result = HgUtils.execute(listconsumer, fileSet.getBasedir(), listCmd);
127
128        if (!result.isSuccess()) {
129            throw new ScmException("Error while executing command " + joinCmd(listCmd));
130        }
131
132        List<ScmFile> files = listconsumer.getFiles();
133        List<ScmFile> fileList = new ArrayList<>();
134        for (ScmFile f : files) {
135            fileList.add(new ScmFile(f.getPath(), ScmFileStatus.TAGGED));
136        }
137
138        return new BranchScmResult(fileList, result);
139    }
140
141    private String joinCmd(String[] cmd) {
142        StringBuilder result = new StringBuilder();
143        for (int i = 0; i < cmd.length; i++) {
144            String s = cmd[i];
145            result.append(s);
146            if (i < cmd.length - 1) {
147                result.append(" ");
148            }
149        }
150        return result.toString();
151    }
152}