Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[JENKINS-47609] Add clone option "core.longpaths" to enable long file names #537

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,7 @@ public CloneCommand clone_() {
private String origin = "origin";
private String reference;
private boolean shallow,shared;
private boolean longPath;
private Integer timeout;
private boolean tags = true;
private List<RefSpec> refspecs;
Expand Down Expand Up @@ -699,6 +700,12 @@ public CloneCommand tags(boolean tags) {
return this;
}

@Override
public CloneCommand longPath(boolean longPath) {
this.longPath = longPath;
return this;
}

@Override
public CloneCommand reference(String reference) {
this.reference = reference;
Expand Down Expand Up @@ -743,6 +750,10 @@ public void execute() throws GitException, InterruptedException {
throw new GitException("Failed to delete workspace", e);
}

if (longPath) {
launchCommand("config", "--global", "core.longpaths", "true");
}

// we don't run a 'git clone' command but git init + git fetch
// this allows launchCommandWithCredentials() to pass credentials via a local gitconfig

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,11 @@ public interface CloneCommand extends GitCommand {
* @return a {@link org.jenkinsci.plugins.gitclient.CloneCommand} object.
*/
CloneCommand depth(Integer depth);

/**
* For Windows systems with msys, surpass the 260 character limit for a filename by enabling core.longpaths
* @param enableLongPath boolean value to set core.longpaths to true in git.config
* @return a {@link org.jenkinsci.plugins.gitclient.CloneCommand} object.
*/
CloneCommand longPath(boolean enableLongPath);
}
13 changes: 13 additions & 0 deletions src/main/java/org/jenkinsci/plugins/gitclient/JGitAPIImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -1319,6 +1319,7 @@ public CloneCommand clone_() {
private String reference;
private Integer timeout;
private boolean shared;
private boolean longPath;
private boolean tags = true;
private List<RefSpec> refspecs;

Expand Down Expand Up @@ -1382,6 +1383,12 @@ public CloneCommand tags(boolean tags) {
return this;
}

@Override
public CloneCommand longPath(boolean longPath) {
this.longPath = longPath;
return this;
}

@Override
public CloneCommand noCheckout() {
// this.noCheckout = true; ignored, we never do a checkout
Expand Down Expand Up @@ -1431,6 +1438,12 @@ public void execute() throws GitException, InterruptedException {
repository = builder.build();
repository.create();

if (longPath) {
StoredConfig config = repository.getConfig();
config.setString("core", null,"longpaths","true");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if that matters, but linting needs to be taken care of in this line.

config.save();
}

// the repository builder does not create the alternates file
if (reference != null && !reference.isEmpty()) {
File referencePath = new File(reference);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import hudson.util.StreamTaskListener;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.text.RandomStringGenerator;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Repository;
Expand All @@ -22,6 +23,8 @@
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
Expand Down Expand Up @@ -323,6 +326,81 @@ public void test_addRemoteUrl_local_clone() throws Exception {
assertThat("Origin URL after add", testGitClient.getRemoteUrl("origin"), is(workspace.localMirror()));
}

@Test
public void test_clone_longPath() throws IOException, InterruptedException {
testGitClient.clone_().url(workspace.localMirror()).repositoryName("origin").longPath(true).execute();
CliGitCommand cmd = new CliGitCommand(testGitClient);

// check if git config contains core.longpaths set as true
assertThat((getConfigValue(cmd, "core.longpaths"))[0], is("true"));
}

/*
* This test is commented until cli git-for-windows issue: https://github.com/git-for-windows/git/issues/2576 is fixed
*/
// @Test
// public void testLongPathWithoutCloneOption() throws Exception {
// RandomStringGenerator generator = new RandomStringGenerator.Builder()
// .withinRange('a', 'z').build();
// String fileName = generator.generate(133); //230 - current
// String subDirName = generator.generate(80);
//
// File tempDir = Files.createTempDirectory(fileName).toFile();
// Path subDirectory = Paths.get(tempDir.getAbsolutePath() + "/" + subDirName);
// File subDir = Files.createDirectory(subDirectory).toFile();
// assertThat(subDir.getAbsolutePath().length(), greaterThan(259)); // Assure test case is testing long path
//
// if (Files.isDirectory(subDirectory)) {
// WorkspaceWithRepo tempRepo = new WorkspaceWithRepo(subDir, gitImplName, listener);
//
// if (isWindows()) {
// GitException gitException = assertThrows(GitException.class, () -> {
// CloneCommand cmd = tempRepo.getGitClient().clone_().url(tempRepo.localMirror()).repositoryName("origin");
// cmd.execute();
// });
// assertThat(gitException.getMessage(), containsString("Filename too long"));
// }
// }
// }

/*
* This test is commented until cli git-for-windows issue: https://github.com/git-for-windows/git/issues/2576 is fixed
*/
// @Test
// public void testLongPathWithCloneOption() throws Exception {
// RandomStringGenerator generator = new RandomStringGenerator.Builder()
// .withinRange('a', 'z').build();
// String fileName = generator.generate(133);
// String subDirName = generator.generate(80);
//
// File tempDir = Files.createTempDirectory(fileName).toFile();
// Path subDirectory = Paths.get(tempDir.getAbsolutePath() + "/" + subDirName);
// subDirectory = Files.createDirectory(subDirectory);
// File subDir = subDirectory.toFile();
// assertThat(subDir.getAbsolutePath().length(), greaterThan(259)); // Assure test case is testing long path
//
// if (Files.isDirectory(subDirectory)) {
// WorkspaceWithRepo tempRepo = new WorkspaceWithRepo(subDir, gitImplName, listener);
//
// if (isWindows()) {
// CloneCommand cmd = tempRepo.getGitClient().clone_().url(tempRepo.localMirror()).repositoryName("origin").longPath(true);
// cmd.execute();
// // Test git clone works with a directory of absolute path of 260+ chars
// tempRepo.getGitClient().checkout().ref("origin/master").branch("master").execute();
// check_remote_url(tempRepo, tempRepo.getGitClient(), "origin");
// assertBranchesExist(tempRepo.getGitClient().getBranches(), "master");
// }
// }
// }

private boolean isWindows() {
return File.pathSeparatorChar==';';
}

private String[] getConfigValue(CliGitCommand command, String name) throws IOException, InterruptedException {
return command.run("config", "--get", name);
}

private void assertAlternatesFileExists() {
final String alternates = ".git" + File.separator + "objects" + File.separator + "info" + File.separator + "alternates";
assertThat(new File(testGitDir, alternates), is(anExistingFile()));
Expand Down