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.git.jgit.command.remoteinfo;
020
021import java.util.Collection;
022import java.util.HashMap;
023import java.util.Map;
024import java.util.function.BiFunction;
025
026import org.apache.maven.scm.CommandParameters;
027import org.apache.maven.scm.ScmException;
028import org.apache.maven.scm.ScmFileSet;
029import org.apache.maven.scm.command.remoteinfo.AbstractRemoteInfoCommand;
030import org.apache.maven.scm.command.remoteinfo.RemoteInfoScmResult;
031import org.apache.maven.scm.provider.ScmProviderRepository;
032import org.apache.maven.scm.provider.git.command.GitCommand;
033import org.apache.maven.scm.provider.git.jgit.command.JGitTransportConfigCallback;
034import org.apache.maven.scm.provider.git.jgit.command.JGitUtils;
035import org.apache.maven.scm.provider.git.jgit.command.ScmProviderAwareSshdSessionFactory;
036import org.apache.maven.scm.provider.git.repository.GitScmProviderRepository;
037import org.eclipse.jgit.api.Git;
038import org.eclipse.jgit.api.LsRemoteCommand;
039import org.eclipse.jgit.lib.Ref;
040import org.eclipse.jgit.lib.Repository;
041import org.eclipse.jgit.transport.CredentialsProvider;
042import org.slf4j.Logger;
043
044/**
045 * @author Dominik Bartholdi (imod)
046 * @since 1.9
047 */
048public class JGitRemoteInfoCommand extends AbstractRemoteInfoCommand implements GitCommand {
049
050    private BiFunction<GitScmProviderRepository, Logger, ScmProviderAwareSshdSessionFactory> sshSessionFactorySupplier;
051
052    public JGitRemoteInfoCommand() {
053        sshSessionFactorySupplier = ScmProviderAwareSshdSessionFactory::new;
054    }
055
056    public void setSshSessionFactorySupplier(
057            BiFunction<GitScmProviderRepository, Logger, ScmProviderAwareSshdSessionFactory>
058                    sshSessionFactorySupplier) {
059        this.sshSessionFactorySupplier = sshSessionFactorySupplier;
060    }
061
062    @Override
063    public RemoteInfoScmResult executeRemoteInfoCommand(
064            ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters) throws ScmException {
065
066        GitScmProviderRepository repo = (GitScmProviderRepository) repository;
067        Git git = null;
068        try {
069            git = JGitUtils.openRepo(fileSet.getBasedir());
070            CredentialsProvider credentials = JGitUtils.getCredentials(repo);
071
072            LsRemoteCommand lsCommand = git.lsRemote()
073                    .setRemote(repo.getPushUrl())
074                    .setCredentialsProvider(credentials)
075                    .setTransportConfigCallback(
076                            new JGitTransportConfigCallback(sshSessionFactorySupplier.apply(repo, logger)));
077
078            Map<String, String> tag = new HashMap<>();
079            Collection<Ref> allTags = lsCommand.setHeads(false).setTags(true).call();
080            for (Ref ref : allTags) {
081                tag.put(
082                        Repository.shortenRefName(ref.getName()),
083                        ref.getObjectId().name());
084            }
085
086            Map<String, String> heads = new HashMap<>();
087            Collection<Ref> allHeads = lsCommand.setHeads(true).setTags(false).call();
088            for (Ref ref : allHeads) {
089                heads.put(
090                        Repository.shortenRefName(ref.getName()),
091                        ref.getObjectId().name());
092            }
093
094            return new RemoteInfoScmResult("JGit remoteinfo", heads, tag);
095        } catch (Exception e) {
096            throw new ScmException("JGit remoteinfo failure!", e);
097        } finally {
098            JGitUtils.closeRepo(git);
099        }
100    }
101}