LsRemoteCommand.java

  1. /*
  2.  * Copyright (C) 2011, 2020 Christoph Brill <egore911@egore911.de> and others
  3.  *
  4.  * This program and the accompanying materials are made available under the
  5.  * terms of the Eclipse Distribution License v. 1.0 which is available at
  6.  * https://www.eclipse.org/org/documents/edl-v10.php.
  7.  *
  8.  * SPDX-License-Identifier: BSD-3-Clause
  9.  */
  10. package org.eclipse.jgit.api;

  11. import java.net.URISyntaxException;
  12. import java.text.MessageFormat;
  13. import java.util.ArrayList;
  14. import java.util.Collection;
  15. import java.util.Collections;
  16. import java.util.HashMap;
  17. import java.util.Map;

  18. import org.eclipse.jgit.api.errors.GitAPIException;
  19. import org.eclipse.jgit.api.errors.InvalidRemoteException;
  20. import org.eclipse.jgit.api.errors.JGitInternalException;
  21. import org.eclipse.jgit.errors.NotSupportedException;
  22. import org.eclipse.jgit.errors.TransportException;
  23. import org.eclipse.jgit.internal.JGitText;
  24. import org.eclipse.jgit.lib.Constants;
  25. import org.eclipse.jgit.lib.Ref;
  26. import org.eclipse.jgit.lib.Repository;
  27. import org.eclipse.jgit.transport.FetchConnection;
  28. import org.eclipse.jgit.transport.RefSpec;
  29. import org.eclipse.jgit.transport.Transport;
  30. import org.eclipse.jgit.transport.URIish;

  31. /**
  32.  * The ls-remote command
  33.  *
  34.  * @see <a
  35.  *      href="http://www.kernel.org/pub/software/scm/git/docs/git-ls-remote.html"
  36.  *      >Git documentation about ls-remote</a>
  37.  */
  38. public class LsRemoteCommand extends
  39.         TransportCommand<LsRemoteCommand, Collection<Ref>> {

  40.     private String remote = Constants.DEFAULT_REMOTE_NAME;

  41.     private boolean heads;

  42.     private boolean tags;

  43.     private String uploadPack;

  44.     /**
  45.      * Constructor for LsRemoteCommand
  46.      *
  47.      * @param repo
  48.      *            local repository or null for operation without local
  49.      *            repository
  50.      */
  51.     public LsRemoteCommand(Repository repo) {
  52.         super(repo);
  53.     }

  54.     /**
  55.      * The remote (uri or name) used for the fetch operation. If no remote is
  56.      * set, the default value of <code>Constants.DEFAULT_REMOTE_NAME</code> will
  57.      * be used.
  58.      *
  59.      * @see Constants#DEFAULT_REMOTE_NAME
  60.      * @param remote
  61.      *            a {@link java.lang.String} object.
  62.      * @return {@code this}
  63.      */
  64.     public LsRemoteCommand setRemote(String remote) {
  65.         checkCallable();
  66.         this.remote = remote;
  67.         return this;
  68.     }

  69.     /**
  70.      * Include refs/heads in references results
  71.      *
  72.      * @param heads
  73.      *            whether to include refs/heads
  74.      * @return {@code this}
  75.      */
  76.     public LsRemoteCommand setHeads(boolean heads) {
  77.         this.heads = heads;
  78.         return this;
  79.     }

  80.     /**
  81.      * Include refs/tags in references results
  82.      *
  83.      * @param tags
  84.      *            whether to include tags
  85.      * @return {@code this}
  86.      */
  87.     public LsRemoteCommand setTags(boolean tags) {
  88.         this.tags = tags;
  89.         return this;
  90.     }

  91.     /**
  92.      * The full path of git-upload-pack on the remote host
  93.      *
  94.      * @param uploadPack
  95.      *            the full path of executable providing the git-upload-pack
  96.      *            service on remote host
  97.      * @return {@code this}
  98.      */
  99.     public LsRemoteCommand setUploadPack(String uploadPack) {
  100.         this.uploadPack = uploadPack;
  101.         return this;
  102.     }

  103.     /**
  104.      * {@inheritDoc}
  105.      * <p>
  106.      * Execute the {@code LsRemote} command with all the options and parameters
  107.      * collected by the setter methods (e.g. {@link #setHeads(boolean)}) of this
  108.      * class. Each instance of this class should only be used for one invocation
  109.      * of the command. Don't call this method twice on an instance.
  110.      */
  111.     @Override
  112.     public Collection<Ref> call() throws GitAPIException,
  113.             InvalidRemoteException,
  114.             org.eclipse.jgit.api.errors.TransportException {
  115.         return execute().values();
  116.     }

  117.     /**
  118.      * Same as {@link #call()}, but return Map instead of Collection.
  119.      *
  120.      * @return a map from names to references in the remote repository
  121.      * @throws org.eclipse.jgit.api.errors.GitAPIException
  122.      *             or subclass thereof when an error occurs
  123.      * @throws org.eclipse.jgit.api.errors.InvalidRemoteException
  124.      *             when called with an invalid remote uri
  125.      * @throws org.eclipse.jgit.api.errors.TransportException
  126.      *             for errors that occurs during transport
  127.      * @since 3.5
  128.      */
  129.     public Map<String, Ref> callAsMap() throws GitAPIException,
  130.             InvalidRemoteException,
  131.             org.eclipse.jgit.api.errors.TransportException {
  132.         return Collections.unmodifiableMap(execute());
  133.     }

  134.     private Map<String, Ref> execute() throws GitAPIException,
  135.             InvalidRemoteException,
  136.             org.eclipse.jgit.api.errors.TransportException {
  137.         checkCallable();

  138.         try (Transport transport = repo != null
  139.                 ? Transport.open(repo, remote)
  140.                 : Transport.open(new URIish(remote))) {
  141.             transport.setOptionUploadPack(uploadPack);
  142.             configure(transport);
  143.             Collection<RefSpec> refSpecs = new ArrayList<>(1);
  144.             if (tags)
  145.                 refSpecs.add(new RefSpec(
  146.                         "refs/tags/*:refs/remotes/origin/tags/*")); //$NON-NLS-1$
  147.             if (heads)
  148.                 refSpecs.add(new RefSpec("refs/heads/*:refs/remotes/origin/*")); //$NON-NLS-1$
  149.             Collection<Ref> refs;
  150.             Map<String, Ref> refmap = new HashMap<>();
  151.             try (FetchConnection fc = transport.openFetch(refSpecs)) {
  152.                 refs = fc.getRefs();
  153.                 if (refSpecs.isEmpty())
  154.                     for (Ref r : refs)
  155.                         refmap.put(r.getName(), r);
  156.                 else
  157.                     for (Ref r : refs)
  158.                         for (RefSpec rs : refSpecs)
  159.                             if (rs.matchSource(r)) {
  160.                                 refmap.put(r.getName(), r);
  161.                                 break;
  162.                             }
  163.                 return refmap;
  164.             }
  165.         } catch (URISyntaxException e) {
  166.             throw new InvalidRemoteException(MessageFormat.format(
  167.                     JGitText.get().invalidRemote, remote), e);
  168.         } catch (NotSupportedException e) {
  169.             throw new JGitInternalException(
  170.                     JGitText.get().exceptionCaughtDuringExecutionOfLsRemoteCommand,
  171.                     e);
  172.         } catch (TransportException e) {
  173.             throw new org.eclipse.jgit.api.errors.TransportException(
  174.                     e.getMessage(),
  175.                     e);
  176.         }
  177.     }

  178. }