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_AUTHOR_EMAIL_KEY);
|
||||||
init(Constants.GIT_COMMITTER_NAME_KEY);
|
init(Constants.GIT_COMMITTER_NAME_KEY);
|
||||||
init(Constants.GIT_COMMITTER_EMAIL_KEY);
|
init(Constants.GIT_COMMITTER_EMAIL_KEY);
|
||||||
|
setProperty(Constants.OS_USER_DIR, ".");
|
||||||
userGitConfig = new MockConfig(null, null);
|
userGitConfig = new MockConfig(null, null);
|
||||||
systemGitConfig = new MockConfig(null, null);
|
systemGitConfig = new MockConfig(null, null);
|
||||||
setCurrentPlatform();
|
setCurrentPlatform();
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
package org.eclipse.jgit.api;
|
package org.eclipse.jgit.api;
|
||||||
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -50,8 +51,12 @@
|
||||||
|
|
||||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||||
import org.eclipse.jgit.api.errors.JGitInternalException;
|
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.junit.RepositoryTestCase;
|
||||||
|
import org.eclipse.jgit.lib.Constants;
|
||||||
import org.eclipse.jgit.lib.Repository;
|
import org.eclipse.jgit.lib.Repository;
|
||||||
|
import org.eclipse.jgit.util.SystemReader;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -101,4 +106,109 @@ public void testInitBareRepository() throws IOException,
|
||||||
assertNotNull(repository);
|
assertNotNull(repository);
|
||||||
assertTrue(repository.isBare());
|
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
|
indexFileIsTooLargeForJgit=Index file is too large for jgit
|
||||||
indexSignatureIsInvalid=Index signature is invalid: {0}
|
indexSignatureIsInvalid=Index signature is invalid: {0}
|
||||||
indexWriteException=Modified index could not be written
|
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
|
inMemoryBufferLimitExceeded=In-memory buffer limit exceeded
|
||||||
inputStreamMustSupportMark=InputStream must support mark()
|
inputStreamMustSupportMark=InputStream must support mark()
|
||||||
integerValueOutOfRange=Integer value {0}.{1} out of range
|
integerValueOutOfRange=Integer value {0}.{1} out of range
|
||||||
|
|
|
@ -44,13 +44,16 @@
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.text.MessageFormat;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||||
import org.eclipse.jgit.api.errors.JGitInternalException;
|
import org.eclipse.jgit.api.errors.JGitInternalException;
|
||||||
|
import org.eclipse.jgit.internal.JGitText;
|
||||||
import org.eclipse.jgit.lib.Constants;
|
import org.eclipse.jgit.lib.Constants;
|
||||||
import org.eclipse.jgit.lib.Repository;
|
import org.eclipse.jgit.lib.Repository;
|
||||||
import org.eclipse.jgit.lib.RepositoryBuilder;
|
import org.eclipse.jgit.lib.RepositoryBuilder;
|
||||||
|
import org.eclipse.jgit.util.SystemReader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an empty git repository or reinitalize an existing one
|
* Create an empty git repository or reinitalize an existing one
|
||||||
|
@ -61,6 +64,8 @@
|
||||||
public class InitCommand implements Callable<Git> {
|
public class InitCommand implements Callable<Git> {
|
||||||
private File directory;
|
private File directory;
|
||||||
|
|
||||||
|
private File gitDir;
|
||||||
|
|
||||||
private boolean bare;
|
private boolean bare;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -74,18 +79,36 @@ public Git call() throws GitAPIException {
|
||||||
if (bare)
|
if (bare)
|
||||||
builder.setBare();
|
builder.setBare();
|
||||||
builder.readEnvironment();
|
builder.readEnvironment();
|
||||||
|
if (gitDir != null)
|
||||||
|
builder.setGitDir(gitDir);
|
||||||
|
else
|
||||||
|
gitDir = builder.getGitDir();
|
||||||
if (directory != null) {
|
if (directory != null) {
|
||||||
File d = directory;
|
if (bare)
|
||||||
if (!bare)
|
builder.setGitDir(directory);
|
||||||
d = new File(d, Constants.DOT_GIT);
|
else {
|
||||||
builder.setGitDir(d);
|
builder.setWorkTree(directory);
|
||||||
|
if (gitDir == null)
|
||||||
|
builder.setGitDir(new File(directory, Constants.DOT_GIT));
|
||||||
|
}
|
||||||
} else if (builder.getGitDir() == null) {
|
} else if (builder.getGitDir() == null) {
|
||||||
File d = new File("."); //$NON-NLS-1$
|
String dStr = SystemReader.getInstance()
|
||||||
if (d.getParentFile() != null)
|
.getProperty("user.dir"); //$NON-NLS-1$
|
||||||
d = d.getParentFile();
|
if (dStr == null)
|
||||||
|
dStr = "."; //$NON-NLS-1$
|
||||||
|
File d = new File(dStr);
|
||||||
if (!bare)
|
if (!bare)
|
||||||
d = new File(d, Constants.DOT_GIT);
|
d = new File(d, Constants.DOT_GIT);
|
||||||
builder.setGitDir(d);
|
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();
|
Repository repository = builder.build();
|
||||||
if (!repository.getObjectDatabase().exists())
|
if (!repository.getObjectDatabase().exists())
|
||||||
|
@ -103,20 +126,67 @@ public Git call() throws GitAPIException {
|
||||||
* @param directory
|
* @param directory
|
||||||
* the directory to init to
|
* the directory to init to
|
||||||
* @return this instance
|
* @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;
|
this.directory = directory;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param bare
|
* @param gitDir
|
||||||
* whether the repository is bare or not
|
* the repository meta directory
|
||||||
* @return this instance
|
* @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) {
|
public InitCommand setGitDir(File gitDir)
|
||||||
this.bare = bare;
|
throws IllegalStateException {
|
||||||
|
validateDirs(directory, gitDir, bare);
|
||||||
|
this.gitDir = gitDir;
|
||||||
return this;
|
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 indexFileIsTooLargeForJgit;
|
||||||
/***/ public String indexSignatureIsInvalid;
|
/***/ public String indexSignatureIsInvalid;
|
||||||
/***/ public String indexWriteException;
|
/***/ public String indexWriteException;
|
||||||
|
/***/ public String initFailedBareRepoDifferentDirs;
|
||||||
|
/***/ public String initFailedNonBareRepoSameDirs;
|
||||||
/***/ public String inMemoryBufferLimitExceeded;
|
/***/ public String inMemoryBufferLimitExceeded;
|
||||||
/***/ public String inputStreamMustSupportMark;
|
/***/ public String inputStreamMustSupportMark;
|
||||||
/***/ public String integerValueOutOfRange;
|
/***/ public String integerValueOutOfRange;
|
||||||
|
|
|
@ -273,7 +273,8 @@ public void create(boolean bare) throws IOException {
|
||||||
ConfigConstants.CONFIG_CORE_SECTION, null,
|
ConfigConstants.CONFIG_CORE_SECTION, null,
|
||||||
ConfigConstants.CONFIG_KEY_HIDEDOTFILES,
|
ConfigConstants.CONFIG_KEY_HIDEDOTFILES,
|
||||||
HideDotFiles.DOTGITONLY);
|
HideDotFiles.DOTGITONLY);
|
||||||
if (hideDotFiles != HideDotFiles.FALSE && !isBare())
|
if (hideDotFiles != HideDotFiles.FALSE && !isBare()
|
||||||
|
&& getDirectory().getName().startsWith(".")) //$NON-NLS-1$
|
||||||
getFS().setHidden(getDirectory(), true);
|
getFS().setHidden(getDirectory(), true);
|
||||||
refs.create();
|
refs.create();
|
||||||
objectDatabase.create();
|
objectDatabase.create();
|
||||||
|
@ -329,6 +330,25 @@ public void create(boolean bare) throws IOException {
|
||||||
// Java has no other way
|
// Java has no other way
|
||||||
cfg.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
|
cfg.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
|
||||||
ConfigConstants.CONFIG_KEY_PRECOMPOSEUNICODE, true);
|
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();
|
cfg.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -272,7 +272,14 @@ public final class Constants {
|
||||||
*/
|
*/
|
||||||
public static final String INFO_EXCLUDE = "info/exclude";
|
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";
|
public static final String OS_USER_NAME_KEY = "user.name";
|
||||||
|
|
||||||
/** The environment variable that contains the author's name */
|
/** The environment variable that contains the author's name */
|
||||||
|
@ -358,6 +365,13 @@ public final class Constants {
|
||||||
/** Name of the .git/shallow file */
|
/** Name of the .git/shallow file */
|
||||||
public static final String SHALLOW = "shallow";
|
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.
|
* Create a new digest function for objects.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue