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.svn.svnexe.command.remoteinfo;
020
021import java.util.HashMap;
022import java.util.Map;
023
024import org.apache.commons.lang3.StringUtils;
025import org.apache.maven.scm.CommandParameters;
026import org.apache.maven.scm.ScmException;
027import org.apache.maven.scm.ScmFileSet;
028import org.apache.maven.scm.command.remoteinfo.AbstractRemoteInfoCommand;
029import org.apache.maven.scm.command.remoteinfo.RemoteInfoScmResult;
030import org.apache.maven.scm.provider.ScmProviderRepository;
031import org.apache.maven.scm.provider.svn.command.SvnCommand;
032import org.apache.maven.scm.provider.svn.repository.SvnScmProviderRepository;
033import org.apache.maven.scm.provider.svn.svnexe.command.SvnCommandLineUtils;
034import org.apache.maven.scm.util.AbstractConsumer;
035import org.codehaus.plexus.util.cli.CommandLineException;
036import org.codehaus.plexus.util.cli.CommandLineUtils;
037import org.codehaus.plexus.util.cli.Commandline;
038
039/**
040 * @author Olivier Lamy
041 * @since 1.6
042 */
043public class SvnRemoteInfoCommand extends AbstractRemoteInfoCommand implements SvnCommand {
044
045    private final boolean interactive;
046
047    public SvnRemoteInfoCommand(boolean interactive) {
048        this.interactive = interactive;
049    }
050
051    @Override
052    public RemoteInfoScmResult executeRemoteInfoCommand(
053            ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters) throws ScmException {
054
055        String url = ((SvnScmProviderRepository) repository).getUrl();
056        // use a default svn layout, url is here http://svn.apache.org/repos/asf/maven/maven-3/trunk
057        // so as we presume we have good users using standard svn layout, we calculate tags and branches url
058        url = StringUtils.stripEnd(url, "/");
059        int idx = url.lastIndexOf("/");
060        String baseUrl = url.substring(0, idx);
061
062        Commandline cl = SvnCommandLineUtils.getBaseSvnCommandLine(
063                fileSet == null ? null : fileSet.getBasedir(), (SvnScmProviderRepository) repository, interactive);
064
065        cl.createArg().setValue("ls");
066
067        cl.createArg().setValue(baseUrl + "/tags" + "@");
068
069        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
070
071        LsConsumer consumer = new LsConsumer(baseUrl + "/tags");
072
073        int exitCode = 0;
074
075        Map<String, String> tagsInfos = null;
076
077        try {
078            exitCode = SvnCommandLineUtils.execute(cl, consumer, stderr);
079            tagsInfos = consumer.infos;
080
081        } catch (CommandLineException ex) {
082            throw new ScmException("Error while executing svn command.", ex);
083        }
084
085        if (exitCode != 0) {
086            return new RemoteInfoScmResult(cl.toString(), "The svn command failed.", stderr.getOutput(), false);
087        }
088
089        cl = SvnCommandLineUtils.getBaseSvnCommandLine(
090                fileSet == null ? null : fileSet.getBasedir(), (SvnScmProviderRepository) repository, interactive);
091
092        cl.createArg().setValue("ls");
093
094        cl.createArg().setValue(baseUrl + "/branches" + "@");
095
096        stderr = new CommandLineUtils.StringStreamConsumer();
097
098        consumer = new LsConsumer(baseUrl + "/branches");
099
100        Map<String, String> branchesInfos = null;
101
102        try {
103            exitCode = SvnCommandLineUtils.execute(cl, consumer, stderr);
104            branchesInfos = consumer.infos;
105
106        } catch (CommandLineException ex) {
107            throw new ScmException("Error while executing svn command.", ex);
108        }
109
110        if (exitCode != 0) {
111            return new RemoteInfoScmResult(cl.toString(), "The svn command failed.", stderr.getOutput(), false);
112        }
113
114        return new RemoteInfoScmResult(cl.toString(), branchesInfos, tagsInfos);
115    }
116
117    public boolean remoteUrlExist(ScmProviderRepository repository, CommandParameters parameters) throws ScmException {
118        String url = ((SvnScmProviderRepository) repository).getUrl();
119
120        Commandline cl =
121                SvnCommandLineUtils.getBaseSvnCommandLine(null, (SvnScmProviderRepository) repository, interactive);
122
123        cl.createArg().setValue("ls");
124
125        cl.createArg().setValue(url + "@");
126
127        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
128
129        LsConsumer consumer = new LsConsumer(url);
130
131        int exitCode = 0;
132
133        try {
134            exitCode = SvnCommandLineUtils.execute(cl, consumer, stderr);
135        } catch (CommandLineException ex) {
136            throw new ScmException("Error while executing svn command.", ex);
137        }
138
139        if (exitCode != 0) {
140            String output = stderr.getOutput();
141            // olamy: a bit ugly but....
142            // trying to parse error from svn cli which indicate no remote path
143            if (output.contains("W160013") || output.contains("svn: URL")) {
144                return false;
145            }
146            throw new ScmException(cl + ".The svn command failed:" + stderr.getOutput());
147        }
148
149        return true;
150    }
151
152    private static class LsConsumer extends AbstractConsumer {
153        Map<String, String> infos = new HashMap<>();
154
155        String url;
156
157        LsConsumer(String url) {
158            this.url = url;
159        }
160
161        public void consumeLine(String s) {
162            infos.put(StringUtils.stripEnd(s, "/"), url + "/" + s);
163        }
164
165        Map<String, String> getInfos() {
166            return infos;
167        }
168    }
169}