1
0
mirror of https://github.com/tw93/Mole.git synced 2026-02-04 14:26:46 +00:00
Files
Mole/bin/clean.ps1
Bhadra 3bd2869e8d feat: Add Windows package manager publishing infrastructure (#343) (#356)
* feat: Add Windows package manager publishing infrastructure (#343)

- Add comprehensive release build scripts:
  - build-release.ps1: Creates portable ZIP + SHA256 checksums
  - build-exe.ps1: Standalone executable builder (PS2EXE)
  - build-msi.ps1: MSI installer builder (WiX Toolset)

- Add GitHub Actions workflow:
  - Automated builds on version tags
  - Runs tests before building
  - Auto-creates GitHub releases with artifacts

- Add package manager manifests:
  - WinGet: Complete manifests ready for microsoft/winget-pkgs
  - Chocolatey: Full package with install/uninstall scripts
  - Scoop: JSON manifest ready for submission

- Add comprehensive documentation:
  - RELEASE.md: Complete guide for building and publishing
  - Package-specific READMEs with submission instructions
  - ISSUE-343-SUMMARY.md: Quick reference and next steps

Successfully tested: Built mole-1.0.0-x64.zip (5 MB) with SHA256 checksums

Addresses #343

* chore: update contributors [skip ci]

* fix: Support uppercase V and -windows suffix in release workflow

* fix: Remove duplicate parameter definitions in clean, optimize, and purge commands

- bin/clean.ps1: Remove duplicate System, GameMedia, DebugMode, Whitelist params
- bin/optimize.ps1: Remove duplicate DebugMode param
- bin/purge.ps1: Remove duplicate DebugMode and Paths params

These duplicates were causing parser errors in tests.

* fix: Update test regex to match --dry-run format in help text

The help output shows --dry-run (kebab-case) but test was checking for DryRun (PascalCase).
Updated regex to accept both formats.

* fix: Handle Pester 5.x result object properties correctly

Pester 5.x uses different property names (Passed.Count, Failed.Count)
instead of PassedCount, FailedCount. Added fallback logic to support both formats.

* fix: Simplify Pester result parsing with better fallback logic

Since Pester already prints test results, just check for failures
and assume success if we can't parse the result object. This handles
different Pester versions more gracefully.

* feat: Add MSI and EXE builds to release workflow

- Install WiX Toolset for MSI creation
- Install PS2EXE module for standalone EXE
- Build all three formats: ZIP, MSI, EXE
- MSI and EXE builds marked optional (continue-on-error)
- Upload all artifacts to GitHub release
- Update release notes with installation instructions for all formats
- Add SHA256 verification instructions for each format

* fix: Resolve MSI and EXE build failures

MSI build fix:
- Use UTF8 without BOM for temp WXS file to avoid XML parsing errors
- WiX compiler requires clean UTF8 encoding without byte order mark

EXE build fix:
- Remove hashtable iteration that modified collection during enumeration
- Exclude null iconFile parameter from ps2exe params instead of removing it
- Prevents 'Collection was modified' exception

* fix: Properly handle encoding and version format for MSI and EXE builds

MSI fix:
- Use System.IO.File.ReadAllText/WriteAllText for consistent UTF8 without BOM
- Prevents XML parsing errors in WiX compiler

EXE fix:
- Extract numeric version only (strip '-windows' suffix) for ps2exe
- ps2exe requires version in format n.n.n.n (numeric only)
- Fallback to 1.0.0.0 if version parsing fails

* fix: Use WriteAllBytes to ensure no BOM in MSI WXS file

- Convert string to UTF8 bytes manually
- Write bytes directly to file
- This guarantees no byte order mark is added
- Prevents WiX XML parsing error at position 7

* fix: Read WXS source as bytes to completely avoid BOM issues

- Read source file as raw bytes
- Convert bytes to string using UTF8Encoding without BOM
- Replace version in string
- Convert back to bytes and write
- This completely avoids PowerShell's Get-Content BOM handling

* chore: Simplify release workflow - remove MSI build, minimal release notes

- Remove MSI build steps (has persistent BOM/encoding issues)
- Remove WiX Toolset installation
- Simplify release notes to bare minimum
- Focus on ZIP and EXE artifacts only

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-01-24 00:08:24 +08:00

324 lines
8.8 KiB
PowerShell

# Mole - Clean Command
# Deep cleanup for Windows with dry-run support and whitelist
#Requires -Version 5.1
[CmdletBinding()]
param(
[Alias('dry-run')]
[switch]$DryRun,
[Alias('s')]
[switch]$System,
[Alias('game-media')]
[switch]$GameMedia,
[Alias('d')]
[switch]$DebugMode,
[Alias('w')]
[switch]$Whitelist,
[Alias('h')]
[switch]$ShowHelp
)
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
# Script location
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$libDir = Join-Path (Split-Path -Parent $scriptDir) "lib"
# Import core modules
. "$libDir\core\base.ps1"
. "$libDir\core\log.ps1"
. "$libDir\core\ui.ps1"
. "$libDir\core\file_ops.ps1"
# Import cleanup modules
. "$libDir\clean\user.ps1"
. "$libDir\clean\caches.ps1"
. "$libDir\clean\dev.ps1"
. "$libDir\clean\apps.ps1"
. "$libDir\clean\system.ps1"
# ============================================================================
# Configuration
# ============================================================================
$script:ExportListFile = "$env:USERPROFILE\.config\mole\clean-list.txt"
# ============================================================================
# Help
# ============================================================================
function Show-CleanHelp {
$esc = [char]27
Write-Host ""
Write-Host "$esc[1;35mmo clean$esc[0m - Deep cleanup for Windows"
Write-Host ""
Write-Host "$esc[33mUsage:$esc[0m mo clean [options]"
Write-Host ""
Write-Host "$esc[33mOptions:$esc[0m"
Write-Host " --dry-run Preview changes without deleting (recommended first run)"
Write-Host " --system Include system-level cleanup (requires admin)"
Write-Host " --game-media Clean old game replays, screenshots, recordings (>90d)"
Write-Host " --whitelist Manage protected paths"
Write-Host " --debug Enable debug logging"
Write-Host " --help Show this help message"
Write-Host ""
Write-Host "$esc[33mExamples:$esc[0m"
Write-Host " mo clean --dry-run # Preview what would be cleaned"
Write-Host " mo clean # Run standard cleanup"
Write-Host " mo clean --game-media # Include old game media cleanup"
Write-Host " mo clean --system # Include system cleanup (as admin)"
Write-Host ""
}
# ============================================================================
# Whitelist Management
# ============================================================================
function Edit-Whitelist {
$whitelistPath = $script:Config.WhitelistFile
$whitelistDir = Split-Path -Parent $whitelistPath
# Ensure directory exists
if (-not (Test-Path $whitelistDir)) {
New-Item -ItemType Directory -Path $whitelistDir -Force | Out-Null
}
# Create default whitelist if doesn't exist
if (-not (Test-Path $whitelistPath)) {
$defaultContent = @"
# Mole Whitelist - Paths listed here will never be cleaned
# Use full paths or patterns with wildcards (*)
#
# Examples:
# C:\Users\YourName\Documents\ImportantProject
# C:\Users\*\AppData\Local\MyApp
# $env:LOCALAPPDATA\CriticalApp
#
# Add your protected paths below:
"@
Set-Content -Path $whitelistPath -Value $defaultContent
}
# Open in default editor
Write-Info "Opening whitelist file: $whitelistPath"
Start-Process notepad.exe -ArgumentList $whitelistPath -Wait
Write-Success "Whitelist saved"
}
# ============================================================================
# Cleanup Summary
# ============================================================================
function Show-CleanupSummary {
param(
[hashtable]$Stats,
[bool]$IsDryRun
)
$esc = [char]27
Write-Host ""
Write-Host "$esc[1;35m" -NoNewline
if ($IsDryRun) {
Write-Host "Dry run complete - no changes made" -NoNewline
}
else {
Write-Host "Cleanup complete" -NoNewline
}
Write-Host "$esc[0m"
Write-Host ""
if ($Stats.TotalSizeKB -gt 0) {
$sizeGB = [Math]::Round($Stats.TotalSizeKB / 1024 / 1024, 2)
if ($IsDryRun) {
Write-Host " Potential space: $esc[32m${sizeGB}GB$esc[0m"
Write-Host " Items found: $($Stats.FilesCleaned)"
Write-Host " Categories: $($Stats.TotalItems)"
Write-Host ""
Write-Host " Detailed list: $esc[90m$($script:ExportListFile)$esc[0m"
Write-Host " Run without --dry-run to apply cleanup"
}
else {
Write-Host " Space freed: $esc[32m${sizeGB}GB$esc[0m"
Write-Host " Items cleaned: $($Stats.FilesCleaned)"
Write-Host " Categories: $($Stats.TotalItems)"
Write-Host ""
Write-Host " Free space now: $(Get-FreeSpace)"
}
}
else {
if ($IsDryRun) {
Write-Host " No significant reclaimable space detected."
}
else {
Write-Host " System was already clean; no additional space freed."
}
Write-Host " Free space now: $(Get-FreeSpace)"
}
Write-Host ""
}
# ============================================================================
# Main Cleanup Flow
# ============================================================================
function Start-Cleanup {
param(
[bool]$IsDryRun,
[bool]$IncludeSystem,
[bool]$IncludeGameMedia
)
$esc = [char]27
# Clear screen
Clear-Host
Write-Host ""
Write-Host "$esc[1;35mClean Your Windows$esc[0m"
Write-Host ""
# Show mode
if ($IsDryRun) {
Write-Host "$esc[33mDry Run Mode$esc[0m - Preview only, no deletions"
Write-Host ""
# Prepare export file
$exportDir = Split-Path -Parent $script:ExportListFile
if (-not (Test-Path $exportDir)) {
New-Item -ItemType Directory -Path $exportDir -Force | Out-Null
}
$header = @"
# Mole Cleanup Preview - $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')
#
# How to protect files:
# 1. Copy any path below to $($script:Config.WhitelistFile)
# 2. Run: mo clean --whitelist
#
"@
Set-Content -Path $script:ExportListFile -Value $header
}
else {
Write-Host "$esc[90m$($script:Icons.Solid) Use --dry-run to preview, --whitelist to manage protected paths$esc[0m"
Write-Host ""
}
# System cleanup confirmation
if ($IncludeSystem -and -not $IsDryRun) {
if (-not (Test-IsAdmin)) {
Write-MoleWarning "System cleanup requires administrator privileges"
Write-Host " Run PowerShell as Administrator for full cleanup"
Write-Host ""
$IncludeSystem = $false
}
else {
Write-Host "$esc[32m$($script:Icons.Success)$esc[0m Running with Administrator privileges"
Write-Host ""
}
}
# Show system info
$winVer = Get-WindowsVersion
Write-Host "$esc[34m$($script:Icons.Admin)$esc[0m $($winVer.Name) | Free space: $(Get-FreeSpace)"
Write-Host ""
# Reset stats
Reset-CleanupStats
Set-DryRunMode -Enabled $IsDryRun
# Run cleanup modules
try {
# User essentials (temp, logs, etc.)
Invoke-UserCleanup -TempDaysOld 7 -LogDaysOld 7
# Browser caches
Clear-BrowserCaches
# GPU shader caches (NVIDIA, AMD, Intel, DirectX)
Clear-GPUShaderCaches
# Application caches
Clear-AppCaches
# Developer tools
Invoke-DevToolsCleanup
# Applications cleanup (with optional game media)
if ($IncludeGameMedia) {
Invoke-AppCleanup -IncludeGameMedia -GameMediaDaysOld 90
}
else {
Invoke-AppCleanup
}
# System cleanup (if requested and admin)
if ($IncludeSystem -and (Test-IsAdmin)) {
Invoke-SystemCleanup
}
}
catch {
Write-MoleError "Cleanup error: $_"
}
# Get final stats
$stats = Get-CleanupStats
# Show summary
Show-CleanupSummary -Stats $stats -IsDryRun $IsDryRun
}
# ============================================================================
# Main Entry Point
# ============================================================================
function Main {
# Enable debug if requested
if ($DebugMode) {
$env:MOLE_DEBUG = "1"
$DebugPreference = "Continue"
}
# Show help
if ($ShowHelp) {
Show-CleanHelp
return
}
# Manage whitelist
if ($Whitelist) {
Edit-Whitelist
return
}
# Set dry-run mode
if ($DryRun) {
$env:MOLE_DRY_RUN = "1"
}
else {
$env:MOLE_DRY_RUN = "0"
}
# Run cleanup
try {
Start-Cleanup -IsDryRun $DryRun -IncludeSystem $System -IncludeGameMedia $GameMedia
}
finally {
# Cleanup temp files
Clear-TempFiles
}
}
# Run main
Main