From 718fd92f85c5a58f0046fa5e8f7d248d64174e2e Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Wed, 4 Feb 2026 21:23:07 +1100 Subject: [PATCH] fix(v2): prevent wails init in non-empty directory with -d flag (#4955) * fix(v2): prevent wails init in non-empty directory with -d flag When using -d to specify a target directory, wails init now checks if the directory is non-empty and errors if so. This prevents accidental data loss (e.g., overwriting .git directories). Fixes #4940 Co-Authored-By: Claude Opus 4.5 * test(v2): add tests for init non-empty directory check Add tests to verify: - Install fails when target directory is non-empty - Install succeeds when target directory is empty Also update changelog with the fix. Co-Authored-By: Claude Opus 4.5 * Apply suggestions from code review Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --------- Co-authored-by: Claude Opus 4.5 Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- v2/pkg/templates/templates.go | 11 +++++++- v2/pkg/templates/templates_test.go | 45 ++++++++++++++++++++++++++++++ website/src/pages/changelog.mdx | 1 + 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/v2/pkg/templates/templates.go b/v2/pkg/templates/templates.go index 9b42ef365..e18185520 100644 --- a/v2/pkg/templates/templates.go +++ b/v2/pkg/templates/templates.go @@ -186,7 +186,16 @@ func Install(options *Options) (bool, *Template, error) { return false, nil, err } options.TargetDir = targetDir - if !fs.DirExists(options.TargetDir) { + if fs.DirExists(options.TargetDir) { + // Check if directory is non-empty + entries, err := os.ReadDir(options.TargetDir) + if err != nil { + return false, nil, err + } + if len(entries) > 0 { + return false, nil, fmt.Errorf("cannot initialise project in non-empty directory: %s", options.TargetDir) + } + } else { err := fs.Mkdir(options.TargetDir) if err != nil { return false, nil, err diff --git a/v2/pkg/templates/templates_test.go b/v2/pkg/templates/templates_test.go index 3b906601a..658ecadb6 100644 --- a/v2/pkg/templates/templates_test.go +++ b/v2/pkg/templates/templates_test.go @@ -52,3 +52,48 @@ func TestInstall(t *testing.T) { is2.NoErr(err) } + +func TestInstallFailsInNonEmptyDirectory(t *testing.T) { + is2 := is.New(t) + + // Create a temp directory with a file in it + tempDir, err := os.MkdirTemp("", "wails-test-nonempty-*") + is2.NoErr(err) + defer func() { + _ = os.RemoveAll(tempDir) + }() + + // Create a file in the directory to make it non-empty + err = os.WriteFile(filepath.Join(tempDir, "existing-file.txt"), []byte("test"), 0644) + is2.NoErr(err) + + options := &Options{ + ProjectName: "test", + TemplateName: "vanilla", + TargetDir: tempDir, + } + + _, _, err = Install(options) + is2.True(err != nil) // Should fail + is2.True(err.Error() == "cannot initialise project in non-empty directory: "+tempDir) +} + +func TestInstallSucceedsInEmptyDirectory(t *testing.T) { + is2 := is.New(t) + + // Create an empty temp directory + tempDir, err := os.MkdirTemp("", "wails-test-empty-*") + is2.NoErr(err) + defer func() { + _ = os.RemoveAll(tempDir) + }() + + options := &Options{ + ProjectName: "test", + TemplateName: "vanilla", + TargetDir: tempDir, + } + + _, _, err = Install(options) + is2.NoErr(err) // Should succeed in empty directory +} diff --git a/website/src/pages/changelog.mdx b/website/src/pages/changelog.mdx index 01fa47a69..50208109b 100644 --- a/website/src/pages/changelog.mdx +++ b/website/src/pages/changelog.mdx @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- Fixed `wails init` to prevent initialization in non-empty directories when using the `-d` flag, avoiding accidental data loss [`#4940`](https://github.com/wailsapp/wails/issues/4940) by `@leaanthony` - Fixed missing `EventsOffAll` in runtime templates for all frontend frameworks [#4883](https://github.com/wailsapp/wails/pull/4883) by @narcilee7 - Fixed Linux crash on panic in JS-bound Go methods due to WebKit overriding signal handlers [#3965](https://github.com/wailsapp/wails/issues/3965) by @leaanthony - Fixed code block range in "How Does It Work?" documentation [#4884](https://github.com/wailsapp/wails/pull/4884) by @msal4