ListBranchCommand.java

  1. /*
  2.  * Copyright (C) 2010, Mathias Kinzler <mathias.kinzler@sap.com>
  3.  * Copyright (C) 2010, Chris Aniszczyk <caniszczyk@gmail.com>
  4.  * Copyright (C) 2014, Robin Stocker <robin@nibor.org> and others
  5.  *
  6.  * This program and the accompanying materials are made available under the
  7.  * terms of the Eclipse Distribution License v. 1.0 which is available at
  8.  * https://www.eclipse.org/org/documents/edl-v10.php.
  9.  *
  10.  * SPDX-License-Identifier: BSD-3-Clause
  11.  */
  12. package org.eclipse.jgit.api;

  13. import static org.eclipse.jgit.lib.Constants.HEAD;
  14. import static org.eclipse.jgit.lib.Constants.R_HEADS;
  15. import static org.eclipse.jgit.lib.Constants.R_REMOTES;

  16. import java.io.IOException;
  17. import java.text.MessageFormat;
  18. import java.util.ArrayList;
  19. import java.util.Collection;
  20. import java.util.Collections;
  21. import java.util.List;

  22. import org.eclipse.jgit.api.errors.GitAPIException;
  23. import org.eclipse.jgit.api.errors.JGitInternalException;
  24. import org.eclipse.jgit.api.errors.RefNotFoundException;
  25. import org.eclipse.jgit.internal.JGitText;
  26. import org.eclipse.jgit.lib.ObjectId;
  27. import org.eclipse.jgit.lib.Ref;
  28. import org.eclipse.jgit.lib.Repository;
  29. import org.eclipse.jgit.revwalk.RevCommit;
  30. import org.eclipse.jgit.revwalk.RevWalk;
  31. import org.eclipse.jgit.revwalk.RevWalkUtils;

  32. /**
  33.  * Used to obtain a list of branches.
  34.  * <p>
  35.  * In case HEAD is detached (it points directly to a commit), it is also
  36.  * returned in the results.
  37.  *
  38.  * @see <a
  39.  *      href="http://www.kernel.org/pub/software/scm/git/docs/git-branch.html"
  40.  *      >Git documentation about Branch</a>
  41.  */
  42. public class ListBranchCommand extends GitCommand<List<Ref>> {
  43.     private ListMode listMode;

  44.     private String containsCommitish;

  45.     /**
  46.      * The modes available for listing branches (corresponding to the -r and -a
  47.      * options)
  48.      */
  49.     public enum ListMode {
  50.         /**
  51.          * Corresponds to the -a option (all branches)
  52.          */
  53.         ALL,
  54.         /**
  55.          * Corresponds to the -r option (remote branches only)
  56.          */
  57.         REMOTE;
  58.     }

  59.     /**
  60.      * Constructor for ListBranchCommand.
  61.      *
  62.      * @param repo
  63.      *            a {@link org.eclipse.jgit.lib.Repository} object.
  64.      */
  65.     protected ListBranchCommand(Repository repo) {
  66.         super(repo);
  67.     }

  68.     /** {@inheritDoc} */
  69.     @Override
  70.     public List<Ref> call() throws GitAPIException {
  71.         checkCallable();
  72.         List<Ref> resultRefs;
  73.         try {
  74.             Collection<Ref> refs = new ArrayList<>();

  75.             // Also return HEAD if it's detached
  76.             Ref head = repo.exactRef(HEAD);
  77.             if (head != null && head.getLeaf().getName().equals(HEAD)) {
  78.                 refs.add(head);
  79.             }

  80.             if (listMode == null) {
  81.                 refs.addAll(repo.getRefDatabase().getRefsByPrefix(R_HEADS));
  82.             } else if (listMode == ListMode.REMOTE) {
  83.                 refs.addAll(repo.getRefDatabase().getRefsByPrefix(R_REMOTES));
  84.             } else {
  85.                 refs.addAll(repo.getRefDatabase().getRefsByPrefix(R_HEADS,
  86.                         R_REMOTES));
  87.             }
  88.             resultRefs = new ArrayList<>(filterRefs(refs));
  89.         } catch (IOException e) {
  90.             throw new JGitInternalException(e.getMessage(), e);
  91.         }

  92.         Collections.sort(resultRefs,
  93.                 (Ref o1, Ref o2) -> o1.getName().compareTo(o2.getName()));
  94.         setCallable(false);
  95.         return resultRefs;
  96.     }

  97.     private Collection<Ref> filterRefs(Collection<Ref> refs)
  98.             throws RefNotFoundException, IOException {
  99.         if (containsCommitish == null)
  100.             return refs;

  101.         try (RevWalk walk = new RevWalk(repo)) {
  102.             ObjectId resolved = repo.resolve(containsCommitish);
  103.             if (resolved == null)
  104.                 throw new RefNotFoundException(MessageFormat.format(
  105.                         JGitText.get().refNotResolved, containsCommitish));

  106.             RevCommit containsCommit = walk.parseCommit(resolved);
  107.             return RevWalkUtils.findBranchesReachableFrom(containsCommit, walk,
  108.                     refs);
  109.         }
  110.     }

  111.     /**
  112.      * Set the list mode
  113.      *
  114.      * @param listMode
  115.      *            optional: corresponds to the -r/-a options; by default, only
  116.      *            local branches will be listed
  117.      * @return this instance
  118.      */
  119.     public ListBranchCommand setListMode(ListMode listMode) {
  120.         checkCallable();
  121.         this.listMode = listMode;
  122.         return this;
  123.     }

  124.     /**
  125.      * If this is set, only the branches that contain the specified commit-ish
  126.      * as an ancestor are returned.
  127.      *
  128.      * @param containsCommitish
  129.      *            a commit ID or ref name
  130.      * @return this instance
  131.      * @since 3.4
  132.      */
  133.     public ListBranchCommand setContains(String containsCommitish) {
  134.         checkCallable();
  135.         this.containsCommitish = containsCommitish;
  136.         return this;
  137.     }
  138. }