Browse Source

init: allow specifying the initial branch name for the new repository

Add option --initial-branch/-b to InitCommand and the CLI init command.
This is the first step to implement support for the new option
init.defaultBranch. Both were added to git in release 2.28.

See https://git-scm.com/docs/git-init#Documentation/git-init.txt--bltbranch-namegt

Bug: 564794
Change-Id: Ia383b3f90b5549db80f99b2310450a7faf6bce4c
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
tags/v5.11.0.202102240950-m3
Matthias Sohn 3 years ago
parent
commit
cb8924a80d

+ 21
- 0
org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/InitTest.java View File

@@ -11,11 +11,14 @@
package org.eclipse.jgit.pgm;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;

import java.io.File;

import org.eclipse.jgit.internal.storage.file.FileRepository;
import org.eclipse.jgit.lib.CLIRepositoryTestCase;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Repository;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
@@ -54,4 +57,22 @@ public class InitTest extends CLIRepositoryTestCase {
assertArrayEquals(expecteds, result);
}

@Test
public void testInitDirectoryInitialBranch() throws Exception {
File workDirectory = tempFolder.getRoot();
File gitDirectory = new File(workDirectory, Constants.DOT_GIT);

String[] result = execute(
"git init -b main '" + workDirectory.getCanonicalPath() + "'");

String[] expecteds = new String[] {
"Initialized empty Git repository in "
+ gitDirectory.getCanonicalPath(),
"" };
assertArrayEquals(expecteds, result);

try (Repository repo = new FileRepository(gitDirectory)) {
assertEquals("refs/heads/main", repo.getFullBranch());
}
}
}

+ 1
- 0
org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties View File

@@ -432,6 +432,7 @@ usage_updateRef=reference to update
usage_updateRemoteRefsFromAnotherRepository=Update remote refs from another repository
usage_useNameInsteadOfOriginToTrackUpstream=use <name> instead of 'origin' to track upstream
usage_checkoutBranchAfterClone=check out named branch instead of remote's HEAD
usage_initialBranch=initial branch in the newly created repository (default 'master')
usage_viewCommitHistory=View commit history
usage_orphan=Create a new orphan branch. The first commit made on this new branch will have no parents and it will be the root of a new history totally disconnected from other branches and commits.
usernameFor=Username for {0}:

+ 8
- 0
org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Init.java View File

@@ -24,6 +24,7 @@ import org.eclipse.jgit.api.InitCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.pgm.internal.CLIText;
import org.eclipse.jgit.util.StringUtils;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option;

@@ -32,6 +33,10 @@ class Init extends TextBuiltin {
@Option(name = "--bare", usage = "usage_CreateABareRepository")
private boolean bare;

@Option(name = "--initial-branch", aliases = { "-b" },
metaVar = "metaVar_branchName", usage = "usage_initialBranch")
private String branch;

@Argument(index = 0, metaVar = "metaVar_directory")
private String directory;

@@ -54,6 +59,9 @@ class Init extends TextBuiltin {
}
Repository repository;
try {
if (!StringUtils.isEmptyOrNull(branch)) {
command.setInitialBranch(branch);
}
repository = command.call().getRepository();
outw.println(MessageFormat.format(
CLIText.get().initializedEmptyGitRepositoryIn,

+ 35
- 1
org.eclipse.jgit.test/tst/org/eclipse/jgit/api/InitCommandTest.java View File

@@ -9,6 +9,7 @@
*/
package org.eclipse.jgit.api;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -42,7 +43,23 @@ public class InitCommandTest extends RepositoryTestCase {
InitCommand command = new InitCommand();
command.setDirectory(directory);
try (Git git = command.call()) {
assertNotNull(git.getRepository());
Repository r = git.getRepository();
assertNotNull(r);
assertEquals("refs/heads/master", r.getFullBranch());
}
}

@Test
public void testInitRepositoryMainInitialBranch()
throws IOException, JGitInternalException, GitAPIException {
File directory = createTempDirectory("testInitRepository");
InitCommand command = new InitCommand();
command.setDirectory(directory);
command.setInitialBranch("main");
try (Git git = command.call()) {
Repository r = git.getRepository();
assertNotNull(r);
assertEquals("refs/heads/main", r.getFullBranch());
}
}

@@ -72,6 +89,23 @@ public class InitCommandTest extends RepositoryTestCase {
Repository repository = git.getRepository();
assertNotNull(repository);
assertTrue(repository.isBare());
assertEquals("refs/heads/master", repository.getFullBranch());
}
}

@Test
public void testInitBareRepositoryMainInitialBranch()
throws IOException, JGitInternalException, GitAPIException {
File directory = createTempDirectory("testInitBareRepository");
InitCommand command = new InitCommand();
command.setDirectory(directory);
command.setBare(true);
command.setInitialBranch("main");
try (Git git = command.call()) {
Repository repository = git.getRepository();
assertNotNull(repository);
assertTrue(repository.isBare());
assertEquals("refs/heads/main", repository.getFullBranch());
}
}


+ 23
- 0
org.eclipse.jgit/src/org/eclipse/jgit/api/InitCommand.java View File

@@ -15,6 +15,7 @@ import java.text.MessageFormat;
import java.util.concurrent.Callable;

import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.InvalidRefNameException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.Constants;
@@ -38,6 +39,8 @@ public class InitCommand implements Callable<Git> {

private FS fs;

private String initialBranch = Constants.MASTER;

/**
* {@inheritDoc}
* <p>
@@ -87,6 +90,7 @@ public class InitCommand implements Callable<Git> {
builder.setWorkTree(new File(dStr));
}
}
builder.setInitialBranch(initialBranch);
Repository repository = builder.build();
if (!repository.getObjectDatabase().exists())
repository.create(bare);
@@ -184,4 +188,23 @@ public class InitCommand implements Callable<Git> {
this.fs = fs;
return this;
}

/**
* Set the initial branch of the new repository. If not specified
* ({@code null} or empty), fall back to the default name (currently
* master).
*
* @param branch
* initial branch name of the new repository
* @return {@code this}
* @throws InvalidRefNameException
* if the branch name is not valid
*
* @since 5.11
*/
public InitCommand setInitialBranch(String branch)
throws InvalidRefNameException {
this.initialBranch = branch;
return this;
}
}

+ 1
- 1
org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java View File

@@ -243,7 +243,7 @@ public class FileRepository extends Repository {

RefUpdate head = updateRef(Constants.HEAD);
head.disableRefLog();
head.link(Constants.R_HEADS + Constants.MASTER);
head.link(Constants.R_HEADS + getInitialBranch());

final boolean fileMode;
if (getFS().supportsExecute()) {

+ 42
- 0
org.eclipse.jgit/src/org/eclipse/jgit/lib/BaseRepositoryBuilder.java View File

@@ -28,6 +28,8 @@ import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.api.errors.InvalidRefNameException;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.internal.JGitText;
@@ -38,6 +40,7 @@ import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.RawParseUtils;
import org.eclipse.jgit.util.StringUtils;
import org.eclipse.jgit.util.SystemReader;

/**
@@ -107,6 +110,8 @@ public class BaseRepositoryBuilder<B extends BaseRepositoryBuilder, R extends Re

private File workTree;

private String initialBranch = Constants.MASTER;

/** Directories limiting the search for a Git repository. */
private List<File> ceilingDirectories;

@@ -349,6 +354,43 @@ public class BaseRepositoryBuilder<B extends BaseRepositoryBuilder, R extends Re
return indexFile;
}

/**
* Set the initial branch of the new repository. If not specified
* ({@code null} or empty), fall back to the default name (currently
* master).
*
* @param branch
* initial branch name of the new repository. If {@code null} or
* empty the configured default branch will be used.
* @return {@code this}
* @throws InvalidRefNameException
* if the branch name is not valid
*
* @since 5.11
*/
public B setInitialBranch(String branch) throws InvalidRefNameException {
if (StringUtils.isEmptyOrNull(branch)) {
this.initialBranch = Constants.MASTER;
} else {
if (!Repository.isValidRefName(Constants.R_HEADS + branch)) {
throw new InvalidRefNameException(MessageFormat
.format(JGitText.get().branchNameInvalid, branch));
}
this.initialBranch = branch;
}
return self();
}

/**
* Get the initial branch of the new repository.
*
* @return the initial branch of the new repository.
* @since 5.11
*/
public @NonNull String getInitialBranch() {
return initialBranch;
}

/**
* Read standard Git environment variables and configure from those.
* <p>

+ 13
- 0
org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java View File

@@ -127,6 +127,8 @@ public abstract class Repository implements AutoCloseable {
/** If not bare, the index file caching the working file states. */
private final File indexFile;

private final String initialBranch;

/**
* Initialize a new repository instance.
*
@@ -138,6 +140,7 @@ public abstract class Repository implements AutoCloseable {
fs = options.getFS();
workTree = options.getWorkTree();
indexFile = options.getIndexFile();
initialBranch = options.getInitialBranch();
}

/**
@@ -1033,6 +1036,16 @@ public abstract class Repository implements AutoCloseable {
return null;
}

/**
* Get the initial branch name of a new repository
*
* @return the initial branch name of a new repository
* @since 5.11
*/
protected @NonNull String getInitialBranch() {
return initialBranch;
}

/**
* Objects known to exist but not expressed by {@link #getAllRefs()}.
* <p>

Loading…
Cancel
Save