diff --git a/agent/src/main/java/com/appland/appmap/config/AppMapConfig.java b/agent/src/main/java/com/appland/appmap/config/AppMapConfig.java index f896472d..f4f9f1c2 100644 --- a/agent/src/main/java/com/appland/appmap/config/AppMapConfig.java +++ b/agent/src/main/java/com/appland/appmap/config/AppMapConfig.java @@ -27,7 +27,6 @@ import org.tinylog.TaggedLogger; import org.tinylog.configuration.Configuration; -import com.alibaba.fastjson.JSON; import com.appland.appmap.Agent; import com.appland.appmap.cli.CLI; import com.appland.appmap.util.FullyQualifiedName; @@ -115,7 +114,7 @@ private static Path findConfig(Path configFile, boolean mustExist) throws FileNo * * @return The AppMapConfig singleton */ - static AppMapConfig load(Path configFile, boolean mustExist) { + public static AppMapConfig load(Path configFile, boolean mustExist) { InputStream inputStream = null; try { diff --git a/agent/src/main/java/com/appland/appmap/record/AppMapSerializer.java b/agent/src/main/java/com/appland/appmap/record/AppMapSerializer.java index 7d7959d8..e1732b1c 100644 --- a/agent/src/main/java/com/appland/appmap/record/AppMapSerializer.java +++ b/agent/src/main/java/com/appland/appmap/record/AppMapSerializer.java @@ -185,8 +185,11 @@ private void writeMetadata(GitUtil git, Metadata metadata) throws IOException { this.json.writeKey("git"); this.json.startObject(); { - this.json.writeKey("repository"); - this.json.writeValue(git.getRepositoryURL()); + String repositoryURL = git.getRepositoryURL(); + if (repositoryURL != null) { + this.json.writeKey("repository"); + this.json.writeValue(repositoryURL); + } this.json.writeKey("branch"); this.json.writeValue(git.getBranch()); this.json.writeKey("commit"); diff --git a/agent/src/main/java/com/appland/appmap/util/GitUtil.java b/agent/src/main/java/com/appland/appmap/util/GitUtil.java index cb42f880..04e64473 100644 --- a/agent/src/main/java/com/appland/appmap/util/GitUtil.java +++ b/agent/src/main/java/com/appland/appmap/util/GitUtil.java @@ -13,6 +13,8 @@ import java.util.Map; import java.util.Optional; +import javax.annotation.Nullable; + import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.errors.RevisionSyntaxException; @@ -60,7 +62,8 @@ public static GitUtil open() throws IOException { FileRepositoryBuilder builder = new FileRepositoryBuilder() .readEnvironment(); - builder.findGitDir(); + Path fsBase = AppMapConfig.get().configFile.toAbsolutePath().getParent(); + builder.findGitDir(fsBase.toFile()); if (builder.getGitDir() == null) { logger.debug("Working directory {}, not in a git repo", () -> Paths.get("").toAbsolutePath()); return null; @@ -73,7 +76,6 @@ public static GitUtil open() throws IOException { return null; } - Path fsBase = AppMapConfig.get().configFile.toAbsolutePath().getParent(); ObjectId tree = repository.resolve(Constants.HEAD + "^{tree}"); if (tree == null) { logger.warn("Couldn't resolve HEAD to a tree in {}, source paths may be incorrect", fsBase); @@ -96,16 +98,23 @@ public Repository getRepository() { return git.getRepository(); } - public String getRepositoryURL() { + public @Nullable String getRepositoryURL() { try { List remotes = git.remoteList().call(); + if (remotes.isEmpty()) { + return null; + } Optional originConfig = remotes.stream().filter(r -> r.getName().equals("origin")).findFirst(); - List uris = originConfig.isPresent() ? originConfig.get().getURIs() : remotes.get(0).getURIs(); + RemoteConfig remote = originConfig.orElseGet(() -> remotes.get(0)); + List uris = remote.getURIs(); + if (uris.isEmpty()) { + return null; + } return uris.get(0).toASCIIString(); } catch (GitAPIException e) { logger.warn(e); } - return ""; + return null; } public String getBranch() { diff --git a/agent/src/test/java/com/appland/appmap/record/AppMapSerializerTest.java b/agent/src/test/java/com/appland/appmap/record/AppMapSerializerTest.java new file mode 100644 index 00000000..3511f3a0 --- /dev/null +++ b/agent/src/test/java/com/appland/appmap/record/AppMapSerializerTest.java @@ -0,0 +1,50 @@ +package com.appland.appmap.record; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.StringWriter; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Map; + +import org.eclipse.jgit.api.Git; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import com.appland.appmap.config.AppMapConfig; +import com.appland.appmap.record.Recorder.Metadata; + +public class AppMapSerializerTest { + @TempDir + Path tempDir; + + @BeforeEach + public void setup() throws Exception { + Path configFile = tempDir.resolve("appmap.yml"); + Files.write(configFile, "name: test\npackages: []".getBytes()); + AppMapConfig.load(configFile, true); + } + + @Test + public void testMetadataNoRepositoryURL() throws Exception { + try (var gitRepo = Git.init().setDirectory(tempDir.toFile()).call()) { + Path testFile = tempDir.resolve("test.txt"); + Files.write(testFile, "test".getBytes()); + gitRepo.add().addFilepattern("test.txt").call(); + gitRepo.commit().setMessage("initial commit").call(); + } + + Metadata metadata = new Metadata("test-recorder", "test-type"); + + StringWriter writer = new StringWriter(); + try (AppMapSerializer serializer = AppMapSerializer.open(writer)) { + serializer.write(new CodeObjectTree(), metadata, Map.of()); + } + + String json = writer.toString(); + assertFalse(json.contains("\"repository\""), "Metadata should not contain 'repository' if URL is null. JSON: " + json); + } +} diff --git a/agent/src/test/java/com/appland/appmap/util/GitUtilTest.java b/agent/src/test/java/com/appland/appmap/util/GitUtilTest.java new file mode 100644 index 00000000..6d440eef --- /dev/null +++ b/agent/src/test/java/com/appland/appmap/util/GitUtilTest.java @@ -0,0 +1,36 @@ +package com.appland.appmap.util; + +import static org.junit.jupiter.api.Assertions.assertNull; + +import java.nio.file.Files; +import java.nio.file.Path; + +import org.eclipse.jgit.api.Git; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import com.appland.appmap.config.AppMapConfig; + +public class GitUtilTest { + @TempDir + Path tempDir; + + @Test + public void testGetRepositoryURLNoRemotes() throws Exception { + try (Git git = Git.init().setDirectory(tempDir.toFile()).call()) { + Path testFile = tempDir.resolve("test.txt"); + Files.write(testFile, "test".getBytes()); + git.add().addFilepattern("test.txt").call(); + git.commit().setMessage("initial commit").call(); + + Path configFile = tempDir.resolve("appmap.yml"); + Files.write(configFile, "name: test\npackages: []".getBytes()); + + AppMapConfig.load(configFile, true); + + try (GitUtil gitUtil = GitUtil.open()) { + assertNull(gitUtil.getRepositoryURL(), "Repository URL should be null when no remotes exist"); + } + } + } +} diff --git a/agent/test/helper.bash b/agent/test/helper.bash index 95a0206a..9175fed1 100644 --- a/agent/test/helper.bash +++ b/agent/test/helper.bash @@ -245,11 +245,12 @@ start_petclinic() { AGENT_JAR="$(find_agent_jar)" local cfg="$WD/test/petclinic/appmap.yml" + cp "$cfg" "${fixture_dir}/appmap.yml" local out="${fixture_dir}/tmp/appmap" pushd build/fixtures/spring-petclinic >/dev/null ./mvnw ${MAVEN_PROFILE} ${BATS_VERSION+--quiet} -DskipTests -Dcheckstyle.skip=true -Dspring-javaformat.skip=true \ -Dspring-boot.run.agents=$AGENT_JAR \ - -Dspring-boot.run.jvmArguments="-Dappmap.config.file='${cfg}' -Dappmap.output.directory='${out}' $jvmargs" \ + -Dspring-boot.run.jvmArguments="-Dappmap.config.file='${fixture_dir}/appmap.yml' -Dappmap.output.directory='${out}' $jvmargs" \ spring-boot:run \ &>$LOG 3>&- & export JVM_MAIN_CLASS=PetClinicApplication