Skip to content

Commit cf348f2

Browse files
committed
feat(devti): enhance ripgrep binary search for Windows and Unix systems #344
- Implement separate search strategies for Windows and Unix-based systems - Add support for locating ripgrep binary in common installation directories on Windows - Improve error handling and logging for better diagnostics - Refactor code to make it more maintainable and easier to understand
1 parent e92515e commit cf348f2

File tree

1 file changed

+59
-6
lines changed

1 file changed

+59
-6
lines changed

core/src/main/kotlin/cc/unitmesh/devti/agent/tool/search/RipgrepSearcher.kt

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,25 +55,77 @@ object RipgrepSearcher {
5555
val osName = System.getProperty("os.name").lowercase(Locale.getDefault())
5656
val binName = if (osName.contains("win")) "rg.exe" else "rg"
5757

58-
// try get from /usr/local/bin/rg if macos
59-
if (osName.contains("mac")) {
58+
return when {
59+
osName.contains("win") -> findRipgrepBinaryOnWindows(binName)
60+
else -> findRipgrepBinaryOnUnix(binName)
61+
}
62+
}
63+
64+
private fun findRipgrepBinaryOnWindows(binName: String): Path? {
65+
try {
66+
val pb = ProcessBuilder("where", binName)
67+
val process = pb.start()
68+
if (process.waitFor(1, TimeUnit.SECONDS) && process.exitValue() == 0) {
69+
val path = String(process.inputStream.readAllBytes(), StandardCharsets.UTF_8)
70+
.lines().firstOrNull()?.trim()
71+
if (path != null) {
72+
return Paths.get(path)
73+
}
74+
}
75+
} catch (e: Exception) {
76+
LOG.debug("Failed to locate rg using 'where' command", e)
77+
}
78+
79+
// Check common installation locations on Windows
80+
val commonPaths = listOf(
81+
Paths.get(System.getenv("ProgramFiles"), "ripgrep", binName),
82+
Paths.get(System.getenv("ProgramFiles(x86)"), "ripgrep", binName),
83+
Paths.get(System.getenv("USERPROFILE"), ".cargo", "bin", binName)
84+
)
85+
86+
for (path in commonPaths) {
87+
if (path.toFile().exists()) {
88+
return path
89+
}
90+
}
91+
92+
return findInPath(binName)
93+
}
94+
95+
private fun findRipgrepBinaryOnUnix(binName: String): Path? {
96+
// Check macOS specific location
97+
if (System.getProperty("os.name").lowercase(Locale.getDefault()).contains("mac")) {
6098
val path = Paths.get("/usr/local/bin/rg")
6199
if (path.toFile().exists()) {
62100
return path
63101
}
64102
}
65103

66-
val pb = ProcessBuilder("which", binName)
67-
val process = pb.start()
68104
try {
105+
val pb = ProcessBuilder("which", binName)
106+
val process = pb.start()
69107
if (process.waitFor(1, TimeUnit.SECONDS) && process.exitValue() == 0) {
70108
val path = String(process.inputStream.readAllBytes(), StandardCharsets.UTF_8).trim { it <= ' ' }
71109
return Paths.get(path)
72110
}
73-
} catch (_: InterruptedException) {
74-
return null
111+
} catch (e: Exception) {
112+
LOG.debug("Failed to locate rg using 'which' command", e)
75113
}
76114

115+
return findInPath(binName)
116+
}
117+
118+
private fun findInPath(executable: String): Path? {
119+
val pathEnv = System.getenv("PATH") ?: return null
120+
val pathSeparator = if (System.getProperty("os.name").lowercase().contains("win")) ";" else ":"
121+
122+
for (dir in pathEnv.split(pathSeparator)) {
123+
val path = Paths.get(dir, executable)
124+
if (path.toFile().exists() && path.toFile().canExecute()) {
125+
return path
126+
}
127+
}
128+
77129
return null
78130
}
79131

@@ -170,3 +222,4 @@ object RipgrepSearcher {
170222
return base.relativize(target).toString().replace('\\', '/')
171223
}
172224
}
225+

0 commit comments

Comments
 (0)