Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ mo optimize --dry-run # Preview optimization actions
mo optimize --debug # Run with detailed operation logs
mo optimize --whitelist # Manage protected optimization rules
mo purge --paths # Configure project scan directories
mo analyze --exclude-volumes # Skip external drives under /Volumes in overview
```

## Tips
Expand Down Expand Up @@ -149,6 +150,8 @@ Use `mo optimize --whitelist` to exclude specific optimizations.

### Disk Space Analyzer

Use `--exclude-volumes` to skip external drives under `/Volumes` in the overview (faster when many volumes are attached).

```bash
$ mo analyze

Expand Down
4 changes: 2 additions & 2 deletions cmd/analyze/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -332,8 +332,8 @@ func removeOverviewSnapshot(path string) {
}

// prefetchOverviewCache warms overview cache in background.
func prefetchOverviewCache(ctx context.Context) {
entries := createOverviewEntries()
func prefetchOverviewCache(ctx context.Context, excludeVolumes bool) {
entries := createOverviewEntries(excludeVolumes)

var needScan []string
for _, entry := range entries {
Expand Down
25 changes: 16 additions & 9 deletions cmd/analyze/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package main

import (
"context"
"flag"
"fmt"
"io/fs"
"os"
Expand Down Expand Up @@ -122,16 +123,21 @@ type model struct {
largeMultiSelected map[string]bool // Track multi-selected large files by path (safer than index)
totalFiles int64 // Total files found in current/last scan
lastTotalFiles int64 // Total files from previous scan (for progress bar)
excludeVolumes bool // Skip /Volumes in overview (--exclude-volumes)
}

func (m model) inOverviewMode() bool {
return m.isOverview && m.path == "/"
}

func main() {
fs := flag.NewFlagSet("analyze", flag.ContinueOnError)
excludeVolumes := fs.Bool("exclude-volumes", false, "exclude /Volumes (external drives) from overview")
_ = fs.Parse(os.Args[1:])

target := os.Getenv("MO_ANALYZE_PATH")
if target == "" && len(os.Args) > 1 {
target = os.Args[1]
if target == "" && fs.NArg() > 0 {
target = fs.Arg(0)
}

var abs string
Expand All @@ -153,16 +159,16 @@ func main() {
// Warm overview cache in background.
prefetchCtx, prefetchCancel := context.WithTimeout(context.Background(), 30*time.Second)
defer prefetchCancel()
go prefetchOverviewCache(prefetchCtx)
go prefetchOverviewCache(prefetchCtx, *excludeVolumes)

p := tea.NewProgram(newModel(abs, isOverview), tea.WithAltScreen())
p := tea.NewProgram(newModel(abs, isOverview, *excludeVolumes), tea.WithAltScreen())
if _, err := p.Run(); err != nil {
fmt.Fprintf(os.Stderr, "analyzer error: %v\n", err)
os.Exit(1)
}
}

func newModel(path string, isOverview bool) model {
func newModel(path string, isOverview bool, excludeVolumes bool) model {
var filesScanned, dirsScanned, bytesScanned int64
currentPath := &atomic.Value{}
currentPath.Store("")
Expand All @@ -189,6 +195,7 @@ func newModel(path string, isOverview bool) model {
overviewScanningSet: make(map[string]bool),
multiSelected: make(map[string]bool),
largeMultiSelected: make(map[string]bool),
excludeVolumes: excludeVolumes,
}

if isOverview {
Expand All @@ -214,7 +221,7 @@ func newModel(path string, isOverview bool) model {
return m
}

func createOverviewEntries() []dirEntry {
func createOverviewEntries(excludeVolumes bool) []dirEntry {
home := os.Getenv("HOME")
entries := []dirEntry{}

Expand All @@ -233,8 +240,8 @@ func createOverviewEntries() []dirEntry {
dirEntry{Name: "System Library", Path: "/Library", IsDir: true, Size: -1},
)

// Include Volumes only when real mounts exist.
if hasUsefulVolumeMounts("/Volumes") {
// Include Volumes only when real mounts exist and not excluded by --exclude-volumes.
if !excludeVolumes && hasUsefulVolumeMounts("/Volumes") {
entries = append(entries, dirEntry{Name: "Volumes", Path: "/Volumes", IsDir: true, Size: -1})
}

Expand Down Expand Up @@ -268,7 +275,7 @@ func hasUsefulVolumeMounts(path string) bool {
}

func (m *model) hydrateOverviewEntries() {
m.entries = createOverviewEntries()
m.entries = createOverviewEntries(m.excludeVolumes)
if m.overviewSizeCache == nil {
m.overviewSizeCache = make(map[string]int64)
}
Expand Down
1 change: 1 addition & 0 deletions mole
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ show_help() {
printf " %s%-28s%s %s\n" "$GREEN" "mo optimize --dry-run" "$NC" "Preview optimization"
printf " %s%-28s%s %s\n" "$GREEN" "mo optimize --whitelist" "$NC" "Manage protected items"
printf " %s%-28s%s %s\n" "$GREEN" "mo purge --paths" "$NC" "Configure scan directories"
printf " %s%-28s%s %s\n" "$GREEN" "mo analyze --exclude-volumes" "$NC" "Skip external drives in overview"
printf " %s%-28s%s %s\n" "$GREEN" "mo update --force" "$NC" "Force reinstall latest version"
echo
printf "%s%s%s\n" "$BLUE" "OPTIONS" "$NC"
Expand Down