mirror of
https://github.com/tw93/Mole.git
synced 2026-03-22 20:15:07 +00:00
56
.github/workflows/release-windows.yml
vendored
56
.github/workflows/release-windows.yml
vendored
@@ -1,10 +1,8 @@
|
|||||||
name: Build Windows Release
|
name: Build Windows Prerelease
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
- 'v*.*.*' # Trigger on version tags (e.g., v1.0.0)
|
|
||||||
- 'V*.*.*' # Also support uppercase V (e.g., V1.0.0)
|
|
||||||
- 'v*.*.*-windows' # Windows-specific releases
|
- 'v*.*.*-windows' # Windows-specific releases
|
||||||
- 'V*.*.*-windows' # Windows-specific releases (uppercase)
|
- 'V*.*.*-windows' # Windows-specific releases (uppercase)
|
||||||
workflow_dispatch: # Allow manual trigger
|
workflow_dispatch: # Allow manual trigger
|
||||||
@@ -19,7 +17,7 @@ permissions:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-windows:
|
build-windows:
|
||||||
name: Build Windows Release Artifacts
|
name: Build Windows Prerelease Artifacts
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
@@ -31,7 +29,7 @@ jobs:
|
|||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.21'
|
go-version: '1.24.6'
|
||||||
|
|
||||||
- name: Setup PowerShell
|
- name: Setup PowerShell
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
@@ -47,6 +45,7 @@ jobs:
|
|||||||
$version = "${{ github.event.inputs.version }}"
|
$version = "${{ github.event.inputs.version }}"
|
||||||
} elseif ("${{ github.ref }}" -like "refs/tags/*") {
|
} elseif ("${{ github.ref }}" -like "refs/tags/*") {
|
||||||
$version = "${{ github.ref }}" -replace '^refs/tags/[Vv]', ''
|
$version = "${{ github.ref }}" -replace '^refs/tags/[Vv]', ''
|
||||||
|
$version = $version -replace '-windows$', ''
|
||||||
} else {
|
} else {
|
||||||
$content = Get-Content mole.ps1 -Raw
|
$content = Get-Content mole.ps1 -Raw
|
||||||
if ($content -match '\$script:MOLE_VER\s*=\s*"([^"]+)"') {
|
if ($content -match '\$script:MOLE_VER\s*=\s*"([^"]+)"') {
|
||||||
@@ -80,6 +79,12 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
& scripts\build-release.ps1 -Version ${{ steps.version.outputs.VERSION }}
|
& scripts\build-release.ps1 -Version ${{ steps.version.outputs.VERSION }}
|
||||||
|
|
||||||
|
- name: Prepare raw TUI binary assets
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
Copy-Item "bin\analyze.exe" "release\analyze-windows-x64.exe" -Force
|
||||||
|
Copy-Item "bin\status.exe" "release\status-windows-x64.exe" -Force
|
||||||
|
|
||||||
|
|
||||||
- name: Build standalone EXE
|
- name: Build standalone EXE
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
@@ -118,21 +123,46 @@ jobs:
|
|||||||
path: release/SHA256SUMS.txt
|
path: release/SHA256SUMS.txt
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Create GitHub Release
|
- name: Upload TUI binaries
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: tui-binaries
|
||||||
|
path: |
|
||||||
|
release/analyze-windows-x64.exe
|
||||||
|
release/status-windows-x64.exe
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
|
- name: Collect release files
|
||||||
|
id: release_files
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
$files = @(
|
||||||
|
"release/mole-${{ steps.version.outputs.VERSION }}-x64.zip",
|
||||||
|
"release/analyze-windows-x64.exe",
|
||||||
|
"release/status-windows-x64.exe",
|
||||||
|
"release/SHA256SUMS.txt"
|
||||||
|
)
|
||||||
|
$optionalExe = "release/mole-${{ steps.version.outputs.VERSION }}-x64.exe"
|
||||||
|
if (Test-Path $optionalExe) {
|
||||||
|
$files += $optionalExe
|
||||||
|
}
|
||||||
|
"files<<EOF" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
|
||||||
|
$files | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
|
||||||
|
"EOF" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
|
||||||
|
|
||||||
|
- name: Create GitHub Prerelease
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v1
|
||||||
with:
|
with:
|
||||||
files: |
|
files: ${{ steps.release_files.outputs.files }}
|
||||||
release/mole-${{ steps.version.outputs.VERSION }}-x64.zip
|
|
||||||
release/mole-${{ steps.version.outputs.VERSION }}-x64.exe
|
|
||||||
release/SHA256SUMS.txt
|
|
||||||
draft: false
|
draft: false
|
||||||
prerelease: false
|
prerelease: true
|
||||||
generate_release_notes: true
|
generate_release_notes: true
|
||||||
body: |
|
body: |
|
||||||
## Windows System Maintenance Toolkit
|
## Windows System Maintenance Toolkit (Prerelease)
|
||||||
|
|
||||||
**Download:** `mole-${{ steps.version.outputs.VERSION }}-x64.zip` (portable) or `.exe` (launcher)
|
**Download:** `mole-${{ steps.version.outputs.VERSION }}-x64.zip` (portable) or `.exe` (launcher)
|
||||||
|
**TUI assets:** `analyze-windows-x64.exe` and `status-windows-x64.exe`
|
||||||
|
|
||||||
**Install:**
|
**Install:**
|
||||||
```powershell
|
```powershell
|
||||||
@@ -141,6 +171,8 @@ jobs:
|
|||||||
.\install.ps1
|
.\install.ps1
|
||||||
```
|
```
|
||||||
|
|
||||||
|
These assets are prerelease-only and do not affect the macOS stable release channel.
|
||||||
|
|
||||||
**Verify:** Check SHA256SUMS.txt for file integrity.
|
**Verify:** Check SHA256SUMS.txt for file integrity.
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|||||||
106
.github/workflows/release.yml
vendored
106
.github/workflows/release.yml
vendored
@@ -1,106 +0,0 @@
|
|||||||
name: Release
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- 'W*' # Windows releases use W prefix (e.g., W1.0.0)
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
name: Build Windows
|
|
||||||
runs-on: windows-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up Go
|
|
||||||
uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version: "1.24.6"
|
|
||||||
|
|
||||||
- name: Build Binaries
|
|
||||||
run: |
|
|
||||||
cd cmd/analyze
|
|
||||||
go build -ldflags="-s -w" -o analyze.exe .
|
|
||||||
cd ../status
|
|
||||||
go build -ldflags="-s -w" -o status.exe .
|
|
||||||
shell: pwsh
|
|
||||||
|
|
||||||
- name: Create release package
|
|
||||||
run: |
|
|
||||||
# Create release directory
|
|
||||||
New-Item -ItemType Directory -Force -Path release
|
|
||||||
|
|
||||||
# Copy binaries
|
|
||||||
Copy-Item cmd/analyze/analyze.exe release/
|
|
||||||
Copy-Item cmd/status/status.exe release/
|
|
||||||
|
|
||||||
# Copy PowerShell scripts
|
|
||||||
Copy-Item mole.ps1 release/
|
|
||||||
Copy-Item install.ps1 release/
|
|
||||||
Copy-Item -Recurse bin release/
|
|
||||||
Copy-Item -Recurse lib release/
|
|
||||||
|
|
||||||
# Copy docs
|
|
||||||
Copy-Item README.md release/
|
|
||||||
Copy-Item LICENSE release/
|
|
||||||
|
|
||||||
# Create zip
|
|
||||||
Compress-Archive -Path release/* -DestinationPath mole-windows.zip
|
|
||||||
shell: pwsh
|
|
||||||
|
|
||||||
- name: Upload artifacts
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: windows-release
|
|
||||||
path: mole-windows.zip
|
|
||||||
retention-days: 5
|
|
||||||
|
|
||||||
release:
|
|
||||||
name: Publish Release
|
|
||||||
needs: build
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Download artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: windows-release
|
|
||||||
|
|
||||||
- name: Display downloaded files
|
|
||||||
run: ls -la
|
|
||||||
|
|
||||||
- name: Create Release
|
|
||||||
uses: softprops/action-gh-release@v2
|
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
|
||||||
with:
|
|
||||||
files: mole-windows.zip
|
|
||||||
generate_release_notes: true
|
|
||||||
draft: false
|
|
||||||
prerelease: false
|
|
||||||
name: "Mole for Windows ${{ github.ref_name }}"
|
|
||||||
body: |
|
|
||||||
## Mole for Windows
|
|
||||||
|
|
||||||
Windows port of the Mole system maintenance toolkit.
|
|
||||||
|
|
||||||
### Installation
|
|
||||||
|
|
||||||
**Quick install:**
|
|
||||||
```powershell
|
|
||||||
irm https://raw.githubusercontent.com/tw93/Mole/windows/install.ps1 | iex
|
|
||||||
```
|
|
||||||
|
|
||||||
**Manual install:**
|
|
||||||
1. Download and extract `mole-windows.zip`
|
|
||||||
2. Run `install.ps1`
|
|
||||||
|
|
||||||
### Features
|
|
||||||
- Deep system cleanup (temp files, caches, logs)
|
|
||||||
- Smart app uninstaller with leftover detection
|
|
||||||
- Disk space analyzer (TUI)
|
|
||||||
- System status monitor (TUI)
|
|
||||||
- Developer artifact cleanup
|
|
||||||
- System optimization
|
|
||||||
10
.github/workflows/test.yml
vendored
10
.github/workflows/test.yml
vendored
@@ -54,21 +54,19 @@ jobs:
|
|||||||
|
|
||||||
- name: Build Go binaries
|
- name: Build Go binaries
|
||||||
run: |
|
run: |
|
||||||
cd cmd/analyze
|
go build -o bin/analyze.exe ./cmd/analyze/
|
||||||
go build -o analyze.exe .
|
go build -o bin/status.exe ./cmd/status/
|
||||||
cd ../status
|
|
||||||
go build -o status.exe .
|
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
|
|
||||||
- name: Verify binaries
|
- name: Verify binaries
|
||||||
run: |
|
run: |
|
||||||
if (Test-Path cmd/analyze/analyze.exe) {
|
if (Test-Path bin/analyze.exe) {
|
||||||
Write-Host "analyze.exe built successfully"
|
Write-Host "analyze.exe built successfully"
|
||||||
} else {
|
} else {
|
||||||
Write-Host "Failed to build analyze.exe"
|
Write-Host "Failed to build analyze.exe"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
if (Test-Path cmd/status/status.exe) {
|
if (Test-Path bin/status.exe) {
|
||||||
Write-Host "status.exe built successfully"
|
Write-Host "status.exe built successfully"
|
||||||
} else {
|
} else {
|
||||||
Write-Host "Failed to build status.exe"
|
Write-Host "Failed to build status.exe"
|
||||||
|
|||||||
196
.github/workflows/windows.yml
vendored
196
.github/workflows/windows.yml
vendored
@@ -1,196 +0,0 @@
|
|||||||
name: Windows CI
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main, dev]
|
|
||||||
paths:
|
|
||||||
- 'windows/**'
|
|
||||||
- '.github/workflows/windows.yml'
|
|
||||||
pull_request:
|
|
||||||
branches: [main, dev]
|
|
||||||
paths:
|
|
||||||
- 'windows/**'
|
|
||||||
- '.github/workflows/windows.yml'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
name: Build & Test
|
|
||||||
runs-on: windows-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up Go
|
|
||||||
uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version: "1.24"
|
|
||||||
cache-dependency-path: windows/go.sum
|
|
||||||
|
|
||||||
- name: Build Go binaries
|
|
||||||
working-directory: windows
|
|
||||||
run: |
|
|
||||||
go build -o bin/analyze.exe ./cmd/analyze/
|
|
||||||
go build -o bin/status.exe ./cmd/status/
|
|
||||||
|
|
||||||
- name: Run Go tests
|
|
||||||
working-directory: windows
|
|
||||||
run: go test -v ./...
|
|
||||||
|
|
||||||
- name: Validate PowerShell syntax
|
|
||||||
shell: pwsh
|
|
||||||
run: |
|
|
||||||
$scripts = Get-ChildItem -Path windows -Filter "*.ps1" -Recurse
|
|
||||||
$errors = @()
|
|
||||||
foreach ($script in $scripts) {
|
|
||||||
$parseErrors = $null
|
|
||||||
$null = [System.Management.Automation.Language.Parser]::ParseFile(
|
|
||||||
$script.FullName,
|
|
||||||
[ref]$null,
|
|
||||||
[ref]$parseErrors
|
|
||||||
)
|
|
||||||
if ($parseErrors) {
|
|
||||||
Write-Host "ERROR: $($script.FullName)" -ForegroundColor Red
|
|
||||||
foreach ($err in $parseErrors) {
|
|
||||||
Write-Host " $($err.Message)" -ForegroundColor Red
|
|
||||||
}
|
|
||||||
$errors += $script.FullName
|
|
||||||
} else {
|
|
||||||
Write-Host "OK: $($script.Name)" -ForegroundColor Green
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($errors.Count -gt 0) {
|
|
||||||
Write-Host "`n$($errors.Count) script(s) have syntax errors!" -ForegroundColor Red
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
pester:
|
|
||||||
name: Pester Tests
|
|
||||||
runs-on: windows-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install Pester
|
|
||||||
shell: pwsh
|
|
||||||
run: |
|
|
||||||
Set-PSRepository -Name PSGallery -InstallationPolicy Trusted
|
|
||||||
Install-Module -Name Pester -MinimumVersion 5.0.0 -Force -SkipPublisherCheck
|
|
||||||
|
|
||||||
- name: Run Pester tests
|
|
||||||
shell: pwsh
|
|
||||||
run: |
|
|
||||||
Import-Module Pester -MinimumVersion 5.0.0
|
|
||||||
|
|
||||||
$config = New-PesterConfiguration
|
|
||||||
$config.Run.Path = "windows/tests"
|
|
||||||
$config.Run.Exit = $true
|
|
||||||
$config.Output.Verbosity = "Detailed"
|
|
||||||
$config.TestResult.Enabled = $true
|
|
||||||
$config.TestResult.OutputPath = "windows/test-results.xml"
|
|
||||||
$config.TestResult.OutputFormat = "NUnitXml"
|
|
||||||
|
|
||||||
Invoke-Pester -Configuration $config
|
|
||||||
|
|
||||||
- name: Upload test results
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
if: always()
|
|
||||||
with:
|
|
||||||
name: pester-results
|
|
||||||
path: windows/test-results.xml
|
|
||||||
|
|
||||||
compatibility:
|
|
||||||
name: Windows Compatibility
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
os: [windows-2022, windows-2019]
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Test PowerShell 5.1
|
|
||||||
shell: powershell
|
|
||||||
run: |
|
|
||||||
Write-Host "Testing on ${{ matrix.os }} with PowerShell $($PSVersionTable.PSVersion)"
|
|
||||||
|
|
||||||
# Test main entry point
|
|
||||||
$result = & powershell -ExecutionPolicy Bypass -File "windows\mole.ps1" -ShowHelp 2>&1
|
|
||||||
if ($LASTEXITCODE -ne 0) {
|
|
||||||
Write-Host "mole.ps1 -ShowHelp failed" -ForegroundColor Red
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
Write-Host "✓ mole.ps1 works on ${{ matrix.os }}"
|
|
||||||
|
|
||||||
- name: Test command scripts
|
|
||||||
shell: powershell
|
|
||||||
run: |
|
|
||||||
$commands = @("clean", "uninstall", "optimize", "purge", "analyze", "status")
|
|
||||||
foreach ($cmd in $commands) {
|
|
||||||
$scriptPath = "windows\bin\$cmd.ps1"
|
|
||||||
if (Test-Path $scriptPath) {
|
|
||||||
$result = & powershell -ExecutionPolicy Bypass -File $scriptPath -ShowHelp 2>&1
|
|
||||||
if ($LASTEXITCODE -ne 0) {
|
|
||||||
Write-Host "✗ $cmd.ps1 failed" -ForegroundColor Red
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
Write-Host "✓ $cmd.ps1 works"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
security:
|
|
||||||
name: Security Checks
|
|
||||||
runs-on: windows-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Check for unsafe patterns
|
|
||||||
shell: pwsh
|
|
||||||
run: |
|
|
||||||
Write-Host "Checking for unsafe removal patterns..."
|
|
||||||
|
|
||||||
$unsafePatterns = @(
|
|
||||||
"Remove-Item.*-Recurse.*-Force.*\\\$env:SystemRoot",
|
|
||||||
"Remove-Item.*-Recurse.*-Force.*C:\\Windows",
|
|
||||||
"Remove-Item.*-Recurse.*-Force.*C:\\Program Files"
|
|
||||||
)
|
|
||||||
|
|
||||||
$files = Get-ChildItem -Path windows -Filter "*.ps1" -Recurse
|
|
||||||
$issues = @()
|
|
||||||
|
|
||||||
foreach ($file in $files) {
|
|
||||||
$content = Get-Content $file.FullName -Raw
|
|
||||||
foreach ($pattern in $unsafePatterns) {
|
|
||||||
if ($content -match $pattern) {
|
|
||||||
$issues += "$($file.Name): matches unsafe pattern"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($issues.Count -gt 0) {
|
|
||||||
Write-Host "Unsafe patterns found:" -ForegroundColor Red
|
|
||||||
$issues | ForEach-Object { Write-Host " $_" -ForegroundColor Red }
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Host "✓ No unsafe patterns found" -ForegroundColor Green
|
|
||||||
|
|
||||||
- name: Verify protection checks
|
|
||||||
shell: pwsh
|
|
||||||
run: |
|
|
||||||
Write-Host "Verifying protection logic..."
|
|
||||||
|
|
||||||
# Source file_ops to get Test-IsProtectedPath
|
|
||||||
. windows\lib\core\base.ps1
|
|
||||||
. windows\lib\core\file_ops.ps1
|
|
||||||
|
|
||||||
$protectedPaths = @(
|
|
||||||
"C:\Windows",
|
|
||||||
"C:\Windows\System32",
|
|
||||||
"C:\Program Files",
|
|
||||||
"C:\Program Files (x86)"
|
|
||||||
)
|
|
||||||
|
|
||||||
foreach ($path in $protectedPaths) {
|
|
||||||
if (-not (Test-ProtectedPath -Path $path)) {
|
|
||||||
Write-Host "✗ $path should be protected!" -ForegroundColor Red
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
Write-Host "✓ $path is protected" -ForegroundColor Green
|
|
||||||
}
|
|
||||||
83
.gitignore
vendored
83
.gitignore
vendored
@@ -1,21 +1,86 @@
|
|||||||
# Windows Mole - .gitignore
|
# Windows Mole - .gitignore
|
||||||
|
|
||||||
# Build artifacts
|
# OS files
|
||||||
bin/*.exe
|
.DS_Store
|
||||||
|
.DS_Store?
|
||||||
|
._*
|
||||||
|
.Spotlight-V100
|
||||||
|
.Trashes
|
||||||
|
ehthumbs.db
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
# Go build cache
|
# Editor files
|
||||||
.gocache/
|
*~
|
||||||
|
*.swp
|
||||||
# IDE files
|
*.swo
|
||||||
.idea/
|
.idea/
|
||||||
.vscode/
|
.vscode/
|
||||||
*.code-workspace
|
*.code-workspace
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
*.log
|
||||||
|
logs/
|
||||||
|
|
||||||
|
# Temporary files
|
||||||
|
tmp/
|
||||||
|
temp/
|
||||||
|
*.tmp
|
||||||
|
*.temp
|
||||||
|
|
||||||
|
# Cache
|
||||||
|
.cache/
|
||||||
|
*.cache
|
||||||
|
.gocache/
|
||||||
|
.gomod/
|
||||||
|
|
||||||
|
# Backup files
|
||||||
|
*.bak
|
||||||
|
*.backup
|
||||||
|
|
||||||
|
# System files
|
||||||
|
*.pid
|
||||||
|
*.lock
|
||||||
|
|
||||||
|
# AI / local assistant files
|
||||||
|
.agents/
|
||||||
|
.claude/
|
||||||
|
.gemini/
|
||||||
|
.kiro/
|
||||||
|
ANTIGRAVITY.md
|
||||||
|
AGENTS.md
|
||||||
|
CLAUDE.md
|
||||||
|
GEMINI.md
|
||||||
|
WARP.md
|
||||||
|
.cursorrules
|
||||||
|
cmd/AGENTS.md
|
||||||
|
lib/AGENTS.md
|
||||||
|
tests/AGENTS.md
|
||||||
|
|
||||||
|
# Build artifacts
|
||||||
|
bin/*.exe
|
||||||
|
cmd/analyze/*.exe
|
||||||
|
cmd/status/*.exe
|
||||||
|
release/
|
||||||
|
mole-windows.zip
|
||||||
|
mole-*-x64.zip
|
||||||
|
mole-*-x64.exe
|
||||||
|
mole-*-x64.msi
|
||||||
|
SHA256SUMS.txt
|
||||||
|
|
||||||
# Test artifacts
|
# Test artifacts
|
||||||
*.test
|
*.test
|
||||||
|
*.out
|
||||||
coverage.out
|
coverage.out
|
||||||
|
coverage.html
|
||||||
|
coverage-go.out
|
||||||
|
coverage-pester.xml
|
||||||
|
test-results.xml
|
||||||
|
tests/tmp-*/
|
||||||
|
tests/*.tmp
|
||||||
|
tests/*.log
|
||||||
|
|
||||||
# Main branch specific files
|
# Branch-specific local notes
|
||||||
ANTIGRAVITY.md
|
|
||||||
CLAUDE.md
|
|
||||||
windows-readme-update.md
|
windows-readme-update.md
|
||||||
|
mole_guidelines.md
|
||||||
|
run_tests.ps1
|
||||||
|
session.json
|
||||||
|
|||||||
88
README.md
88
README.md
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://github.com/tw93/mole/stargazers"><img src="https://img.shields.io/github/stars/tw93/mole?style=flat-square" alt="Stars"></a>
|
<a href="https://github.com/tw93/mole/stargazers"><img src="https://img.shields.io/github/stars/tw93/mole?style=flat-square" alt="Stars"></a>
|
||||||
<a href="https://github.com/tw93/mole/releases"><img src="https://img.shields.io/github/v/tag/tw93/mole?label=version&style=flat-square" alt="Version"></a>
|
<img src="https://img.shields.io/badge/channel-windows%20source-orange?style=flat-square" alt="Channel">
|
||||||
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square" alt="License"></a>
|
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square" alt="License"></a>
|
||||||
<a href="https://github.com/tw93/mole/commits"><img src="https://img.shields.io/github/commit-activity/m/tw93/mole?style=flat-square" alt="Commits"></a>
|
<a href="https://github.com/tw93/mole/commits"><img src="https://img.shields.io/github/commit-activity/m/tw93/mole?style=flat-square" alt="Commits"></a>
|
||||||
<a href="https://twitter.com/HiTw93"><img src="https://img.shields.io/badge/follow-Tw93-red?style=flat-square&logo=Twitter" alt="Twitter"></a>
|
<a href="https://twitter.com/HiTw93"><img src="https://img.shields.io/badge/follow-Tw93-red?style=flat-square&logo=Twitter" alt="Twitter"></a>
|
||||||
@@ -23,6 +23,7 @@
|
|||||||
- **Smart uninstaller**: Thoroughly removes apps along with AppData, preferences, and hidden remnants
|
- **Smart uninstaller**: Thoroughly removes apps along with AppData, preferences, and hidden remnants
|
||||||
- **Disk insights**: Visualizes usage, manages large files, and refreshes system services
|
- **Disk insights**: Visualizes usage, manages large files, and refreshes system services
|
||||||
- **Live monitoring**: Real-time stats for CPU, memory, disk, and network to diagnose performance issues
|
- **Live monitoring**: Real-time stats for CPU, memory, disk, and network to diagnose performance issues
|
||||||
|
- **Source channel updates**: Install from the `windows` branch and refresh to the latest source with `mo update`
|
||||||
|
|
||||||
## Platform Support
|
## Platform Support
|
||||||
|
|
||||||
@@ -32,7 +33,8 @@ Mole is designed for Windows 10/11. This is the native Windows version ported fr
|
|||||||
|
|
||||||
- Windows 10/11
|
- Windows 10/11
|
||||||
- PowerShell 5.1 or later (pre-installed on Windows 10/11)
|
- PowerShell 5.1 or later (pre-installed on Windows 10/11)
|
||||||
- Go 1.24+ (for building TUI tools)
|
- Git (required for source-channel install and `mo update`)
|
||||||
|
- Go 1.24+ (optional, only needed when building TUI tools locally)
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
@@ -44,25 +46,23 @@ Mole is designed for Windows 10/11. This is the native Windows version ported fr
|
|||||||
iwr -useb https://raw.githubusercontent.com/tw93/Mole/windows/quick-install.ps1 | iex
|
iwr -useb https://raw.githubusercontent.com/tw93/Mole/windows/quick-install.ps1 | iex
|
||||||
```
|
```
|
||||||
|
|
||||||
This will automatically download and install Mole with PATH configuration.
|
This will clone the latest `windows` branch into your install directory and configure PATH.
|
||||||
|
|
||||||
### Manual Installation
|
### Manual Installation
|
||||||
|
|
||||||
If you prefer to review the code first or customize the installation:
|
If you prefer to review the code first or customize the installation:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Clone the repository
|
# Clone the windows branch into your install directory
|
||||||
git clone https://github.com/tw93/Mole.git
|
$installDir = "$env:LOCALAPPDATA\Mole"
|
||||||
cd Mole
|
git clone --branch windows https://github.com/tw93/Mole.git $installDir
|
||||||
|
cd $installDir
|
||||||
|
|
||||||
# Switch to windows branch
|
# Run the installer in place (keeps .git for mo update)
|
||||||
git checkout windows
|
.\install.ps1 -InstallDir $installDir -AddToPath
|
||||||
|
|
||||||
# Run the installer
|
|
||||||
.\install.ps1 -AddToPath
|
|
||||||
|
|
||||||
# Optional: Create Start Menu shortcut
|
# Optional: Create Start Menu shortcut
|
||||||
.\install.ps1 -AddToPath -CreateShortcut
|
.\install.ps1 -InstallDir $installDir -AddToPath -CreateShortcut
|
||||||
```
|
```
|
||||||
|
|
||||||
Run:
|
Run:
|
||||||
@@ -74,6 +74,8 @@ mo uninstall # Remove apps + leftovers
|
|||||||
mo optimize # Refresh caches & services
|
mo optimize # Refresh caches & services
|
||||||
mo analyze # Visual disk explorer
|
mo analyze # Visual disk explorer
|
||||||
mo status # Live system health dashboard
|
mo status # Live system health dashboard
|
||||||
|
mo update # Pull the latest windows source
|
||||||
|
mo remove # Remove Mole from this system
|
||||||
mo purge # Clean project build artifacts
|
mo purge # Clean project build artifacts
|
||||||
|
|
||||||
mo --help # Show help
|
mo --help # Show help
|
||||||
@@ -88,6 +90,38 @@ mo optimize --debug # Run with detailed operation logs
|
|||||||
mo purge --paths # Configure project scan directories
|
mo purge --paths # Configure project scan directories
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Source-channel installs can later be refreshed with:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
mo update
|
||||||
|
```
|
||||||
|
|
||||||
|
If a matching Windows prerelease exists for the installed version, Mole will reuse/download prebuilt `analyze` and `status` binaries before falling back to a local Go build.
|
||||||
|
|
||||||
|
## macOS Parity
|
||||||
|
|
||||||
|
Windows is closest to macOS on these commands:
|
||||||
|
|
||||||
|
- `clean`
|
||||||
|
- `uninstall`
|
||||||
|
- `optimize`
|
||||||
|
- `analyze`
|
||||||
|
- `status`
|
||||||
|
- `purge`
|
||||||
|
- `update`
|
||||||
|
- `remove`
|
||||||
|
|
||||||
|
Still missing or intentionally platform-specific compared with `main`:
|
||||||
|
|
||||||
|
- `installer`: no dedicated Windows installer-file cleanup command yet
|
||||||
|
- `completion`: no PowerShell completion setup command yet
|
||||||
|
- `touchid`: macOS-only, not applicable on Windows
|
||||||
|
- Release channels: Windows currently uses a git source channel, not Homebrew/stable release installs
|
||||||
|
- Update options: `mo update --nightly` is not implemented on Windows
|
||||||
|
- Optimization controls: `mo optimize --whitelist` is not implemented on Windows
|
||||||
|
- Some UI depth: macOS `status` and `analyze` expose richer device-specific details than Windows today
|
||||||
|
- Windows prereleases use `Vx.y.z-windows` tags so they stay isolated from the macOS stable release channel
|
||||||
|
|
||||||
## Tips
|
## Tips
|
||||||
|
|
||||||
- **Safety**: Built with strict protections. Preview changes with `mo clean --dry-run`.
|
- **Safety**: Built with strict protections. Preview changes with `mo clean --dry-run`.
|
||||||
@@ -245,14 +279,14 @@ Custom scan paths can be configured with `mo purge --paths`.
|
|||||||
### Manual Installation
|
### Manual Installation
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Install to custom location
|
# Install to custom location from a cloned windows branch
|
||||||
.\install.ps1 -InstallDir C:\Tools\Mole -AddToPath
|
.\install.ps1 -InstallDir C:\Tools\Mole -AddToPath
|
||||||
|
|
||||||
# Create Start Menu shortcut
|
# Create Start Menu shortcut
|
||||||
.\install.ps1 -AddToPath -CreateShortcut
|
.\install.ps1 -InstallDir C:\Tools\Mole -AddToPath -CreateShortcut
|
||||||
|
|
||||||
# Optional: Custom install location
|
# Refresh the source channel later
|
||||||
.\install.ps1 -InstallDir C:\Tools\Mole -AddToPath
|
mo update
|
||||||
```
|
```
|
||||||
|
|
||||||
### Uninstall
|
### Uninstall
|
||||||
@@ -280,12 +314,14 @@ mole/ (windows branch)
|
|||||||
├── go.mod # Go module definition
|
├── go.mod # Go module definition
|
||||||
├── go.sum # Go dependencies
|
├── go.sum # Go dependencies
|
||||||
├── bin/
|
├── bin/
|
||||||
301: │ ├── clean.ps1 # Deep cleanup orchestrator
|
│ ├── clean.ps1 # Deep cleanup orchestrator
|
||||||
302: │ ├── uninstall.ps1 # Interactive app uninstaller
|
│ ├── uninstall.ps1 # Interactive app uninstaller
|
||||||
303: │ ├── optimize.ps1 # System optimization
|
│ ├── optimize.ps1 # System optimization
|
||||||
304: │ ├── purge.ps1 # Project artifact cleanup
|
│ ├── purge.ps1 # Project artifact cleanup
|
||||||
305: │ ├── analyze.ps1 # Disk analyzer wrapper
|
│ ├── analyze.ps1 # Disk analyzer wrapper
|
||||||
306: │ └── status.ps1 # Status monitor wrapper
|
│ ├── status.ps1 # Status monitor wrapper
|
||||||
|
│ ├── update.ps1 # Source channel updater
|
||||||
|
│ └── remove.ps1 # Self-uninstall wrapper
|
||||||
├── cmd/
|
├── cmd/
|
||||||
│ ├── analyze/ # Disk analyzer (Go TUI)
|
│ ├── analyze/ # Disk analyzer (Go TUI)
|
||||||
│ │ └── main.go
|
│ │ └── main.go
|
||||||
@@ -297,6 +333,7 @@ mole/ (windows branch)
|
|||||||
│ ├── common.ps1 # Common functions loader
|
│ ├── common.ps1 # Common functions loader
|
||||||
│ ├── file_ops.ps1 # Safe file operations
|
│ ├── file_ops.ps1 # Safe file operations
|
||||||
│ ├── log.ps1 # Logging functions
|
│ ├── log.ps1 # Logging functions
|
||||||
|
│ ├── tui_binaries.ps1 # TUI binary restore/build helpers
|
||||||
│ └── ui.ps1 # Interactive UI components
|
│ └── ui.ps1 # Interactive UI components
|
||||||
└── clean/
|
└── clean/
|
||||||
├── user.ps1 # User cleanup (temp, downloads, etc.)
|
├── user.ps1 # User cleanup (temp, downloads, etc.)
|
||||||
@@ -308,7 +345,7 @@ mole/ (windows branch)
|
|||||||
|
|
||||||
## Building TUI Tools
|
## Building TUI Tools
|
||||||
|
|
||||||
The analyze and status commands require Go to be installed:
|
Install Go if you want to build the analyze and status tools locally:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# From the repository root
|
# From the repository root
|
||||||
@@ -320,7 +357,8 @@ make build
|
|||||||
go build -o bin/analyze.exe ./cmd/analyze/
|
go build -o bin/analyze.exe ./cmd/analyze/
|
||||||
go build -o bin/status.exe ./cmd/status/
|
go build -o bin/status.exe ./cmd/status/
|
||||||
|
|
||||||
# The wrapper scripts will auto-build if Go is available
|
# The wrapper scripts try bin/ first, then Windows prerelease assets,
|
||||||
|
# then auto-build if Go is available
|
||||||
```
|
```
|
||||||
|
|
||||||
## Support
|
## Support
|
||||||
@@ -351,6 +389,8 @@ go build -o bin/status.exe ./cmd/status/
|
|||||||
- [x] `cmd/status/` - Real-time system monitor (Go)
|
- [x] `cmd/status/` - Real-time system monitor (Go)
|
||||||
- [x] `bin/analyze.ps1` - Analyzer wrapper
|
- [x] `bin/analyze.ps1` - Analyzer wrapper
|
||||||
- [x] `bin/status.ps1` - Status wrapper
|
- [x] `bin/status.ps1` - Status wrapper
|
||||||
|
- [x] `bin/update.ps1` - Source channel updater
|
||||||
|
- [x] `bin/remove.ps1` - Self-uninstall wrapper
|
||||||
|
|
||||||
### Phase 4: Testing & CI (Planned)
|
### Phase 4: Testing & CI (Planned)
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ $ErrorActionPreference = "Stop"
|
|||||||
# Script location
|
# Script location
|
||||||
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||||
$windowsDir = Split-Path -Parent $scriptDir
|
$windowsDir = Split-Path -Parent $scriptDir
|
||||||
$binPath = Join-Path $windowsDir "bin\analyze.exe"
|
$defaultBinPath = Join-Path $windowsDir "bin\analyze.exe"
|
||||||
|
. (Join-Path $windowsDir "lib\core\tui_binaries.ps1")
|
||||||
|
|
||||||
# Help
|
# Help
|
||||||
function Show-AnalyzeHelp {
|
function Show-AnalyzeHelp {
|
||||||
@@ -47,29 +48,11 @@ if ($ShowHelp) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check if binary exists
|
$binPath = Ensure-TuiBinary -Name "analyze" -WindowsDir $windowsDir -DestinationPath $defaultBinPath -SourcePath "./cmd/analyze/"
|
||||||
if (-not (Test-Path $binPath)) {
|
if (-not $binPath) {
|
||||||
Write-Host "Building analyze tool..." -ForegroundColor Cyan
|
Write-Host "Analyze binary not found, no prerelease asset was available, and Go 1.24+ is not installed." -ForegroundColor Red
|
||||||
|
Write-Host "Install Go or wait for a Windows prerelease asset that includes analyze.exe." -ForegroundColor Yellow
|
||||||
$cmdDir = Join-Path $windowsDir "cmd\analyze"
|
exit 1
|
||||||
$binDir = Join-Path $windowsDir "bin"
|
|
||||||
|
|
||||||
if (-not (Test-Path $binDir)) {
|
|
||||||
New-Item -ItemType Directory -Path $binDir -Force | Out-Null
|
|
||||||
}
|
|
||||||
|
|
||||||
Push-Location $windowsDir
|
|
||||||
try {
|
|
||||||
$result = & go build -o "$binPath" "./cmd/analyze/" 2>&1
|
|
||||||
if ($LASTEXITCODE -ne 0) {
|
|
||||||
Write-Host "Failed to build analyze tool: $result" -ForegroundColor Red
|
|
||||||
Pop-Location
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
Pop-Location
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Set path environment variable if provided
|
# Set path environment variable if provided
|
||||||
|
|||||||
40
bin/remove.ps1
Normal file
40
bin/remove.ps1
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# Mole - Remove Command
|
||||||
|
# Removes Mole from the current installation directory.
|
||||||
|
|
||||||
|
#Requires -Version 5.1
|
||||||
|
param(
|
||||||
|
[Alias('h')]
|
||||||
|
[switch]$ShowHelp
|
||||||
|
)
|
||||||
|
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||||
|
$windowsDir = Split-Path -Parent $scriptDir
|
||||||
|
$installScript = Join-Path $windowsDir "install.ps1"
|
||||||
|
|
||||||
|
function Show-RemoveHelp {
|
||||||
|
$esc = [char]27
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "$esc[1;35mmo remove$esc[0m - Remove Mole from this system"
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "$esc[33mUsage:$esc[0m mo remove"
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "$esc[33mBehavior:$esc[0m"
|
||||||
|
Write-Host " - Removes the current Mole installation directory"
|
||||||
|
Write-Host " - Removes PATH entries created for this install"
|
||||||
|
Write-Host " - Prompts before deleting Mole config files"
|
||||||
|
Write-Host ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($ShowHelp) {
|
||||||
|
Show-RemoveHelp
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not (Test-Path $installScript)) {
|
||||||
|
Write-Host "Installer not found at: $installScript" -ForegroundColor Red
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
& $installScript -InstallDir $windowsDir -Uninstall
|
||||||
@@ -12,7 +12,8 @@ $ErrorActionPreference = "Stop"
|
|||||||
# Script location
|
# Script location
|
||||||
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||||
$windowsDir = Split-Path -Parent $scriptDir
|
$windowsDir = Split-Path -Parent $scriptDir
|
||||||
$binPath = Join-Path $windowsDir "bin\status.exe"
|
$defaultBinPath = Join-Path $windowsDir "bin\status.exe"
|
||||||
|
. (Join-Path $windowsDir "lib\core\tui_binaries.ps1")
|
||||||
|
|
||||||
# Help
|
# Help
|
||||||
function Show-StatusHelp {
|
function Show-StatusHelp {
|
||||||
@@ -45,29 +46,11 @@ if ($ShowHelp) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check if binary exists
|
$binPath = Ensure-TuiBinary -Name "status" -WindowsDir $windowsDir -DestinationPath $defaultBinPath -SourcePath "./cmd/status/"
|
||||||
if (-not (Test-Path $binPath)) {
|
if (-not $binPath) {
|
||||||
Write-Host "Building status tool..." -ForegroundColor Cyan
|
Write-Host "Status binary not found, no prerelease asset was available, and Go 1.24+ is not installed." -ForegroundColor Red
|
||||||
|
Write-Host "Install Go or wait for a Windows prerelease asset that includes status.exe." -ForegroundColor Yellow
|
||||||
$cmdDir = Join-Path $windowsDir "cmd\status"
|
exit 1
|
||||||
$binDir = Join-Path $windowsDir "bin"
|
|
||||||
|
|
||||||
if (-not (Test-Path $binDir)) {
|
|
||||||
New-Item -ItemType Directory -Path $binDir -Force | Out-Null
|
|
||||||
}
|
|
||||||
|
|
||||||
Push-Location $windowsDir
|
|
||||||
try {
|
|
||||||
$result = & go build -o "$binPath" "./cmd/status/" 2>&1
|
|
||||||
if ($LASTEXITCODE -ne 0) {
|
|
||||||
Write-Host "Failed to build status tool: $result" -ForegroundColor Red
|
|
||||||
Pop-Location
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
Pop-Location
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Run the binary
|
# Run the binary
|
||||||
|
|||||||
126
bin/update.ps1
Normal file
126
bin/update.ps1
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
# Mole - Update Command
|
||||||
|
# Updates a source-channel installation from the windows branch.
|
||||||
|
|
||||||
|
#Requires -Version 5.1
|
||||||
|
param(
|
||||||
|
[Alias('h')]
|
||||||
|
[switch]$ShowHelp
|
||||||
|
)
|
||||||
|
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||||
|
$windowsDir = Split-Path -Parent $scriptDir
|
||||||
|
$installScript = Join-Path $windowsDir "install.ps1"
|
||||||
|
$gitDir = Join-Path $windowsDir ".git"
|
||||||
|
|
||||||
|
function Show-UpdateHelp {
|
||||||
|
$esc = [char]27
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "$esc[1;35mmo update$esc[0m - Update the Windows source channel"
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "$esc[33mUsage:$esc[0m mo update"
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "$esc[33mBehavior:$esc[0m"
|
||||||
|
Write-Host " - Pulls the latest commit from origin/windows"
|
||||||
|
Write-Host " - Re-runs the local installer in-place"
|
||||||
|
Write-Host " - Rebuilds analyze/status if Go is available"
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "$esc[33mNotes:$esc[0m"
|
||||||
|
Write-Host " - Works only for git-based source installs"
|
||||||
|
Write-Host " - Legacy copied installs should be reinstalled with quick-install"
|
||||||
|
Write-Host ""
|
||||||
|
}
|
||||||
|
|
||||||
|
function Test-InstallDirOnUserPath {
|
||||||
|
param([string]$Path)
|
||||||
|
|
||||||
|
$currentPath = [Environment]::GetEnvironmentVariable("PATH", "User")
|
||||||
|
if (-not $currentPath) {
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
|
||||||
|
return $currentPath -split ";" | Where-Object { $_ -eq $Path }
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($ShowHelp) {
|
||||||
|
Show-UpdateHelp
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not (Get-Command git -ErrorAction SilentlyContinue)) {
|
||||||
|
Write-Host "Git is not installed. Install Git to use 'mo update'." -ForegroundColor Red
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not (Test-Path $installScript)) {
|
||||||
|
Write-Host "Installer not found at: $installScript" -ForegroundColor Red
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not (Test-Path $gitDir)) {
|
||||||
|
Write-Host "This installation is not a git-based source install." -ForegroundColor Red
|
||||||
|
Write-Host "Reinstall with quick-install to enable 'mo update'." -ForegroundColor Yellow
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$dirtyOutput = & git -C $windowsDir status --porcelain --untracked-files=no 2>&1
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
Write-Host "Failed to inspect git status: $dirtyOutput" -ForegroundColor Red
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($dirtyOutput) {
|
||||||
|
Write-Host "Local tracked changes detected in the installation directory." -ForegroundColor Red
|
||||||
|
Write-Host "Commit or discard them before running 'mo update'." -ForegroundColor Yellow
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$remote = (& git -C $windowsDir remote get-url origin 2>&1).Trim()
|
||||||
|
if ($LASTEXITCODE -ne 0 -or -not $remote) {
|
||||||
|
Write-Host "Git remote 'origin' is not configured for this install." -ForegroundColor Red
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$branch = (& git -C $windowsDir branch --show-current 2>&1).Trim()
|
||||||
|
if ($LASTEXITCODE -ne 0 -or -not $branch) {
|
||||||
|
$branch = "windows"
|
||||||
|
}
|
||||||
|
|
||||||
|
$before = (& git -C $windowsDir rev-parse --short HEAD 2>&1).Trim()
|
||||||
|
if ($LASTEXITCODE -ne 0 -or -not $before) {
|
||||||
|
Write-Host "Failed to read current revision." -ForegroundColor Red
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Updating source from $remote ($branch)..." -ForegroundColor Cyan
|
||||||
|
|
||||||
|
$pullOutput = & git -C $windowsDir pull --ff-only origin $branch 2>&1
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
Write-Host "Failed to update source: $pullOutput" -ForegroundColor Red
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$after = (& git -C $windowsDir rev-parse --short HEAD 2>&1).Trim()
|
||||||
|
if ($LASTEXITCODE -ne 0 -or -not $after) {
|
||||||
|
Write-Host "Updated source, but failed to read the new revision." -ForegroundColor Red
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($after -eq $before) {
|
||||||
|
Write-Host "Already up to date at $after." -ForegroundColor Green
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Host "Updated source: $before -> $after" -ForegroundColor Green
|
||||||
|
}
|
||||||
|
|
||||||
|
$installArgs = @(
|
||||||
|
"-InstallDir", $windowsDir
|
||||||
|
)
|
||||||
|
|
||||||
|
if (Test-InstallDirOnUserPath -Path $windowsDir) {
|
||||||
|
$installArgs += "-AddToPath"
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Refreshing local installation..." -ForegroundColor Cyan
|
||||||
|
& $installScript @installArgs
|
||||||
Binary file not shown.
55
install.ps1
55
install.ps1
@@ -39,6 +39,8 @@ $script:Colors = @{
|
|||||||
NC = "$($script:ESC)[0m"
|
NC = "$($script:ESC)[0m"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
. (Join-Path $script:SourceDir "lib\core\tui_binaries.ps1")
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Helpers
|
# Helpers
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
@@ -67,6 +69,21 @@ function Write-MoleError {
|
|||||||
Write-Host " $($c.Red)ERROR$($c.NC) $Message"
|
Write-Host " $($c.Red)ERROR$($c.NC) $Message"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Get-NormalizedPath {
|
||||||
|
param([string]$Path)
|
||||||
|
|
||||||
|
return [System.IO.Path]::GetFullPath($Path).TrimEnd('\', '/')
|
||||||
|
}
|
||||||
|
|
||||||
|
function Test-SamePath {
|
||||||
|
param(
|
||||||
|
[string]$PathA,
|
||||||
|
[string]$PathB
|
||||||
|
)
|
||||||
|
|
||||||
|
return (Get-NormalizedPath -Path $PathA) -eq (Get-NormalizedPath -Path $PathB)
|
||||||
|
}
|
||||||
|
|
||||||
function Show-Banner {
|
function Show-Banner {
|
||||||
$c = $script:Colors
|
$c = $script:Colors
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
@@ -227,12 +244,38 @@ function Remove-StartMenuShortcut {
|
|||||||
# Install
|
# Install
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
|
function Ensure-OptionalTuiTools {
|
||||||
|
param([string]$RootDir)
|
||||||
|
|
||||||
|
Write-Info "Ensuring optional TUI tools..."
|
||||||
|
|
||||||
|
$tools = @(
|
||||||
|
@{ Name = "analyze"; Output = "bin\analyze.exe"; Source = "./cmd/analyze/" },
|
||||||
|
@{ Name = "status"; Output = "bin\status.exe"; Source = "./cmd/status/" }
|
||||||
|
)
|
||||||
|
|
||||||
|
$version = Get-MoleVersionFromScriptFile -WindowsDir $RootDir
|
||||||
|
|
||||||
|
foreach ($tool in $tools) {
|
||||||
|
$destination = Join-Path $RootDir $tool.Output
|
||||||
|
$binPath = Ensure-TuiBinary -Name $tool.Name -WindowsDir $RootDir -DestinationPath $destination -SourcePath $tool.Source -Version $version
|
||||||
|
if ($binPath) {
|
||||||
|
Write-Success "Ready: $($tool.Name).exe"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-MoleWarning "Could not prepare $($tool.Name).exe. Install Go or wait for a Windows prerelease asset."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function Install-Mole {
|
function Install-Mole {
|
||||||
Write-Info "Installing Mole v$script:VERSION..."
|
Write-Info "Installing Mole v$script:VERSION..."
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
|
|
||||||
|
$inPlaceInstall = Test-SamePath -PathA $script:SourceDir -PathB $InstallDir
|
||||||
|
|
||||||
# Check if already installed
|
# Check if already installed
|
||||||
if ((Test-Path $InstallDir) -and -not $Force) {
|
if ((Test-Path $InstallDir) -and -not $Force -and -not $inPlaceInstall) {
|
||||||
Write-MoleError "Mole is already installed at: $InstallDir"
|
Write-MoleError "Mole is already installed at: $InstallDir"
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host " Use -Force to overwrite or -Uninstall to remove first"
|
Write-Host " Use -Force to overwrite or -Uninstall to remove first"
|
||||||
@@ -252,6 +295,10 @@ function Install-Mole {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($inPlaceInstall) {
|
||||||
|
Write-Info "Using in-place source installation in: $InstallDir"
|
||||||
|
}
|
||||||
|
else {
|
||||||
# Copy files
|
# Copy files
|
||||||
Write-Info "Copying files..."
|
Write-Info "Copying files..."
|
||||||
|
|
||||||
@@ -288,6 +335,7 @@ function Install-Mole {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# Create scripts and tests directories if they don't exist
|
# Create scripts and tests directories if they don't exist
|
||||||
$extraDirs = @("scripts", "tests")
|
$extraDirs = @("scripts", "tests")
|
||||||
@@ -298,6 +346,9 @@ function Install-Mole {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Write-Host ""
|
||||||
|
Ensure-OptionalTuiTools -RootDir $InstallDir
|
||||||
|
|
||||||
# Create launcher batch file for easier access
|
# Create launcher batch file for easier access
|
||||||
# Note: Store %~dp0 immediately to avoid issues with delayed expansion in the parse loop
|
# Note: Store %~dp0 immediately to avoid issues with delayed expansion in the parse loop
|
||||||
$batchContent = @"
|
$batchContent = @"
|
||||||
@@ -355,6 +406,8 @@ powershell.exe -ExecutionPolicy Bypass -NoLogo -NoProfile -Command "& '%MOLE_DIR
|
|||||||
Write-Host " .\install.ps1 -AddToPath"
|
Write-Host " .\install.ps1 -AddToPath"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host " Run 'mo update' to pull the latest source from the windows branch"
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
return $true
|
return $true
|
||||||
}
|
}
|
||||||
|
|||||||
184
lib/core/tui_binaries.ps1
Normal file
184
lib/core/tui_binaries.ps1
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
# Mole - TUI binary helper
|
||||||
|
# Resolves, downloads, or builds analyze/status executables on Windows.
|
||||||
|
|
||||||
|
#Requires -Version 5.1
|
||||||
|
Set-StrictMode -Version Latest
|
||||||
|
|
||||||
|
if ((Get-Variable -Name 'MOLE_TUI_BINARIES_LOADED' -Scope Script -ErrorAction SilentlyContinue) -and $script:MOLE_TUI_BINARIES_LOADED) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
$script:MOLE_TUI_BINARIES_LOADED = $true
|
||||||
|
|
||||||
|
$script:MoleGitHubRepo = "tw93/Mole"
|
||||||
|
$script:MoleGitHubApiRoot = "https://api.github.com/repos/$($script:MoleGitHubRepo)"
|
||||||
|
$script:MoleGitHubHeaders = @{
|
||||||
|
"User-Agent" = "Mole-Windows"
|
||||||
|
"Accept" = "application/vnd.github+json"
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-MoleVersionFromScriptFile {
|
||||||
|
param([string]$WindowsDir)
|
||||||
|
|
||||||
|
$moleScript = Join-Path $WindowsDir "mole.ps1"
|
||||||
|
if (-not (Test-Path $moleScript)) {
|
||||||
|
return $null
|
||||||
|
}
|
||||||
|
|
||||||
|
$content = Get-Content $moleScript -Raw
|
||||||
|
if ($content -match '\$script:MOLE_VER\s*=\s*"([^"]+)"') {
|
||||||
|
return $Matches[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
return $null
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-TuiBinaryAssetName {
|
||||||
|
param([string]$Name)
|
||||||
|
|
||||||
|
return "$Name-windows-x64.exe"
|
||||||
|
}
|
||||||
|
|
||||||
|
function Resolve-TuiBinaryPath {
|
||||||
|
param(
|
||||||
|
[string]$WindowsDir,
|
||||||
|
[string]$Name
|
||||||
|
)
|
||||||
|
|
||||||
|
$candidates = @(
|
||||||
|
(Join-Path $WindowsDir "bin\$Name.exe"),
|
||||||
|
(Join-Path $WindowsDir "$Name.exe")
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach ($candidate in $candidates) {
|
||||||
|
if (Test-Path $candidate) {
|
||||||
|
return $candidate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $null
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-WindowsPrereleaseReleaseInfo {
|
||||||
|
param([string]$Version)
|
||||||
|
|
||||||
|
if (-not $Version) {
|
||||||
|
return $null
|
||||||
|
}
|
||||||
|
|
||||||
|
$tagCandidates = @(
|
||||||
|
"V$Version-windows",
|
||||||
|
"v$Version-windows"
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach ($tag in $tagCandidates) {
|
||||||
|
$uri = "$($script:MoleGitHubApiRoot)/releases/tags/$tag"
|
||||||
|
try {
|
||||||
|
return Invoke-RestMethod -Uri $uri -Headers $script:MoleGitHubHeaders -Method Get
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $null
|
||||||
|
}
|
||||||
|
|
||||||
|
function Restore-PrebuiltTuiBinary {
|
||||||
|
param(
|
||||||
|
[string]$Name,
|
||||||
|
[string]$WindowsDir,
|
||||||
|
[string]$DestinationPath,
|
||||||
|
[string]$Version
|
||||||
|
)
|
||||||
|
|
||||||
|
$releaseInfo = Get-WindowsPrereleaseReleaseInfo -Version $Version
|
||||||
|
if (-not $releaseInfo) {
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
|
||||||
|
$assetName = Get-TuiBinaryAssetName -Name $Name
|
||||||
|
$asset = $releaseInfo.assets | Where-Object { $_.name -eq $assetName } | Select-Object -First 1
|
||||||
|
if (-not $asset) {
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
|
||||||
|
$binDir = Split-Path -Parent $DestinationPath
|
||||||
|
if (-not (Test-Path $binDir)) {
|
||||||
|
New-Item -ItemType Directory -Path $binDir -Force | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Downloading prebuilt $Name tool..." -ForegroundColor Cyan
|
||||||
|
|
||||||
|
try {
|
||||||
|
Invoke-WebRequest -Uri $asset.browser_download_url -Headers $script:MoleGitHubHeaders -OutFile $DestinationPath -UseBasicParsing
|
||||||
|
return (Test-Path $DestinationPath)
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
if (Test-Path $DestinationPath) {
|
||||||
|
Remove-Item $DestinationPath -Force -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Build-TuiBinary {
|
||||||
|
param(
|
||||||
|
[string]$Name,
|
||||||
|
[string]$WindowsDir,
|
||||||
|
[string]$DestinationPath,
|
||||||
|
[string]$SourcePath
|
||||||
|
)
|
||||||
|
|
||||||
|
$binDir = Split-Path -Parent $DestinationPath
|
||||||
|
if (-not (Test-Path $binDir)) {
|
||||||
|
New-Item -ItemType Directory -Path $binDir -Force | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Building $Name tool..." -ForegroundColor Cyan
|
||||||
|
|
||||||
|
Push-Location $WindowsDir
|
||||||
|
try {
|
||||||
|
$result = & go build -o "$DestinationPath" $SourcePath 2>&1
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
Write-Host "Failed to build $Name tool: $result" -ForegroundColor Red
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
Pop-Location
|
||||||
|
}
|
||||||
|
|
||||||
|
return $true
|
||||||
|
}
|
||||||
|
|
||||||
|
function Ensure-TuiBinary {
|
||||||
|
param(
|
||||||
|
[string]$Name,
|
||||||
|
[string]$WindowsDir,
|
||||||
|
[string]$DestinationPath,
|
||||||
|
[string]$SourcePath,
|
||||||
|
[string]$Version
|
||||||
|
)
|
||||||
|
|
||||||
|
$existingBin = Resolve-TuiBinaryPath -WindowsDir $WindowsDir -Name $Name
|
||||||
|
if ($existingBin) {
|
||||||
|
return $existingBin
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not $Version) {
|
||||||
|
$Version = Get-MoleVersionFromScriptFile -WindowsDir $WindowsDir
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Restore-PrebuiltTuiBinary -Name $Name -WindowsDir $WindowsDir -DestinationPath $DestinationPath -Version $Version) {
|
||||||
|
return $DestinationPath
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Get-Command go -ErrorAction SilentlyContinue) {
|
||||||
|
if (Build-TuiBinary -Name $Name -WindowsDir $WindowsDir -DestinationPath $DestinationPath -SourcePath $SourcePath) {
|
||||||
|
return $DestinationPath
|
||||||
|
}
|
||||||
|
return $null
|
||||||
|
}
|
||||||
|
|
||||||
|
return $null
|
||||||
|
}
|
||||||
24
mole.ps1
24
mole.ps1
@@ -65,6 +65,8 @@ function Show-MainHelp {
|
|||||||
Write-Host " ${cyan}optimize${nc} System optimization and repairs"
|
Write-Host " ${cyan}optimize${nc} System optimization and repairs"
|
||||||
Write-Host " ${cyan}analyze${nc} Disk space analyzer"
|
Write-Host " ${cyan}analyze${nc} Disk space analyzer"
|
||||||
Write-Host " ${cyan}status${nc} System monitor"
|
Write-Host " ${cyan}status${nc} System monitor"
|
||||||
|
Write-Host " ${cyan}update${nc} Update the source channel"
|
||||||
|
Write-Host " ${cyan}remove${nc} Remove Mole from this system"
|
||||||
Write-Host " ${cyan}purge${nc} Clean project artifacts"
|
Write-Host " ${cyan}purge${nc} Clean project artifacts"
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host " ${green}OPTIONS:${nc}"
|
Write-Host " ${green}OPTIONS:${nc}"
|
||||||
@@ -80,15 +82,11 @@ function Show-MainHelp {
|
|||||||
Write-Host " ${gray}mo uninstall${nc} ${gray}# Uninstall apps${nc}"
|
Write-Host " ${gray}mo uninstall${nc} ${gray}# Uninstall apps${nc}"
|
||||||
Write-Host " ${gray}mo analyze${nc} ${gray}# Disk analyzer${nc}"
|
Write-Host " ${gray}mo analyze${nc} ${gray}# Disk analyzer${nc}"
|
||||||
Write-Host " ${gray}mo status${nc} ${gray}# System monitor${nc}"
|
Write-Host " ${gray}mo status${nc} ${gray}# System monitor${nc}"
|
||||||
|
Write-Host " ${gray}mo update${nc} ${gray}# Pull latest windows source${nc}"
|
||||||
|
Write-Host " ${gray}mo remove${nc} ${gray}# Remove Mole from this system${nc}"
|
||||||
Write-Host " ${gray}mo optimize${nc} ${gray}# Optimize system (includes repairs)${nc}"
|
Write-Host " ${gray}mo optimize${nc} ${gray}# Optimize system (includes repairs)${nc}"
|
||||||
Write-Host " ${gray}mo optimize --dry-run${nc} ${gray}# Preview optimizations${nc}"
|
Write-Host " ${gray}mo optimize --dry-run${nc} ${gray}# Preview optimizations${nc}"
|
||||||
Write-Host " ${gray}mo purge${nc} ${gray}# Clean dev artifacts${nc}"
|
Write-Host " ${gray}mo purge${nc} ${gray}# Clean dev artifacts${nc}"
|
||||||
Write-Host " ${gray}mo${nc} ${gray}# Interactive menu${nc}"
|
|
||||||
Write-Host " ${gray}mo clean${nc} ${gray}# Deep cleanup${nc}"
|
|
||||||
Write-Host " ${gray}mo clean --dry-run${nc} ${gray}# Preview cleanup${nc}"
|
|
||||||
Write-Host " ${gray}mo optimize${nc} ${gray}# Optimize system${nc}"
|
|
||||||
Write-Host " ${gray}mo optimize --dry-run${nc} ${gray}# Preview optimization${nc}"
|
|
||||||
Write-Host " ${gray}mo uninstall${nc} ${gray}# Uninstall apps${nc}"
|
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host " ${green}ENVIRONMENT:${nc}"
|
Write-Host " ${green}ENVIRONMENT:${nc}"
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
@@ -135,6 +133,18 @@ function Show-MainMenu {
|
|||||||
Command = "status"
|
Command = "status"
|
||||||
Icon = $script:Icons.Solid
|
Icon = $script:Icons.Solid
|
||||||
}
|
}
|
||||||
|
@{
|
||||||
|
Name = "Update"
|
||||||
|
Description = "Pull latest source"
|
||||||
|
Command = "update"
|
||||||
|
Icon = $script:Icons.Arrow
|
||||||
|
}
|
||||||
|
@{
|
||||||
|
Name = "Remove"
|
||||||
|
Description = "Uninstall Mole"
|
||||||
|
Command = "remove"
|
||||||
|
Icon = $script:Icons.Trash
|
||||||
|
}
|
||||||
@{
|
@{
|
||||||
Name = "Purge"
|
Name = "Purge"
|
||||||
Description = "Clean dev artifacts"
|
Description = "Clean dev artifacts"
|
||||||
@@ -273,7 +283,7 @@ function Main {
|
|||||||
|
|
||||||
# If command specified, route to it
|
# If command specified, route to it
|
||||||
if ($effectiveCommand) {
|
if ($effectiveCommand) {
|
||||||
$validCommands = @("clean", "uninstall", "analyze", "status", "optimize", "purge")
|
$validCommands = @("clean", "uninstall", "analyze", "status", "optimize", "update", "remove", "purge")
|
||||||
|
|
||||||
if ($effectiveCommand -in $validCommands) {
|
if ($effectiveCommand -in $validCommands) {
|
||||||
Invoke-MoleCommand -CommandName $effectiveCommand -Arguments $CommandArgs
|
Invoke-MoleCommand -CommandName $effectiveCommand -Arguments $CommandArgs
|
||||||
|
|||||||
@@ -4,6 +4,10 @@
|
|||||||
|
|
||||||
#Requires -Version 5.1
|
#Requires -Version 5.1
|
||||||
|
|
||||||
|
param(
|
||||||
|
[string]$InstallDir = "$env:LOCALAPPDATA\Mole"
|
||||||
|
)
|
||||||
|
|
||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
Set-StrictMode -Version Latest
|
Set-StrictMode -Version Latest
|
||||||
|
|
||||||
@@ -32,11 +36,17 @@ function Write-ErrorMsg {
|
|||||||
Write-Host " $($Colors.Red)✗$($Colors.NC) $Message"
|
Write-Host " $($Colors.Red)✗$($Colors.NC) $Message"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Test-SourceInstall {
|
||||||
|
param([string]$Path)
|
||||||
|
|
||||||
|
return (Test-Path (Join-Path $Path ".git"))
|
||||||
|
}
|
||||||
|
|
||||||
# Main installation
|
# Main installation
|
||||||
try {
|
try {
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host " $($Colors.Cyan)Mole Quick Installer$($Colors.NC)"
|
Write-Host " $($Colors.Cyan)Mole Quick Installer$($Colors.NC)"
|
||||||
Write-Host " $($Colors.Yellow)Installing experimental Windows version...$($Colors.NC)"
|
Write-Host " $($Colors.Yellow)Installing experimental Windows source channel...$($Colors.NC)"
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
|
|
||||||
# Check prerequisites
|
# Check prerequisites
|
||||||
@@ -50,38 +60,61 @@ try {
|
|||||||
|
|
||||||
Write-Success "Git found"
|
Write-Success "Git found"
|
||||||
|
|
||||||
# Create temp directory
|
if (Test-Path $InstallDir) {
|
||||||
$TempDir = Join-Path $env:TEMP "mole-install-$(Get-Random)"
|
if (Test-SourceInstall -Path $InstallDir) {
|
||||||
Write-Step "Downloading Mole..."
|
Write-Step "Existing source install found, refreshing..."
|
||||||
|
|
||||||
# Clone windows branch
|
Push-Location $InstallDir
|
||||||
git clone --quiet --depth 1 --branch windows https://github.com/tw93/Mole.git $TempDir 2>&1 | Out-Null
|
try {
|
||||||
|
git fetch --quiet origin windows 2>&1 | Out-Null
|
||||||
if (-not (Test-Path "$TempDir\install.ps1")) {
|
if ($LASTEXITCODE -ne 0) {
|
||||||
Write-ErrorMsg "Failed to download installer"
|
Write-ErrorMsg "Failed to fetch latest source"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Success "Downloaded to temp directory"
|
git pull --ff-only origin windows 2>&1 | Out-Null
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
Write-ErrorMsg "Failed to fast-forward source install"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
Pop-Location
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-ErrorMsg "Install directory already exists and is not a source install: $InstallDir"
|
||||||
|
Write-Host " Remove it first or reinstall with the latest quick installer."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Step "Cloning Mole source..."
|
||||||
|
|
||||||
|
git clone --quiet --depth 1 --branch windows https://github.com/tw93/Mole.git $InstallDir 2>&1 | Out-Null
|
||||||
|
|
||||||
|
if (-not (Test-Path (Join-Path $InstallDir "install.ps1"))) {
|
||||||
|
Write-ErrorMsg "Failed to clone source installer"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Success "Cloned source to $InstallDir"
|
||||||
|
}
|
||||||
|
|
||||||
# Run installer
|
# Run installer
|
||||||
Write-Step "Running installer..."
|
Write-Step "Running installer..."
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
|
|
||||||
& "$TempDir\install.ps1" -AddToPath
|
& (Join-Path $InstallDir "install.ps1") -InstallDir $InstallDir -AddToPath
|
||||||
|
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Success "Installation complete!"
|
Write-Success "Installation complete!"
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host " Run ${Colors.Green}mole$($Colors.NC) to get started"
|
Write-Host " Run ${Colors.Green}mole$($Colors.NC) to get started"
|
||||||
|
Write-Host " Run ${Colors.Green}mo update$($Colors.NC) to pull the latest windows source later"
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
|
|
||||||
} catch {
|
} catch {
|
||||||
Write-ErrorMsg "Installation failed: $_"
|
Write-ErrorMsg "Installation failed: $_"
|
||||||
exit 1
|
exit 1
|
||||||
} finally {
|
|
||||||
# Cleanup
|
|
||||||
if (Test-Path $TempDir) {
|
|
||||||
Remove-Item $TempDir -Recurse -Force -ErrorAction SilentlyContinue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -211,6 +211,8 @@ New-Item -ItemType Directory -Path $tempBuildDir -Force | Out-Null
|
|||||||
$filesToInclude = @(
|
$filesToInclude = @(
|
||||||
@{Source = "$projectRoot\mole.ps1"; Dest = "$tempBuildDir\mole.ps1"},
|
@{Source = "$projectRoot\mole.ps1"; Dest = "$tempBuildDir\mole.ps1"},
|
||||||
@{Source = "$projectRoot\install.ps1"; Dest = "$tempBuildDir\install.ps1"},
|
@{Source = "$projectRoot\install.ps1"; Dest = "$tempBuildDir\install.ps1"},
|
||||||
|
@{Source = "$projectRoot\go.mod"; Dest = "$tempBuildDir\go.mod"},
|
||||||
|
@{Source = "$projectRoot\go.sum"; Dest = "$tempBuildDir\go.sum"},
|
||||||
@{Source = "$projectRoot\LICENSE"; Dest = "$tempBuildDir\LICENSE"},
|
@{Source = "$projectRoot\LICENSE"; Dest = "$tempBuildDir\LICENSE"},
|
||||||
@{Source = "$projectRoot\README.md"; Dest = "$tempBuildDir\README.md"}
|
@{Source = "$projectRoot\README.md"; Dest = "$tempBuildDir\README.md"}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -109,6 +109,36 @@ Describe "Status Command" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Describe "Update Command" {
|
||||||
|
Context "Help Display" {
|
||||||
|
It "Should show help without error" {
|
||||||
|
$result = & powershell -ExecutionPolicy Bypass -File "$script:BinDir\update.ps1" -ShowHelp 2>&1
|
||||||
|
$result | Should -Not -BeNullOrEmpty
|
||||||
|
$LASTEXITCODE | Should -Be 0
|
||||||
|
}
|
||||||
|
|
||||||
|
It "Should explain the source channel" {
|
||||||
|
$result = & powershell -ExecutionPolicy Bypass -File "$script:BinDir\update.ps1" -ShowHelp 2>&1
|
||||||
|
$result -join "`n" | Should -Match "source|origin/windows|git"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Describe "Remove Command" {
|
||||||
|
Context "Help Display" {
|
||||||
|
It "Should show help without error" {
|
||||||
|
$result = & powershell -ExecutionPolicy Bypass -File "$script:BinDir\remove.ps1" -ShowHelp 2>&1
|
||||||
|
$result | Should -Not -BeNullOrEmpty
|
||||||
|
$LASTEXITCODE | Should -Be 0
|
||||||
|
}
|
||||||
|
|
||||||
|
It "Should mention uninstall behavior" {
|
||||||
|
$result = & powershell -ExecutionPolicy Bypass -File "$script:BinDir\remove.ps1" -ShowHelp 2>&1
|
||||||
|
$result -join "`n" | Should -Match "Remove Mole|PATH|config"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Describe "Main Entry Point" {
|
Describe "Main Entry Point" {
|
||||||
Context "mole.ps1" {
|
Context "mole.ps1" {
|
||||||
BeforeAll {
|
BeforeAll {
|
||||||
@@ -135,6 +165,8 @@ Describe "Main Entry Point" {
|
|||||||
$helpText | Should -Match "purge"
|
$helpText | Should -Match "purge"
|
||||||
$helpText | Should -Match "analyze"
|
$helpText | Should -Match "analyze"
|
||||||
$helpText | Should -Match "status"
|
$helpText | Should -Match "status"
|
||||||
|
$helpText | Should -Match "update"
|
||||||
|
$helpText | Should -Match "remove"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user