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