bgit 0.4.2

User-friendly Git wrapper for beginners, automating essential tasks like adding, committing, and pushing changes. It includes smart rules to avoid common pitfalls, such as accidentally adding sensitive files or directories and has exclusive support for portable hooks!
param(
  [ValidateSet('install','update','uninstall','purge')]
  [string]$Cmd = 'install',
  [string]$Tag = "",
  [string]$To = ""
)

$ErrorActionPreference = 'Stop'

# Usage: iwr -useb https://raw.githubusercontent.com/rootCircle/bgit/main/scripts/install.ps1 | iex

$Repo = 'rootCircle/bgit'
$Bin = 'bgit.exe'

function Get-DefaultInstallDir {
  $localBin = Join-Path $env:LOCALAPPDATA 'Programs\bgit'
  return $localBin
}

function Invoke-Http($Url) {
  (Invoke-WebRequest -UseBasicParsing -Uri $Url).Content
}

function Get-LatestTag {
  $json = Invoke-Http "https://api.github.com/repos/$Repo/releases/latest" | ConvertFrom-Json
  return $json.tag_name
}

function Resolve-Tag {
  if (-not $script:Tag) { $script:Tag = Get-LatestTag }
  if (-not $script:Tag) { throw 'Could not determine latest release tag' }
}

# Map OS label and arch to artifact naming
$OsLabel = 'windows-latest'
$Arch = $env:PROCESSOR_ARCHITECTURE
# Normalize arch
switch -regex ($Arch) {
  'AMD64|X86_64' { $Arch = 'AMD64' }
  'ARM64' { $Arch = 'ARM64' }
}

function Install-Bgit {
  Resolve-Tag
  $AssetZip = "bgit-$Tag-$OsLabel-$Arch.zip"
  $AssetSha = "$AssetZip.sha256"

  $rel = Invoke-Http "https://api.github.com/repos/$Repo/releases/tags/$Tag" | ConvertFrom-Json
  $urlZip = ($rel.assets | Where-Object { $_.name -eq $AssetZip }).browser_download_url
  $urlSha = ($rel.assets | Where-Object { $_.name -eq $AssetSha }).browser_download_url
  if (-not $urlZip) { throw "Could not find asset $AssetZip" }

  $tmp = New-Item -ItemType Directory -Force -Path ([System.IO.Path]::GetTempPath() + [System.Guid]::NewGuid())
  try {
    $zipPath = Join-Path $tmp.FullName $AssetZip
    $shaPath = Join-Path $tmp.FullName $AssetSha
    Invoke-WebRequest -UseBasicParsing -Uri $urlZip -OutFile $zipPath
    if ($urlSha) { Invoke-WebRequest -UseBasicParsing -Uri $urlSha -OutFile $shaPath }

    if (Test-Path $shaPath) {
      $expected = (Get-Content $shaPath).Split(' ')[0].Trim().ToLower()
      $actual = (Get-FileHash $zipPath -Algorithm SHA256).Hash.ToLower()
      if ($expected -ne $actual) { throw "Checksum mismatch for $AssetZip" }
    }

    $extractDir = Join-Path $tmp.FullName 'extract'
    New-Item -ItemType Directory -Force -Path $extractDir | Out-Null
    Add-Type -AssemblyName System.IO.Compression.FileSystem
    [System.IO.Compression.ZipFile]::ExtractToDirectory($zipPath, $extractDir)

    $src = Join-Path $extractDir $Bin
    if (-not (Test-Path $src)) { throw 'Binary not found in archive' }

    if (-not $To) { $To = Get-DefaultInstallDir }
    New-Item -ItemType Directory -Force -Path $To | Out-Null
    $dst = Join-Path $To $Bin
    Copy-Item -Force $src $dst

    $onPath = ($env:PATH -split ';') -contains $To
    if (-not $onPath) {
      Write-Host "Note: $To is not on PATH. Add it via System Properties or:`n  setx PATH `"$env:PATH;$To`""
    }

    Write-Host "Installed bgit $Tag to $dst"
  }
  finally {
    Remove-Item -Recurse -Force $tmp
  }
}

function Uninstall-Bgit {
  $candidate = $null
  if ($To) {
    $p = Join-Path $To $Bin
    if (Test-Path $p) { $candidate = $p }
  }
  if (-not $candidate) {
    $pathHit = (Get-Command bgit.exe -ErrorAction SilentlyContinue)
    if ($pathHit) { $candidate = $pathHit.Source }
  }
  if (-not $candidate) {
    $common = @(
      Join-Path $env:LOCALAPPDATA 'Programs\bgit\bgit.exe'),
      'C:\\Program Files\\bgit\\bgit.exe'
    foreach ($c in $common) { if (Test-Path $c) { $candidate = $c; break } }
  }
  if (-not $candidate) { Write-Host 'bgit not found; nothing to uninstall'; return }
  Remove-Item -Force $candidate
  Write-Host "Removed $candidate"
}

function Purge-Bgit {
  Uninstall-Bgit
  $agentSock = Join-Path $env:USERPROFILE '.ssh\bgit_ssh_agent.sock'
  if (Test-Path $agentSock) { Remove-Item -Force $agentSock; Write-Host "Removed $agentSock" }
  # Global per-user config in %APPDATA%\bgit
  $globalCfg = Join-Path $env:APPDATA 'bgit'
  if (Test-Path $globalCfg) { Remove-Item -Recurse -Force $globalCfg; Write-Host "Removed $globalCfg" }
}

switch ($Cmd) {
  'install' { Install-Bgit }
  'update' { Install-Bgit }
  'uninstall' { Uninstall-Bgit }
  'purge' { Purge-Bgit }
}