More error handling

This commit is contained in:
Kyle Brown 2022-11-04 19:08:32 -07:00
parent 1bec41cbed
commit 81af6923e0
5 changed files with 108 additions and 82 deletions

View file

@ -2,7 +2,7 @@
# pmm
#
# @file
# @version 0.5
# @version 0.5.1
SRC = *.nim
SRCDIR = src
@ -19,15 +19,15 @@ all: pretty release man docs
.PHONY: release
release:
nimble build '--cc:clang -d:release --opt:size -d:strip' -y
nimble build '--cc:clang -d:release --opt:size -d:strip --experimental:strictEffects --panics:on' -y
.PHONY: static
static:
nimble build '--cc:clang -d:release --passL:-static --opt:size -d:strip' -y
nimble build '--cc:clang -d:release --passL:-static --opt:size -d:strip --experimental:strictEffects --panics:on' -y
.PHONY: debug
debug:
nimble build '--cc:clang' --verbose
nimble build '--cc:clang --experimental:strictEffects --panics:on' --verbose
.PHONY: clean
clean:

View file

@ -1,6 +1,6 @@
# Package
version = "0.5.0"
version = "0.5.1"
author = "Kyle Brown"
description = "Gentoo's world file, but everywhere."
license = "MIT"
@ -10,8 +10,8 @@ bin = @["pmm"]
# Dependencies
requires "nim >= 1.4.6"
requires "docopt >= 0.6.7"
requires "nim >= 1.6.8"
requires "docopt >= 0.7.0"
requires "envconfig >= 1.1.0"
task buildRelease, "Builds the release version":

View file

@ -7,26 +7,32 @@ import strutils
import typetraits
proc brewBundleDump(): string =
const cmd = fmt"brew bundle dump -q --force --file=/tmp/pmm"
discard execProcess(cmd)
return "/tmp/pmm"
proc brewBundleDump(): string {.raises: [].} =
try:
const cmd = fmt"brew bundle dump -q --force --file=/tmp/pmm"
discard execProcess(cmd)
return "/tmp/pmm"
except: return ""
proc brewBundleList(world: string): seq[string] =
let cmd = fmt"brew bundle list -q --file={world}"
return split(execProcess(cmd))
proc brewBundleList(world: string): seq[string] {.raises: [].} =
try:
let cmd = fmt"brew bundle list -q --file={world}"
return split(execProcess(cmd))
except: return @[""]
proc generatePackageList*(listCommand: string, worldFile: string): seq[string] =
proc generatePackageList*(listCommand: string, worldFile: string): seq[string] {.raises: [].} =
# Generates a newline seperated list of packages, and returns it
# as a sorted seq[string]
if "brew" in listCommand:
return brewBundleList(brewBundleDump())
else: return split(execProcess(listCommand))
try:
if "brew" in listCommand:
return brewBundleList(brewBundleDump())
else: return split(execProcess(listCommand))
except: return @[""]
proc clean*(input: seq[string]): seq[string] =
proc clean*(input: seq[string]): seq[string] {.raises: [].} =
return filter(input, proc(x: string): bool = not x.isEmptyOrWhitespace).deduplicate
proc readWorldFile*(input: string, listCommand: string): seq[string] =
proc readWorldFile*(input: string, listCommand: string): seq[string] {.raises: [ValueError].} =
try:
# Checks for a brewfile, and creates a world file proper if it is one
var packageFile: seq[string]
@ -61,31 +67,37 @@ proc readWorldFile*(input: string, listCommand: string): seq[string] =
quit(QuitFailure)
proc removeOrphans*(command: string, worldFile: string) =
proc removeOrphans*(command: string, worldFile: string) {.raises: [].} =
var cmd: string
if "brew" in command: cmd = command & " --file=" & worldFile
else: cmd = command
let pid = startProcess(cmd, options = {poEchoCmd, poInteractive,
poParentStreams, poUsePath, poEvalCommand})
pid.waitForExit.echo
pid.close
proc installRemove*(command: string, packages: seq[string]) =
# Installs or removes a list of packages
if packages.clean.len >= 1:
let fullCommand = command & " " & packages.join(sep = " ")
let pid = startProcess(fullCommand, options = {poEchoCmd, poInteractive,
poParentStreams, poUsePath, poEvalCommand})
discard pid.waitForExit
try:
let pid = startProcess(cmd, options = {poEchoCmd, poInteractive,
poParentStreams, poUsePath, poEvalCommand})
pid.waitForExit.echo
pid.close
except:
"Failed to remove orphans".echo
proc listDiff*(added: seq[string], removed: seq[string]) =
proc installRemove*(command: string, packages: seq[string]) {.raises: [].} =
# Installs or removes a list of packages
try:
if packages.clean.len >= 1:
let fullCommand = command & " " & packages.join(sep = " ")
let pid = startProcess(fullCommand, options = {poEchoCmd, poInteractive,
poParentStreams, poUsePath, poEvalCommand})
discard pid.waitForExit
pid.close
except:
"Failed to install or remove packages".echo
proc listDiff*(added: seq[string], removed: seq[string]) {.raises: [].} =
echo ("Added: " & added.join(sep = " "))
echo ("Removed: " & removed.join(sep = " "))
proc createWorldFile*(worldFile: string, listCommand: string) =
proc createWorldFile*(worldFile: string, listCommand: string) {.raises: [IOError].} =
# Mac
if "brew" in listCommand:
const prefix = "brew bundle dump --force --file="
@ -93,56 +105,68 @@ proc createWorldFile*(worldFile: string, listCommand: string) =
write(stdout, "Worldfile exists. Overwrite? (y/N) ")
if readLine(stdin).toLowerAscii != "y": return
let pid = startProcess(prefix & worldFile, options = {poEchoCmd,
poInteractive, poParentStreams, poUsePath, poEvalCommand})
discard pid.waitForExit
pid.close
try:
let pid = startProcess(prefix & worldFile, options = {poEchoCmd,
poInteractive, poParentStreams, poUsePath, poEvalCommand})
discard pid.waitForExit
pid.close
except: "Unable to create a world file".echo
else: # Linux
let world = generatePackageList(listCommand, worldfile)
# Create directory if it does not exist. No error if exists
createDir(parentDir(worldFile))
if worldFile.fileExists:
write(stdout, "Worldfile exists. Overwrite? (y/N) ")
if readLine(stdin).toLowerAscii != "y": return
try:
createDir(parentDir(worldFile))
if worldFile.fileExists:
write(stdout, "Worldfile exists. Overwrite? (y/N) ")
if readLine(stdin).toLowerAscii != "y": return
writeFile(worldFile, world.join(sep = "\n"))
writeFile(worldFile, world.join(sep = "\n"))
except: "Unable to create a world file".echo
proc sync*(installCommand: string, removeCommand: string, added: seq[string],
removed: seq[string], worldFile: string) =
removed: seq[string], worldFile: string) {.raises: [].} =
if "brew" in installCommand:
# sync with brew
let installCmd = fmt"brew bundle --force install -q --file={worldFile}"
discard execProcess(installCmd)
let removeCmd = fmt"brew bundle --force cleanup -q --file={worldFile}"
discard execProcess(removeCmd)
try:
let installCmd = fmt"brew bundle --force install -q --file={worldFile}"
discard execProcess(installCmd)
let removeCmd = fmt"brew bundle --force cleanup -q --file={worldFile}"
discard execProcess(removeCmd)
except: "Unable to sync a world file".echo
else:
installRemove(installCommand, added)
installRemove(removeCommand, removed)
proc install*(installCommand: string, pkglist: string, worldFile: string) =
proc install*(installCommand: string, pkglist: string, worldFile: string) {.raises: [].} =
let packages = @[pkglist]
# Installs package, and adds it to worldfile
installRemove(installCommand, packages)
var worldNoRecurse = worldFile.read_file.split
let newWorld = (worldNoRecurse & installCommand.split).clean.join(sep = "\n")
writeFile(worldFile, newWorld)
proc remove*(removeCommand: string, packages: string, worldFile: string) =
var worldNoRecurse = worldFile.read_file.split
let toDelete = find(worldNoRecurse, packages)
if toDelete != -1:
delete(worldNoRecurse, toDelete)
let newWorld = worldNoRecurse.clean.join(sep = "\n")
try:
var worldNoRecurse = worldFile.read_file.split
let newWorld = (worldNoRecurse & installCommand.split).clean.join(sep = "\n")
writeFile(worldFile, newWorld)
installRemove(removeCommand, @[packages])
else: fmt"Could not find {packages} in worldfile.".echo
except IOError: "Unable to install".echo
proc remove*(removeCommand: string, packages: string, worldFile: string) {.raises: [ValueError].} =
try:
var worldNoRecurse = worldFile.read_file.split
let toDelete = find(worldNoRecurse, packages)
if toDelete != -1:
delete(worldNoRecurse, toDelete)
let newWorld = worldNoRecurse.clean.join(sep = "\n")
writeFile(worldFile, newWorld)
installRemove(removeCommand, @[packages])
else: fmt"Could not find {packages} in worldfile.".echo
except IOError: "Unable to remove".echo
proc bash*(installCommand: string, removeCommand: string, added: seq[string],
removed: seq[string]) =
removed: seq[string]) {.raises: [].} =
let ic = installCommand & " " & added.join(sep = " ")
let rc = removeCommand & " " & removed.join(sep = " ")
if removed.len > 0: stdout.write rc
if added.len > 0 and removed.len > 0: stdout.write " && "
if added.len > 0: stdout.write ic
stdout.flushFile
try:
if removed.len > 0: stdout.write rc
if added.len > 0 and removed.len > 0: stdout.write " && "
if added.len > 0: stdout.write ic
stdout.flushFile
except IOError: "Unable to output to bash".echo

View file

@ -1,16 +1,18 @@
import osproc
proc detectCommand(command: string): bool =
let pid = startProcess(command, options = {poUsePath, poEvalCommand})
discard pid.waitForExit
if pid.peekExitCode == 0:
pid.close
return true
else:
pid.close
return false
proc detectCommand(command: string): bool {.raises: [].} =
try:
let pid = startProcess(command, options = {poUsePath, poEvalCommand})
discard pid.waitForExit
if pid.peekExitCode == 0:
pid.close
return true
else:
pid.close
return false
except: return false
proc listCommand*(): string =
proc listCommand*(): string {.raises: [].} =
if detectCommand("which yay"):
return "yay -Qqe"
elif detectCommand("which pacman"):
@ -27,7 +29,7 @@ proc listCommand*(): string =
"Could not find a list command".echo
quit(QuitFailure)
proc installCommand*(): string =
proc installCommand*(): string {.raises: [].} =
if detectCommand("which yay"):
return "yay -S --asexplicit"
elif detectCommand("which pacman"):
@ -44,7 +46,7 @@ proc installCommand*(): string =
"Could not find an install command".echo
quit(QuitFailure)
proc removeCommand*(): string =
proc removeCommand*(): string {.raises: [].} =
if detectCommand("which yay"):
return "yay -D --asdeps"
elif detectCommand("which pacman"):
@ -59,7 +61,7 @@ proc removeCommand*(): string =
"Could not find a remove command".echo
quit(QuitFailure)
proc orphansCommand*(): string =
proc orphansCommand*(): string {.raises: [].} =
if detectCommand("which yay"):
return "yay -Qtdq | yay -Rns -"
elif detectCommand("which pacman"):

View file

@ -37,7 +37,7 @@ type
when isMainModule:
var config = getEnvConfig(Pmm)
let args = docopt(doc, version = "Pmm 0.5.0")
let args = docopt(doc, version = "Pmm 0.5.1")
if args["--worldfile"]: config.world = $args["--worldfile"]
if args["--listCommand"]: config.listCommand = $args["--listCommand"]
if args["--installCommand"]: config.installCommand = $args["--installCommand"]