| /* | |
| * Copyright (C) 2011, GitHub Inc. and others | |
| * | |
| * This program and the accompanying materials are made available under the | |
| * terms of the Eclipse Distribution License v. 1.0 which is available at | |
| * https://www.eclipse.org/org/documents/edl-v10.php. | |
| * | |
| * SPDX-License-Identifier: BSD-3-Clause | |
| */ | |
| package org.eclipse.jgit.submodule; | |
| import java.io.File; | |
| import java.io.IOException; | |
| import java.text.MessageFormat; | |
| import java.util.HashMap; | |
| import java.util.Map; | |
| import org.eclipse.jgit.dircache.DirCache; | |
| import org.eclipse.jgit.dircache.DirCacheIterator; | |
| import org.eclipse.jgit.errors.ConfigInvalidException; | |
| import org.eclipse.jgit.errors.CorruptObjectException; | |
| import org.eclipse.jgit.errors.IncorrectObjectTypeException; | |
| import org.eclipse.jgit.errors.MissingObjectException; | |
| import org.eclipse.jgit.errors.RepositoryNotFoundException; | |
| import org.eclipse.jgit.internal.JGitText; | |
| import org.eclipse.jgit.lib.AnyObjectId; | |
| import org.eclipse.jgit.lib.BaseRepositoryBuilder; | |
| import org.eclipse.jgit.lib.BlobBasedConfig; | |
| import org.eclipse.jgit.lib.Config; | |
| import org.eclipse.jgit.lib.ConfigConstants; | |
| import org.eclipse.jgit.lib.Constants; | |
| import org.eclipse.jgit.lib.FileMode; | |
| import org.eclipse.jgit.lib.ObjectId; | |
| import org.eclipse.jgit.lib.Ref; | |
| import org.eclipse.jgit.lib.Repository; | |
| import org.eclipse.jgit.lib.RepositoryBuilder; | |
| import org.eclipse.jgit.lib.RepositoryBuilderFactory; | |
| import org.eclipse.jgit.lib.StoredConfig; | |
| import org.eclipse.jgit.storage.file.FileBasedConfig; | |
| import org.eclipse.jgit.treewalk.AbstractTreeIterator; | |
| import org.eclipse.jgit.treewalk.CanonicalTreeParser; | |
| import org.eclipse.jgit.treewalk.TreeWalk; | |
| import org.eclipse.jgit.treewalk.filter.PathFilter; | |
| import org.eclipse.jgit.treewalk.filter.TreeFilter; | |
| import org.eclipse.jgit.util.FS; | |
| /** | |
| * Walker that visits all submodule entries found in a tree | |
| */ | |
| public class SubmoduleWalk implements AutoCloseable { | |
| /** | |
| * The values for the config parameter submodule.<name>.ignore | |
| * | |
| * @since 3.6 | |
| */ | |
| public enum IgnoreSubmoduleMode { | |
| /** | |
| * Ignore all modifications to submodules | |
| */ | |
| ALL, | |
| /** | |
| * Ignore changes to the working tree of a submodule | |
| */ | |
| DIRTY, | |
| /** | |
| * Ignore changes to untracked files in the working tree of a submodule | |
| */ | |
| UNTRACKED, | |
| /** | |
| * Ignore nothing. That's the default | |
| */ | |
| NONE; | |
| } | |
| /** | |
| * Create a generator to walk over the submodule entries currently in the | |
| * index | |
| * | |
| * The {@code .gitmodules} file is read from the index. | |
| * | |
| * @param repository | |
| * a {@link org.eclipse.jgit.lib.Repository} object. | |
| * @return generator over submodule index entries. The caller is responsible | |
| * for calling {@link #close()}. | |
| * @throws java.io.IOException | |
| * if an IO error occurred | |
| */ | |
| public static SubmoduleWalk forIndex(Repository repository) | |
| throws IOException { | |
| @SuppressWarnings("resource") // The caller closes it | |
| SubmoduleWalk generator = new SubmoduleWalk(repository); | |
| try { | |
| DirCache index = repository.readDirCache(); | |
| generator.setTree(new DirCacheIterator(index)); | |
| } catch (IOException e) { | |
| generator.close(); | |
| throw e; | |
| } | |
| return generator; | |
| } | |
| /** | |
| * Create a generator and advance it to the submodule entry at the given | |
| * path | |
| * | |
| * @param repository | |
| * a {@link org.eclipse.jgit.lib.Repository} object. | |
| * @param treeId | |
| * the root of a tree containing both a submodule at the given | |
| * path and .gitmodules at the root. | |
| * @param path | |
| * a {@link java.lang.String} object. | |
| * @return generator at given path. The caller is responsible for calling | |
| * {@link #close()}. Null if no submodule at given path. | |
| * @throws java.io.IOException | |
| * if an IO error occurred | |
| */ | |
| public static SubmoduleWalk forPath(Repository repository, | |
| AnyObjectId treeId, String path) throws IOException { | |
| SubmoduleWalk generator = new SubmoduleWalk(repository); | |
| try { | |
| generator.setTree(treeId); | |
| PathFilter filter = PathFilter.create(path); | |
| generator.setFilter(filter); | |
| generator.setRootTree(treeId); | |
| while (generator.next()) | |
| if (filter.isDone(generator.walk)) | |
| return generator; | |
| } catch (IOException e) { | |
| generator.close(); | |
| throw e; | |
| } | |
| generator.close(); | |
| return null; | |
| } | |
| /** | |
| * Create a generator and advance it to the submodule entry at the given | |
| * path | |
| * | |
| * @param repository | |
| * a {@link org.eclipse.jgit.lib.Repository} object. | |
| * @param iterator | |
| * the root of a tree containing both a submodule at the given | |
| * path and .gitmodules at the root. | |
| * @param path | |
| * a {@link java.lang.String} object. | |
| * @return generator at given path. The caller is responsible for calling | |
| * {@link #close()}. Null if no submodule at given path. | |
| * @throws java.io.IOException | |
| * if an IO error occurred | |
| */ | |
| public static SubmoduleWalk forPath(Repository repository, | |
| AbstractTreeIterator iterator, String path) throws IOException { | |
| SubmoduleWalk generator = new SubmoduleWalk(repository); | |
| try { | |
| generator.setTree(iterator); | |
| PathFilter filter = PathFilter.create(path); | |
| generator.setFilter(filter); | |
| generator.setRootTree(iterator); | |
| while (generator.next()) | |
| if (filter.isDone(generator.walk)) | |
| return generator; | |
| } catch (IOException e) { | |
| generator.close(); | |
| throw e; | |
| } | |
| generator.close(); | |
| return null; | |
| } | |
| /** | |
| * Get submodule directory | |
| * | |
| * @param parent | |
| * the {@link org.eclipse.jgit.lib.Repository}. | |
| * @param path | |
| * submodule path | |
| * @return directory | |
| */ | |
| public static File getSubmoduleDirectory(final Repository parent, | |
| final String path) { | |
| return new File(parent.getWorkTree(), path); | |
| } | |
| /** | |
| * Get submodule repository | |
| * | |
| * @param parent | |
| * the {@link org.eclipse.jgit.lib.Repository}. | |
| * @param path | |
| * submodule path | |
| * @return repository or null if repository doesn't exist | |
| * @throws java.io.IOException | |
| * if an IO error occurred | |
| */ | |
| public static Repository getSubmoduleRepository(final Repository parent, | |
| final String path) throws IOException { | |
| return getSubmoduleRepository(parent.getWorkTree(), path, | |
| parent.getFS()); | |
| } | |
| /** | |
| * Get submodule repository at path | |
| * | |
| * @param parent | |
| * the parent | |
| * @param path | |
| * submodule path | |
| * @return repository or null if repository doesn't exist | |
| * @throws java.io.IOException | |
| * if an IO error occurred | |
| */ | |
| public static Repository getSubmoduleRepository(final File parent, | |
| final String path) throws IOException { | |
| return getSubmoduleRepository(parent, path, FS.DETECTED); | |
| } | |
| /** | |
| * Get submodule repository at path, using the specified file system | |
| * abstraction | |
| * | |
| * @param parent | |
| * {@link Repository} that contains the submodule | |
| * @param path | |
| * of the working tree of the submodule | |
| * @param fs | |
| * the file system abstraction to be used | |
| * @return repository or null if repository doesn't exist | |
| * @throws IOException | |
| * if an IO error occurred | |
| * @since 4.10 | |
| */ | |
| public static Repository getSubmoduleRepository(final File parent, | |
| final String path, FS fs) throws IOException { | |
| return getSubmoduleRepository(parent, path, fs, | |
| new RepositoryBuilder()); | |
| } | |
| /** | |
| * Get submodule repository at path, using the specified file system | |
| * abstraction and the specified builder | |
| * | |
| * @param parent | |
| * {@link Repository} that contains the submodule | |
| * @param path | |
| * of the working tree of the submodule | |
| * @param fs | |
| * {@link FS} to use | |
| * @param builder | |
| * {@link BaseRepositoryBuilder} to use to build the submodule | |
| * repository | |
| * @return the {@link Repository} of the submodule, or {@code null} if it | |
| * doesn't exist | |
| * @throws IOException | |
| * if an IO error occurred | |
| * @since 5.6 | |
| */ | |
| public static Repository getSubmoduleRepository(File parent, String path, | |
| FS fs, BaseRepositoryBuilder<?, ? extends Repository> builder) | |
| throws IOException { | |
| File subWorkTree = new File(parent, path); | |
| if (!subWorkTree.isDirectory()) { | |
| return null; | |
| } | |
| try { | |
| return builder // | |
| .setMustExist(true) // | |
| .setFS(fs) // | |
| .setWorkTree(subWorkTree) // | |
| .build(); | |
| } catch (RepositoryNotFoundException e) { | |
| return null; | |
| } | |
| } | |
| /** | |
| * Resolve submodule repository URL. | |
| * <p> | |
| * This handles relative URLs that are typically specified in the | |
| * '.gitmodules' file by resolving them against the remote URL of the parent | |
| * repository. | |
| * <p> | |
| * Relative URLs will be resolved against the parent repository's working | |
| * directory if the parent repository has no configured remote URL. | |
| * | |
| * @param parent | |
| * parent repository | |
| * @param url | |
| * absolute or relative URL of the submodule repository | |
| * @return resolved URL | |
| * @throws java.io.IOException | |
| * if an IO error occurred | |
| */ | |
| public static String getSubmoduleRemoteUrl(final Repository parent, | |
| final String url) throws IOException { | |
| if (!url.startsWith("./") && !url.startsWith("../")) //$NON-NLS-1$ //$NON-NLS-2$ | |
| return url; | |
| String remoteName = null; | |
| // Look up remote URL associated wit HEAD ref | |
| Ref ref = parent.exactRef(Constants.HEAD); | |
| if (ref != null) { | |
| if (ref.isSymbolic()) | |
| ref = ref.getLeaf(); | |
| remoteName = parent.getConfig().getString( | |
| ConfigConstants.CONFIG_BRANCH_SECTION, | |
| Repository.shortenRefName(ref.getName()), | |
| ConfigConstants.CONFIG_KEY_REMOTE); | |
| } | |
| // Fall back to 'origin' if current HEAD ref has no remote URL | |
| if (remoteName == null) | |
| remoteName = Constants.DEFAULT_REMOTE_NAME; | |
| String remoteUrl = parent.getConfig().getString( | |
| ConfigConstants.CONFIG_REMOTE_SECTION, remoteName, | |
| ConfigConstants.CONFIG_KEY_URL); | |
| // Fall back to parent repository's working directory if no remote URL | |
| if (remoteUrl == null) { | |
| remoteUrl = parent.getWorkTree().getAbsolutePath(); | |
| // Normalize slashes to '/' | |
| if ('\\' == File.separatorChar) | |
| remoteUrl = remoteUrl.replace('\\', '/'); | |
| } | |
| // Remove trailing '/' | |
| if (remoteUrl.charAt(remoteUrl.length() - 1) == '/') | |
| remoteUrl = remoteUrl.substring(0, remoteUrl.length() - 1); | |
| char separator = '/'; | |
| String submoduleUrl = url; | |
| while (submoduleUrl.length() > 0) { | |
| if (submoduleUrl.startsWith("./")) //$NON-NLS-1$ | |
| submoduleUrl = submoduleUrl.substring(2); | |
| else if (submoduleUrl.startsWith("../")) { //$NON-NLS-1$ | |
| int lastSeparator = remoteUrl.lastIndexOf('/'); | |
| if (lastSeparator < 1) { | |
| lastSeparator = remoteUrl.lastIndexOf(':'); | |
| separator = ':'; | |
| } | |
| if (lastSeparator < 1) | |
| throw new IOException(MessageFormat.format( | |
| JGitText.get().submoduleParentRemoteUrlInvalid, | |
| remoteUrl)); | |
| remoteUrl = remoteUrl.substring(0, lastSeparator); | |
| submoduleUrl = submoduleUrl.substring(3); | |
| } else | |
| break; | |
| } | |
| return remoteUrl + separator + submoduleUrl; | |
| } | |
| private final Repository repository; | |
| private final TreeWalk walk; | |
| private StoredConfig repoConfig; | |
| private AbstractTreeIterator rootTree; | |
| private Config modulesConfig; | |
| private String path; | |
| private Map<String, String> pathToName; | |
| private RepositoryBuilderFactory factory; | |
| /** | |
| * Create submodule generator | |
| * | |
| * @param repository | |
| * the {@link org.eclipse.jgit.lib.Repository}. | |
| * @throws java.io.IOException | |
| * if an IO error occurred | |
| */ | |
| public SubmoduleWalk(Repository repository) throws IOException { | |
| this.repository = repository; | |
| repoConfig = repository.getConfig(); | |
| walk = new TreeWalk(repository); | |
| walk.setRecursive(true); | |
| } | |
| /** | |
| * Set the config used by this walk. | |
| * | |
| * This method need only be called if constructing a walk manually instead of | |
| * with one of the static factory methods above. | |
| * | |
| * @param config | |
| * .gitmodules config object | |
| * @return this generator | |
| */ | |
| public SubmoduleWalk setModulesConfig(Config config) { | |
| modulesConfig = config; | |
| loadPathNames(); | |
| return this; | |
| } | |
| /** | |
| * Set the tree used by this walk for finding {@code .gitmodules}. | |
| * <p> | |
| * The root tree is not read until the first submodule is encountered by the | |
| * walk. | |
| * <p> | |
| * This method need only be called if constructing a walk manually instead of | |
| * with one of the static factory methods above. | |
| * | |
| * @param tree | |
| * tree containing .gitmodules | |
| * @return this generator | |
| */ | |
| public SubmoduleWalk setRootTree(AbstractTreeIterator tree) { | |
| rootTree = tree; | |
| modulesConfig = null; | |
| pathToName = null; | |
| return this; | |
| } | |
| /** | |
| * Set the tree used by this walk for finding {@code .gitmodules}. | |
| * <p> | |
| * The root tree is not read until the first submodule is encountered by the | |
| * walk. | |
| * <p> | |
| * This method need only be called if constructing a walk manually instead | |
| * of with one of the static factory methods above. | |
| * | |
| * @param id | |
| * ID of a tree containing .gitmodules | |
| * @return this generator | |
| * @throws java.io.IOException | |
| * if an IO error occurred | |
| */ | |
| public SubmoduleWalk setRootTree(AnyObjectId id) throws IOException { | |
| final CanonicalTreeParser p = new CanonicalTreeParser(); | |
| p.reset(walk.getObjectReader(), id); | |
| rootTree = p; | |
| modulesConfig = null; | |
| pathToName = null; | |
| return this; | |
| } | |
| /** | |
| * Load the config for this walk from {@code .gitmodules}. | |
| * <p> | |
| * Uses the root tree if {@link #setRootTree(AbstractTreeIterator)} was | |
| * previously called, otherwise uses the working tree. | |
| * <p> | |
| * If no submodule config is found, loads an empty config. | |
| * | |
| * @return this generator | |
| * @throws java.io.IOException | |
| * if an error occurred, or if the repository is bare | |
| * @throws org.eclipse.jgit.errors.ConfigInvalidException | |
| * if .gitmodules config is invalid | |
| */ | |
| public SubmoduleWalk loadModulesConfig() throws IOException, ConfigInvalidException { | |
| if (rootTree == null) { | |
| File modulesFile = new File(repository.getWorkTree(), | |
| Constants.DOT_GIT_MODULES); | |
| FileBasedConfig config = new FileBasedConfig(modulesFile, | |
| repository.getFS()); | |
| config.load(); | |
| modulesConfig = config; | |
| loadPathNames(); | |
| } else { | |
| try (TreeWalk configWalk = new TreeWalk(repository)) { | |
| configWalk.addTree(rootTree); | |
| // The root tree may be part of the submodule walk, so we need to revert | |
| // it after this walk. | |
| int idx; | |
| for (idx = 0; !rootTree.first(); idx++) { | |
| rootTree.back(1); | |
| } | |
| try { | |
| configWalk.setRecursive(false); | |
| PathFilter filter = PathFilter.create(Constants.DOT_GIT_MODULES); | |
| configWalk.setFilter(filter); | |
| while (configWalk.next()) { | |
| if (filter.isDone(configWalk)) { | |
| modulesConfig = new BlobBasedConfig(null, repository, | |
| configWalk.getObjectId(0)); | |
| loadPathNames(); | |
| return this; | |
| } | |
| } | |
| modulesConfig = new Config(); | |
| pathToName = null; | |
| } finally { | |
| if (idx > 0) | |
| rootTree.next(idx); | |
| } | |
| } | |
| } | |
| return this; | |
| } | |
| private void loadPathNames() { | |
| pathToName = null; | |
| if (modulesConfig != null) { | |
| HashMap<String, String> pathNames = new HashMap<>(); | |
| for (String name : modulesConfig | |
| .getSubsections(ConfigConstants.CONFIG_SUBMODULE_SECTION)) { | |
| pathNames.put(modulesConfig.getString( | |
| ConfigConstants.CONFIG_SUBMODULE_SECTION, name, | |
| ConfigConstants.CONFIG_KEY_PATH), name); | |
| } | |
| pathToName = pathNames; | |
| } | |
| } | |
| /** | |
| * Checks whether the working tree contains a .gitmodules file. That's a | |
| * hint that the repo contains submodules. | |
| * | |
| * @param repository | |
| * the repository to check | |
| * @return <code>true</code> if the working tree contains a .gitmodules | |
| * file, <code>false</code> otherwise. Always returns | |
| * <code>false</code> for bare repositories. | |
| * @throws java.io.IOException | |
| * if an IO error occurred | |
| * @throws CorruptObjectException | |
| * if a corrupt object was found | |
| * @since 3.6 | |
| */ | |
| public static boolean containsGitModulesFile(Repository repository) | |
| throws IOException { | |
| if (repository.isBare()) { | |
| return false; | |
| } | |
| File modulesFile = new File(repository.getWorkTree(), | |
| Constants.DOT_GIT_MODULES); | |
| return modulesFile.exists(); | |
| } | |
| private void lazyLoadModulesConfig() throws IOException, ConfigInvalidException { | |
| if (modulesConfig == null) { | |
| loadModulesConfig(); | |
| } | |
| } | |
| private String getModuleName(String modulePath) { | |
| String name = pathToName != null ? pathToName.get(modulePath) : null; | |
| return name != null ? name : modulePath; | |
| } | |
| /** | |
| * Set tree filter | |
| * | |
| * @param filter | |
| * a {@link org.eclipse.jgit.treewalk.filter.TreeFilter} object. | |
| * @return this generator | |
| */ | |
| public SubmoduleWalk setFilter(TreeFilter filter) { | |
| walk.setFilter(filter); | |
| return this; | |
| } | |
| /** | |
| * Set the tree iterator used for finding submodule entries | |
| * | |
| * @param iterator | |
| * an {@link org.eclipse.jgit.treewalk.AbstractTreeIterator} | |
| * object. | |
| * @return this generator | |
| * @throws org.eclipse.jgit.errors.CorruptObjectException | |
| * if a corrupt object was found | |
| */ | |
| public SubmoduleWalk setTree(AbstractTreeIterator iterator) | |
| throws CorruptObjectException { | |
| walk.addTree(iterator); | |
| return this; | |
| } | |
| /** | |
| * Set the tree used for finding submodule entries | |
| * | |
| * @param treeId | |
| * an {@link org.eclipse.jgit.lib.AnyObjectId} object. | |
| * @return this generator | |
| * @throws java.io.IOException | |
| * if an IO error occurred | |
| * @throws IncorrectObjectTypeException | |
| * if object has unexpected type | |
| * @throws MissingObjectException | |
| * if object is missing | |
| */ | |
| public SubmoduleWalk setTree(AnyObjectId treeId) throws IOException { | |
| walk.addTree(treeId); | |
| return this; | |
| } | |
| /** | |
| * Reset generator and start new submodule walk | |
| * | |
| * @return this generator | |
| */ | |
| public SubmoduleWalk reset() { | |
| repoConfig = repository.getConfig(); | |
| modulesConfig = null; | |
| pathToName = null; | |
| walk.reset(); | |
| return this; | |
| } | |
| /** | |
| * Get directory that will be the root of the submodule's local repository | |
| * | |
| * @return submodule repository directory | |
| */ | |
| public File getDirectory() { | |
| return getSubmoduleDirectory(repository, path); | |
| } | |
| /** | |
| * Advance to next submodule in the index tree. | |
| * | |
| * The object id and path of the next entry can be obtained by calling | |
| * {@link #getObjectId()} and {@link #getPath()}. | |
| * | |
| * @return true if entry found, false otherwise | |
| * @throws java.io.IOException | |
| * if an IO error occurred | |
| */ | |
| public boolean next() throws IOException { | |
| while (walk.next()) { | |
| if (FileMode.GITLINK != walk.getFileMode(0)) | |
| continue; | |
| path = walk.getPathString(); | |
| return true; | |
| } | |
| path = null; | |
| return false; | |
| } | |
| /** | |
| * Get path of current submodule entry | |
| * | |
| * @return path | |
| */ | |
| public String getPath() { | |
| return path; | |
| } | |
| /** | |
| * Sets the {@link RepositoryBuilderFactory} to use for creating submodule | |
| * repositories. If none is set, a plain {@link RepositoryBuilder} is used. | |
| * | |
| * @param factory | |
| * to set | |
| * @since 5.6 | |
| */ | |
| public void setBuilderFactory(RepositoryBuilderFactory factory) { | |
| this.factory = factory; | |
| } | |
| private BaseRepositoryBuilder<?, ? extends Repository> getBuilder() { | |
| return factory != null ? factory.get() : new RepositoryBuilder(); | |
| } | |
| /** | |
| * The module name for the current submodule entry (used for the section | |
| * name of .git/config) | |
| * | |
| * @since 4.10 | |
| * @return name of the submodule | |
| * @throws ConfigInvalidException | |
| * if the .gitmodules config is invalid | |
| * @throws IOException | |
| * if an IO error occurred | |
| */ | |
| public String getModuleName() throws IOException, ConfigInvalidException { | |
| lazyLoadModulesConfig(); | |
| return getModuleName(path); | |
| } | |
| /** | |
| * Get object id of current submodule entry | |
| * | |
| * @return object id | |
| */ | |
| public ObjectId getObjectId() { | |
| return walk.getObjectId(0); | |
| } | |
| /** | |
| * Get the configured path for current entry. This will be the value from | |
| * the .gitmodules file in the current repository's working tree. | |
| * | |
| * @return configured path | |
| * @throws org.eclipse.jgit.errors.ConfigInvalidException | |
| * if .gitmodules config is invalid | |
| * @throws java.io.IOException | |
| * if an IO error occurred | |
| */ | |
| public String getModulesPath() throws IOException, ConfigInvalidException { | |
| lazyLoadModulesConfig(); | |
| return modulesConfig.getString(ConfigConstants.CONFIG_SUBMODULE_SECTION, | |
| getModuleName(), ConfigConstants.CONFIG_KEY_PATH); | |
| } | |
| /** | |
| * Get the configured remote URL for current entry. This will be the value | |
| * from the repository's config. | |
| * | |
| * @return configured URL | |
| * @throws org.eclipse.jgit.errors.ConfigInvalidException | |
| * if .gitmodules config is invalid | |
| * @throws java.io.IOException | |
| * if an IO error occurred | |
| */ | |
| public String getConfigUrl() throws IOException, ConfigInvalidException { | |
| return repoConfig.getString(ConfigConstants.CONFIG_SUBMODULE_SECTION, | |
| getModuleName(), ConfigConstants.CONFIG_KEY_URL); | |
| } | |
| /** | |
| * Get the configured remote URL for current entry. This will be the value | |
| * from the .gitmodules file in the current repository's working tree. | |
| * | |
| * @return configured URL | |
| * @throws org.eclipse.jgit.errors.ConfigInvalidException | |
| * if .gitmodules config is invalid | |
| * @throws java.io.IOException | |
| * if an IO error occurred | |
| */ | |
| public String getModulesUrl() throws IOException, ConfigInvalidException { | |
| lazyLoadModulesConfig(); | |
| return modulesConfig.getString(ConfigConstants.CONFIG_SUBMODULE_SECTION, | |
| getModuleName(), ConfigConstants.CONFIG_KEY_URL); | |
| } | |
| /** | |
| * Get the configured update field for current entry. This will be the value | |
| * from the repository's config. | |
| * | |
| * @return update value | |
| * @throws org.eclipse.jgit.errors.ConfigInvalidException | |
| * if .gitmodules config is invalid | |
| * @throws java.io.IOException | |
| * if an IO error occurred | |
| */ | |
| public String getConfigUpdate() throws IOException, ConfigInvalidException { | |
| return repoConfig.getString(ConfigConstants.CONFIG_SUBMODULE_SECTION, | |
| getModuleName(), ConfigConstants.CONFIG_KEY_UPDATE); | |
| } | |
| /** | |
| * Get the configured update field for current entry. This will be the value | |
| * from the .gitmodules file in the current repository's working tree. | |
| * | |
| * @return update value | |
| * @throws org.eclipse.jgit.errors.ConfigInvalidException | |
| * if .gitmodules config is invalid | |
| * @throws java.io.IOException | |
| * if an IO error occurred | |
| */ | |
| public String getModulesUpdate() throws IOException, ConfigInvalidException { | |
| lazyLoadModulesConfig(); | |
| return modulesConfig.getString(ConfigConstants.CONFIG_SUBMODULE_SECTION, | |
| getModuleName(), ConfigConstants.CONFIG_KEY_UPDATE); | |
| } | |
| /** | |
| * Get the configured ignore field for the current entry. This will be the | |
| * value from the .gitmodules file in the current repository's working tree. | |
| * | |
| * @return ignore value | |
| * @throws org.eclipse.jgit.errors.ConfigInvalidException | |
| * if .gitmodules config is invalid | |
| * @throws java.io.IOException | |
| * if an IO error occurred | |
| * @since 3.6 | |
| */ | |
| public IgnoreSubmoduleMode getModulesIgnore() throws IOException, | |
| ConfigInvalidException { | |
| IgnoreSubmoduleMode mode = repoConfig.getEnum( | |
| IgnoreSubmoduleMode.values(), | |
| ConfigConstants.CONFIG_SUBMODULE_SECTION, getModuleName(), | |
| ConfigConstants.CONFIG_KEY_IGNORE); | |
| if (mode != null) { | |
| return mode; | |
| } | |
| lazyLoadModulesConfig(); | |
| return modulesConfig.getEnum(ConfigConstants.CONFIG_SUBMODULE_SECTION, | |
| getModuleName(), ConfigConstants.CONFIG_KEY_IGNORE, | |
| IgnoreSubmoduleMode.NONE); | |
| } | |
| /** | |
| * Get repository for current submodule entry | |
| * | |
| * @return repository or null if non-existent | |
| * @throws java.io.IOException | |
| * if an IO error occurred | |
| */ | |
| public Repository getRepository() throws IOException { | |
| return getSubmoduleRepository(repository.getWorkTree(), path, | |
| repository.getFS(), getBuilder()); | |
| } | |
| /** | |
| * Get commit id that HEAD points to in the current submodule's repository | |
| * | |
| * @return object id of HEAD reference | |
| * @throws java.io.IOException | |
| * if an IO error occurred | |
| */ | |
| public ObjectId getHead() throws IOException { | |
| try (Repository subRepo = getRepository()) { | |
| if (subRepo == null) { | |
| return null; | |
| } | |
| return subRepo.resolve(Constants.HEAD); | |
| } | |
| } | |
| /** | |
| * Get ref that HEAD points to in the current submodule's repository | |
| * | |
| * @return ref name, null on failures | |
| * @throws java.io.IOException | |
| * if an IO error occurred | |
| */ | |
| public String getHeadRef() throws IOException { | |
| try (Repository subRepo = getRepository()) { | |
| if (subRepo == null) { | |
| return null; | |
| } | |
| Ref head = subRepo.exactRef(Constants.HEAD); | |
| return head != null ? head.getLeaf().getName() : null; | |
| } | |
| } | |
| /** | |
| * Get the resolved remote URL for the current submodule. | |
| * <p> | |
| * This method resolves the value of {@link #getModulesUrl()} to an absolute | |
| * URL | |
| * | |
| * @return resolved remote URL | |
| * @throws java.io.IOException | |
| * if an IO error occurred | |
| * @throws org.eclipse.jgit.errors.ConfigInvalidException | |
| * if .gitmodules config is invalid | |
| */ | |
| public String getRemoteUrl() throws IOException, ConfigInvalidException { | |
| String url = getModulesUrl(); | |
| return url != null ? getSubmoduleRemoteUrl(repository, url) : null; | |
| } | |
| /** | |
| * {@inheritDoc} | |
| * <p> | |
| * Release any resources used by this walker's reader. | |
| * | |
| * @since 4.0 | |
| */ | |
| @Override | |
| public void close() { | |
| walk.close(); | |
| } | |
| } |