This commit is contained in:
Sangelo 2023-10-15 18:22:33 +02:00
parent 06b129bcbf
commit 21578c9877
16 changed files with 258 additions and 18 deletions

View file

@ -2,6 +2,7 @@
# Set some common options # Set some common options
switch("d", "release") switch("d", "release")
switch("d", "ssl")
switch("hints", "off") switch("hints", "off")
# Helper procs to abstract away OS-specific commands # Helper procs to abstract away OS-specific commands

View file

@ -10,3 +10,5 @@ bin = @["dashinit"]
# Dependencies # Dependencies
requires "nim >= 2.0.0" requires "nim >= 2.0.0"
requires "parsetoml >= 0.7.1"
requires "downit >= 0.2.2"

View file

@ -10,7 +10,7 @@ proc createConfigFile*() =
when defined(release): when defined(release):
# Determine the operating system # Determine the operating system
when defined(windows): when defined(windows):
configPath = os.getHomeDir() / "dashinit" / "config.toml" configPath = os.getHomeDir() / "AppData" / "Roaming" / "dashinit" / "config.toml"
else: else:
configPath = os.getHomeDir() / ".config" / "dashinit" / "config.toml" configPath = os.getHomeDir() / ".config" / "dashinit" / "config.toml"
else: else:

View file

@ -0,0 +1,65 @@
import strutils, httpclient, streams, zippy/tarballs, async, os, parsetoml
import ../lib/progress
const
defaultMetaRepo = "https://gitpot.dev/dashinit/templates"
configPath = "~/.config/dashinit/config.toml"
templatesDir = "~/.local/share/dashinit/templates/"
tempDir = templatesDir / ".tmp/"
# Fetch meta-repository from the config file
proc getMetaRepoFromConfig(): string =
if fileExists(expandFilename(configPath)):
let tomlData = parseFile(expandFilename(configPath))
if "template" in tomlData and "repository" in tomlData["template"]:
return tomlData["template"]["repository"].getStr()
return defaultMetaRepo
proc downloadFile*(url: string, filename: string) {.async.} =
var downloaded = 0
proc onProgressChanged(total, progress: BiggestInt, speed: float64) =
let downloadProgress = (progress.float / total.float) * 100
printProgressBar(int(downloadProgress), "Downloading file...")
var client = newHttpClient()
client.onProgressChanged = onProgressChanged
let content = await client.getContent(url)
writeFile(filename, content)
# Ensure the progress bar reaches 100% at the end
printProgressBar(100, "Download complete!")
proc downloadTemplate*(package: string, repo: string = getMetaRepoFromConfig(), release: string = "latest") =
# Construct the tar URL
let tarUrl = if release == "latest":
repo & "/" & package & "/archive/main.tar.gz"
else:
repo & "/" & package & "/archive/" & release & ".tar.gz"
# Ensure temporary directory exists
if not dirExists(expandFilename(tempDir)):
createDir(expandFilename(tempDir))
let tarFilePath = expandFilename(tempDir) / package / ".temp.tar.gz"
# Use the re-implemented downloadFile procedure
waitFor downloadFile(tarUrl, tarFilePath)
# Open the tarball from the saved file for extraction
let tarFile = open(tarFilePath)
for entry in tarFile:
let outputPath = expandFilename(tempDir) / entry.name
if entry.kind == ekDirectory:
createDir(outputPath)
else:
writeFile(outputPath, entry.contents)
# Optionally delete the tarball file afterward
removeFile(tarFilePath)
# After extraction, move the files to the correct directory (parent of .tmp)
moveDir(expandFilename(tempDir / package), expandFilename(templatesDir / package))
removeDir(expandFilename(tempDir)) # Clear the temporary directory
# Usage: downloadTemplate("default")

View file

@ -0,0 +1,83 @@
# src/handlers/initialRunHandler.nim
import os, osproc
import ../lib/styledOut
# Path of the default dashinit config
const dashinitConfig = staticRead("../resources/config/config.toml")
let roamingAppData = getEnv("APPDATA")
let localAppData = getEnv("LOCALAPPDATA")
let homeDir = os.getHomeDir()
# Base directory containing templates and other files
let dashinitBaseDir* = if hostOS == "windows":
roamingAppData / "dashinit"
else:
homeDir / ".local" / "share" / "dashinit"
# Dashinit config directory containing the config files
let confBaseDir* = if hostOs == "windows":
roamingAppData / "dashinit"
else:
homeDir / ".config" / "dashinit"
# Cache directory containing donwloaded templates used as cache
let cacheBaseDir* = if hostOs == "windows":
localAppData / "dashinit"
else:
homeDir / ".cache" / "dashinit"
# Get the template directory path based on the OS
let templateBaseDir* = dashinitBaseDir / "templates"
# Get the config file path based on the OS
let configPath* = confBaseDir / "config.toml"
let contentsConf = execProcess("ls -l " & $confBaseDir)
let contentsLocal = execProcess("ls -l " & $dashinitBaseDir)
styledPrint("Contents of config path: " & $contentsConf, debug)
styledPrint("Contents of local path: " & $contentsLocal, debug)
# Ensure the templates directory exists
proc ensureTemplatesDirExists() =
if not dirExists(templateBaseDir):
try:
os.createDir(templateBaseDir)
except:
styledPrint("Failed to create templates directory at " & $templateBaseDir, error)
# Ensure the config file exists
proc ensureConfigFileExists() =
# Create the directory if it doesn't exist
let dir = confBaseDir
if not dir.dirExists():
try:
dir.createDir()
except:
styledPrint("Failed to create config directory at " & $confBaseDir, error)
# Write the template config to the determined path
if not configPath.fileExists():
try:
writeFile(configPath, dashinitConfig)
except:
styledPrint("Failed to create config file at " & $configPath, error)
# Ensure the cache directory exists
proc ensureCacheDirExists() =
# Create the directory if it doesn't exist
let dir = cacheBaseDir
if not dir.dirExists():
try:
dir.createDir()
except:
styledPrint("Failed to create cache directory at " & $cacheBaseDir, error)
# Ensure all initial directories and files are set up
proc initialSetup*() =
ensureTemplatesDirExists()
ensureConfigFileExists()
ensureCacheDirExists()

21
src/lib/downloader.nim Normal file
View file

@ -0,0 +1,21 @@
import tables, strutils, downit, ./progress
proc downloadFile*(url: string, path: string) =
var client = newHttpClient()
try:
let response = client.get(url)
let totalSize = parseInt(response.headers.getOrDefault("Content-Length", "-1"))
var downloadedSize = 0
let file = open(path, fmWrite)
try:
for chunk in response.bodyStream:
file.write(chunk)
downloadedSize += chunk.len
let progress = (downloadedSize.float / totalSize.float) * 100
printProgressBar(int(progress), "Downloading to " & path & "...")
finally:
file.close()
finally:
client.close()
downloadFile("https://files.sangelo.space/whoogle-yacht/whoogle-yacht.json", "whoogle-yacht.json")

20
src/lib/progress.nim Normal file
View file

@ -0,0 +1,20 @@
import strutils, terminal, system
import os
proc printProgressBar*(progress: int, msg: string) =
hideCursor()
const totalWidth = 50
let filledWidth = int(progress.float * totalWidth / 100)
let emptyWidth = totalWidth - filledWidth
stdout.styledWrite(fgCyan, "[")
stdout.styledWrite(fgGreen, "".repeat(filledWidth))
stdout.styledWrite(fgWhite, "".repeat(emptyWidth))
stdout.styledWrite(fgCyan, "] ")
stdout.styledWrite(fgYellow, $(int(progress.float)), "%")
stdout.styledWrite(" ", msg & "\r")
flushFile(stdout)
showCursor()
for i in 0..100:
printProgressBar(i, "Time consuming task...")
sleep(100)

21
src/lib/styledOut.nim Normal file
View file

@ -0,0 +1,21 @@
import terminal
type
StyleKind* = enum
info, warning, error, success, debug
proc styledPrint*(msg: string, kind: StyleKind) =
case kind
of info:
styledEcho styleBright, fgBlue, "Info: ", resetStyle, fgBlue, msg, resetStyle
of warning:
styledEcho styleBright, fgYellow, "Warning: ", resetStyle, fgYellow, msg, resetStyle
of error:
styledEcho styleBright, fgRed, "Error: ", resetStyle, fgRed, msg, resetStyle
of debug:
styledEcho styleBright, styleDim, "Debug: ", resetStyle, styleDim, msg, resetStyle
of success:
styledEcho styleBright, fgGreen, msg, resetStyle
proc styledPrintln*(msg: string, kind: StyleKind) =
styledPrint(msg & "\n", kind)

View file

@ -2,11 +2,12 @@
import os, strutils import os, strutils
import subcommands/help import subcommands/help
import subcommands/init import subcommands/init
import handlers/configHandler import handlers/initialRunHandler
import lib/styledOut
proc main() = proc main() =
# Create the config file if it doesn't exist already # Initialise the program on first run
createConfigFile() initialSetup()
# Check for arguments and initialise directly if none are found # Check for arguments and initialise directly if none are found
let args = commandLineParams() let args = commandLineParams()
@ -22,6 +23,12 @@ proc main() =
displayHelp() displayHelp()
of "init": of "init":
init() init()
of "--debug-colors":
styledPrintln("This is an info message.", info)
styledPrintln("This is a warning message.", warning)
styledPrintln("This is an error message.", error)
styledPrintln("This is a success message.", success)
styledPrint("This is a debug message.", debug)
else: else:
echo "Unknown argument '", subcommand, "'. Use 'help' for available commands." echo "Unknown argument '", subcommand, "'. Use 'help' for available commands."

View file

@ -1,13 +1,12 @@
# dashinit Configuration File # dashinit Configuration File
[general] [template]
# Where to download templates from
template_repo = "https://gitpot.dev/dashinit/templates"
# The default template to be used when initialising # The default template to be used when initialising
default_template = "default" default = "default"
# Which meta repository to use as a source for templates
repository = "https://gitpot.dev/dashinit/templates"
[templates]
# Allow user scripts to be executed # Allow user scripts to be executed
allow_scripts = false allow_scripts = false

View file

@ -0,0 +1,14 @@
[template]
name = "Default"
version = "0.1.0"
authors = [
"Dashinit Contributors",
"Sangelo"
]
links = [
"https://gitpot.dev/dashinit/templates/src/branch/main/default/README.md"
]
[automation]
enabled = true
script = "./scripts/main.sh"

View file

@ -1,26 +1,31 @@
import os, strutils, strformat import os, strutils, strformat
import ../lib/styledOut
# import parsetoml # import parsetoml
# Define how to handle failed copies # Define how to handle failed copies
proc copyFile(src, dest: string): bool = proc copyFile(src, dest: string): bool =
try: try:
os.copyFile(src, dest) os.copyFile(src, dest)
echo "Successfully copied ", src, " to ", dest styledPrint(&"Successfully copied {src} to {dest}", success)
return true return true
except: except:
echo "Failed to copy ", src, " to ", dest styledPrint(&"Failed to copy {src} to {dest}", error)
return false return false
# Define how to handle failed directory creations # Define how to handle failed directory creations
proc createDir(dir: string): bool = proc createDir(dir: string): bool =
try: try:
os.createDir(dir) os.createDir(dir)
echo "Successfully created ", dir styledPrint(&"Successfully created {dir}", success)
return true return true
except: except:
echo "Failed to create ", dir styledPrint(&"Failed to create {dir}", error)
return false return false
proc initialiseProject() =
discard createDir("testdir")
discard copyFile("test", "testdir/test1")
# Define how to handle configuring a git repo # Define how to handle configuring a git repo
proc configureGitRepo(gitRemote, gitBranch: string) = proc configureGitRepo(gitRemote, gitBranch: string) =
let setupGitRepo = execShellCmd(&"git remote add origin {gitRemote}") let setupGitRepo = execShellCmd(&"git remote add origin {gitRemote}")
@ -42,18 +47,20 @@ proc init*() =
for entry in walkDir("."): for entry in walkDir("."):
count += 1 count += 1
# If there are files, ask for confirmation, otherwise continue. # If there are files, ask for confirmation, otherwise continue.
if not count == 0: if count > 0:
echo "This directory is not empty." styledPrint("This directory is not empty.", warning)
echo "Continue initialising? [y/N]" stdout.write("Continue initialising? [y/N] ")
var input = stdin.readLine() var input = stdin.readLine()
case input.toLower case input.toLower
of "yes", "y", "z", "j": of "yes", "y", "z", "j":
echo "Initialising non-empty directory..." echo "Initialising non-empty directory..."
initialiseProject()
else: else:
echo "Cancelling..." echo "Cancelling..."
quit 0 quit 0
else: else:
echo "Initialising..." echo "Initialising..."
initialiseProject()
# Handle -g parameter for git repos. # Handle -g parameter for git repos.
if "-g" in (commandLineParams()): if "-g" in (commandLineParams()):

0
test/test Normal file
View file

0
test/testdir/test1 Normal file
View file