Fix too long path problem with Windows

The long path was problematic under Windows without explicitly setting Git config.
To prevent this the repository data is copied to tmp dir from a zip file.
This commit is contained in:
Fabian Krüger
2023-12-20 22:32:25 +00:00
committed by GitHub
parent 4ca27764d4
commit 3310247dc8
41 changed files with 73 additions and 569 deletions

View File

@@ -163,6 +163,13 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.lingala.zip4j</groupId>
<artifactId>zip4j</artifactId>
<version>2.6.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -15,7 +15,7 @@
*/
package org.springframework.sbm;
import org.apache.commons.io.FileUtils;
import net.lingala.zip4j.ZipFile;
import org.apache.maven.shared.invoker.*;
import org.junit.jupiter.api.*;
import org.junit.jupiter.api.io.TempDir;
@@ -42,14 +42,11 @@ import org.testcontainers.utility.DockerImageName;
import org.testcontainers.utility.MountableFile;
import java.io.*;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Fail.fail;
@@ -97,30 +94,52 @@ public class PrivateArtifactRepositoryTest {
// All test resources live here
public static final String TESTCODE_DIR = "testcode/maven-projects/private-repository";
public static final String REPOSITORIES_ZIP = Path
.of("./testcode/maven-projects/private-repository/reposilite-data.zip")
.toAbsolutePath()
.toString();
public static final String DEPENDENCY_CLASS_FQNAME = "com.example.dependency.DependencyClass";
private static final String NEW_USER_HOME = Path.of(".")
.resolve(TESTCODE_DIR + "/user.home")
.toAbsolutePath()
.normalize()
.toString();
private static final File LOCAL_MAVEN_REPOSITORY = Path.of(NEW_USER_HOME + "/.m2/repository").toFile();
private static final Path DEPENDENCY_PATH_IN_LOCAL_MAVEN_REPO = Path
.of(NEW_USER_HOME + "/.m2/repository/com/example/dependency/dependency-project")
.toAbsolutePath()
.normalize();
// File path was too long under Windows when Maven repository was under TESTCODE_DIR +
// "/reposilite-data"
// To fix this the repo with jars for reposilite is extracted from a zip to its target
// dir.
private static final Path TEMP_DIR;
static {
try {
TEMP_DIR = Files.createTempDirectory("reposilite-data");
}
catch (IOException e) {
throw new RuntimeException(e);
}
if (!Files.exists(TEMP_DIR.resolve("reposilite-data"))) {
TestHelper.unzip(TEMP_DIR);
}
}
private static final Path REPOSILITE_DATA_DIR = TEMP_DIR.resolve("reposilite-data");
// The private Artifact repository (reposilite) provides the dependency.
@Container
static GenericContainer reposilite = new GenericContainer(DockerImageName.parse("dzikoysk/reposilite:3.4.10"))
.withExposedPorts(8080)
// copy required config files and cached dependency to repository
.withCopyFileToContainer(MountableFile.forHostPath("./" + TESTCODE_DIR + "/reposilite-data"), "/app/data")
.withCopyFileToContainer(MountableFile.forHostPath(REPOSILITE_DATA_DIR), "/app/data")
// Create temp user 'user' with password 'secret'
.withEnv("REPOSILITE_OPTS", "--token user:secret --shared-config shared.configuration.json");
public static final String DEPENDENCY_CLASS_FQNAME = "com.example.dependency.DependencyClass";
private static final String NEW_USER_HOME = Path.of(".")
.resolve(TESTCODE_DIR + "/user.home")
.toAbsolutePath()
.normalize()
.toString();
private static final Path DEPENDENCY_PATH_IN_LOCAL_MAVEN_REPO = Path
.of(NEW_USER_HOME + "/.m2/repository/com/example/dependency/dependency-project")
.toAbsolutePath()
.normalize();
private static final File LOCAL_MAVEN_REPOSITORY = Path.of(NEW_USER_HOME + "/.m2/repository").toFile();
private static MavenRepository originalMavenRepository;
private static String originalUserHome;
@@ -146,14 +165,6 @@ public class PrivateArtifactRepositoryTest {
Whitebox.setInternalState(MavenRepository.class, "MAVEN_LOCAL_DEFAULT", mavenRepository);
}
@AfterAll
static void afterAll() {
// set back to initial values
System.setProperty("user.home", originalUserHome);
Whitebox.setInternalState(MavenRepository.class, "MAVEN_LOCAL_DEFAULT", originalMavenRepository);
FileSystemUtils.deleteRecursively(LOCAL_MAVEN_REPOSITORY);
}
@BeforeEach
void beforeEach() throws IOException {
Integer port = reposilite.getMappedPort(8080);
@@ -162,6 +173,14 @@ public class PrivateArtifactRepositoryTest {
TestHelper.clearDependencyFromLocalMavenRepo();
}
@AfterAll
static void afterAll() {
// set back to initial values
System.setProperty("user.home", originalUserHome);
Whitebox.setInternalState(MavenRepository.class, "MAVEN_LOCAL_DEFAULT", originalMavenRepository);
FileSystemUtils.deleteRecursively(LOCAL_MAVEN_REPOSITORY);
}
@Test
@DisplayName("Maven settings should be read from secured private repo")
void mavenSettingsShouldBeReadFromSecuredPrivateRepo() {
@@ -275,15 +294,6 @@ public class PrivateArtifactRepositoryTest {
}
}
}
/*
* Currently not used as the dependency is provided to the container (cached). But
* kept in case deployment of the dependency or building the dependent project is
* needed.
*/
class DeploymentHelper {
void deployDependency(Path pomXmlPath) throws MavenInvocationException {
InvocationRequest request = new DefaultInvocationRequest();
request.setPomFile(pomXmlPath.toFile());
@@ -328,86 +338,24 @@ public class PrivateArtifactRepositoryTest {
}
}
static void installMavenForTestIfNotExists(Path tempDir) {
if (!Path.of("./testcode/maven-projects/private-repository/user.home/apache-maven-3.9.5/bin/mvn")
.toFile()
.exists()) {
String mavenDownloadUrl = "https://dlcdn.apache.org/maven/maven-3/3.9.5/binaries/apache-maven-3.9.5-bin.zip";
try {
Path mavenInstallDir = Path.of(TESTCODE_DIR + "/user.home");
File downloadedMavenZipFile = tempDir.resolve("apache-maven-3.9.5-bin.zip").toFile();
FileUtils.copyURLToFile(new URL(mavenDownloadUrl), downloadedMavenZipFile, 10000, 30000);
Unzipper.unzip(downloadedMavenZipFile, mavenInstallDir);
File file = mavenInstallDir.resolve("apache-maven-3.9.5/bin/mvn").toFile();
file.setExecutable(true, false);
assertThat(file.canExecute()).isTrue();
}
catch (IOException e) {
throw new RuntimeException(e);
}
static void unzip(Path repoDir) {
try {
;
ZipFile zipFile = new ZipFile(REPOSITORIES_ZIP);
zipFile.extractAll(repoDir.toString());
}
}
class Unzipper {
private static void unzip(File downloadedMavenZipFile, Path mavenInstallDir) {
try {
byte[] buffer = new byte[1024];
ZipInputStream zis = null;
zis = new ZipInputStream(new FileInputStream(downloadedMavenZipFile));
ZipEntry zipEntry = zis.getNextEntry();
while (zipEntry != null) {
File newFile = newFile(mavenInstallDir.toFile(), zipEntry);
if (zipEntry.isDirectory()) {
if (!newFile.isDirectory() && !newFile.mkdirs()) {
throw new IOException("Failed to create directory " + newFile);
}
}
else {
// fix for Windows-created archives
File parent = newFile.getParentFile();
if (!parent.isDirectory() && !parent.mkdirs()) {
throw new IOException("Failed to create directory " + parent);
}
// write file content
FileOutputStream fos = new FileOutputStream(newFile);
int len;
while ((len = zis.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
fos.close();
}
zipEntry = zis.getNextEntry();
}
zis.closeEntry();
zis.close();
}
catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
public static File newFile(File destinationDir, ZipEntry zipEntry) throws IOException {
File destFile = new File(destinationDir, zipEntry.getName());
String destDirPath = destinationDir.getCanonicalPath();
String destFilePath = destFile.getCanonicalPath();
if (!destFilePath.startsWith(destDirPath + java.io.File.separator)) {
throw new IOException("Entry is outside of the target dir: " + zipEntry.getName());
}
return destFile;
catch (IOException e) {
throw new RuntimeException(e);
}
}
static void mkdir(Path target) {
boolean mkdir = target.toFile().mkdir();
if (!mkdir) {
throw new RuntimeException("Could not create target dir");
}
}
}
}

View File

@@ -8,8 +8,9 @@
/user.home/.m2/settings.xml
!/user.home/.m2/settings.xml.template
!/user.home/.m2/settings-security.xml
/reposilite-data/static
/reposilite-data/.local
/reposilite-data/plugins
/reposilite-data/reposilite.db
/reposilite-data/configuration.cdn
#/reposilite-data/static
#/reposilite-data/.local
#/reposilite-data/plugins
#/reposilite-data/repositories
#/reposilite-data/reposilite.db
#/reposilite-data--/configuration.cdn

View File

@@ -1,25 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example.dependency</groupId>
<artifactId>dependency-project</artifactId>
<version>1.0-SNAPSHOT</version>
<name>dependency-project</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<distributionManagement>
<repository>
<id>repository-snapshots</id>
<name>Snapshots Repository</name>
<url>http://localhost:52260/snapshots</url>
</repository>
</distributionManagement>
</project>

View File

@@ -1,25 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<metadata modelVersion="1.1.0">
<groupId>com.example.dependency</groupId>
<artifactId>dependency-project</artifactId>
<versioning>
<lastUpdated>20231105102337</lastUpdated>
<snapshot>
<timestamp>20231105.102337</timestamp>
<buildNumber>1</buildNumber>
</snapshot>
<snapshotVersions>
<snapshotVersion>
<extension>pom</extension>
<value>1.0-20231105.102337-1</value>
<updated>20231105102337</updated>
</snapshotVersion>
<snapshotVersion>
<extension>jar</extension>
<value>1.0-20231105.102337-1</value>
<updated>20231105102337</updated>
</snapshotVersion>
</snapshotVersions>
</versioning>
<version>1.0-SNAPSHOT</version>
</metadata>

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<groupId>com.example.dependency</groupId>
<artifactId>dependency-project</artifactId>
<versioning>
<versions>
<version>1.0-SNAPSHOT</version>
</versions>
<lastUpdated>20231105102337</lastUpdated>
</versioning>
</metadata>

View File

@@ -1,75 +0,0 @@
{
"statistics": {
"enabled": true,
"resolvedRequestsInterval": "MONTHLY"
},
"web": {
"forwardedIp": "X-Forwarded-For"
},
"frontend": {
"id": "reposilite-repository",
"title": "Reposilite Repository",
"description": "Public Maven repository hosted through the Reposilite",
"organizationWebsite": "https://reposilite.com",
"organizationLogo": "https://avatars.githubusercontent.com/u/88636591",
"icpLicense": ""
},
"authentication": {
"ldap": {
"enabled": false,
"ssl": false,
"hostname": "ldap.domain.com",
"port": 389,
"baseDn": "dc=company,dc=com",
"searchUserDn": "cn=reposilite,ou=admins,dc=domain,dc=com",
"searchUserPassword": "reposilite-admin-secret",
"typeAttribute": "person",
"userAttribute": "cn",
"userFilter": "(&(objectClass=person)(ou=Maven Users))",
"userType": "PERSISTENT"
}
},
"maven": {
"repositories": [
{
"id": "releases",
"visibility": "PRIVATE",
"redeployment": false,
"preserveSnapshots": false,
"storageProvider": {
"type": "fs",
"quota": "100%",
"mount": ""
},
"storagePolicy": "PRIORITIZE_UPSTREAM_METADATA",
"proxied": []
},
{
"id": "snapshots",
"visibility": "PRIVATE",
"redeployment": true,
"preserveSnapshots": false,
"storageProvider": {
"type": "fs",
"quota": "100%",
"mount": "./snapshots"
},
"storagePolicy": "PRIORITIZE_UPSTREAM_METADATA",
"proxied": []
},
{
"id": "private",
"visibility": "PRIVATE",
"redeployment": false,
"preserveSnapshots": false,
"storageProvider": {
"type": "fs",
"quota": "100%",
"mount": ""
},
"storagePolicy": "PRIORITIZE_UPSTREAM_METADATA",
"proxied": []
}
]
}
}

View File

@@ -1,17 +0,0 @@
/testcode/**/target/**
/testcode/testcode/**/.rewrite-cache/**
/dependency-project/pom.xml
/dependency-project/target
/dependent-project/pom.xml
/dependent-project/target
/user.home/.config/
/user.home/apache-maven-3.9.5/
/user.home/.m2/repository
/user.home/.m2/settings.xml
!/user.home/.m2/settings.xml.template
!/user.home/.m2/settings-security.xml
/reposilite-data/static
/reposilite-data/.local
/reposilite-data/plugins
/reposilite-data/reposilite.db
/reposilite-data/configuration.cdn

View File

@@ -1,36 +0,0 @@
# Artifact Repository Test
Test that artifacts available in a private artifact repository configured in `~/.m2/settings.xml` can be accessed.
This is important as many enterprise projects use their private artifact repository to retrieve private dependencies.
- A private artifact repository using (https://github.com/dzikoysk/reposilite[reposilite]) is started in a Docker container.
The reposilite instance has a user configured (admin:secret) which can deploy and access artifacts.
- The repositories in the artifact repository (e.g. snapshot) require successful authentication (deploy + download).
- `dependency-project` has a simple class `DependencyClass` and gets deployed to the artifact repository.
- `dependent-project` depends on `dependency-project` and has a class `DependentClass` that uses `DependencyClass`
- `dependent-project` gets parsed
- The resulting AST has the type information of `dependency-project` resolved when the repository information and credentials were read from `settings.xml` and `security-settings.xml`.
Technical requirements:
- The port of the Docker container is dynamic and used in settings.xml and pom.xml.
- The local Maven installation of any system should not be affected by this test.
- The location of the Maven dir `.m2` must therefore point to a different location while the test is running.
This requires temporarily a different `.m2` location, here `testcode/maven-projects/private-repository/user.home/.m2`.
When deploying the `dependency-project` the path to `settings.xml` is provided, pointing to `testcode/maven-projects/private-repository/user.home/.m2/settings.xml`.
This file declares the location of the local Maven repository pointing to the same dir.
Because these paths can't be relative for this test and absolute paths
The `user.home` is set to point to `testcode/maven-projects/private-repository/user.home` which contains a `.m2` directory providing access configuration to the reposilite instance through `.m2/settings.xml` and `.m2/security-settings.xml`,

View File

@@ -1,25 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example.dependency</groupId>
<artifactId>dependency-project</artifactId>
<version>1.0-SNAPSHOT</version>
<name>dependency-project</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<distributionManagement>
<repository>
<id>repository-snapshots</id>
<name>Snapshots Repository</name>
<url>http://localhost:${port}/snapshots</url>
</repository>
</distributionManagement>
</project>

View File

@@ -1,13 +0,0 @@
package com.example.dependency;
public class DependencyClass
{
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}

View File

@@ -1,33 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example.dependent</groupId>
<artifactId>dependent-project</artifactId>
<version>1.0-SNAPSHOT</version>
<name>dependent-project</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.example.dependency</groupId>
<artifactId>dependency-project</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>repository-snapshots</id>
<name>Snapshots Repository</name>
<url>http://localhost:${port}/snapshots</url>
</repository>
</repositories>
</project>

View File

@@ -1,7 +0,0 @@
package com.example.dependent;
import com.example.dependency.DependencyClass;
public class DependentClass {
private DependencyClass dependencyClass;
}

View File

@@ -1,25 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example.dependency</groupId>
<artifactId>dependency-project</artifactId>
<version>1.0-SNAPSHOT</version>
<name>dependency-project</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<distributionManagement>
<repository>
<id>repository-snapshots</id>
<name>Snapshots Repository</name>
<url>http://localhost:52260/snapshots</url>
</repository>
</distributionManagement>
</project>

View File

@@ -1,25 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<metadata modelVersion="1.1.0">
<groupId>com.example.dependency</groupId>
<artifactId>dependency-project</artifactId>
<versioning>
<lastUpdated>20231105102337</lastUpdated>
<snapshot>
<timestamp>20231105.102337</timestamp>
<buildNumber>1</buildNumber>
</snapshot>
<snapshotVersions>
<snapshotVersion>
<extension>pom</extension>
<value>1.0-20231105.102337-1</value>
<updated>20231105102337</updated>
</snapshotVersion>
<snapshotVersion>
<extension>jar</extension>
<value>1.0-20231105.102337-1</value>
<updated>20231105102337</updated>
</snapshotVersion>
</snapshotVersions>
</versioning>
<version>1.0-SNAPSHOT</version>
</metadata>

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<groupId>com.example.dependency</groupId>
<artifactId>dependency-project</artifactId>
<versioning>
<versions>
<version>1.0-SNAPSHOT</version>
</versions>
<lastUpdated>20231105102337</lastUpdated>
</versioning>
</metadata>

View File

@@ -1,75 +0,0 @@
{
"statistics": {
"enabled": true,
"resolvedRequestsInterval": "MONTHLY"
},
"web": {
"forwardedIp": "X-Forwarded-For"
},
"frontend": {
"id": "reposilite-repository",
"title": "Reposilite Repository",
"description": "Public Maven repository hosted through the Reposilite",
"organizationWebsite": "https://reposilite.com",
"organizationLogo": "https://avatars.githubusercontent.com/u/88636591",
"icpLicense": ""
},
"authentication": {
"ldap": {
"enabled": false,
"ssl": false,
"hostname": "ldap.domain.com",
"port": 389,
"baseDn": "dc=company,dc=com",
"searchUserDn": "cn=reposilite,ou=admins,dc=domain,dc=com",
"searchUserPassword": "reposilite-admin-secret",
"typeAttribute": "person",
"userAttribute": "cn",
"userFilter": "(&(objectClass=person)(ou=Maven Users))",
"userType": "PERSISTENT"
}
},
"maven": {
"repositories": [
{
"id": "releases",
"visibility": "PRIVATE",
"redeployment": false,
"preserveSnapshots": false,
"storageProvider": {
"type": "fs",
"quota": "100%",
"mount": ""
},
"storagePolicy": "PRIORITIZE_UPSTREAM_METADATA",
"proxied": []
},
{
"id": "snapshots",
"visibility": "PRIVATE",
"redeployment": true,
"preserveSnapshots": false,
"storageProvider": {
"type": "fs",
"quota": "100%",
"mount": "./snapshots"
},
"storagePolicy": "PRIORITIZE_UPSTREAM_METADATA",
"proxied": []
},
{
"id": "private",
"visibility": "PRIVATE",
"redeployment": false,
"preserveSnapshots": false,
"storageProvider": {
"type": "fs",
"quota": "100%",
"mount": ""
},
"storagePolicy": "PRIORITIZE_UPSTREAM_METADATA",
"proxied": []
}
]
}
}

View File

@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<settings xsi:schemaLocation='http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd'
xmlns='http://maven.apache.org/SETTINGS/1.0.0' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
<localRepository>/Users/fkrueger/projects/spring-boot-migrator/sbm-support-rewrite/testcode/maven-projects/private-repository/user.home/.m2/repository</localRepository>
<servers>
<server>
<!-- must match the id in pom.xml -->
<id>repository-snapshots</id>
<username>user</username>
<!-- password is 'secret' -->
<password>secret</password>
</server>
</servers>
</settings>

View File

@@ -1,4 +0,0 @@
<settingsSecurity>
<!-- password is 'password' -->
<master>{BzCEWWQMgMkHk0P8+Rr+hsscSisZT6A4+G9Mub7f/m4=}</master>
</settingsSecurity>

View File

@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<settings xsi:schemaLocation='http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd'
xmlns='http://maven.apache.org/SETTINGS/1.0.0' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
<localRepository>${user.home}/.m2/repository</localRepository>
<servers>
<server>
<!-- must match the id in pom.xml -->
<id>repository-snapshots</id>
<username>user</username>
<!-- password is 'secret' -->
<password>{iKYxpFKiVu0HTAe4w0RAzev3TAav0DG8wEom2qNoRws=}</password>
<!--password>secret</password-->
</server>
</servers>
</settings>