You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SubmoduleSyncCommand.java 3.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  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.ConfigConstants;
  20. import org.eclipse.jgit.lib.Constants;
  21. import org.eclipse.jgit.lib.Ref;
  22. import org.eclipse.jgit.lib.Repository;
  23. import org.eclipse.jgit.lib.StoredConfig;
  24. import org.eclipse.jgit.submodule.SubmoduleWalk;
  25. import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
  26. /**
  27. * A class used to execute a submodule sync command.
  28. *
  29. * This will set the remote URL in a submodule's repository to the current value
  30. * in the .gitmodules file.
  31. *
  32. * @see <a href=
  33. * "http://www.kernel.org/pub/software/scm/git/docs/git-submodule.html"
  34. * >Git documentation about submodules</a>
  35. */
  36. public class SubmoduleSyncCommand extends GitCommand<Map<String, String>> {
  37. private final Collection<String> paths;
  38. /**
  39. * Constructor for SubmoduleSyncCommand.
  40. *
  41. * @param repo
  42. * a {@link org.eclipse.jgit.lib.Repository} object.
  43. */
  44. public SubmoduleSyncCommand(Repository repo) {
  45. super(repo);
  46. paths = new ArrayList<>();
  47. }
  48. /**
  49. * Add repository-relative submodule path to synchronize
  50. *
  51. * @param path
  52. * (with <code>/</code> as separator)
  53. * @return this command
  54. */
  55. public SubmoduleSyncCommand addPath(String path) {
  56. paths.add(path);
  57. return this;
  58. }
  59. /**
  60. * Get branch that HEAD currently points to
  61. *
  62. * @param subRepo
  63. * a {@link org.eclipse.jgit.lib.Repository} object.
  64. * @return shortened branch name, null on failures
  65. * @throws java.io.IOException
  66. */
  67. protected String getHeadBranch(Repository subRepo) throws IOException {
  68. Ref head = subRepo.exactRef(Constants.HEAD);
  69. if (head != null && head.isSymbolic()) {
  70. return Repository.shortenRefName(head.getLeaf().getName());
  71. }
  72. return null;
  73. }
  74. /** {@inheritDoc} */
  75. @Override
  76. public Map<String, String> call() throws GitAPIException {
  77. checkCallable();
  78. try (SubmoduleWalk generator = SubmoduleWalk.forIndex(repo)) {
  79. if (!paths.isEmpty())
  80. generator.setFilter(PathFilterGroup.createFromStrings(paths));
  81. Map<String, String> synced = new HashMap<>();
  82. StoredConfig config = repo.getConfig();
  83. while (generator.next()) {
  84. String remoteUrl = generator.getRemoteUrl();
  85. if (remoteUrl == null)
  86. continue;
  87. String path = generator.getPath();
  88. config.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION,
  89. path, ConfigConstants.CONFIG_KEY_URL, remoteUrl);
  90. synced.put(path, remoteUrl);
  91. try (Repository subRepo = generator.getRepository()) {
  92. if (subRepo == null) {
  93. continue;
  94. }
  95. StoredConfig subConfig;
  96. String branch;
  97. subConfig = subRepo.getConfig();
  98. // Get name of remote associated with current branch and
  99. // fall back to default remote name as last resort
  100. branch = getHeadBranch(subRepo);
  101. String remote = null;
  102. if (branch != null) {
  103. remote = subConfig.getString(
  104. ConfigConstants.CONFIG_BRANCH_SECTION, branch,
  105. ConfigConstants.CONFIG_KEY_REMOTE);
  106. }
  107. if (remote == null) {
  108. remote = Constants.DEFAULT_REMOTE_NAME;
  109. }
  110. subConfig.setString(ConfigConstants.CONFIG_REMOTE_SECTION,
  111. remote, ConfigConstants.CONFIG_KEY_URL, remoteUrl);
  112. subConfig.save();
  113. }
  114. }
  115. if (!synced.isEmpty())
  116. config.save();
  117. return synced;
  118. } catch (IOException | ConfigInvalidException e) {
  119. throw new JGitInternalException(e.getMessage(), e);
  120. }
  121. }
  122. }