From 243fba9a0ae7e4f6679338c8b7175cc2a0ec06f2 Mon Sep 17 00:00:00 2001 From: David Turner Date: Fri, 13 Oct 2017 14:56:04 -0400 Subject: [PATCH] Add a command to deinitialize submodules Change-Id: Iaaefc2cbafbf083d6ab158b1c378ec69cc76d282 Signed-off-by: David Turner Signed-off-by: Matthias Sohn --- .../jgit/submodule/SubmoduleDeinitTest.java | 251 ++++++++++++++ .../eclipse/jgit/internal/JGitText.properties | 2 + .../src/org/eclipse/jgit/api/Git.java | 13 +- .../jgit/api/SubmoduleDeinitCommand.java | 319 ++++++++++++++++++ .../jgit/api/SubmoduleDeinitResult.java | 105 ++++++ .../org/eclipse/jgit/internal/JGitText.java | 2 + 6 files changed, 691 insertions(+), 1 deletion(-) create mode 100644 org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleDeinitTest.java create mode 100644 org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleDeinitCommand.java create mode 100644 org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleDeinitResult.java diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleDeinitTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleDeinitTest.java new file mode 100644 index 000000000..df4b96398 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleDeinitTest.java @@ -0,0 +1,251 @@ +/* + * Copyright (C) 2017, Two Sigma Open Source + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.eclipse.jgit.submodule; + +import java.io.File; +import java.io.IOException; +import java.util.Collection; + +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.SubmoduleDeinitCommand; +import org.eclipse.jgit.api.SubmoduleDeinitResult; +import org.eclipse.jgit.api.SubmoduleUpdateCommand; +import org.eclipse.jgit.api.errors.GitAPIException; +import org.eclipse.jgit.dircache.DirCache; +import org.eclipse.jgit.dircache.DirCacheEditor; +import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit; +import org.eclipse.jgit.dircache.DirCacheEntry; +import org.eclipse.jgit.junit.JGitTestUtil; +import org.eclipse.jgit.junit.RepositoryTestCase; +import org.eclipse.jgit.lib.ConfigConstants; +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.lib.StoredConfig; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.storage.file.FileBasedConfig; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +/** + * Unit tests of {@link SubmoduleDeinitCommand} + */ +public class SubmoduleDeinitTest extends RepositoryTestCase { + + @Test + public void repositoryWithNoSubmodules() throws GitAPIException { + SubmoduleDeinitCommand command = new SubmoduleDeinitCommand(db); + Collection modules = command.call(); + assertNotNull(modules); + assertTrue(modules.isEmpty()); + } + + @Test + public void alreadyClosedSubmodule() throws Exception { + final String path = "sub"; + Git git = Git.wrap(db); + + commitSubmoduleCreation(path, git); + + SubmoduleDeinitResult result = runDeinit(new SubmoduleDeinitCommand(db).addPath("sub")); + assertEquals(path, result.getPath()); + assertEquals(SubmoduleDeinitCommand.SubmoduleDeinitStatus.ALREADY_DEINITIALIZED, result.getStatus()); + } + + @Test + public void dirtySubmoduleBecauseUntracked() throws Exception { + final String path = "sub"; + Git git = Git.wrap(db); + + commitSubmoduleCreation(path, git); + + Collection updated = new SubmoduleUpdateCommand(db).addPath(path).setFetch(false).call(); + assertEquals(1, updated.size()); + + File submoduleDir = assertSubmoduleIsInitialized(); + SubmoduleWalk generator; + + write(new File(submoduleDir, "untracked"), "untracked"); + + SubmoduleDeinitResult result = runDeinit(new SubmoduleDeinitCommand(db).addPath("sub")); + assertEquals(path, result.getPath()); + assertEquals(SubmoduleDeinitCommand.SubmoduleDeinitStatus.DIRTY, result.getStatus()); + + generator = SubmoduleWalk.forIndex(db); + assertTrue(generator.next()); + assertTrue(submoduleDir.isDirectory()); + assertNotEquals(0, submoduleDir.list().length); + } + + @Test + public void dirtySubmoduleBecauseNewCommit() throws Exception { + final String path = "sub"; + Git git = Git.wrap(db); + + commitSubmoduleCreation(path, git); + + Collection updated = new SubmoduleUpdateCommand(db).addPath(path).setFetch(false).call(); + assertEquals(1, updated.size()); + + File submoduleDir = assertSubmoduleIsInitialized(); + SubmoduleWalk generator = SubmoduleWalk.forIndex(db); + generator.next(); + + //want to create a commit inside the repo... + Repository submoduleLocalRepo = generator.getRepository(); + JGitTestUtil.writeTrashFile(submoduleLocalRepo, "file.txt", "new data"); + Git.wrap(submoduleLocalRepo).commit().setAll(true).setMessage("local commit").call(); + + SubmoduleDeinitResult result = runDeinit(new SubmoduleDeinitCommand(db).addPath("sub")); + assertEquals(path, result.getPath()); + assertEquals(SubmoduleDeinitCommand.SubmoduleDeinitStatus.DIRTY, result.getStatus()); + + generator = SubmoduleWalk.forIndex(db); + assertTrue(generator.next()); + assertTrue(submoduleDir.isDirectory()); + assertNotEquals(0, submoduleDir.list().length); + } + + private File assertSubmoduleIsInitialized() throws IOException { + SubmoduleWalk generator = SubmoduleWalk.forIndex(db); + assertTrue(generator.next()); + File submoduleDir = new File(db.getWorkTree(), generator.getPath()); + assertTrue(submoduleDir.isDirectory()); + assertNotEquals(0, submoduleDir.list().length); + return submoduleDir; + } + + @Test + public void dirtySubmoduleWithForce() throws Exception { + final String path = "sub"; + Git git = Git.wrap(db); + + commitSubmoduleCreation(path, git); + + Collection updated = new SubmoduleUpdateCommand(db).addPath(path).setFetch(false).call(); + assertEquals(1, updated.size()); + + File submoduleDir = assertSubmoduleIsInitialized(); + + write(new File(submoduleDir, "untracked"), "untracked"); + + SubmoduleDeinitCommand command = new SubmoduleDeinitCommand(db).addPath("sub").setForce(true); + SubmoduleDeinitResult result = runDeinit(command); + assertEquals(path, result.getPath()); + assertEquals(SubmoduleDeinitCommand.SubmoduleDeinitStatus.FORCED, result.getStatus()); + + SubmoduleWalk generator = SubmoduleWalk.forIndex(db); + assertTrue(generator.next()); + assertTrue(submoduleDir.isDirectory()); + assertEquals(0, submoduleDir.list().length); + } + + @Test + public void cleanSubmodule() throws Exception { + final String path = "sub"; + Git git = Git.wrap(db); + + commitSubmoduleCreation(path, git); + + Collection updated = new SubmoduleUpdateCommand(db).addPath(path).setFetch(false).call(); + assertEquals(1, updated.size()); + + File submoduleDir = assertSubmoduleIsInitialized(); + + SubmoduleDeinitResult result = runDeinit(new SubmoduleDeinitCommand(db).addPath("sub")); + assertEquals(path, result.getPath()); + assertEquals(SubmoduleDeinitCommand.SubmoduleDeinitStatus.SUCCESS, result.getStatus()); + + SubmoduleWalk generator = SubmoduleWalk.forIndex(db); + assertTrue(generator.next()); + assertTrue(submoduleDir.isDirectory()); + assertEquals(0, submoduleDir.list().length); + } + + private SubmoduleDeinitResult runDeinit(SubmoduleDeinitCommand command) throws GitAPIException { + Collection deinitialized = command.call(); + assertNotNull(deinitialized); + assertEquals(1, deinitialized.size()); + return deinitialized.iterator().next(); + } + + + private RevCommit commitSubmoduleCreation(String path, Git git) throws IOException, GitAPIException { + writeTrashFile("file.txt", "content"); + git.add().addFilepattern("file.txt").call(); + final RevCommit commit = git.commit().setMessage("create file").call(); + + DirCache cache = db.lockDirCache(); + DirCacheEditor editor = cache.editor(); + editor.add(new PathEdit(path) { + + @Override + public void apply(DirCacheEntry ent) { + ent.setFileMode(FileMode.GITLINK); + ent.setObjectId(commit); + } + }); + editor.commit(); + + StoredConfig config = db.getConfig(); + config.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path, + ConfigConstants.CONFIG_KEY_URL, db.getDirectory().toURI() + .toString()); + config.save(); + + FileBasedConfig modulesConfig = new FileBasedConfig(new File( + db.getWorkTree(), Constants.DOT_GIT_MODULES), db.getFS()); + modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path, + ConfigConstants.CONFIG_KEY_PATH, path); + modulesConfig.save(); + + new File(db.getWorkTree(), "sub").mkdir(); + git.add().addFilepattern(Constants.DOT_GIT_MODULES).call(); + git.commit().setMessage("create submodule").call(); + return commit; + } +} diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties index f626724c4..45032de9b 100644 --- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties +++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties @@ -286,6 +286,7 @@ expectedACKNAKFoundEOF=Expected ACK/NAK, found EOF expectedACKNAKGot=Expected ACK/NAK, got: {0} expectedBooleanStringValue=Expected boolean string value expectedCharacterEncodingGuesses=Expected {0} character encoding guesses +expectedDirectoryNotSubmodule=Expected submodule ''{0}'' to be a directory expectedEOFReceived=expected EOF; received ''{0}'' instead expectedGot=expected ''{0}'', got ''{1}'' expectedLessThanGot=expected less than ''{0}'', got ''{1}'' @@ -701,6 +702,7 @@ unexpectedOddResult=odd: {0} + {1} - {2} unexpectedRefReport={0}: unexpected ref report: {1} unexpectedReportLine=unexpected report line: {0} unexpectedReportLine2={0} unexpected report line: {1} +unexpectedSubmoduleStatus=Unexpected submodule status: ''{0}'' unknownOrUnsupportedCommand=Unknown or unsupported command "{0}", only "{1}" is allowed. unknownDIRCVersion=Unknown DIRC version {0} unknownHost=unknown host diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/Git.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/Git.java index 516620b43..400a7dfe4 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/Git.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/Git.java @@ -623,7 +623,18 @@ public class Git implements AutoCloseable { } /** - * Return a command object to execute a {@code submodule status} command + * Returns a command object to execute a {@code submodule deinit} command + * + * @return a {@link org.eclipse.jgit.api.SubmoduleDeinitCommand} used to + * remove a submodule's working tree manifestation + * @since 4.10 + */ + public SubmoduleDeinitCommand submoduleDeinit() { + return new SubmoduleDeinitCommand(repo); + } + + /** + * Returns a command object to execute a {@code submodule status} command * * @return a {@link org.eclipse.jgit.api.SubmoduleStatusCommand} used to * report the status of a repository's configured submodules diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleDeinitCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleDeinitCommand.java new file mode 100644 index 000000000..569a8e359 --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleDeinitCommand.java @@ -0,0 +1,319 @@ +/* + * Copyright (C) 2017, Two Sigma Open Source + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.eclipse.jgit.api; + +import static org.eclipse.jgit.util.FileUtils.RECURSIVE; + +import java.io.File; +import java.io.IOException; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import org.eclipse.jgit.api.errors.GitAPIException; +import org.eclipse.jgit.api.errors.JGitInternalException; +import org.eclipse.jgit.api.errors.NoHeadException; +import org.eclipse.jgit.internal.JGitText; +import org.eclipse.jgit.lib.ConfigConstants; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.Ref; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.lib.StoredConfig; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.revwalk.RevTree; +import org.eclipse.jgit.revwalk.RevWalk; +import org.eclipse.jgit.submodule.SubmoduleWalk; +import org.eclipse.jgit.treewalk.filter.PathFilter; +import org.eclipse.jgit.treewalk.filter.PathFilterGroup; +import org.eclipse.jgit.treewalk.filter.TreeFilter; +import org.eclipse.jgit.util.FileUtils; + +/** + * A class used to execute a submodule deinit command. + *

+ * This will remove the module(s) from the working tree, but won't affect + * .git/modules. + * + * @since 4.10 + * @see Git documentation about submodules + */ +public class SubmoduleDeinitCommand + extends GitCommand> { + + private final Collection paths; + + private boolean force; + + /** + * Constructor of SubmoduleDeinitCommand + * + * @param repo + */ + public SubmoduleDeinitCommand(Repository repo) { + super(repo); + paths = new ArrayList<>(); + } + + /** + * {@inheritDoc} + *

+ * + * @return the set of repositories successfully deinitialized. + * @throws NoSuchSubmoduleException + * if any of the submodules which we might want to deinitialize + * don't exist + */ + @Override + public Collection call() throws GitAPIException { + checkCallable(); + try { + if (paths.isEmpty()) { + return Collections.emptyList(); + } + for (String path : paths) { + if (!submoduleExists(path)) { + throw new NoSuchSubmoduleException(path); + } + } + List results = new ArrayList<>(paths.size()); + try (RevWalk revWalk = new RevWalk(repo); + SubmoduleWalk generator = SubmoduleWalk.forIndex(repo)) { + generator.setFilter(PathFilterGroup.createFromStrings(paths)); + StoredConfig config = repo.getConfig(); + while (generator.next()) { + String path = generator.getPath(); + String name = generator.getModuleName(); + SubmoduleDeinitStatus status = checkDirty(revWalk, path); + switch (status) { + case SUCCESS: + deinit(path); + break; + case ALREADY_DEINITIALIZED: + break; + case DIRTY: + if (force) { + deinit(path); + status = SubmoduleDeinitStatus.FORCED; + } + break; + default: + throw new JGitInternalException(MessageFormat.format( + JGitText.get().unexpectedSubmoduleStatus, + status)); + } + + config.unsetSection( + ConfigConstants.CONFIG_SUBMODULE_SECTION, name); + results.add(new SubmoduleDeinitResult(path, status)); + } + } + return results; + } catch (IOException e) { + throw new JGitInternalException(e.getMessage(), e); + } + } + + /** + * Recursively delete the *contents* of path, but leave path as an empty + * directory + * + * @param path + * the path to clean + * @throws IOException + */ + private void deinit(String path) throws IOException { + File dir = new File(repo.getWorkTree(), path); + if (!dir.isDirectory()) { + throw new JGitInternalException(MessageFormat.format( + JGitText.get().expectedDirectoryNotSubmodule, path)); + } + final File[] ls = dir.listFiles(); + if (ls != null) { + for (int i = 0; i < ls.length; i++) { + FileUtils.delete(ls[i], RECURSIVE); + } + } + } + + /** + * Check if a submodule is dirty. A submodule is dirty if there are local + * changes to the submodule relative to its HEAD, including untracked files. + * It is also dirty if the HEAD of the submodule does not match the value in + * the parent repo's index or HEAD. + * + * @param revWalk + * @param path + * @return status of the command + * @throws GitAPIException + * @throws IOException + */ + private SubmoduleDeinitStatus checkDirty(RevWalk revWalk, String path) + throws GitAPIException, IOException { + Ref head = repo.exactRef("HEAD"); //$NON-NLS-1$ + if (head == null) { + throw new NoHeadException( + JGitText.get().invalidRepositoryStateNoHead); + } + RevCommit headCommit = revWalk.parseCommit(head.getObjectId()); + RevTree tree = headCommit.getTree(); + + ObjectId submoduleHead; + try (SubmoduleWalk w = SubmoduleWalk.forPath(repo, tree, path)) { + submoduleHead = w.getHead(); + if (submoduleHead == null) { + // The submodule is not checked out. + return SubmoduleDeinitStatus.ALREADY_DEINITIALIZED; + } + if (!submoduleHead.equals(w.getObjectId())) { + // The submodule's current HEAD doesn't match the value in the + // outer repo's HEAD. + return SubmoduleDeinitStatus.DIRTY; + } + } + + try (SubmoduleWalk w = SubmoduleWalk.forIndex(repo)) { + if (!w.next()) { + // The submodule does not exist in the index (shouldn't happen + // since we check this earlier) + return SubmoduleDeinitStatus.DIRTY; + } + if (!submoduleHead.equals(w.getObjectId())) { + // The submodule's current HEAD doesn't match the value in the + // outer repo's index. + return SubmoduleDeinitStatus.DIRTY; + } + + Repository submoduleRepo = w.getRepository(); + + Status status = Git.wrap(submoduleRepo).status().call(); + return status.isClean() ? SubmoduleDeinitStatus.SUCCESS + : SubmoduleDeinitStatus.DIRTY; + } + } + + /** + * Check if this path is a submodule by checking the index, which is what + * git submodule deinit checks. + * + * @param path + * path of the submodule + * + * @return {@code true} if path exists and is a submodule in index, + * {@code false} otherwise + * @throws IOException + */ + private boolean submoduleExists(String path) throws IOException { + TreeFilter filter = PathFilter.create(path); + try (SubmoduleWalk w = SubmoduleWalk.forIndex(repo)) { + return w.setFilter(filter).next(); + } + } + + /** + * Add repository-relative submodule path to deinitialize + * + * @param path + * (with / as separator) + * @return this command + */ + public SubmoduleDeinitCommand addPath(String path) { + paths.add(path); + return this; + } + + /** + * If {@code true}, call() will deinitialize modules with local changes; + * else it will refuse to do so. + * + * @param force + * @return {@code this} + */ + public SubmoduleDeinitCommand setForce(boolean force) { + this.force = force; + return this; + } + + /** + * The user tried to deinitialize a submodule that doesn't exist in the + * index. + */ + public static class NoSuchSubmoduleException extends GitAPIException { + private static final long serialVersionUID = 1L; + + /** + * Constructor of NoSuchSubmoduleException + * + * @param path + * path of non-existing submodule + */ + public NoSuchSubmoduleException(String path) { + super(MessageFormat.format(JGitText.get().noSuchSubmodule, path)); + } + } + + /** + * The effect of a submodule deinit command for a given path + */ + public enum SubmoduleDeinitStatus { + /** + * The submodule was not initialized in the first place + */ + ALREADY_DEINITIALIZED, + /** + * The submodule was deinitialized + */ + SUCCESS, + /** + * The submodule had local changes, but was deinitialized successfully + */ + FORCED, + /** + * The submodule had local changes and force was false + */ + DIRTY, + } +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleDeinitResult.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleDeinitResult.java new file mode 100644 index 000000000..5a9cbc102 --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleDeinitResult.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2017, Two Sigma Open Source + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.eclipse.jgit.api; + +/** + * The result of a submodule deinit command for a particular path + * + * @since 4.10 + */ +public class SubmoduleDeinitResult { + private String path; + + private SubmoduleDeinitCommand.SubmoduleDeinitStatus status; + + /** + * Constructor for SubmoduleDeinitResult + * + * @param path + * path of the submodule + * @param status + */ + public SubmoduleDeinitResult(String path, + SubmoduleDeinitCommand.SubmoduleDeinitStatus status) { + this.path = path; + this.status = status; + } + + /** + * Get the path of the submodule + * + * @return path of the submodule + */ + public String getPath() { + return path; + } + + /** + * Set the path of the submodule + * + * @param path + * path of the submodule + */ + public void setPath(String path) { + this.path = path; + } + + /** + * Get the status of the command + * + * @return the status of the command + */ + public SubmoduleDeinitCommand.SubmoduleDeinitStatus getStatus() { + return status; + } + + /** + * Set the status of the command + * + * @param status + * the status of the command + */ + public void setStatus(SubmoduleDeinitCommand.SubmoduleDeinitStatus status) { + this.status = status; + } +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java index 5241ea232..e23d2534b 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java @@ -347,6 +347,7 @@ public class JGitText extends TranslationBundle { /***/ public String expectedACKNAKGot; /***/ public String expectedBooleanStringValue; /***/ public String expectedCharacterEncodingGuesses; + /***/ public String expectedDirectoryNotSubmodule; /***/ public String expectedEOFReceived; /***/ public String expectedGot; /***/ public String expectedLessThanGot; @@ -762,6 +763,7 @@ public class JGitText extends TranslationBundle { /***/ public String unexpectedRefReport; /***/ public String unexpectedReportLine; /***/ public String unexpectedReportLine2; + /***/ public String unexpectedSubmoduleStatus; /***/ public String unknownOrUnsupportedCommand; /***/ public String unknownDIRCVersion; /***/ public String unknownHost;