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 */
048public class HgBranchCommand extends AbstractBranchCommand implements Command {
049
050    protected ScmResult executeBranchCommand(
051            ScmProviderRepository scmProviderRepository, ScmFileSet fileSet, String branch, String message)
052            throws ScmException {
053        return executeBranchCommand(scmProviderRepository, fileSet, branch, new ScmBranchParameters(message));
054    }
055
056    /**
057     * {@inheritDoc}
058     */
059    protected ScmResult executeBranchCommand(
060            ScmProviderRepository scmProviderRepository,
061            ScmFileSet fileSet,
062            String branch,
063            ScmBranchParameters scmBranchParameters)
064            throws ScmException {
065
066        if (StringUtils.isBlank(branch)) {
067            throw new ScmException("branch must be specified");
068        }
069
070        if (!fileSet.getFileList().isEmpty()) {
071            throw new ScmException("This provider doesn't support branchging subsets of a directory");
072        }
073
074        File workingDir = fileSet.getBasedir();
075
076        // build the command
077        String[] branchCmd = new String[] {HgCommandConstants.BRANCH_CMD, branch};
078
079        // keep the command about in string form for reporting
080        HgConsumer branchConsumer = new HgConsumer() {
081            public void doConsume(ScmFileStatus status, String trimmedLine) {
082                // noop
083            }
084        };
085
086        ScmResult result = HgUtils.execute(branchConsumer, workingDir, branchCmd);
087        HgScmProviderRepository repository = (HgScmProviderRepository) scmProviderRepository;
088
089        if (!result.isSuccess()) {
090            throw new ScmException("Error while executing command " + joinCmd(branchCmd));
091        }
092
093        // First commit.
094        String[] commitCmd = new String[] {
095            HgCommandConstants.COMMIT_CMD, HgCommandConstants.MESSAGE_OPTION, scmBranchParameters.getMessage()
096        };
097
098        result = HgUtils.execute(new HgConsumer(), workingDir, commitCmd);
099
100        if (!result.isSuccess()) {
101            throw new ScmException("Error while executing command " + joinCmd(commitCmd));
102        }
103
104        // now push, if we should.
105
106        if (repository.isPushChanges()) {
107            if (!repository.getURI().equals(fileSet.getBasedir().getAbsolutePath())) {
108
109                String[] pushCmd = new String[] {
110                    HgCommandConstants.PUSH_CMD, HgCommandConstants.NEW_BRANCH_OPTION, repository.getURI()
111                };
112
113                result = HgUtils.execute(new HgConsumer(), fileSet.getBasedir(), pushCmd);
114
115                if (!result.isSuccess()) {
116                    throw new ScmException("Error while executing command " + joinCmd(pushCmd));
117                }
118            }
119        }
120
121        // do an inventory to return the files branched (all of them)
122        String[] listCmd = new String[] {HgCommandConstants.INVENTORY_CMD};
123        HgListConsumer listconsumer = new HgListConsumer();
124
125        result = HgUtils.execute(listconsumer, fileSet.getBasedir(), listCmd);
126
127        if (!result.isSuccess()) {
128            throw new ScmException("Error while executing command " + joinCmd(listCmd));
129        }
130
131        List<ScmFile> files = listconsumer.getFiles();
132        List<ScmFile> fileList = new ArrayList<>();
133        for (ScmFile f : files) {
134            fileList.add(new ScmFile(f.getPath(), ScmFileStatus.TAGGED));
135        }
136
137        return new BranchScmResult(fileList, result);
138    }
139
140    private String joinCmd(String[] cmd) {
141        StringBuilder result = new StringBuilder();
142        for (int i = 0; i < cmd.length; i++) {
143            String s = cmd[i];
144            result.append(s);
145            if (i < cmd.length - 1) {
146                result.append(" ");
147            }
148        }
149        return result.toString();
150    }
151}