Skip to content

Fix fundamental design issues: circular references, untestable prompts, and implicit init()#122

Merged
babarot merged 5 commits into
mainfrom
babarot/refactor-file-storage-cleanup
Apr 4, 2026
Merged

Fix fundamental design issues: circular references, untestable prompts, and implicit init()#122
babarot merged 5 commits into
mainfrom
babarot/refactor-file-storage-cleanup

Conversation

@babarot

@babarot babarot commented Apr 4, 2026

Copy link
Copy Markdown
Owner

WHAT

Address four fundamental design problems identified during code review: remove the circular File-Storage reference, extract a Prompter interface for testable CLI interactions, deduplicate Manager's storage lookup, and replace two init() functions with explicit initialization.

WHY

  1. File.storage circular reference β€” File held a reference back to its managing Storage, but Manager never used it (it finds storage via TrashPath prefix matching). The field existed only as dead weight creating a circular dependency.

  2. Untestable CLI prompts β€” restore.go and prune.go called ui.Confirm() / ui.ConfirmYes() / ui.InputFilename() directly, making it impossible to test CLI commands without starting a real BubbleTea terminal program.

  3. Duplicated storage lookup β€” Restore() and Remove() had identical inline closures to find which storage manages a file. Restore had verbose debug logging while Remove had none.

  4. init() side effects β€” Two packages used init() to perform filesystem operations on import: env set global path variables, and history/migration renamed files. Both violated the principle of explicit initialization.

babarot added 5 commits April 4, 2026 20:43
Restore() and Remove() had identical inline closures to find the
storage backend for a given file. Extract into a shared helper
method. Also removes verbose debug logging that was only in
Restore but not Remove, making both paths consistent.
File held a reference to its managing Storage, creating a circular
dependency (Storage creates Files, Files reference Storage). This
field was never consumed β€” Manager.findStorageForFile() uses
TrashPath prefix matching instead. Remove the storage field,
SetStorage(), and GetStorage() methods.
Define a Prompter interface (Confirm, ConfirmYes, InputFilename) in
the CLI package. restore.go and prune.go now call c.prompter instead
of ui package functions directly. The default uiPrompter delegates
to the existing ui.Confirm/ui.ConfirmYes/ui.InputFilename functions.

This enables mock-based testing of CLI commands that require user
confirmation without starting a real BubbleTea program.
The env package used init() to set GOMI_LOG_PATH and CLICOLOR_FORCE
as side effects on import. Replace with an explicit Init() call
from CLI.Run(), protected by sync.Once. Also remove the unused
GOMI_CONFIG_PATH variable and defaultXDGConfigDirname constant.
The history package used init() to auto-rename inventory.json to
history.json on import, causing filesystem writes as a side effect.
Replace with migrateIfNeeded() called explicitly from New(). Also
replace log.Fatalf with slog.Error to avoid process termination on
migration failure.
@github-actions

github-actions Bot commented Apr 4, 2026

Copy link
Copy Markdown
Contributor

Code Metrics Report

main (d7e0503) #122 (9d67d02) +/-
Coverage 44.2% 42.1% -2.1%
Code to Test Ratio 1:1.5 1:1.5 +0.0
Test Execution Time 4s 3s -1s
Details
  |                     | main (d7e0503) | #122 (9d67d02) |  +/-  |
  |---------------------|----------------|----------------|-------|
- | Coverage            |          44.2% |          42.1% | -2.1% |
  |   Files             |             24 |             24 |     0 |
  |   Lines             |           1822 |           1839 |   +17 |
- |   Covered           |            806 |            776 |   -30 |
+ | Code to Test Ratio  |          1:1.5 |          1:1.5 |  +0.0 |
  |   Code              |           2772 |           2720 |   -52 |
- |   Test              |           4248 |           4238 |   -10 |
+ | Test Execution Time |             4s |             3s |   -1s |

Code coverage of files in pull request scope (39.2% β†’ 35.2%)

Files Coverage +/- Status
internal/trash/legacy/history/history.go 42.7% +0.2% modified
internal/trash/legacy/history/migration.go 25.0% -32.2% modified
internal/trash/legacy/storage.go 32.0% -0.8% modified
internal/trash/manager.go 39.1% -3.7% modified
internal/trash/storage.go 38.7% -37.8% modified
internal/trash/xdg/storage.go 32.3% +1.1% modified
internal/utils/env/env.go 0.0% -63.2% modified

Reported by octocov

@babarot babarot added the kind/cleanup Categorizes issue or PR as related to cleaning up code, issues, etc. label Apr 4, 2026
@babarot babarot marked this pull request as ready for review April 4, 2026 11:58
@babarot babarot merged commit a73fb08 into main Apr 4, 2026
6 checks passed
@babarot babarot deleted the babarot/refactor-file-storage-cleanup branch April 4, 2026 11:58
@github-actions github-actions Bot mentioned this pull request Apr 4, 2026
tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request Jun 10, 2026
This MR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [babarot/gomi](https://github.com/babarot/gomi) | patch | `v1.6.3` β†’ `v1.6.4` |

MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot).

**Proposed changes to behavior should be submitted there as MRs.**

---

### Release Notes

<details>
<summary>babarot/gomi (babarot/gomi)</summary>

### [`v1.6.4`](https://github.com/babarot/gomi/blob/HEAD/CHANGELOG.md#v164---2026-06-07)

[Compare Source](babarot/gomi@v1.6.3...v1.6.4)

##### Improvements

- fix: keep restore TUI within terminal bounds (closes [#&#8203;125](babarot/gomi#125)) by [@&#8203;babarot](https://github.com/babarot) in [#&#8203;127](babarot/gomi#127)
- Allow --prune to skip confirmation with -f by [@&#8203;babarot](https://github.com/babarot) in [#&#8203;129](babarot/gomi#129)

##### Refactorings

- Fix concurrency safety: eliminate global SelectionManager and add mutex to legacy Storage by [@&#8203;babarot](https://github.com/babarot) in [#&#8203;118](babarot/gomi#118)
- Refactor: extract Trash interface, move orphan logic, and DRY up XDG storage by [@&#8203;babarot](https://github.com/babarot) in [#&#8203;119](babarot/gomi#119)
- Refactor: decouple config, remove unused fields, and narrow UI dependencies by [@&#8203;babarot](https://github.com/babarot) in [#&#8203;120](babarot/gomi#120)
- Update architecture docs and rename manager variables to match Trash interface by [@&#8203;babarot](https://github.com/babarot) in [#&#8203;121](babarot/gomi#121)
- Fix fundamental design issues: circular references, untestable prompts, and implicit init() by [@&#8203;babarot](https://github.com/babarot) in [#&#8203;122](babarot/gomi#122)
- Reduce syscalls in gomi -b restore path by [@&#8203;babarot](https://github.com/babarot) in [#&#8203;123](babarot/gomi#123)

</details>

---

### Configuration

πŸ“… **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Enabled.

β™» **Rebasing**: Whenever MR is behind base branch, or you tick the rebase/retry checkbox.

πŸ”• **Ignore**: Close this MR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xOTEuMiIsInVwZGF0ZWRJblZlciI6IjQzLjE5MS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJSZW5vdmF0ZSBCb3QiLCJhdXRvbWF0aW9uOmJvdC1hdXRob3JlZCIsImRlcGVuZGVuY3ktdHlwZTo6cGF0Y2giXX0=-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind/cleanup Categorizes issue or PR as related to cleaning up code, issues, etc.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant