SubmoduleStatusCommand.java

  1. /*
  2.  * Copyright (C) 2011, GitHub Inc. 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.io.IOException;
  12. import java.util.ArrayList;
  13. import java.util.Collection;
  14. import java.util.HashMap;
  15. import java.util.Map;

  16. import org.eclipse.jgit.api.errors.GitAPIException;
  17. import org.eclipse.jgit.api.errors.JGitInternalException;
  18. import org.eclipse.jgit.errors.ConfigInvalidException;
  19. import org.eclipse.jgit.lib.Constants;
  20. import org.eclipse.jgit.lib.ObjectId;
  21. import org.eclipse.jgit.lib.Repository;
  22. import org.eclipse.jgit.submodule.SubmoduleStatus;
  23. import org.eclipse.jgit.submodule.SubmoduleStatusType;
  24. import org.eclipse.jgit.submodule.SubmoduleWalk;
  25. import org.eclipse.jgit.treewalk.filter.PathFilterGroup;

  26. /**
  27.  * A class used to execute a submodule status command.
  28.  *
  29.  * @see <a href=
  30.  *      "http://www.kernel.org/pub/software/scm/git/docs/git-submodule.html"
  31.  *      >Git documentation about submodules</a>
  32.  */
  33. public class SubmoduleStatusCommand extends
  34.         GitCommand<Map<String, SubmoduleStatus>> {

  35.     private final Collection<String> paths;

  36.     /**
  37.      * Constructor for SubmoduleStatusCommand.
  38.      *
  39.      * @param repo
  40.      *            a {@link org.eclipse.jgit.lib.Repository} object.
  41.      */
  42.     public SubmoduleStatusCommand(Repository repo) {
  43.         super(repo);
  44.         paths = new ArrayList<>();
  45.     }

  46.     /**
  47.      * Add repository-relative submodule path to limit status reporting to
  48.      *
  49.      * @param path
  50.      *            (with <code>/</code> as separator)
  51.      * @return this command
  52.      */
  53.     public SubmoduleStatusCommand addPath(String path) {
  54.         paths.add(path);
  55.         return this;
  56.     }

  57.     /** {@inheritDoc} */
  58.     @Override
  59.     public Map<String, SubmoduleStatus> call() throws GitAPIException {
  60.         checkCallable();

  61.         try (SubmoduleWalk generator = SubmoduleWalk.forIndex(repo)) {
  62.             if (!paths.isEmpty())
  63.                 generator.setFilter(PathFilterGroup.createFromStrings(paths));
  64.             Map<String, SubmoduleStatus> statuses = new HashMap<>();
  65.             while (generator.next()) {
  66.                 SubmoduleStatus status = getStatus(generator);
  67.                 statuses.put(status.getPath(), status);
  68.             }
  69.             return statuses;
  70.         } catch (IOException | ConfigInvalidException e) {
  71.             throw new JGitInternalException(e.getMessage(), e);
  72.         }
  73.     }

  74.     private SubmoduleStatus getStatus(SubmoduleWalk generator)
  75.             throws IOException, ConfigInvalidException {
  76.         ObjectId id = generator.getObjectId();
  77.         String path = generator.getPath();

  78.         // Report missing if no path in .gitmodules file
  79.         if (generator.getModulesPath() == null)
  80.             return new SubmoduleStatus(SubmoduleStatusType.MISSING, path, id);

  81.         // Report uninitialized if no URL in config file
  82.         if (generator.getConfigUrl() == null)
  83.             return new SubmoduleStatus(SubmoduleStatusType.UNINITIALIZED, path,
  84.                     id);

  85.         // Report uninitialized if no submodule repository
  86.         ObjectId headId = null;
  87.         try (Repository subRepo = generator.getRepository()) {
  88.             if (subRepo == null) {
  89.                 return new SubmoduleStatus(SubmoduleStatusType.UNINITIALIZED,
  90.                         path, id);
  91.             }

  92.             headId = subRepo.resolve(Constants.HEAD);
  93.         }

  94.         // Report uninitialized if no HEAD commit in submodule repository
  95.         if (headId == null)
  96.             return new SubmoduleStatus(SubmoduleStatusType.UNINITIALIZED, path,
  97.                     id, headId);

  98.         // Report checked out if HEAD commit is different than index commit
  99.         if (!headId.equals(id))
  100.             return new SubmoduleStatus(SubmoduleStatusType.REV_CHECKED_OUT,
  101.                     path, id, headId);

  102.         // Report initialized if HEAD commit is the same as the index commit
  103.         return new SubmoduleStatus(SubmoduleStatusType.INITIALIZED, path, id,
  104.                 headId);
  105.     }
  106. }