Skip to content

Commit 93663f4

Browse files
timilirisclaude
andcommitted
Fix Linux/macOS: auto chmod +x gradlew/mvnw wrappers
On fresh git clones, wrapper scripts may lack execute permission. Now automatically runs chmod +x if needed before executing build. Fixes "No such file or directory" error on Ubuntu. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent fe678a5 commit 93663f4

File tree

3 files changed

+44
-8
lines changed

3 files changed

+44
-8
lines changed

CHANGELOG.md

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22

33
## [Unreleased]
44

5+
## [1.4.1] - 2026-02-06
6+
7+
### Fixed
8+
9+
- **Linux/macOS: Gradle wrapper not executable**: Auto-fix `gradlew` and `mvnw` permissions on Unix systems
10+
- Runs `chmod +x` automatically if wrapper lacks execute permission
11+
- Fixes "No such file or directory" error on fresh clones
12+
513
## [1.4.0] - 2026-02-05
614

715
### Added
@@ -11,18 +19,15 @@
1119
- Profiles stored in `~/.hytale-intellij/servers.json`
1220
- Import servers from existing directories with auto-detection
1321
- Quick switch between servers from the Tool Window
14-
1522
- **Server Selector UI**: New dropdown in the Tool Window
1623
- Visual server selector with status indicator (running/stopped/starting)
1724
- Auto-detects `server/` folder in project and creates default profile
1825
- Browse button to quickly add new server directories
1926
- Gear button to open full Server Manager dialog
20-
2127
- **Multi-Server Support**: Run multiple Hytale servers simultaneously
2228
- Each server runs on its own port
2329
- Independent start/stop/status per server
2430
- Port conflict detection prevents duplicate bindings
25-
2631
- **Improved Java Detection**: Comprehensive cross-platform Java 25+ detection
2732
- Windows: Registry, Scoop, Chocolatey, SDKMAN, jabba, GraalVM, Microsoft JDK
2833
- macOS: Homebrew (Intel & Apple Silicon), `/usr/libexec/java_home`, SDKMAN, asdf, mise
@@ -38,7 +43,6 @@
3843
- Timestamped filenames when files are locked
3944
- Retry with exponential backoff (1s, 2s, 4s)
4045
- Automatic cleanup of old timestamped JARs
41-
4246
- **IntelliJ 2025.3 API Compatibility**: Updated deprecated `textFieldWithBrowseButton` calls
4347

4448
### Changed
@@ -206,7 +210,9 @@
206210
- Supports IntelliJ IDEA 2024.3+
207211
- Requires Java 25 for Hytale development
208212

209-
[Unreleased]: https://github.com/HytaleDocs/hytale-intellij-plugin/compare/v1.3.9...HEAD
213+
[Unreleased]: https://github.com/HytaleDocs/hytale-intellij-plugin/compare/v1.4.1...HEAD
214+
[1.4.1]: https://github.com/HytaleDocs/hytale-intellij-plugin/compare/v1.4.0...v1.4.1
215+
[1.4.0]: https://github.com/HytaleDocs/hytale-intellij-plugin/compare/v1.3.9...v1.4.0
210216
[1.3.9]: https://github.com/HytaleDocs/hytale-intellij-plugin/compare/v1.3.7...v1.3.9
211217
[1.3.7]: https://github.com/HytaleDocs/hytale-intellij-plugin/compare/v1.3.6...v1.3.7
212218
[1.3.6]: https://github.com/HytaleDocs/hytale-intellij-plugin/compare/v1.3.5...v1.3.6

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ pluginGroup = com.hytaledocs.hytale
44
pluginName = Hytale Development Tools
55
pluginRepositoryUrl = https://github.com/HytaleDocs/hytale-intellij-plugin
66
# SemVer format -> https://semver.org
7-
pluginVersion = 1.4.0
7+
pluginVersion = 1.4.1
88

99
# Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
1010
pluginSinceBuild = 242

src/main/kotlin/com/hytaledocs/intellij/run/HytaleServerRunState.kt

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,14 +249,44 @@ class HytaleServerProcessHandler(
249249
val isWindows = System.getProperty("os.name").lowercase().contains("windows")
250250
val wrapperName = if (isWindows) "gradlew.bat" else "gradlew"
251251
val wrapper = Path.of(projectBasePath, wrapperName)
252-
return if (Files.exists(wrapper)) wrapper.toString() else null
252+
if (!Files.exists(wrapper)) return null
253+
254+
// On Unix, ensure the wrapper is executable
255+
if (!isWindows) {
256+
makeExecutableIfNeeded(wrapper)
257+
}
258+
return wrapper.toString()
253259
}
254260

255261
private fun findMavenWrapper(projectBasePath: String): String? {
256262
val isWindows = System.getProperty("os.name").lowercase().contains("windows")
257263
val wrapperName = if (isWindows) "mvnw.cmd" else "mvnw"
258264
val wrapper = Path.of(projectBasePath, wrapperName)
259-
return if (Files.exists(wrapper)) wrapper.toString() else null
265+
if (!Files.exists(wrapper)) return null
266+
267+
// On Unix, ensure the wrapper is executable
268+
if (!isWindows) {
269+
makeExecutableIfNeeded(wrapper)
270+
}
271+
return wrapper.toString()
272+
}
273+
274+
/**
275+
* Makes a file executable on Unix systems if it isn't already.
276+
* This fixes "No such file or directory" errors when gradlew/mvnw lack execute permission.
277+
*/
278+
private fun makeExecutableIfNeeded(file: Path) {
279+
try {
280+
if (!Files.isExecutable(file)) {
281+
LOG.info("Making ${file.fileName} executable")
282+
val process = ProcessBuilder("chmod", "+x", file.toString())
283+
.start()
284+
process.waitFor(5, TimeUnit.SECONDS)
285+
}
286+
} catch (e: Exception) {
287+
LOG.warn("Failed to make ${file.fileName} executable: ${e.message}")
288+
// Continue anyway - might still work or fail with better error
289+
}
260290
}
261291

262292
private fun findGlobalGradle(): String? = findGlobalTool("gradle")

0 commit comments

Comments
 (0)