|
32 | 32 | import io.github.guacsec.trustifyda.logging.LoggersFactory; |
33 | 33 | import io.github.guacsec.trustifyda.providers.JavaMavenProvider; |
34 | 34 | import io.github.guacsec.trustifyda.providers.golang.model.GoWorkspace; |
| 35 | +import io.github.guacsec.trustifyda.providers.gradle.workspace.GradleWorkspaceDiscovery; |
35 | 36 | import io.github.guacsec.trustifyda.providers.javascript.workspace.JsWorkspaceDiscovery; |
36 | 37 | import io.github.guacsec.trustifyda.providers.rust.model.CargoMetadata; |
37 | 38 | import io.github.guacsec.trustifyda.tools.Ecosystem; |
@@ -852,7 +853,13 @@ int resolveBatchConcurrency() { |
852 | 853 |
|
853 | 854 | private static final Set<String> DEFAULT_WORKSPACE_DISCOVERY_IGNORE = |
854 | 855 | Set.of( |
855 | | - "**/node_modules/**", "**/.git/**", "**/target/**", "**/__pycache__/**", "**/.venv/**", "**/build/**", "**/.gradle/**"); |
| 856 | + "**/node_modules/**", |
| 857 | + "**/.git/**", |
| 858 | + "**/target/**", |
| 859 | + "**/__pycache__/**", |
| 860 | + "**/.venv/**", |
| 861 | + "**/build/**", |
| 862 | + "**/.gradle/**"); |
856 | 863 |
|
857 | 864 | /** Merges default ignore patterns, env var overrides, and caller-provided patterns. */ |
858 | 865 | Set<String> resolveIgnorePatterns(Set<String> callerPatterns) { |
@@ -917,7 +924,7 @@ List<Path> discoverWorkspaceManifests(Path workspaceDir, Set<String> ignorePatte |
917 | 924 | Files.isRegularFile(workspaceDir.resolve("settings.gradle")) |
918 | 925 | || Files.isRegularFile(workspaceDir.resolve("settings.gradle.kts")); |
919 | 926 | if (hasGradleSettings) { |
920 | | - return discoverGradleSubprojects(workspaceDir, ignorePatterns); |
| 927 | + return GradleWorkspaceDiscovery.discoverSubprojects(workspaceDir, ignorePatterns); |
921 | 928 | } |
922 | 929 |
|
923 | 930 | // JS workspace: require package.json + a lock file |
@@ -975,131 +982,6 @@ private List<Path> discoverCargoManifests(Path workspaceDir, Set<String> ignoreP |
975 | 982 | } |
976 | 983 | } |
977 | 984 |
|
978 | | - private static final String GRADLE_INIT_SCRIPT = |
979 | | - "allprojects {\n" |
980 | | - + " task daListProjects {\n" |
981 | | - + " doLast {\n" |
982 | | - + " println \"::DA_PROJECT::${project.path}::${project.projectDir}\"\n" |
983 | | - + " }\n" |
984 | | - + " }\n" |
985 | | - + "}\n"; |
986 | | - |
987 | | - /** |
988 | | - * Resolve the Gradle binary, preferring gradlew wrapper when available and configured. |
989 | | - * |
990 | | - * @param startDir directory from which to start the wrapper search |
991 | | - * @return path to the Gradle binary |
992 | | - */ |
993 | | - private static String resolveGradleBinary(Path startDir) { |
994 | | - if (Operations.getWrapperPreference("gradle")) { |
995 | | - String wrapperName = Operations.isWindows() ? "gradlew.bat" : "gradlew"; |
996 | | - String wrapper = |
997 | | - JavaMavenProvider.traverseForMvnw( |
998 | | - wrapperName, startDir.resolve("build.gradle").toString(), null); |
999 | | - if (wrapper != null) { |
1000 | | - return wrapper; |
1001 | | - } |
1002 | | - } |
1003 | | - return Operations.getCustomPathOrElse("gradle"); |
1004 | | - } |
1005 | | - |
1006 | | - /** |
1007 | | - * Discover all build.gradle[.kts] manifest paths in a Gradle multi-project build. Uses a custom |
1008 | | - * init script to get a structured project listing. |
1009 | | - */ |
1010 | | - private List<Path> discoverGradleSubprojects(Path workspaceDir, Set<String> ignorePatterns) { |
1011 | | - Path rootBuildKts = workspaceDir.resolve("build.gradle.kts"); |
1012 | | - Path rootBuild = workspaceDir.resolve("build.gradle"); |
1013 | | - |
1014 | | - List<Path> manifestPaths = new ArrayList<>(); |
1015 | | - if (Files.isRegularFile(rootBuildKts)) { |
1016 | | - manifestPaths.add(rootBuildKts); |
1017 | | - } else if (Files.isRegularFile(rootBuild)) { |
1018 | | - manifestPaths.add(rootBuild); |
1019 | | - } |
1020 | | - |
1021 | | - String gradleBin = resolveGradleBinary(workspaceDir); |
1022 | | - Path initScriptPath = null; |
1023 | | - try { |
1024 | | - initScriptPath = Files.createTempFile("da-list-projects-", ".gradle"); |
1025 | | - Files.writeString(initScriptPath, GRADLE_INIT_SCRIPT); |
1026 | | - |
1027 | | - Operations.ProcessExecOutput output = |
1028 | | - Operations.runProcessGetFullOutput( |
1029 | | - workspaceDir, |
1030 | | - new String[] { |
1031 | | - gradleBin, |
1032 | | - "-q", |
1033 | | - "--no-daemon", |
1034 | | - "--init-script", |
1035 | | - initScriptPath.toString(), |
1036 | | - "daListProjects" |
1037 | | - }, |
1038 | | - null); |
1039 | | - |
1040 | | - if (output.getExitCode() != 0) { |
1041 | | - LOG.warning( |
1042 | | - "gradle daListProjects failed with exit code " |
1043 | | - + output.getExitCode() |
1044 | | - + ": " |
1045 | | - + output.getError()); |
1046 | | - return WorkspaceUtils.filterByIgnorePatterns(workspaceDir, manifestPaths, ignorePatterns); |
1047 | | - } |
1048 | | - |
1049 | | - for (var proj : parseGradleInitScriptOutput(output.getOutput())) { |
1050 | | - if (":".equals(proj.path())) { |
1051 | | - continue; |
1052 | | - } |
1053 | | - Path projDir = Path.of(proj.dir()).toAbsolutePath().normalize(); |
1054 | | - Path buildKts = projDir.resolve("build.gradle.kts"); |
1055 | | - Path buildGroovy = projDir.resolve("build.gradle"); |
1056 | | - if (Files.isRegularFile(buildKts)) { |
1057 | | - manifestPaths.add(buildKts); |
1058 | | - } else if (Files.isRegularFile(buildGroovy)) { |
1059 | | - manifestPaths.add(buildGroovy); |
1060 | | - } |
1061 | | - } |
1062 | | - } catch (Exception e) { |
1063 | | - LOG.warning("Failed to discover Gradle subprojects: " + e.getMessage()); |
1064 | | - return WorkspaceUtils.filterByIgnorePatterns(workspaceDir, manifestPaths, ignorePatterns); |
1065 | | - } finally { |
1066 | | - if (initScriptPath != null) { |
1067 | | - try { |
1068 | | - Files.deleteIfExists(initScriptPath); |
1069 | | - } catch (IOException ignored) { |
1070 | | - } |
1071 | | - } |
1072 | | - } |
1073 | | - |
1074 | | - return WorkspaceUtils.filterByIgnorePatterns(workspaceDir, manifestPaths, ignorePatterns); |
1075 | | - } |
1076 | | - |
1077 | | - record GradleProject(String path, String dir) {} |
1078 | | - |
1079 | | - static List<GradleProject> parseGradleInitScriptOutput(String raw) { |
1080 | | - if (raw == null || raw.isBlank()) { |
1081 | | - return List.of(); |
1082 | | - } |
1083 | | - String prefix = "::DA_PROJECT::"; |
1084 | | - List<GradleProject> projects = new ArrayList<>(); |
1085 | | - for (String line : raw.lines().toList()) { |
1086 | | - if (!line.startsWith(prefix)) { |
1087 | | - continue; |
1088 | | - } |
1089 | | - String remainder = line.substring(prefix.length()); |
1090 | | - int lastSep = remainder.lastIndexOf("::"); |
1091 | | - if (lastSep < 0) { |
1092 | | - continue; |
1093 | | - } |
1094 | | - String path = remainder.substring(0, lastSep); |
1095 | | - String dir = remainder.substring(lastSep + 2); |
1096 | | - if (!path.isEmpty() && !dir.isEmpty()) { |
1097 | | - projects.add(new GradleProject(path, dir)); |
1098 | | - } |
1099 | | - } |
1100 | | - return projects; |
1101 | | - } |
1102 | | - |
1103 | 985 | /** |
1104 | 986 | * Discover all go.mod manifest paths in a Go workspace. Uses {@code go work edit -json} to get |
1105 | 987 | * workspace members. |
|
0 commit comments