Allow explicit configuration of git directory in InitCommand
Native git's "init" command allows to specify the location of the .git folder with the option "--separate-git-dir". This allows for example to setup repositories with a non-standard layout. E.g. .git folder under /repos/a.git and the worktree under /home/git/a. Both directories contain pointers to the other side: /repos/a.git/config contains core.worktree=/home/git/a . And /home/git/a/.git is a file containing "gitdir: /repos/a.git". This commit adds that option to InitCommand. This feature is needed to support the new submodule layout where the .git folder of the submodules is under .git/modules/<submodule>. Change-Id: I0208f643808bf8f28e2c979d6e33662607775f1f
This commit is contained in:
parent
ca7c928eae
commit
03e860a7b7
|
@ -90,6 +90,7 @@ public MockSystemReader() {
|
|||
init(Constants.GIT_AUTHOR_EMAIL_KEY);
|
||||
init(Constants.GIT_COMMITTER_NAME_KEY);
|
||||
init(Constants.GIT_COMMITTER_EMAIL_KEY);
|
||||
setProperty(Constants.OS_USER_DIR, ".");
|
||||
userGitConfig = new MockConfig(null, null);
|
||||
systemGitConfig = new MockConfig(null, null);
|
||||
setCurrentPlatform();
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
package org.eclipse.jgit.api;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -50,8 +51,12 @@
|
|||
|
||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||
import org.eclipse.jgit.api.errors.JGitInternalException;
|
||||
import org.eclipse.jgit.errors.NoWorkTreeException;
|
||||
import org.eclipse.jgit.junit.MockSystemReader;
|
||||
import org.eclipse.jgit.junit.RepositoryTestCase;
|
||||
import org.eclipse.jgit.lib.Constants;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.util.SystemReader;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -101,4 +106,109 @@ public void testInitBareRepository() throws IOException,
|
|||
assertNotNull(repository);
|
||||
assertTrue(repository.isBare());
|
||||
}
|
||||
|
||||
// non-bare repos where gitDir and directory is set. Same as
|
||||
// "git init --separate-git-dir /tmp/a /tmp/b"
|
||||
@Test
|
||||
public void testInitWithExplicitGitDir() throws IOException,
|
||||
JGitInternalException, GitAPIException {
|
||||
File wt = createTempDirectory("testInitRepositoryWT");
|
||||
File gitDir = createTempDirectory("testInitRepositoryGIT");
|
||||
InitCommand command = new InitCommand();
|
||||
command.setDirectory(wt);
|
||||
command.setGitDir(gitDir);
|
||||
Repository repository = command.call().getRepository();
|
||||
addRepoToClose(repository);
|
||||
assertNotNull(repository);
|
||||
assertEqualsFile(wt, repository.getWorkTree());
|
||||
assertEqualsFile(gitDir, repository.getDirectory());
|
||||
}
|
||||
|
||||
// non-bare repos where only gitDir is set. Same as
|
||||
// "git init --separate-git-dir /tmp/a"
|
||||
@Test
|
||||
public void testInitWithOnlyExplicitGitDir() throws IOException,
|
||||
JGitInternalException, GitAPIException {
|
||||
MockSystemReader reader = (MockSystemReader) SystemReader.getInstance();
|
||||
reader.setProperty(Constants.OS_USER_DIR, getTemporaryDirectory()
|
||||
.getAbsolutePath());
|
||||
File gitDir = createTempDirectory("testInitRepository/.git");
|
||||
InitCommand command = new InitCommand();
|
||||
command.setGitDir(gitDir);
|
||||
Repository repository = command.call().getRepository();
|
||||
addRepoToClose(repository);
|
||||
assertNotNull(repository);
|
||||
assertEqualsFile(gitDir, repository.getDirectory());
|
||||
assertEqualsFile(new File(reader.getProperty("user.dir")),
|
||||
repository.getWorkTree());
|
||||
}
|
||||
|
||||
// Bare repos where gitDir and directory is set will only work if gitDir and
|
||||
// directory is pointing to same dir. Same as
|
||||
// "git init --bare --separate-git-dir /tmp/a /tmp/b"
|
||||
// (works in native git but I guess that's more a bug)
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void testInitBare_DirAndGitDirMustBeEqual() throws IOException,
|
||||
JGitInternalException, GitAPIException {
|
||||
File gitDir = createTempDirectory("testInitRepository.git");
|
||||
InitCommand command = new InitCommand();
|
||||
command.setBare(true);
|
||||
command.setDirectory(gitDir);
|
||||
command.setGitDir(new File(gitDir, ".."));
|
||||
command.call();
|
||||
}
|
||||
|
||||
// If neither directory nor gitDir is set in a non-bare repo make sure
|
||||
// worktree and gitDir are set correctly. Standard case. Same as
|
||||
// "git init"
|
||||
@Test
|
||||
public void testInitWithDefaultsNonBare() throws JGitInternalException,
|
||||
GitAPIException, IOException {
|
||||
MockSystemReader reader = (MockSystemReader) SystemReader.getInstance();
|
||||
reader.setProperty(Constants.OS_USER_DIR, getTemporaryDirectory()
|
||||
.getAbsolutePath());
|
||||
InitCommand command = new InitCommand();
|
||||
command.setBare(false);
|
||||
Repository repository = command.call().getRepository();
|
||||
addRepoToClose(repository);
|
||||
assertNotNull(repository);
|
||||
assertEqualsFile(new File(reader.getProperty("user.dir"), ".git"),
|
||||
repository.getDirectory());
|
||||
assertEqualsFile(new File(reader.getProperty("user.dir")),
|
||||
repository.getWorkTree());
|
||||
}
|
||||
|
||||
// If neither directory nor gitDir is set in a bare repo make sure
|
||||
// worktree and gitDir are set correctly. Standard case. Same as
|
||||
// "git init --bare"
|
||||
@Test(expected = NoWorkTreeException.class)
|
||||
public void testInitWithDefaultsBare() throws JGitInternalException,
|
||||
GitAPIException, IOException {
|
||||
MockSystemReader reader = (MockSystemReader) SystemReader.getInstance();
|
||||
reader.setProperty(Constants.OS_USER_DIR, getTemporaryDirectory()
|
||||
.getAbsolutePath());
|
||||
InitCommand command = new InitCommand();
|
||||
command.setBare(true);
|
||||
Repository repository = command.call().getRepository();
|
||||
addRepoToClose(repository);
|
||||
assertNotNull(repository);
|
||||
assertEqualsFile(new File(reader.getProperty("user.dir")),
|
||||
repository.getDirectory());
|
||||
assertNull(repository.getWorkTree());
|
||||
}
|
||||
|
||||
// In a non-bare repo when directory and gitDir is set then they shouldn't
|
||||
// point to the same dir. Same as
|
||||
// "git init --separate-git-dir /tmp/a /tmp/a"
|
||||
// (works in native git but I guess that's more a bug)
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void testInitNonBare_GitdirAndDirShouldntBeSame()
|
||||
throws JGitInternalException, GitAPIException, IOException {
|
||||
File gitDir = createTempDirectory("testInitRepository.git");
|
||||
InitCommand command = new InitCommand();
|
||||
command.setBare(false);
|
||||
command.setGitDir(gitDir);
|
||||
command.setDirectory(gitDir);
|
||||
command.call().getRepository();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -249,6 +249,8 @@ indexFileIsInUse=Index file is in use
|
|||
indexFileIsTooLargeForJgit=Index file is too large for jgit
|
||||
indexSignatureIsInvalid=Index signature is invalid: {0}
|
||||
indexWriteException=Modified index could not be written
|
||||
initFailedBareRepoDifferentDirs=When initializing a bare repo with directory {0} and separate git-dir {1} specified both folders must point to the same location
|
||||
initFailedNonBareRepoSameDirs=When initializing a non-bare repo with directory {0} and separate git-dir {1} specified both folders should not point to the same location
|
||||
inMemoryBufferLimitExceeded=In-memory buffer limit exceeded
|
||||
inputStreamMustSupportMark=InputStream must support mark()
|
||||
integerValueOutOfRange=Integer value {0}.{1} out of range
|
||||
|
|
|
@ -44,13 +44,16 @@
|
|||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||
import org.eclipse.jgit.api.errors.JGitInternalException;
|
||||
import org.eclipse.jgit.internal.JGitText;
|
||||
import org.eclipse.jgit.lib.Constants;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.lib.RepositoryBuilder;
|
||||
import org.eclipse.jgit.util.SystemReader;
|
||||
|
||||
/**
|
||||
* Create an empty git repository or reinitalize an existing one
|
||||
|
@ -61,6 +64,8 @@
|
|||
public class InitCommand implements Callable<Git> {
|
||||
private File directory;
|
||||
|
||||
private File gitDir;
|
||||
|
||||
private boolean bare;
|
||||
|
||||
/**
|
||||
|
@ -74,18 +79,36 @@ public Git call() throws GitAPIException {
|
|||
if (bare)
|
||||
builder.setBare();
|
||||
builder.readEnvironment();
|
||||
if (gitDir != null)
|
||||
builder.setGitDir(gitDir);
|
||||
else
|
||||
gitDir = builder.getGitDir();
|
||||
if (directory != null) {
|
||||
File d = directory;
|
||||
if (!bare)
|
||||
d = new File(d, Constants.DOT_GIT);
|
||||
builder.setGitDir(d);
|
||||
if (bare)
|
||||
builder.setGitDir(directory);
|
||||
else {
|
||||
builder.setWorkTree(directory);
|
||||
if (gitDir == null)
|
||||
builder.setGitDir(new File(directory, Constants.DOT_GIT));
|
||||
}
|
||||
} else if (builder.getGitDir() == null) {
|
||||
File d = new File("."); //$NON-NLS-1$
|
||||
if (d.getParentFile() != null)
|
||||
d = d.getParentFile();
|
||||
String dStr = SystemReader.getInstance()
|
||||
.getProperty("user.dir"); //$NON-NLS-1$
|
||||
if (dStr == null)
|
||||
dStr = "."; //$NON-NLS-1$
|
||||
File d = new File(dStr);
|
||||
if (!bare)
|
||||
d = new File(d, Constants.DOT_GIT);
|
||||
builder.setGitDir(d);
|
||||
} else {
|
||||
// directory was not set but gitDir was set
|
||||
if (!bare) {
|
||||
String dStr = SystemReader.getInstance().getProperty(
|
||||
"user.dir"); //$NON-NLS-1$
|
||||
if (dStr == null)
|
||||
dStr = "."; //$NON-NLS-1$
|
||||
builder.setWorkTree(new File(dStr));
|
||||
}
|
||||
}
|
||||
Repository repository = builder.build();
|
||||
if (!repository.getObjectDatabase().exists())
|
||||
|
@ -103,20 +126,67 @@ public Git call() throws GitAPIException {
|
|||
* @param directory
|
||||
* the directory to init to
|
||||
* @return this instance
|
||||
* @throws IllegalStateException
|
||||
* if the combination of directory, gitDir and bare is illegal.
|
||||
* E.g. if for a non-bare repository directory and gitDir point
|
||||
* to the same directory of if for a bare repository both
|
||||
* directory and gitDir are specified
|
||||
*/
|
||||
public InitCommand setDirectory(File directory) {
|
||||
public InitCommand setDirectory(File directory)
|
||||
throws IllegalStateException {
|
||||
validateDirs(directory, gitDir, bare);
|
||||
this.directory = directory;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bare
|
||||
* whether the repository is bare or not
|
||||
* @param gitDir
|
||||
* the repository meta directory
|
||||
* @return this instance
|
||||
* @throws IllegalStateException
|
||||
* if the combination of directory, gitDir and bare is illegal.
|
||||
* E.g. if for a non-bare repository directory and gitDir point
|
||||
* to the same directory of if for a bare repository both
|
||||
* directory and gitDir are specified
|
||||
* @since 3.6
|
||||
*/
|
||||
public InitCommand setBare(boolean bare) {
|
||||
this.bare = bare;
|
||||
public InitCommand setGitDir(File gitDir)
|
||||
throws IllegalStateException {
|
||||
validateDirs(directory, gitDir, bare);
|
||||
this.gitDir = gitDir;
|
||||
return this;
|
||||
}
|
||||
|
||||
private static void validateDirs(File directory, File gitDir, boolean bare)
|
||||
throws IllegalStateException {
|
||||
if (directory != null) {
|
||||
if (bare) {
|
||||
if (gitDir != null && !gitDir.equals(directory))
|
||||
throw new IllegalStateException(MessageFormat.format(
|
||||
JGitText.get().initFailedBareRepoDifferentDirs,
|
||||
gitDir, directory));
|
||||
} else {
|
||||
if (gitDir != null && gitDir.equals(directory))
|
||||
throw new IllegalStateException(MessageFormat.format(
|
||||
JGitText.get().initFailedNonBareRepoSameDirs,
|
||||
gitDir, directory));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bare
|
||||
* whether the repository is bare or not
|
||||
* @throws IllegalStateException
|
||||
* if the combination of directory, gitDir and bare is illegal.
|
||||
* E.g. if for a non-bare repository directory and gitDir point
|
||||
* to the same directory of if for a bare repository both
|
||||
* directory and gitDir are specified
|
||||
* @return this instance
|
||||
*/
|
||||
public InitCommand setBare(boolean bare) {
|
||||
validateDirs(directory, gitDir, bare);
|
||||
this.bare = bare;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -308,6 +308,8 @@ public static JGitText get() {
|
|||
/***/ public String indexFileIsTooLargeForJgit;
|
||||
/***/ public String indexSignatureIsInvalid;
|
||||
/***/ public String indexWriteException;
|
||||
/***/ public String initFailedBareRepoDifferentDirs;
|
||||
/***/ public String initFailedNonBareRepoSameDirs;
|
||||
/***/ public String inMemoryBufferLimitExceeded;
|
||||
/***/ public String inputStreamMustSupportMark;
|
||||
/***/ public String integerValueOutOfRange;
|
||||
|
|
|
@ -273,7 +273,8 @@ public void create(boolean bare) throws IOException {
|
|||
ConfigConstants.CONFIG_CORE_SECTION, null,
|
||||
ConfigConstants.CONFIG_KEY_HIDEDOTFILES,
|
||||
HideDotFiles.DOTGITONLY);
|
||||
if (hideDotFiles != HideDotFiles.FALSE && !isBare())
|
||||
if (hideDotFiles != HideDotFiles.FALSE && !isBare()
|
||||
&& getDirectory().getName().startsWith(".")) //$NON-NLS-1$
|
||||
getFS().setHidden(getDirectory(), true);
|
||||
refs.create();
|
||||
objectDatabase.create();
|
||||
|
@ -329,6 +330,25 @@ public void create(boolean bare) throws IOException {
|
|||
// Java has no other way
|
||||
cfg.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
|
||||
ConfigConstants.CONFIG_KEY_PRECOMPOSEUNICODE, true);
|
||||
if (!bare) {
|
||||
File workTree = getWorkTree();
|
||||
if (!getDirectory().getParentFile().equals(workTree)) {
|
||||
cfg.setString(ConfigConstants.CONFIG_CORE_SECTION, null,
|
||||
ConfigConstants.CONFIG_KEY_WORKTREE, getWorkTree()
|
||||
.getAbsolutePath());
|
||||
LockFile dotGitLockFile = new LockFile(new File(workTree,
|
||||
Constants.DOT_GIT), getFS());
|
||||
try {
|
||||
if (dotGitLockFile.lock()) {
|
||||
dotGitLockFile.write(Constants.encode(Constants.GITDIR
|
||||
+ getDirectory().getAbsolutePath()));
|
||||
dotGitLockFile.commit();
|
||||
}
|
||||
} finally {
|
||||
dotGitLockFile.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
cfg.save();
|
||||
}
|
||||
|
||||
|
|
|
@ -272,7 +272,14 @@ public final class Constants {
|
|||
*/
|
||||
public static final String INFO_EXCLUDE = "info/exclude";
|
||||
|
||||
/** The environment variable that contains the system user name */
|
||||
/**
|
||||
* The system property that contains the system user name
|
||||
*
|
||||
* @since 3.6
|
||||
*/
|
||||
public static final String OS_USER_DIR = "user.dir";
|
||||
|
||||
/** The system property that contains the system user name */
|
||||
public static final String OS_USER_NAME_KEY = "user.name";
|
||||
|
||||
/** The environment variable that contains the author's name */
|
||||
|
@ -358,6 +365,13 @@ public final class Constants {
|
|||
/** Name of the .git/shallow file */
|
||||
public static final String SHALLOW = "shallow";
|
||||
|
||||
/**
|
||||
* Prefix of the first line in a ".git" file
|
||||
*
|
||||
* @since 3.6
|
||||
*/
|
||||
public static final String GITDIR = "gitdir: ";
|
||||
|
||||
/**
|
||||
* Create a new digest function for objects.
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue