Browse Source
Adds the following commands: - Add - Init - Status - Sync - Update This also updates AddCommand so that file patterns added that are submodules can be staged in the index. Change-Id: Ie5112aa26430e5a2a3acd65a7b0e1d76067dc545 Signed-off-by: Kevin Sawicki <kevin@github.com> Signed-off-by: Chris Aniszczyk <zx@twitter.com>stable-1.3
Kevin Sawicki
13 years ago
committed by
Chris Aniszczyk
21 changed files with 2661 additions and 13 deletions
@ -0,0 +1,172 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2011, GitHub Inc. |
||||||
|
* 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 static org.junit.Assert.assertEquals; |
||||||
|
import static org.junit.Assert.assertNotNull; |
||||||
|
import static org.junit.Assert.assertTrue; |
||||||
|
import static org.junit.Assert.fail; |
||||||
|
|
||||||
|
import java.text.MessageFormat; |
||||||
|
|
||||||
|
import org.eclipse.jgit.JGitText; |
||||||
|
import org.eclipse.jgit.api.Git; |
||||||
|
import org.eclipse.jgit.api.Status; |
||||||
|
import org.eclipse.jgit.api.SubmoduleAddCommand; |
||||||
|
import org.eclipse.jgit.api.errors.JGitInternalException; |
||||||
|
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.lib.Constants; |
||||||
|
import org.eclipse.jgit.lib.FileMode; |
||||||
|
import org.eclipse.jgit.lib.ObjectId; |
||||||
|
import org.eclipse.jgit.lib.Repository; |
||||||
|
import org.eclipse.jgit.lib.RepositoryTestCase; |
||||||
|
import org.eclipse.jgit.revwalk.RevCommit; |
||||||
|
import org.junit.Test; |
||||||
|
|
||||||
|
/** |
||||||
|
* Unit tests of {@link org.eclipse.jgit.api.SubmoduleAddCommand} |
||||||
|
*/ |
||||||
|
public class SubmoduleAddTest extends RepositoryTestCase { |
||||||
|
|
||||||
|
@Test |
||||||
|
public void commandWithNullPath() { |
||||||
|
try { |
||||||
|
new SubmoduleAddCommand(db).setURI("uri").call(); |
||||||
|
fail("Exception not thrown"); |
||||||
|
} catch (IllegalArgumentException e) { |
||||||
|
assertEquals(JGitText.get().pathNotConfigured, e.getMessage()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void commandWithEmptyPath() { |
||||||
|
try { |
||||||
|
new SubmoduleAddCommand(db).setPath("").setURI("uri").call(); |
||||||
|
fail("Exception not thrown"); |
||||||
|
} catch (IllegalArgumentException e) { |
||||||
|
assertEquals(JGitText.get().pathNotConfigured, e.getMessage()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void commandWithNullUri() { |
||||||
|
try { |
||||||
|
new SubmoduleAddCommand(db).setPath("sub").call(); |
||||||
|
fail("Exception not thrown"); |
||||||
|
} catch (IllegalArgumentException e) { |
||||||
|
assertEquals(JGitText.get().uriNotConfigured, e.getMessage()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void commandWithEmptyUri() { |
||||||
|
try { |
||||||
|
new SubmoduleAddCommand(db).setPath("sub").setURI("").call(); |
||||||
|
fail("Exception not thrown"); |
||||||
|
} catch (IllegalArgumentException e) { |
||||||
|
assertEquals(JGitText.get().uriNotConfigured, e.getMessage()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void addSubmodule() throws Exception { |
||||||
|
Git git = new Git(db); |
||||||
|
writeTrashFile("file.txt", "content"); |
||||||
|
git.add().addFilepattern("file.txt").call(); |
||||||
|
RevCommit commit = git.commit().setMessage("create file").call(); |
||||||
|
|
||||||
|
SubmoduleAddCommand command = new SubmoduleAddCommand(db); |
||||||
|
String path = "sub"; |
||||||
|
command.setPath(path); |
||||||
|
String uri = db.getDirectory().toURI().toString(); |
||||||
|
command.setURI(uri); |
||||||
|
Repository repo = command.call(); |
||||||
|
assertNotNull(repo); |
||||||
|
|
||||||
|
SubmoduleWalk generator = SubmoduleWalk.forIndex(db); |
||||||
|
assertTrue(generator.next()); |
||||||
|
assertEquals(path, generator.getPath()); |
||||||
|
assertEquals(commit, generator.getObjectId()); |
||||||
|
assertEquals(uri, generator.getModulesUrl()); |
||||||
|
assertEquals(path, generator.getModulesPath()); |
||||||
|
assertEquals(uri, generator.getConfigUrl()); |
||||||
|
assertNotNull(generator.getRepository()); |
||||||
|
assertEquals(commit, repo.resolve(Constants.HEAD)); |
||||||
|
|
||||||
|
Status status = Git.wrap(db).status().call(); |
||||||
|
assertTrue(status.getAdded().contains(Constants.DOT_GIT_MODULES)); |
||||||
|
assertTrue(status.getAdded().contains(path)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void addExistentSubmodule() throws Exception { |
||||||
|
final ObjectId id = ObjectId |
||||||
|
.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234"); |
||||||
|
final String path = "sub"; |
||||||
|
DirCache cache = db.lockDirCache(); |
||||||
|
DirCacheEditor editor = cache.editor(); |
||||||
|
editor.add(new PathEdit(path) { |
||||||
|
|
||||||
|
public void apply(DirCacheEntry ent) { |
||||||
|
ent.setFileMode(FileMode.GITLINK); |
||||||
|
ent.setObjectId(id); |
||||||
|
} |
||||||
|
}); |
||||||
|
editor.commit(); |
||||||
|
|
||||||
|
SubmoduleAddCommand command = new SubmoduleAddCommand(db); |
||||||
|
command.setPath(path); |
||||||
|
command.setURI("git://server/repo.git"); |
||||||
|
try { |
||||||
|
command.call(); |
||||||
|
fail("Exception not thrown"); |
||||||
|
} catch (JGitInternalException e) { |
||||||
|
assertEquals( |
||||||
|
MessageFormat.format(JGitText.get().submoduleExists, path), |
||||||
|
e.getMessage()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,126 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2011, GitHub Inc. |
||||||
|
* 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 static org.junit.Assert.assertEquals; |
||||||
|
import static org.junit.Assert.assertNotNull; |
||||||
|
import static org.junit.Assert.assertNull; |
||||||
|
import static org.junit.Assert.assertTrue; |
||||||
|
|
||||||
|
import java.io.File; |
||||||
|
import java.io.IOException; |
||||||
|
import java.util.Collection; |
||||||
|
|
||||||
|
import org.eclipse.jgit.api.SubmoduleInitCommand; |
||||||
|
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.errors.ConfigInvalidException; |
||||||
|
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.RepositoryTestCase; |
||||||
|
import org.eclipse.jgit.storage.file.FileBasedConfig; |
||||||
|
import org.junit.Test; |
||||||
|
|
||||||
|
/** |
||||||
|
* Unit tests of {@link SubmoduleInitCommand} |
||||||
|
*/ |
||||||
|
public class SubmoduleInitTest extends RepositoryTestCase { |
||||||
|
|
||||||
|
@Test |
||||||
|
public void repositoryWithNoSubmodules() { |
||||||
|
SubmoduleInitCommand command = new SubmoduleInitCommand(db); |
||||||
|
Collection<String> modules = command.call(); |
||||||
|
assertNotNull(modules); |
||||||
|
assertTrue(modules.isEmpty()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void repositoryWithUninitializedModule() throws IOException, |
||||||
|
ConfigInvalidException { |
||||||
|
final ObjectId id = ObjectId |
||||||
|
.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234"); |
||||||
|
final String path = "sub"; |
||||||
|
DirCache cache = db.lockDirCache(); |
||||||
|
DirCacheEditor editor = cache.editor(); |
||||||
|
editor.add(new PathEdit(path) { |
||||||
|
|
||||||
|
public void apply(DirCacheEntry ent) { |
||||||
|
ent.setFileMode(FileMode.GITLINK); |
||||||
|
ent.setObjectId(id); |
||||||
|
} |
||||||
|
}); |
||||||
|
editor.commit(); |
||||||
|
|
||||||
|
SubmoduleWalk generator = SubmoduleWalk.forIndex(db); |
||||||
|
assertTrue(generator.next()); |
||||||
|
assertNull(generator.getConfigUrl()); |
||||||
|
assertNull(generator.getConfigUpdate()); |
||||||
|
|
||||||
|
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); |
||||||
|
String url = "git://server/repo.git"; |
||||||
|
modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path, |
||||||
|
ConfigConstants.CONFIG_KEY_URL, url); |
||||||
|
String update = "rebase"; |
||||||
|
modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path, |
||||||
|
ConfigConstants.CONFIG_KEY_UPDATE, update); |
||||||
|
modulesConfig.save(); |
||||||
|
|
||||||
|
SubmoduleInitCommand command = new SubmoduleInitCommand(db); |
||||||
|
Collection<String> modules = command.call(); |
||||||
|
assertNotNull(modules); |
||||||
|
assertEquals(1, modules.size()); |
||||||
|
assertEquals(path, modules.iterator().next()); |
||||||
|
|
||||||
|
generator = SubmoduleWalk.forIndex(db); |
||||||
|
assertTrue(generator.next()); |
||||||
|
assertEquals(url, generator.getConfigUrl()); |
||||||
|
assertEquals(update, generator.getConfigUpdate()); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,359 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2011, GitHub Inc. |
||||||
|
* 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 static org.junit.Assert.assertEquals; |
||||||
|
import static org.junit.Assert.assertNotNull; |
||||||
|
import static org.junit.Assert.assertTrue; |
||||||
|
|
||||||
|
import java.io.File; |
||||||
|
import java.io.IOException; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Map.Entry; |
||||||
|
|
||||||
|
import org.eclipse.jgit.api.Git; |
||||||
|
import org.eclipse.jgit.api.SubmoduleStatusCommand; |
||||||
|
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.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.RefUpdate; |
||||||
|
import org.eclipse.jgit.lib.Repository; |
||||||
|
import org.eclipse.jgit.lib.RepositoryTestCase; |
||||||
|
import org.eclipse.jgit.lib.StoredConfig; |
||||||
|
import org.eclipse.jgit.storage.file.FileBasedConfig; |
||||||
|
import org.junit.Test; |
||||||
|
|
||||||
|
/** |
||||||
|
* Unit tests of {@link SubmoduleStatusCommand} |
||||||
|
*/ |
||||||
|
public class SubmoduleStatusTest extends RepositoryTestCase { |
||||||
|
|
||||||
|
@Test |
||||||
|
public void repositoryWithNoSubmodules() { |
||||||
|
SubmoduleStatusCommand command = new SubmoduleStatusCommand(db); |
||||||
|
Map<String, SubmoduleStatus> statuses = command.call(); |
||||||
|
assertNotNull(statuses); |
||||||
|
assertTrue(statuses.isEmpty()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void repositoryWithMissingSubmodule() throws IOException { |
||||||
|
final ObjectId id = ObjectId |
||||||
|
.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234"); |
||||||
|
final String path = "sub"; |
||||||
|
DirCache cache = db.lockDirCache(); |
||||||
|
DirCacheEditor editor = cache.editor(); |
||||||
|
editor.add(new PathEdit(path) { |
||||||
|
|
||||||
|
public void apply(DirCacheEntry ent) { |
||||||
|
ent.setFileMode(FileMode.GITLINK); |
||||||
|
ent.setObjectId(id); |
||||||
|
} |
||||||
|
}); |
||||||
|
editor.commit(); |
||||||
|
|
||||||
|
SubmoduleStatusCommand command = new SubmoduleStatusCommand(db); |
||||||
|
Map<String, SubmoduleStatus> statuses = command.call(); |
||||||
|
assertNotNull(statuses); |
||||||
|
assertEquals(1, statuses.size()); |
||||||
|
Entry<String, SubmoduleStatus> module = statuses.entrySet().iterator() |
||||||
|
.next(); |
||||||
|
assertNotNull(module); |
||||||
|
assertEquals(path, module.getKey()); |
||||||
|
SubmoduleStatus status = module.getValue(); |
||||||
|
assertNotNull(status); |
||||||
|
assertEquals(path, status.getPath()); |
||||||
|
assertEquals(id, status.getIndexId()); |
||||||
|
assertEquals(SubmoduleStatusType.MISSING, status.getType()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void repositoryWithUninitializedSubmodule() throws IOException { |
||||||
|
final ObjectId id = ObjectId |
||||||
|
.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234"); |
||||||
|
final String path = "sub"; |
||||||
|
DirCache cache = db.lockDirCache(); |
||||||
|
DirCacheEditor editor = cache.editor(); |
||||||
|
editor.add(new PathEdit(path) { |
||||||
|
|
||||||
|
public void apply(DirCacheEntry ent) { |
||||||
|
ent.setFileMode(FileMode.GITLINK); |
||||||
|
ent.setObjectId(id); |
||||||
|
} |
||||||
|
}); |
||||||
|
editor.commit(); |
||||||
|
|
||||||
|
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.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path, |
||||||
|
ConfigConstants.CONFIG_KEY_URL, "git://server/repo.git"); |
||||||
|
modulesConfig.save(); |
||||||
|
|
||||||
|
SubmoduleStatusCommand command = new SubmoduleStatusCommand(db); |
||||||
|
Map<String, SubmoduleStatus> statuses = command.call(); |
||||||
|
assertNotNull(statuses); |
||||||
|
assertEquals(1, statuses.size()); |
||||||
|
Entry<String, SubmoduleStatus> module = statuses.entrySet().iterator() |
||||||
|
.next(); |
||||||
|
assertNotNull(module); |
||||||
|
assertEquals(path, module.getKey()); |
||||||
|
SubmoduleStatus status = module.getValue(); |
||||||
|
assertNotNull(status); |
||||||
|
assertEquals(path, status.getPath()); |
||||||
|
assertEquals(id, status.getIndexId()); |
||||||
|
assertEquals(SubmoduleStatusType.UNINITIALIZED, status.getType()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void repositoryWithNoHeadInSubmodule() throws IOException { |
||||||
|
final ObjectId id = ObjectId |
||||||
|
.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234"); |
||||||
|
final String path = "sub"; |
||||||
|
DirCache cache = db.lockDirCache(); |
||||||
|
DirCacheEditor editor = cache.editor(); |
||||||
|
editor.add(new PathEdit(path) { |
||||||
|
|
||||||
|
public void apply(DirCacheEntry ent) { |
||||||
|
ent.setFileMode(FileMode.GITLINK); |
||||||
|
ent.setObjectId(id); |
||||||
|
} |
||||||
|
}); |
||||||
|
editor.commit(); |
||||||
|
|
||||||
|
String url = "git://server/repo.git"; |
||||||
|
StoredConfig config = db.getConfig(); |
||||||
|
config.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path, |
||||||
|
ConfigConstants.CONFIG_KEY_URL, url); |
||||||
|
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.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path, |
||||||
|
ConfigConstants.CONFIG_KEY_URL, url); |
||||||
|
modulesConfig.save(); |
||||||
|
|
||||||
|
Repository subRepo = Git.init().setBare(false) |
||||||
|
.setDirectory(new File(db.getWorkTree(), path)).call() |
||||||
|
.getRepository(); |
||||||
|
assertNotNull(subRepo); |
||||||
|
|
||||||
|
SubmoduleStatusCommand command = new SubmoduleStatusCommand(db); |
||||||
|
Map<String, SubmoduleStatus> statuses = command.call(); |
||||||
|
assertNotNull(statuses); |
||||||
|
assertEquals(1, statuses.size()); |
||||||
|
Entry<String, SubmoduleStatus> module = statuses.entrySet().iterator() |
||||||
|
.next(); |
||||||
|
assertNotNull(module); |
||||||
|
assertEquals(path, module.getKey()); |
||||||
|
SubmoduleStatus status = module.getValue(); |
||||||
|
assertNotNull(status); |
||||||
|
assertEquals(path, status.getPath()); |
||||||
|
assertEquals(id, status.getIndexId()); |
||||||
|
assertEquals(SubmoduleStatusType.UNINITIALIZED, status.getType()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void repositoryWithNoSubmoduleRepository() throws IOException { |
||||||
|
final ObjectId id = ObjectId |
||||||
|
.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234"); |
||||||
|
final String path = "sub"; |
||||||
|
DirCache cache = db.lockDirCache(); |
||||||
|
DirCacheEditor editor = cache.editor(); |
||||||
|
editor.add(new PathEdit(path) { |
||||||
|
|
||||||
|
public void apply(DirCacheEntry ent) { |
||||||
|
ent.setFileMode(FileMode.GITLINK); |
||||||
|
ent.setObjectId(id); |
||||||
|
} |
||||||
|
}); |
||||||
|
editor.commit(); |
||||||
|
|
||||||
|
String url = "git://server/repo.git"; |
||||||
|
StoredConfig config = db.getConfig(); |
||||||
|
config.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path, |
||||||
|
ConfigConstants.CONFIG_KEY_URL, url); |
||||||
|
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.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path, |
||||||
|
ConfigConstants.CONFIG_KEY_URL, url); |
||||||
|
modulesConfig.save(); |
||||||
|
|
||||||
|
SubmoduleStatusCommand command = new SubmoduleStatusCommand(db); |
||||||
|
Map<String, SubmoduleStatus> statuses = command.call(); |
||||||
|
assertNotNull(statuses); |
||||||
|
assertEquals(1, statuses.size()); |
||||||
|
Entry<String, SubmoduleStatus> module = statuses.entrySet().iterator() |
||||||
|
.next(); |
||||||
|
assertNotNull(module); |
||||||
|
assertEquals(path, module.getKey()); |
||||||
|
SubmoduleStatus status = module.getValue(); |
||||||
|
assertNotNull(status); |
||||||
|
assertEquals(path, status.getPath()); |
||||||
|
assertEquals(id, status.getIndexId()); |
||||||
|
assertEquals(SubmoduleStatusType.UNINITIALIZED, status.getType()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void repositoryWithInitializedSubmodule() throws IOException { |
||||||
|
final ObjectId id = ObjectId |
||||||
|
.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234"); |
||||||
|
final String path = "sub"; |
||||||
|
DirCache cache = db.lockDirCache(); |
||||||
|
DirCacheEditor editor = cache.editor(); |
||||||
|
editor.add(new PathEdit(path) { |
||||||
|
|
||||||
|
public void apply(DirCacheEntry ent) { |
||||||
|
ent.setFileMode(FileMode.GITLINK); |
||||||
|
ent.setObjectId(id); |
||||||
|
} |
||||||
|
}); |
||||||
|
editor.commit(); |
||||||
|
|
||||||
|
String url = "git://server/repo.git"; |
||||||
|
StoredConfig config = db.getConfig(); |
||||||
|
config.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path, |
||||||
|
ConfigConstants.CONFIG_KEY_URL, url); |
||||||
|
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.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path, |
||||||
|
ConfigConstants.CONFIG_KEY_URL, url); |
||||||
|
modulesConfig.save(); |
||||||
|
|
||||||
|
Repository subRepo = Git.init().setBare(false) |
||||||
|
.setDirectory(new File(db.getWorkTree(), path)).call() |
||||||
|
.getRepository(); |
||||||
|
assertNotNull(subRepo); |
||||||
|
|
||||||
|
RefUpdate update = subRepo.updateRef(Constants.HEAD, true); |
||||||
|
update.setNewObjectId(id); |
||||||
|
update.forceUpdate(); |
||||||
|
|
||||||
|
SubmoduleStatusCommand command = new SubmoduleStatusCommand(db); |
||||||
|
Map<String, SubmoduleStatus> statuses = command.call(); |
||||||
|
assertNotNull(statuses); |
||||||
|
assertEquals(1, statuses.size()); |
||||||
|
Entry<String, SubmoduleStatus> module = statuses.entrySet().iterator() |
||||||
|
.next(); |
||||||
|
assertNotNull(module); |
||||||
|
assertEquals(path, module.getKey()); |
||||||
|
SubmoduleStatus status = module.getValue(); |
||||||
|
assertNotNull(status); |
||||||
|
assertEquals(path, status.getPath()); |
||||||
|
assertEquals(id, status.getIndexId()); |
||||||
|
assertEquals(SubmoduleStatusType.INITIALIZED, status.getType()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void repositoryWithDifferentRevCheckedOutSubmodule() |
||||||
|
throws IOException { |
||||||
|
final ObjectId id = ObjectId |
||||||
|
.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234"); |
||||||
|
final String path = "sub"; |
||||||
|
DirCache cache = db.lockDirCache(); |
||||||
|
DirCacheEditor editor = cache.editor(); |
||||||
|
editor.add(new PathEdit(path) { |
||||||
|
|
||||||
|
public void apply(DirCacheEntry ent) { |
||||||
|
ent.setFileMode(FileMode.GITLINK); |
||||||
|
ent.setObjectId(id); |
||||||
|
} |
||||||
|
}); |
||||||
|
editor.commit(); |
||||||
|
|
||||||
|
String url = "git://server/repo.git"; |
||||||
|
StoredConfig config = db.getConfig(); |
||||||
|
config.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path, |
||||||
|
ConfigConstants.CONFIG_KEY_URL, url); |
||||||
|
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.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path, |
||||||
|
ConfigConstants.CONFIG_KEY_URL, url); |
||||||
|
modulesConfig.save(); |
||||||
|
|
||||||
|
Repository subRepo = Git.init().setBare(false) |
||||||
|
.setDirectory(new File(db.getWorkTree(), path)).call() |
||||||
|
.getRepository(); |
||||||
|
assertNotNull(subRepo); |
||||||
|
|
||||||
|
RefUpdate update = subRepo.updateRef(Constants.HEAD, true); |
||||||
|
update.setNewObjectId(ObjectId |
||||||
|
.fromString("aaaa0000aaaa0000aaaa0000aaaa0000aaaa0000")); |
||||||
|
update.forceUpdate(); |
||||||
|
|
||||||
|
SubmoduleStatusCommand command = new SubmoduleStatusCommand(db); |
||||||
|
Map<String, SubmoduleStatus> statuses = command.call(); |
||||||
|
assertNotNull(statuses); |
||||||
|
assertEquals(1, statuses.size()); |
||||||
|
Entry<String, SubmoduleStatus> module = statuses.entrySet().iterator() |
||||||
|
.next(); |
||||||
|
assertNotNull(module); |
||||||
|
assertEquals(path, module.getKey()); |
||||||
|
SubmoduleStatus status = module.getValue(); |
||||||
|
assertNotNull(status); |
||||||
|
assertEquals(path, status.getPath()); |
||||||
|
assertEquals(id, status.getIndexId()); |
||||||
|
assertEquals(update.getNewObjectId(), status.getHeadId()); |
||||||
|
assertEquals(SubmoduleStatusType.REV_CHECKED_OUT, status.getType()); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,140 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2011, GitHub Inc. |
||||||
|
* 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 static org.junit.Assert.assertEquals; |
||||||
|
import static org.junit.Assert.assertNotNull; |
||||||
|
import static org.junit.Assert.assertNull; |
||||||
|
import static org.junit.Assert.assertTrue; |
||||||
|
|
||||||
|
import java.io.File; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Map.Entry; |
||||||
|
|
||||||
|
import org.eclipse.jgit.api.Git; |
||||||
|
import org.eclipse.jgit.api.SubmoduleSyncCommand; |
||||||
|
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.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.Repository; |
||||||
|
import org.eclipse.jgit.lib.RepositoryTestCase; |
||||||
|
import org.eclipse.jgit.lib.StoredConfig; |
||||||
|
import org.eclipse.jgit.storage.file.FileBasedConfig; |
||||||
|
import org.junit.Test; |
||||||
|
|
||||||
|
/** |
||||||
|
* Unit tests of {@link SubmoduleSyncCommand} |
||||||
|
*/ |
||||||
|
public class SubmoduleSyncTest extends RepositoryTestCase { |
||||||
|
|
||||||
|
@Test |
||||||
|
public void repositoryWithNoSubmodules() { |
||||||
|
SubmoduleSyncCommand command = new SubmoduleSyncCommand(db); |
||||||
|
Map<String, String> modules = command.call(); |
||||||
|
assertNotNull(modules); |
||||||
|
assertTrue(modules.isEmpty()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void repositoryWithSubmodule() throws Exception { |
||||||
|
writeTrashFile("file.txt", "content"); |
||||||
|
Git git = Git.wrap(db); |
||||||
|
git.add().addFilepattern("file.txt").call(); |
||||||
|
git.commit().setMessage("create file").call(); |
||||||
|
|
||||||
|
final ObjectId id = ObjectId |
||||||
|
.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234"); |
||||||
|
final String path = "sub"; |
||||||
|
DirCache cache = db.lockDirCache(); |
||||||
|
DirCacheEditor editor = cache.editor(); |
||||||
|
editor.add(new PathEdit(path) { |
||||||
|
|
||||||
|
public void apply(DirCacheEntry ent) { |
||||||
|
ent.setFileMode(FileMode.GITLINK); |
||||||
|
ent.setObjectId(id); |
||||||
|
} |
||||||
|
}); |
||||||
|
editor.commit(); |
||||||
|
|
||||||
|
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); |
||||||
|
String url = "git://server/repo.git"; |
||||||
|
modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path, |
||||||
|
ConfigConstants.CONFIG_KEY_URL, url); |
||||||
|
modulesConfig.save(); |
||||||
|
|
||||||
|
Repository subRepo = Git.cloneRepository() |
||||||
|
.setURI(db.getDirectory().toURI().toString()) |
||||||
|
.setDirectory(new File(db.getWorkTree(), path)).call() |
||||||
|
.getRepository(); |
||||||
|
assertNotNull(subRepo); |
||||||
|
|
||||||
|
SubmoduleWalk generator = SubmoduleWalk.forIndex(db); |
||||||
|
assertTrue(generator.next()); |
||||||
|
assertNull(generator.getConfigUrl()); |
||||||
|
assertEquals(url, generator.getModulesUrl()); |
||||||
|
|
||||||
|
SubmoduleSyncCommand command = new SubmoduleSyncCommand(db); |
||||||
|
Map<String, String> synced = command.call(); |
||||||
|
assertNotNull(synced); |
||||||
|
assertEquals(1, synced.size()); |
||||||
|
Entry<String, String> module = synced.entrySet().iterator().next(); |
||||||
|
assertEquals(path, module.getKey()); |
||||||
|
assertEquals(url, module.getValue()); |
||||||
|
|
||||||
|
generator = SubmoduleWalk.forIndex(db); |
||||||
|
assertTrue(generator.next()); |
||||||
|
assertEquals(url, generator.getConfigUrl()); |
||||||
|
StoredConfig submoduleConfig = generator.getRepository().getConfig(); |
||||||
|
assertEquals(url, submoduleConfig.getString( |
||||||
|
ConfigConstants.CONFIG_REMOTE_SECTION, |
||||||
|
Constants.DEFAULT_REMOTE_NAME, ConfigConstants.CONFIG_KEY_URL)); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,187 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2011, GitHub Inc. |
||||||
|
* 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 static org.junit.Assert.assertEquals; |
||||||
|
import static org.junit.Assert.assertNotNull; |
||||||
|
import static org.junit.Assert.assertTrue; |
||||||
|
|
||||||
|
import java.io.File; |
||||||
|
import java.io.IOException; |
||||||
|
import java.util.Collection; |
||||||
|
|
||||||
|
import org.eclipse.jgit.api.Git; |
||||||
|
import org.eclipse.jgit.api.SubmoduleUpdateCommand; |
||||||
|
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.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.Repository; |
||||||
|
import org.eclipse.jgit.lib.RepositoryTestCase; |
||||||
|
import org.eclipse.jgit.lib.StoredConfig; |
||||||
|
import org.eclipse.jgit.revwalk.RevCommit; |
||||||
|
import org.eclipse.jgit.storage.file.FileBasedConfig; |
||||||
|
import org.junit.Test; |
||||||
|
|
||||||
|
/** |
||||||
|
* Unit tests of {@link SubmoduleUpdateCommand} |
||||||
|
*/ |
||||||
|
public class SubmoduleUpdateTest extends RepositoryTestCase { |
||||||
|
|
||||||
|
@Test |
||||||
|
public void repositoryWithNoSubmodules() { |
||||||
|
SubmoduleUpdateCommand command = new SubmoduleUpdateCommand(db); |
||||||
|
Collection<String> modules = command.call(); |
||||||
|
assertNotNull(modules); |
||||||
|
assertTrue(modules.isEmpty()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void repositoryWithSubmodule() throws Exception { |
||||||
|
writeTrashFile("file.txt", "content"); |
||||||
|
Git git = Git.wrap(db); |
||||||
|
git.add().addFilepattern("file.txt").call(); |
||||||
|
final RevCommit commit = git.commit().setMessage("create file").call(); |
||||||
|
|
||||||
|
final String path = "sub"; |
||||||
|
DirCache cache = db.lockDirCache(); |
||||||
|
DirCacheEditor editor = cache.editor(); |
||||||
|
editor.add(new PathEdit(path) { |
||||||
|
|
||||||
|
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(); |
||||||
|
|
||||||
|
SubmoduleUpdateCommand command = new SubmoduleUpdateCommand(db); |
||||||
|
Collection<String> updated = command.call(); |
||||||
|
assertNotNull(updated); |
||||||
|
assertEquals(1, updated.size()); |
||||||
|
assertEquals(path, updated.iterator().next()); |
||||||
|
|
||||||
|
SubmoduleWalk generator = SubmoduleWalk.forIndex(db); |
||||||
|
assertTrue(generator.next()); |
||||||
|
Repository subRepo = generator.getRepository(); |
||||||
|
assertNotNull(subRepo); |
||||||
|
assertEquals(commit, subRepo.resolve(Constants.HEAD)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void repositoryWithUnconfiguredSubmodule() throws IOException { |
||||||
|
final ObjectId id = ObjectId |
||||||
|
.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234"); |
||||||
|
final String path = "sub"; |
||||||
|
DirCache cache = db.lockDirCache(); |
||||||
|
DirCacheEditor editor = cache.editor(); |
||||||
|
editor.add(new PathEdit(path) { |
||||||
|
|
||||||
|
public void apply(DirCacheEntry ent) { |
||||||
|
ent.setFileMode(FileMode.GITLINK); |
||||||
|
ent.setObjectId(id); |
||||||
|
} |
||||||
|
}); |
||||||
|
editor.commit(); |
||||||
|
|
||||||
|
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); |
||||||
|
String url = "git://server/repo.git"; |
||||||
|
modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path, |
||||||
|
ConfigConstants.CONFIG_KEY_URL, url); |
||||||
|
String update = "rebase"; |
||||||
|
modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path, |
||||||
|
ConfigConstants.CONFIG_KEY_UPDATE, update); |
||||||
|
modulesConfig.save(); |
||||||
|
|
||||||
|
SubmoduleUpdateCommand command = new SubmoduleUpdateCommand(db); |
||||||
|
Collection<String> updated = command.call(); |
||||||
|
assertNotNull(updated); |
||||||
|
assertTrue(updated.isEmpty()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void repositoryWithInitializedSubmodule() throws IOException { |
||||||
|
final ObjectId id = ObjectId |
||||||
|
.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234"); |
||||||
|
final String path = "sub"; |
||||||
|
DirCache cache = db.lockDirCache(); |
||||||
|
DirCacheEditor editor = cache.editor(); |
||||||
|
editor.add(new PathEdit(path) { |
||||||
|
|
||||||
|
public void apply(DirCacheEntry ent) { |
||||||
|
ent.setFileMode(FileMode.GITLINK); |
||||||
|
ent.setObjectId(id); |
||||||
|
} |
||||||
|
}); |
||||||
|
editor.commit(); |
||||||
|
|
||||||
|
Repository subRepo = Git.init().setBare(false) |
||||||
|
.setDirectory(new File(db.getWorkTree(), path)).call() |
||||||
|
.getRepository(); |
||||||
|
assertNotNull(subRepo); |
||||||
|
|
||||||
|
SubmoduleUpdateCommand command = new SubmoduleUpdateCommand(db); |
||||||
|
Collection<String> updated = command.call(); |
||||||
|
assertNotNull(updated); |
||||||
|
assertTrue(updated.isEmpty()); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,177 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2011, GitHub Inc. |
||||||
|
* 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 static org.junit.Assert.assertEquals; |
||||||
|
import static org.junit.Assert.assertFalse; |
||||||
|
import static org.junit.Assert.assertNull; |
||||||
|
import static org.junit.Assert.assertTrue; |
||||||
|
|
||||||
|
import java.io.File; |
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
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.errors.ConfigInvalidException; |
||||||
|
import org.eclipse.jgit.lib.Constants; |
||||||
|
import org.eclipse.jgit.lib.FileMode; |
||||||
|
import org.eclipse.jgit.lib.ObjectId; |
||||||
|
import org.eclipse.jgit.lib.RepositoryTestCase; |
||||||
|
import org.eclipse.jgit.treewalk.filter.PathFilter; |
||||||
|
import org.junit.Test; |
||||||
|
|
||||||
|
/** |
||||||
|
* Unit tests of {@link SubmoduleWalk} |
||||||
|
*/ |
||||||
|
public class SubmoduleWalkTest extends RepositoryTestCase { |
||||||
|
|
||||||
|
@Test |
||||||
|
public void repositoryWithNoSubmodules() throws IOException { |
||||||
|
SubmoduleWalk gen = SubmoduleWalk.forIndex(db); |
||||||
|
assertFalse(gen.next()); |
||||||
|
assertNull(gen.getPath()); |
||||||
|
assertEquals(ObjectId.zeroId(), gen.getObjectId()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void repositoryWithRootLevelSubmodule() throws IOException, |
||||||
|
ConfigInvalidException { |
||||||
|
final ObjectId id = ObjectId |
||||||
|
.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234"); |
||||||
|
final String path = "sub"; |
||||||
|
DirCache cache = db.lockDirCache(); |
||||||
|
DirCacheEditor editor = cache.editor(); |
||||||
|
editor.add(new PathEdit(path) { |
||||||
|
|
||||||
|
public void apply(DirCacheEntry ent) { |
||||||
|
ent.setFileMode(FileMode.GITLINK); |
||||||
|
ent.setObjectId(id); |
||||||
|
} |
||||||
|
}); |
||||||
|
editor.commit(); |
||||||
|
|
||||||
|
SubmoduleWalk gen = SubmoduleWalk.forIndex(db); |
||||||
|
assertTrue(gen.next()); |
||||||
|
assertEquals(path, gen.getPath()); |
||||||
|
assertEquals(id, gen.getObjectId()); |
||||||
|
assertEquals(new File(db.getWorkTree(), path), gen.getDirectory()); |
||||||
|
assertEquals(new File(db.getWorkTree(), path + File.separatorChar |
||||||
|
+ Constants.DOT_GIT), gen.getGitDirectory()); |
||||||
|
assertNull(gen.getConfigUpdate()); |
||||||
|
assertNull(gen.getConfigUrl()); |
||||||
|
assertNull(gen.getModulesPath()); |
||||||
|
assertNull(gen.getModulesUpdate()); |
||||||
|
assertNull(gen.getModulesUrl()); |
||||||
|
assertNull(gen.getRepository()); |
||||||
|
assertFalse(gen.next()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void repositoryWithNestedSubmodule() throws IOException, |
||||||
|
ConfigInvalidException { |
||||||
|
final ObjectId id = ObjectId |
||||||
|
.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234"); |
||||||
|
final String path = "sub/dir/final"; |
||||||
|
DirCache cache = db.lockDirCache(); |
||||||
|
DirCacheEditor editor = cache.editor(); |
||||||
|
editor.add(new PathEdit(path) { |
||||||
|
|
||||||
|
public void apply(DirCacheEntry ent) { |
||||||
|
ent.setFileMode(FileMode.GITLINK); |
||||||
|
ent.setObjectId(id); |
||||||
|
} |
||||||
|
}); |
||||||
|
editor.commit(); |
||||||
|
|
||||||
|
SubmoduleWalk gen = SubmoduleWalk.forIndex(db); |
||||||
|
assertTrue(gen.next()); |
||||||
|
assertEquals(path, gen.getPath()); |
||||||
|
assertEquals(id, gen.getObjectId()); |
||||||
|
assertEquals(new File(db.getWorkTree(), path), gen.getDirectory()); |
||||||
|
assertEquals(new File(db.getWorkTree(), path + File.separatorChar |
||||||
|
+ Constants.DOT_GIT), gen.getGitDirectory()); |
||||||
|
assertNull(gen.getConfigUpdate()); |
||||||
|
assertNull(gen.getConfigUrl()); |
||||||
|
assertNull(gen.getModulesPath()); |
||||||
|
assertNull(gen.getModulesUpdate()); |
||||||
|
assertNull(gen.getModulesUrl()); |
||||||
|
assertNull(gen.getRepository()); |
||||||
|
assertFalse(gen.next()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void generatorFilteredToOneOfTwoSubmodules() throws IOException { |
||||||
|
final ObjectId id1 = ObjectId |
||||||
|
.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234"); |
||||||
|
final String path1 = "sub1"; |
||||||
|
final ObjectId id2 = ObjectId |
||||||
|
.fromString("abcd1234abcd1234abcd1234abcd1234abcd1235"); |
||||||
|
final String path2 = "sub2"; |
||||||
|
DirCache cache = db.lockDirCache(); |
||||||
|
DirCacheEditor editor = cache.editor(); |
||||||
|
editor.add(new PathEdit(path1) { |
||||||
|
|
||||||
|
public void apply(DirCacheEntry ent) { |
||||||
|
ent.setFileMode(FileMode.GITLINK); |
||||||
|
ent.setObjectId(id1); |
||||||
|
} |
||||||
|
}); |
||||||
|
editor.add(new PathEdit(path2) { |
||||||
|
|
||||||
|
public void apply(DirCacheEntry ent) { |
||||||
|
ent.setFileMode(FileMode.GITLINK); |
||||||
|
ent.setObjectId(id2); |
||||||
|
} |
||||||
|
}); |
||||||
|
editor.commit(); |
||||||
|
|
||||||
|
SubmoduleWalk gen = SubmoduleWalk.forIndex(db); |
||||||
|
gen.setFilter(PathFilter.create(path1)); |
||||||
|
assertTrue(gen.next()); |
||||||
|
assertEquals(path1, gen.getPath()); |
||||||
|
assertEquals(id1, gen.getObjectId()); |
||||||
|
assertFalse(gen.next()); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,211 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2011, GitHub Inc. |
||||||
|
* 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 java.io.File; |
||||||
|
import java.io.IOException; |
||||||
|
import java.text.MessageFormat; |
||||||
|
|
||||||
|
import org.eclipse.jgit.JGitText; |
||||||
|
import org.eclipse.jgit.api.errors.JGitInternalException; |
||||||
|
import org.eclipse.jgit.api.errors.NoFilepatternException; |
||||||
|
import org.eclipse.jgit.lib.ConfigConstants; |
||||||
|
import org.eclipse.jgit.lib.Constants; |
||||||
|
import org.eclipse.jgit.lib.NullProgressMonitor; |
||||||
|
import org.eclipse.jgit.lib.ProgressMonitor; |
||||||
|
import org.eclipse.jgit.lib.Repository; |
||||||
|
import org.eclipse.jgit.lib.StoredConfig; |
||||||
|
import org.eclipse.jgit.storage.file.FileBasedConfig; |
||||||
|
import org.eclipse.jgit.submodule.SubmoduleWalk; |
||||||
|
import org.eclipse.jgit.transport.CredentialsProvider; |
||||||
|
import org.eclipse.jgit.treewalk.filter.PathFilter; |
||||||
|
import org.eclipse.jgit.treewalk.filter.TreeFilter; |
||||||
|
|
||||||
|
/** |
||||||
|
* A class used to execute a submodule add command. |
||||||
|
* |
||||||
|
* This will clone the configured submodule, register the submodule in the |
||||||
|
* .gitmodules file and the repository config file, and also add the submodule |
||||||
|
* and .gitmodules file to the index. |
||||||
|
* |
||||||
|
* @see <a |
||||||
|
* href="http://www.kernel.org/pub/software/scm/git/docs/git-submodule.html" |
||||||
|
* >Git documentation about submodules</a> |
||||||
|
*/ |
||||||
|
public class SubmoduleAddCommand extends GitCommand<Repository> { |
||||||
|
|
||||||
|
private String path; |
||||||
|
|
||||||
|
private String uri; |
||||||
|
|
||||||
|
private ProgressMonitor monitor; |
||||||
|
|
||||||
|
private CredentialsProvider credentialsProvider; |
||||||
|
|
||||||
|
/** |
||||||
|
* @param repo |
||||||
|
*/ |
||||||
|
public SubmoduleAddCommand(final Repository repo) { |
||||||
|
super(repo); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Set repository-relative path of submodule |
||||||
|
* |
||||||
|
* @param path |
||||||
|
* @return this command |
||||||
|
*/ |
||||||
|
public SubmoduleAddCommand setPath(final String path) { |
||||||
|
this.path = path; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Set URI to clone submodule from |
||||||
|
* |
||||||
|
* @param uri |
||||||
|
* @return this command |
||||||
|
*/ |
||||||
|
public SubmoduleAddCommand setURI(final String uri) { |
||||||
|
this.uri = uri; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* The progress monitor associated with the clone operation. By default, |
||||||
|
* this is set to <code>NullProgressMonitor</code> |
||||||
|
* |
||||||
|
* @see NullProgressMonitor |
||||||
|
* @param monitor |
||||||
|
* @return this command |
||||||
|
*/ |
||||||
|
public SubmoduleAddCommand setProgressMonitor(final ProgressMonitor monitor) { |
||||||
|
this.monitor = monitor; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @param credentialsProvider |
||||||
|
* the {@link CredentialsProvider} to use |
||||||
|
* @return this command |
||||||
|
*/ |
||||||
|
public SubmoduleAddCommand setCredentialsProvider( |
||||||
|
final CredentialsProvider credentialsProvider) { |
||||||
|
this.credentialsProvider = credentialsProvider; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Is the configured already a submodule in the index? |
||||||
|
* |
||||||
|
* @return true if submodule exists in index, false otherwise |
||||||
|
* @throws IOException |
||||||
|
*/ |
||||||
|
protected boolean submoduleExists() throws IOException { |
||||||
|
TreeFilter filter = PathFilter.create(path); |
||||||
|
return SubmoduleWalk.forIndex(repo).setFilter(filter).next(); |
||||||
|
} |
||||||
|
|
||||||
|
public Repository call() throws JGitInternalException { |
||||||
|
checkCallable(); |
||||||
|
if (path == null || path.length() == 0) |
||||||
|
throw new IllegalArgumentException(JGitText.get().pathNotConfigured); |
||||||
|
if (uri == null || uri.length() == 0) |
||||||
|
throw new IllegalArgumentException(JGitText.get().uriNotConfigured); |
||||||
|
|
||||||
|
try { |
||||||
|
if (submoduleExists()) |
||||||
|
throw new JGitInternalException(MessageFormat.format( |
||||||
|
JGitText.get().submoduleExists, path)); |
||||||
|
} catch (IOException e) { |
||||||
|
throw new JGitInternalException(e.getMessage(), e); |
||||||
|
} |
||||||
|
|
||||||
|
// Clone submodule repository
|
||||||
|
File moduleDirectory = SubmoduleWalk.getSubmoduleDirectory(repo, path); |
||||||
|
CloneCommand clone = Git.cloneRepository(); |
||||||
|
clone.setDirectory(moduleDirectory); |
||||||
|
clone.setURI(uri); |
||||||
|
if (monitor != null) |
||||||
|
clone.setProgressMonitor(monitor); |
||||||
|
if (credentialsProvider != null) |
||||||
|
clone.setCredentialsProvider(credentialsProvider); |
||||||
|
Repository subRepo = clone.call().getRepository(); |
||||||
|
|
||||||
|
// Save submodule URL to parent repository's config
|
||||||
|
StoredConfig config = repo.getConfig(); |
||||||
|
config.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path, |
||||||
|
ConfigConstants.CONFIG_KEY_URL, uri); |
||||||
|
try { |
||||||
|
config.save(); |
||||||
|
} catch (IOException e) { |
||||||
|
throw new JGitInternalException(e.getMessage(), e); |
||||||
|
} |
||||||
|
|
||||||
|
// Save path and URL to parent repository's .gitmodules file
|
||||||
|
FileBasedConfig modulesConfig = new FileBasedConfig(new File( |
||||||
|
repo.getWorkTree(), Constants.DOT_GIT_MODULES), repo.getFS()); |
||||||
|
modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path, |
||||||
|
ConfigConstants.CONFIG_KEY_PATH, path); |
||||||
|
modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path, |
||||||
|
ConfigConstants.CONFIG_KEY_URL, uri); |
||||||
|
try { |
||||||
|
modulesConfig.save(); |
||||||
|
} catch (IOException e) { |
||||||
|
throw new JGitInternalException(e.getMessage(), e); |
||||||
|
} |
||||||
|
|
||||||
|
AddCommand add = new AddCommand(repo); |
||||||
|
// Add .gitmodules file to parent repository's index
|
||||||
|
add.addFilepattern(Constants.DOT_GIT_MODULES); |
||||||
|
// Add submodule directory to parent repository's index
|
||||||
|
add.addFilepattern(path); |
||||||
|
try { |
||||||
|
add.call(); |
||||||
|
} catch (NoFilepatternException e) { |
||||||
|
throw new JGitInternalException(e.getMessage(), e); |
||||||
|
} |
||||||
|
|
||||||
|
return subRepo; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,130 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2011, GitHub Inc. |
||||||
|
* 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 java.io.IOException; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Collection; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import org.eclipse.jgit.api.errors.JGitInternalException; |
||||||
|
import org.eclipse.jgit.errors.ConfigInvalidException; |
||||||
|
import org.eclipse.jgit.lib.ConfigConstants; |
||||||
|
import org.eclipse.jgit.lib.Repository; |
||||||
|
import org.eclipse.jgit.lib.StoredConfig; |
||||||
|
import org.eclipse.jgit.submodule.SubmoduleWalk; |
||||||
|
import org.eclipse.jgit.treewalk.filter.PathFilterGroup; |
||||||
|
|
||||||
|
/** |
||||||
|
* A class used to execute a submodule init command. |
||||||
|
* |
||||||
|
* This will copy the 'url' and 'update' fields from the working tree |
||||||
|
* .gitmodules file to a repository's config file for each submodule not |
||||||
|
* currently present in the repository's config file. |
||||||
|
* |
||||||
|
* @see <a |
||||||
|
* href="http://www.kernel.org/pub/software/scm/git/docs/git-submodule.html" |
||||||
|
* >Git documentation about submodules</a> |
||||||
|
*/ |
||||||
|
public class SubmoduleInitCommand extends GitCommand<Collection<String>> { |
||||||
|
|
||||||
|
private final Collection<String> paths; |
||||||
|
|
||||||
|
/** |
||||||
|
* @param repo |
||||||
|
*/ |
||||||
|
public SubmoduleInitCommand(final Repository repo) { |
||||||
|
super(repo); |
||||||
|
paths = new ArrayList<String>(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Add repository-relative submodule path to initialize |
||||||
|
* |
||||||
|
* @param path |
||||||
|
* @return this command |
||||||
|
*/ |
||||||
|
public SubmoduleInitCommand addPath(final String path) { |
||||||
|
paths.add(path); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public Collection<String> call() throws JGitInternalException { |
||||||
|
checkCallable(); |
||||||
|
|
||||||
|
try { |
||||||
|
SubmoduleWalk generator = SubmoduleWalk.forIndex(repo); |
||||||
|
if (!paths.isEmpty()) |
||||||
|
generator.setFilter(PathFilterGroup.createFromStrings(paths)); |
||||||
|
StoredConfig config = repo.getConfig(); |
||||||
|
List<String> initialized = new ArrayList<String>(); |
||||||
|
while (generator.next()) { |
||||||
|
// Ignore entry if URL is already present in config file
|
||||||
|
if (generator.getConfigUrl() != null) |
||||||
|
continue; |
||||||
|
|
||||||
|
String path = generator.getPath(); |
||||||
|
// Copy 'url' and 'update' fields from .gitmodules to config
|
||||||
|
// file
|
||||||
|
String url = generator.getModulesUrl(); |
||||||
|
String update = generator.getModulesUpdate(); |
||||||
|
if (url != null) |
||||||
|
config.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, |
||||||
|
path, ConfigConstants.CONFIG_KEY_URL, url); |
||||||
|
if (update != null) |
||||||
|
config.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, |
||||||
|
path, ConfigConstants.CONFIG_KEY_UPDATE, update); |
||||||
|
if (url != null || update != null) |
||||||
|
initialized.add(path); |
||||||
|
} |
||||||
|
// Save repository config if any values were updated
|
||||||
|
if (!initialized.isEmpty()) |
||||||
|
config.save(); |
||||||
|
return initialized; |
||||||
|
} catch (IOException e) { |
||||||
|
throw new JGitInternalException(e.getMessage(), e); |
||||||
|
} catch (ConfigInvalidException e) { |
||||||
|
throw new JGitInternalException(e.getMessage(), e); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,148 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2011, GitHub Inc. |
||||||
|
* 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 java.io.IOException; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Collection; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
import org.eclipse.jgit.api.errors.JGitInternalException; |
||||||
|
import org.eclipse.jgit.errors.ConfigInvalidException; |
||||||
|
import org.eclipse.jgit.lib.Constants; |
||||||
|
import org.eclipse.jgit.lib.ObjectId; |
||||||
|
import org.eclipse.jgit.lib.Repository; |
||||||
|
import org.eclipse.jgit.submodule.SubmoduleWalk; |
||||||
|
import org.eclipse.jgit.submodule.SubmoduleStatus; |
||||||
|
import org.eclipse.jgit.submodule.SubmoduleStatusType; |
||||||
|
import org.eclipse.jgit.treewalk.filter.PathFilterGroup; |
||||||
|
|
||||||
|
/** |
||||||
|
* A class used to execute a submodule status command. |
||||||
|
* |
||||||
|
* @see <a |
||||||
|
* href="http://www.kernel.org/pub/software/scm/git/docs/git-submodule.html" |
||||||
|
* >Git documentation about submodules</a> |
||||||
|
*/ |
||||||
|
public class SubmoduleStatusCommand extends |
||||||
|
GitCommand<Map<String, SubmoduleStatus>> { |
||||||
|
|
||||||
|
private final Collection<String> paths; |
||||||
|
|
||||||
|
/** |
||||||
|
* @param repo |
||||||
|
*/ |
||||||
|
public SubmoduleStatusCommand(final Repository repo) { |
||||||
|
super(repo); |
||||||
|
paths = new ArrayList<String>(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Add repository-relative submodule path to limit status reporting to |
||||||
|
* |
||||||
|
* @param path |
||||||
|
* @return this command |
||||||
|
*/ |
||||||
|
public SubmoduleStatusCommand addPath(final String path) { |
||||||
|
paths.add(path); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public Map<String, SubmoduleStatus> call() throws JGitInternalException { |
||||||
|
checkCallable(); |
||||||
|
|
||||||
|
try { |
||||||
|
SubmoduleWalk generator = SubmoduleWalk.forIndex(repo); |
||||||
|
if (!paths.isEmpty()) |
||||||
|
generator.setFilter(PathFilterGroup.createFromStrings(paths)); |
||||||
|
Map<String, SubmoduleStatus> statuses = new HashMap<String, SubmoduleStatus>(); |
||||||
|
while (generator.next()) { |
||||||
|
SubmoduleStatus status = getStatus(generator); |
||||||
|
statuses.put(status.getPath(), status); |
||||||
|
} |
||||||
|
return statuses; |
||||||
|
} catch (IOException e) { |
||||||
|
throw new JGitInternalException(e.getMessage(), e); |
||||||
|
} catch (ConfigInvalidException e) { |
||||||
|
throw new JGitInternalException(e.getMessage(), e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private SubmoduleStatus getStatus(SubmoduleWalk generator) |
||||||
|
throws IOException, ConfigInvalidException { |
||||||
|
ObjectId id = generator.getObjectId(); |
||||||
|
String path = generator.getPath(); |
||||||
|
|
||||||
|
// Report missing if no path in .gitmodules file
|
||||||
|
if (generator.getModulesPath() == null) |
||||||
|
return new SubmoduleStatus(SubmoduleStatusType.MISSING, path, id); |
||||||
|
|
||||||
|
// Report uninitialized if no URL in config file
|
||||||
|
if (generator.getConfigUrl() == null) |
||||||
|
return new SubmoduleStatus(SubmoduleStatusType.UNINITIALIZED, path, |
||||||
|
id); |
||||||
|
|
||||||
|
// Report uninitialized if no submodule repository
|
||||||
|
Repository subRepo = generator.getRepository(); |
||||||
|
if (subRepo == null) |
||||||
|
return new SubmoduleStatus(SubmoduleStatusType.UNINITIALIZED, path, |
||||||
|
id); |
||||||
|
|
||||||
|
ObjectId headId = subRepo.resolve(Constants.HEAD); |
||||||
|
|
||||||
|
// Report uninitialized if no HEAD commit in submodule repository
|
||||||
|
if (headId == null) |
||||||
|
return new SubmoduleStatus(SubmoduleStatusType.UNINITIALIZED, path, |
||||||
|
id, headId); |
||||||
|
|
||||||
|
// Report checked out if HEAD commit is different than index commit
|
||||||
|
if (!headId.equals(id)) |
||||||
|
return new SubmoduleStatus(SubmoduleStatusType.REV_CHECKED_OUT, |
||||||
|
path, id, headId); |
||||||
|
|
||||||
|
// Report initialized if HEAD commit is the same as the index commit
|
||||||
|
return new SubmoduleStatus(SubmoduleStatusType.INITIALIZED, path, id, |
||||||
|
headId); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,157 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2011, GitHub Inc. |
||||||
|
* 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 java.io.IOException; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Collection; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
import org.eclipse.jgit.api.errors.JGitInternalException; |
||||||
|
import org.eclipse.jgit.errors.ConfigInvalidException; |
||||||
|
import org.eclipse.jgit.lib.ConfigConstants; |
||||||
|
import org.eclipse.jgit.lib.Constants; |
||||||
|
import org.eclipse.jgit.lib.Ref; |
||||||
|
import org.eclipse.jgit.lib.Repository; |
||||||
|
import org.eclipse.jgit.lib.StoredConfig; |
||||||
|
import org.eclipse.jgit.submodule.SubmoduleWalk; |
||||||
|
import org.eclipse.jgit.treewalk.filter.PathFilterGroup; |
||||||
|
|
||||||
|
/** |
||||||
|
* A class used to execute a submodule sync command. |
||||||
|
* |
||||||
|
* This will set the remote URL in a submodule's repository to the current value |
||||||
|
* in the .gitmodules file. |
||||||
|
* |
||||||
|
* @see <a |
||||||
|
* href="http://www.kernel.org/pub/software/scm/git/docs/git-submodule.html" |
||||||
|
* >Git documentation about submodules</a> |
||||||
|
*/ |
||||||
|
public class SubmoduleSyncCommand extends GitCommand<Map<String, String>> { |
||||||
|
|
||||||
|
private final Collection<String> paths; |
||||||
|
|
||||||
|
/** |
||||||
|
* @param repo |
||||||
|
*/ |
||||||
|
public SubmoduleSyncCommand(final Repository repo) { |
||||||
|
super(repo); |
||||||
|
paths = new ArrayList<String>(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Add repository-relative submodule path to synchronize |
||||||
|
* |
||||||
|
* @param path |
||||||
|
* @return this command |
||||||
|
*/ |
||||||
|
public SubmoduleSyncCommand addPath(final String path) { |
||||||
|
paths.add(path); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get branch that HEAD currently points to |
||||||
|
* |
||||||
|
* @param subRepo |
||||||
|
* @return shortened branch name, null on failures |
||||||
|
* @throws IOException |
||||||
|
*/ |
||||||
|
protected String getHeadBranch(final Repository subRepo) throws IOException { |
||||||
|
Ref head = subRepo.getRef(Constants.HEAD); |
||||||
|
if (head != null && head.isSymbolic()) |
||||||
|
return Repository.shortenRefName(head.getLeaf().getName()); |
||||||
|
else |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public Map<String, String> call() throws JGitInternalException { |
||||||
|
checkCallable(); |
||||||
|
|
||||||
|
try { |
||||||
|
SubmoduleWalk generator = SubmoduleWalk.forIndex(repo); |
||||||
|
if (!paths.isEmpty()) |
||||||
|
generator.setFilter(PathFilterGroup.createFromStrings(paths)); |
||||||
|
Map<String, String> synced = new HashMap<String, String>(); |
||||||
|
StoredConfig config = repo.getConfig(); |
||||||
|
while (generator.next()) { |
||||||
|
String remoteUrl = generator.getModulesUrl(); |
||||||
|
if (remoteUrl == null) |
||||||
|
continue; |
||||||
|
|
||||||
|
String path = generator.getPath(); |
||||||
|
config.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, |
||||||
|
path, ConfigConstants.CONFIG_KEY_URL, remoteUrl); |
||||||
|
synced.put(path, remoteUrl); |
||||||
|
|
||||||
|
Repository subRepo = generator.getRepository(); |
||||||
|
if (subRepo == null) |
||||||
|
continue; |
||||||
|
|
||||||
|
StoredConfig subConfig = subRepo.getConfig(); |
||||||
|
// Get name of remote associated with current branch and
|
||||||
|
// fall back to default remote name as last resort
|
||||||
|
String branch = getHeadBranch(subRepo); |
||||||
|
String remote = null; |
||||||
|
if (branch != null) |
||||||
|
remote = subConfig.getString( |
||||||
|
ConfigConstants.CONFIG_BRANCH_SECTION, branch, |
||||||
|
ConfigConstants.CONFIG_KEY_REMOTE); |
||||||
|
if (remote == null) |
||||||
|
remote = Constants.DEFAULT_REMOTE_NAME; |
||||||
|
|
||||||
|
subConfig.setString(ConfigConstants.CONFIG_REMOTE_SECTION, |
||||||
|
remote, ConfigConstants.CONFIG_KEY_URL, remoteUrl); |
||||||
|
subConfig.save(); |
||||||
|
} |
||||||
|
if (!synced.isEmpty()) |
||||||
|
config.save(); |
||||||
|
return synced; |
||||||
|
} catch (IOException e) { |
||||||
|
throw new JGitInternalException(e.getMessage(), e); |
||||||
|
} catch (ConfigInvalidException e) { |
||||||
|
throw new JGitInternalException(e.getMessage(), e); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,190 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2011, GitHub Inc. |
||||||
|
* 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 java.io.IOException; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Collection; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import org.eclipse.jgit.api.errors.GitAPIException; |
||||||
|
import org.eclipse.jgit.api.errors.JGitInternalException; |
||||||
|
import org.eclipse.jgit.dircache.DirCacheCheckout; |
||||||
|
import org.eclipse.jgit.errors.ConfigInvalidException; |
||||||
|
import org.eclipse.jgit.lib.ConfigConstants; |
||||||
|
import org.eclipse.jgit.lib.Constants; |
||||||
|
import org.eclipse.jgit.lib.NullProgressMonitor; |
||||||
|
import org.eclipse.jgit.lib.ProgressMonitor; |
||||||
|
import org.eclipse.jgit.lib.RefUpdate; |
||||||
|
import org.eclipse.jgit.lib.Repository; |
||||||
|
import org.eclipse.jgit.revwalk.RevCommit; |
||||||
|
import org.eclipse.jgit.revwalk.RevWalk; |
||||||
|
import org.eclipse.jgit.submodule.SubmoduleWalk; |
||||||
|
import org.eclipse.jgit.transport.CredentialsProvider; |
||||||
|
import org.eclipse.jgit.treewalk.filter.PathFilterGroup; |
||||||
|
|
||||||
|
/** |
||||||
|
* A class used to execute a submodule update command. |
||||||
|
* |
||||||
|
* @see <a |
||||||
|
* href="http://www.kernel.org/pub/software/scm/git/docs/git-submodule.html" |
||||||
|
* >Git documentation about submodules</a> |
||||||
|
*/ |
||||||
|
public class SubmoduleUpdateCommand extends GitCommand<Collection<String>> { |
||||||
|
|
||||||
|
private ProgressMonitor monitor; |
||||||
|
|
||||||
|
private CredentialsProvider credentialsProvider; |
||||||
|
|
||||||
|
private final Collection<String> paths; |
||||||
|
|
||||||
|
/** |
||||||
|
* @param repo |
||||||
|
*/ |
||||||
|
public SubmoduleUpdateCommand(final Repository repo) { |
||||||
|
super(repo); |
||||||
|
paths = new ArrayList<String>(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* The progress monitor associated with the clone operation. By default, |
||||||
|
* this is set to <code>NullProgressMonitor</code> |
||||||
|
* |
||||||
|
* @see NullProgressMonitor |
||||||
|
* @param monitor |
||||||
|
* @return this command |
||||||
|
*/ |
||||||
|
public SubmoduleUpdateCommand setProgressMonitor( |
||||||
|
final ProgressMonitor monitor) { |
||||||
|
this.monitor = monitor; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @param credentialsProvider |
||||||
|
* the {@link CredentialsProvider} to use |
||||||
|
* @return this command |
||||||
|
*/ |
||||||
|
public SubmoduleUpdateCommand setCredentialsProvider( |
||||||
|
final CredentialsProvider credentialsProvider) { |
||||||
|
this.credentialsProvider = credentialsProvider; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Add repository-relative submodule path to initialize |
||||||
|
* |
||||||
|
* @param path |
||||||
|
* @return this command |
||||||
|
*/ |
||||||
|
public SubmoduleUpdateCommand addPath(final String path) { |
||||||
|
paths.add(path); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public Collection<String> call() throws JGitInternalException { |
||||||
|
checkCallable(); |
||||||
|
|
||||||
|
try { |
||||||
|
SubmoduleWalk generator = SubmoduleWalk.forIndex(repo); |
||||||
|
if (!paths.isEmpty()) |
||||||
|
generator.setFilter(PathFilterGroup.createFromStrings(paths)); |
||||||
|
List<String> updated = new ArrayList<String>(); |
||||||
|
while (generator.next()) { |
||||||
|
// Skip submodules not registered in .gitmodules file
|
||||||
|
if (generator.getModulesPath() == null) |
||||||
|
continue; |
||||||
|
// Skip submodules not registered in parent repository's config
|
||||||
|
String url = generator.getConfigUrl(); |
||||||
|
if (url == null) |
||||||
|
continue; |
||||||
|
|
||||||
|
Repository submoduleRepo = generator.getRepository(); |
||||||
|
// Clone repository is not present
|
||||||
|
if (submoduleRepo == null) { |
||||||
|
CloneCommand clone = Git.cloneRepository(); |
||||||
|
clone.setURI(url); |
||||||
|
clone.setDirectory(generator.getDirectory()); |
||||||
|
if (monitor != null) |
||||||
|
clone.setProgressMonitor(monitor); |
||||||
|
if (credentialsProvider != null) |
||||||
|
clone.setCredentialsProvider(credentialsProvider); |
||||||
|
submoduleRepo = clone.call().getRepository(); |
||||||
|
} |
||||||
|
|
||||||
|
RevWalk walk = new RevWalk(submoduleRepo); |
||||||
|
RevCommit commit = walk.parseCommit(generator.getObjectId()); |
||||||
|
|
||||||
|
String update = generator.getConfigUpdate(); |
||||||
|
if (ConfigConstants.CONFIG_KEY_MERGE.equals(update)) { |
||||||
|
MergeCommand merge = new MergeCommand(submoduleRepo); |
||||||
|
merge.include(commit); |
||||||
|
merge.call(); |
||||||
|
} else if (ConfigConstants.CONFIG_KEY_REBASE.equals(update)) { |
||||||
|
RebaseCommand rebase = new RebaseCommand(submoduleRepo); |
||||||
|
rebase.setUpstream(commit); |
||||||
|
rebase.call(); |
||||||
|
} else { |
||||||
|
// Checkout commit referenced in parent repository's index
|
||||||
|
// as a detached HEAD
|
||||||
|
DirCacheCheckout co = new DirCacheCheckout(submoduleRepo, |
||||||
|
submoduleRepo.lockDirCache(), commit.getTree()); |
||||||
|
co.setFailOnConflict(true); |
||||||
|
co.checkout(); |
||||||
|
RefUpdate refUpdate = submoduleRepo.updateRef( |
||||||
|
Constants.HEAD, true); |
||||||
|
refUpdate.setNewObjectId(commit); |
||||||
|
refUpdate.forceUpdate(); |
||||||
|
} |
||||||
|
updated.add(generator.getPath()); |
||||||
|
} |
||||||
|
return updated; |
||||||
|
} catch (IOException e) { |
||||||
|
throw new JGitInternalException(e.getMessage(), e); |
||||||
|
} catch (ConfigInvalidException e) { |
||||||
|
throw new JGitInternalException(e.getMessage(), e); |
||||||
|
} catch (GitAPIException e) { |
||||||
|
throw new JGitInternalException(e.getMessage(), e); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,115 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2011, GitHub Inc. |
||||||
|
* 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 org.eclipse.jgit.lib.ObjectId; |
||||||
|
|
||||||
|
/** |
||||||
|
* Status class containing the type, path, and commit id of the submodule. |
||||||
|
*/ |
||||||
|
public class SubmoduleStatus { |
||||||
|
|
||||||
|
private final SubmoduleStatusType type; |
||||||
|
|
||||||
|
private final String path; |
||||||
|
|
||||||
|
private final ObjectId indexId; |
||||||
|
|
||||||
|
private final ObjectId headId; |
||||||
|
|
||||||
|
/** |
||||||
|
* Create submodule status |
||||||
|
* |
||||||
|
* @param type |
||||||
|
* @param path |
||||||
|
* @param indexId |
||||||
|
*/ |
||||||
|
public SubmoduleStatus(final SubmoduleStatusType type, final String path, |
||||||
|
final ObjectId indexId) { |
||||||
|
this(type, path, indexId, null); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create submodule status |
||||||
|
* |
||||||
|
* @param type |
||||||
|
* @param path |
||||||
|
* @param indexId |
||||||
|
* @param headId |
||||||
|
*/ |
||||||
|
public SubmoduleStatus(final SubmoduleStatusType type, final String path, |
||||||
|
final ObjectId indexId, final ObjectId headId) { |
||||||
|
this.type = type; |
||||||
|
this.path = path; |
||||||
|
this.indexId = indexId; |
||||||
|
this.headId = headId; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @return type |
||||||
|
*/ |
||||||
|
public SubmoduleStatusType getType() { |
||||||
|
return type; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @return path |
||||||
|
*/ |
||||||
|
public String getPath() { |
||||||
|
return path; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @return index object id |
||||||
|
*/ |
||||||
|
public ObjectId getIndexId() { |
||||||
|
return indexId; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @return HEAD object id |
||||||
|
*/ |
||||||
|
public ObjectId getHeadId() { |
||||||
|
return headId; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,64 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2011, GitHub Inc. |
||||||
|
* 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; |
||||||
|
|
||||||
|
/** |
||||||
|
* Enumeration of different statuses that a submodule can be in |
||||||
|
*/ |
||||||
|
public enum SubmoduleStatusType { |
||||||
|
|
||||||
|
/** Submodule's configuration is missing */ |
||||||
|
MISSING, |
||||||
|
|
||||||
|
/** Submodule's Git repository is not initialized */ |
||||||
|
UNINITIALIZED, |
||||||
|
|
||||||
|
/** Submodule's Git repository is initialized */ |
||||||
|
INITIALIZED, |
||||||
|
|
||||||
|
/** |
||||||
|
* Submodule commit checked out is different than the commit referenced in |
||||||
|
* the index tree |
||||||
|
*/ |
||||||
|
REV_CHECKED_OUT; |
||||||
|
} |
@ -0,0 +1,435 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2011, GitHub Inc. |
||||||
|
* 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 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.lib.AnyObjectId; |
||||||
|
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.StoredConfig; |
||||||
|
import org.eclipse.jgit.storage.file.FileBasedConfig; |
||||||
|
import org.eclipse.jgit.treewalk.AbstractTreeIterator; |
||||||
|
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 { |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a generator to walk over the submodule entries currently in the |
||||||
|
* index |
||||||
|
* |
||||||
|
* @param repository |
||||||
|
* @return generator over submodule index entries |
||||||
|
* @throws IOException |
||||||
|
*/ |
||||||
|
public static SubmoduleWalk forIndex(Repository repository) |
||||||
|
throws IOException { |
||||||
|
SubmoduleWalk generator = new SubmoduleWalk(repository); |
||||||
|
generator.setTree(new DirCacheIterator(repository.readDirCache())); |
||||||
|
return generator; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a generator and advance it to the submodule entry at the given |
||||||
|
* path |
||||||
|
* |
||||||
|
* @param repository |
||||||
|
* @param treeId |
||||||
|
* @param path |
||||||
|
* @return generator at given path, null if no submodule at given path |
||||||
|
* @throws IOException |
||||||
|
*/ |
||||||
|
public static SubmoduleWalk forPath(Repository repository, |
||||||
|
AnyObjectId treeId, String path) throws IOException { |
||||||
|
SubmoduleWalk generator = new SubmoduleWalk(repository); |
||||||
|
generator.setTree(treeId); |
||||||
|
PathFilter filter = PathFilter.create(path); |
||||||
|
generator.setFilter(filter); |
||||||
|
while (generator.next()) |
||||||
|
if (filter.isDone(generator.walk)) |
||||||
|
return generator; |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a generator and advance it to the submodule entry at the given |
||||||
|
* path |
||||||
|
* |
||||||
|
* @param repository |
||||||
|
* @param iterator |
||||||
|
* @param path |
||||||
|
* @return generator at given path, null if no submodule at given path |
||||||
|
* @throws IOException |
||||||
|
*/ |
||||||
|
public static SubmoduleWalk forPath(Repository repository, |
||||||
|
AbstractTreeIterator iterator, String path) throws IOException { |
||||||
|
SubmoduleWalk generator = new SubmoduleWalk(repository); |
||||||
|
generator.setTree(iterator); |
||||||
|
PathFilter filter = PathFilter.create(path); |
||||||
|
generator.setFilter(filter); |
||||||
|
while (generator.next()) |
||||||
|
if (filter.isDone(generator.walk)) |
||||||
|
return generator; |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get submodule directory |
||||||
|
* |
||||||
|
* @param parent |
||||||
|
* @param path |
||||||
|
* @return directory |
||||||
|
*/ |
||||||
|
public static File getSubmoduleDirectory(final Repository parent, |
||||||
|
final String path) { |
||||||
|
return new File(parent.getWorkTree(), path); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get submodule repository |
||||||
|
* |
||||||
|
* @param parent |
||||||
|
* @param path |
||||||
|
* @return repository or null if repository doesn't exist |
||||||
|
* @throws IOException |
||||||
|
*/ |
||||||
|
public static Repository getSubmoduleRepository(final Repository parent, |
||||||
|
final String path) throws IOException { |
||||||
|
File directory = getSubmoduleGitDirectory(parent, path); |
||||||
|
if (!directory.isDirectory()) |
||||||
|
return null; |
||||||
|
try { |
||||||
|
return new RepositoryBuilder().setMustExist(true) |
||||||
|
.setFS(FS.DETECTED).setGitDir(directory).build(); |
||||||
|
} catch (RepositoryNotFoundException e) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the .git directory for a repository submodule path |
||||||
|
* |
||||||
|
* @param parent |
||||||
|
* @param path |
||||||
|
* @return .git for submodule repository |
||||||
|
*/ |
||||||
|
public static File getSubmoduleGitDirectory(final Repository parent, |
||||||
|
final String path) { |
||||||
|
return new File(getSubmoduleDirectory(parent, path), Constants.DOT_GIT); |
||||||
|
} |
||||||
|
|
||||||
|
private final Repository repository; |
||||||
|
|
||||||
|
private final TreeWalk walk; |
||||||
|
|
||||||
|
private StoredConfig repoConfig; |
||||||
|
|
||||||
|
private FileBasedConfig modulesConfig; |
||||||
|
|
||||||
|
private String path; |
||||||
|
|
||||||
|
/** |
||||||
|
* Create submodule generator |
||||||
|
* |
||||||
|
* @param repository |
||||||
|
* @throws IOException |
||||||
|
*/ |
||||||
|
public SubmoduleWalk(final Repository repository) throws IOException { |
||||||
|
this.repository = repository; |
||||||
|
repoConfig = repository.getConfig(); |
||||||
|
walk = new TreeWalk(repository); |
||||||
|
walk.setRecursive(true); |
||||||
|
} |
||||||
|
|
||||||
|
private void loadModulesConfig() throws IOException, ConfigInvalidException { |
||||||
|
if (modulesConfig == null) { |
||||||
|
File modulesFile = new File(repository.getWorkTree(), |
||||||
|
Constants.DOT_GIT_MODULES); |
||||||
|
FileBasedConfig config = new FileBasedConfig(modulesFile, |
||||||
|
repository.getFS()); |
||||||
|
config.load(); |
||||||
|
modulesConfig = config; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Set tree filter |
||||||
|
* |
||||||
|
* @param filter |
||||||
|
* @return this generator |
||||||
|
*/ |
||||||
|
public SubmoduleWalk setFilter(TreeFilter filter) { |
||||||
|
walk.setFilter(filter); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Set the tree iterator used for finding submodule entries |
||||||
|
* |
||||||
|
* @param iterator |
||||||
|
* @return this generator |
||||||
|
* @throws CorruptObjectException |
||||||
|
*/ |
||||||
|
public SubmoduleWalk setTree(final AbstractTreeIterator iterator) |
||||||
|
throws CorruptObjectException { |
||||||
|
walk.addTree(iterator); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Set the tree used for finding submodule entries |
||||||
|
* |
||||||
|
* @param treeId |
||||||
|
* @return this generator |
||||||
|
* @throws IOException |
||||||
|
* @throws IncorrectObjectTypeException |
||||||
|
* @throws MissingObjectException |
||||||
|
*/ |
||||||
|
public SubmoduleWalk setTree(final 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; |
||||||
|
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); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the .git directory for the current submodule entry |
||||||
|
* |
||||||
|
* @return .git for submodule repository |
||||||
|
*/ |
||||||
|
public File getGitDirectory() { |
||||||
|
return getSubmoduleGitDirectory(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 IOException |
||||||
|
*/ |
||||||
|
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; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 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 ConfigInvalidException |
||||||
|
* @throws IOException |
||||||
|
*/ |
||||||
|
public String getModulesPath() throws IOException, ConfigInvalidException { |
||||||
|
loadModulesConfig(); |
||||||
|
return modulesConfig.getString( |
||||||
|
ConfigConstants.CONFIG_SUBMODULE_SECTION, path, |
||||||
|
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 ConfigInvalidException |
||||||
|
* @throws IOException |
||||||
|
*/ |
||||||
|
public String getConfigUrl() throws IOException, ConfigInvalidException { |
||||||
|
return repoConfig.getString(ConfigConstants.CONFIG_SUBMODULE_SECTION, |
||||||
|
path, 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 ConfigInvalidException |
||||||
|
* @throws IOException |
||||||
|
*/ |
||||||
|
public String getModulesUrl() throws IOException, ConfigInvalidException { |
||||||
|
loadModulesConfig(); |
||||||
|
return modulesConfig.getString( |
||||||
|
ConfigConstants.CONFIG_SUBMODULE_SECTION, path, |
||||||
|
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 ConfigInvalidException |
||||||
|
* @throws IOException |
||||||
|
*/ |
||||||
|
public String getConfigUpdate() throws IOException, ConfigInvalidException { |
||||||
|
return repoConfig.getString(ConfigConstants.CONFIG_SUBMODULE_SECTION, |
||||||
|
path, 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 ConfigInvalidException |
||||||
|
* @throws IOException |
||||||
|
*/ |
||||||
|
public String getModulesUpdate() throws IOException, ConfigInvalidException { |
||||||
|
loadModulesConfig(); |
||||||
|
return modulesConfig.getString( |
||||||
|
ConfigConstants.CONFIG_SUBMODULE_SECTION, path, |
||||||
|
ConfigConstants.CONFIG_KEY_UPDATE); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Does the current submodule entry have a .git directory in the parent |
||||||
|
* repository's working tree? |
||||||
|
* |
||||||
|
* @return true if .git directory exists, false otherwise |
||||||
|
*/ |
||||||
|
public boolean hasGitDirectory() { |
||||||
|
return getGitDirectory().isDirectory(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get repository for current submodule entry |
||||||
|
* |
||||||
|
* @see #hasGitDirectory() |
||||||
|
* @return repository or null if non-existent |
||||||
|
* @throws IOException |
||||||
|
*/ |
||||||
|
public Repository getRepository() throws IOException { |
||||||
|
return getSubmoduleRepository(repository, path); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get commit id that HEAD points to in the current submodule's repository |
||||||
|
* |
||||||
|
* @return object id of HEAD reference |
||||||
|
* @throws IOException |
||||||
|
*/ |
||||||
|
public ObjectId getHead() throws IOException { |
||||||
|
Repository subRepo = getRepository(); |
||||||
|
return subRepo != null ? subRepo.resolve(Constants.HEAD) : null; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get ref that HEAD points to in the current submodule's repository |
||||||
|
* |
||||||
|
* @return ref name, null on failures |
||||||
|
* @throws IOException |
||||||
|
*/ |
||||||
|
public String getHeadRef() throws IOException { |
||||||
|
Repository subRepo = getRepository(); |
||||||
|
if (subRepo == null) |
||||||
|
return null; |
||||||
|
Ref head = subRepo.getRef(Constants.HEAD); |
||||||
|
return head != null ? head.getLeaf().getName() : null; |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue