From 6287d4ef8ff8ae61e44d6b044fb2df3b7bf953eb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 5 May 2026 18:47:33 +0000 Subject: [PATCH 1/5] Initial plan From 5a406a922f2c83e1b495d192788af1807f969775 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 5 May 2026 18:50:54 +0000 Subject: [PATCH 2/5] Fix IndexOutOfBoundsException in GitUtil.getRepositoryURL when no remotes exist Agent-Logs-Url: https://github.com/getappmap/appmap-java/sessions/2575e3fc-ec41-4655-ab8e-0d6c7f3670b7 Co-authored-by: kgilpin <86395+kgilpin@users.noreply.github.com> --- agent/src/main/java/com/appland/appmap/util/GitUtil.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) 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..36cd0a52 100644 --- a/agent/src/main/java/com/appland/appmap/util/GitUtil.java +++ b/agent/src/main/java/com/appland/appmap/util/GitUtil.java @@ -99,8 +99,15 @@ public Repository getRepository() { public String getRepositoryURL() { try { List remotes = git.remoteList().call(); + if (remotes.isEmpty()) { + return ""; + } 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 ""; + } return uris.get(0).toASCIIString(); } catch (GitAPIException e) { logger.warn(e); From 5956839f6665ade2bed844455831c56b4f6d7cba Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 5 May 2026 19:01:56 +0000 Subject: [PATCH 3/5] Return null from getRepositoryURL when no remotes; skip writing repository key in serializer Agent-Logs-Url: https://github.com/getappmap/appmap-java/sessions/9269e403-28ed-4394-be5f-17ca657e822a Co-authored-by: kgilpin <86395+kgilpin@users.noreply.github.com> --- .../java/com/appland/appmap/record/AppMapSerializer.java | 7 +++++-- agent/src/main/java/com/appland/appmap/util/GitUtil.java | 6 +++--- 2 files changed, 8 insertions(+), 5 deletions(-) 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 36cd0a52..0ad84cb7 100644 --- a/agent/src/main/java/com/appland/appmap/util/GitUtil.java +++ b/agent/src/main/java/com/appland/appmap/util/GitUtil.java @@ -100,19 +100,19 @@ public String getRepositoryURL() { try { List remotes = git.remoteList().call(); if (remotes.isEmpty()) { - return ""; + return null; } Optional originConfig = remotes.stream().filter(r -> r.getName().equals("origin")).findFirst(); RemoteConfig remote = originConfig.orElseGet(() -> remotes.get(0)); List uris = remote.getURIs(); if (uris.isEmpty()) { - return ""; + return null; } return uris.get(0).toASCIIString(); } catch (GitAPIException e) { logger.warn(e); } - return ""; + return null; } public String getBranch() { From 871a9c99aa3496c681f12de565127b909993ecc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Rzepecki?= Date: Mon, 11 May 2026 13:39:45 +0200 Subject: [PATCH 4/5] Add tests; look for git repo from the config file --- .../appland/appmap/config/AppMapConfig.java | 3 +- .../java/com/appland/appmap/util/GitUtil.java | 8 +-- .../appmap/record/AppMapSerializerTest.java | 50 +++++++++++++++++++ .../com/appland/appmap/util/GitUtilTest.java | 36 +++++++++++++ 4 files changed, 92 insertions(+), 5 deletions(-) create mode 100644 agent/src/test/java/com/appland/appmap/record/AppMapSerializerTest.java create mode 100644 agent/src/test/java/com/appland/appmap/util/GitUtilTest.java 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/util/GitUtil.java b/agent/src/main/java/com/appland/appmap/util/GitUtil.java index 0ad84cb7..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,7 +98,7 @@ public Repository getRepository() { return git.getRepository(); } - public String getRepositoryURL() { + public @Nullable String getRepositoryURL() { try { List remotes = git.remoteList().call(); if (remotes.isEmpty()) { 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"); + } + } + } +} From 8a8baa06a137a205523431ac95428b40a67021c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Rzepecki?= Date: Mon, 11 May 2026 14:12:22 +0200 Subject: [PATCH 5/5] Fix tests to put the config file in the right place --- agent/test/helper.bash | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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