Compare commits
10 commits
fa64cf55f4
...
3904cf98fc
Author | SHA1 | Date | |
---|---|---|---|
3904cf98fc | |||
37dba25244 | |||
23cd0aa9fa | |||
82ea1eed73 | |||
b2fdf9e5d5 | |||
4590b0ce7a | |||
c8ddbf3243 | |||
bc815f46fd | |||
bba41d1225 | |||
d79780b98b |
16 changed files with 183 additions and 50 deletions
|
@ -27,4 +27,8 @@ nimble install
|
||||||
```
|
```
|
||||||
|
|
||||||
## Pre-compiled Binaries
|
## Pre-compiled Binaries
|
||||||
We are working on providing pre-compiled binaries on our [releases page at Codeberg](https://codeberg.org/pswilde/norgbackup/releases). Currently these are not available, so using the options above are the best option.
|
Pre-compiled binaries are available on our [releases page at Codeberg](https://codeberg.org/pswilde/norgbackup/releases).
|
||||||
|
|
||||||
|
### Updating
|
||||||
|
If installed from our Codeberg repository, or if your hostOS and architecture matches a pre-compiled version hosted on our Codeberg respository, then you can update norg by simply running `norg --update`.
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 9b5c6dd04825d33cb27a9c6715764ad7e23182c4
|
Subproject commit 60170c69606dd3a0b92532409878bfd8ea8648ce
|
5
docs/static/other/command_line.txt
vendored
5
docs/static/other/command_line.txt
vendored
|
@ -1,5 +1,5 @@
|
||||||
Norg -- v0.1.10
|
Norg -- v0.1.15
|
||||||
A portable borg backup wrapper utility.
|
A portable borg backup and restic orchestration tool.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
[options] [command] [further_args ...]
|
[options] [command] [further_args ...]
|
||||||
|
@ -19,4 +19,5 @@ Options:
|
||||||
-a, --archive=ARCHIVE The archive or snapshot to operate on.
|
-a, --archive=ARCHIVE The archive or snapshot to operate on.
|
||||||
-s, --stats Provides statistics at the end of a backup (Borg only).
|
-s, --stats Provides statistics at the end of a backup (Borg only).
|
||||||
-v, --version Shows the current norg version.
|
-v, --version Shows the current norg version.
|
||||||
|
-u, --update Checks for a Norg update and attempts to install it.
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Package
|
# Package
|
||||||
|
|
||||||
version = "0.1.13"
|
version = "0.1.15"
|
||||||
author = "Paul Wilde"
|
author = "Paul Wilde"
|
||||||
description = "A Borg Backup Orchestration Tool"
|
description = "A Borg Backup Orchestration Tool"
|
||||||
license = "AGPL-3.0-or-later"
|
license = "AGPL-3.0-or-later"
|
||||||
|
|
|
@ -10,7 +10,6 @@ import mount
|
||||||
import extract
|
import extract
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
proc initRepo(nc: NorgConfig, repo: Repository): int =
|
proc initRepo(nc: NorgConfig, repo: Repository): int =
|
||||||
return runDiscard genCommand(cmd = "init", repo = repo.path, further_args = nc.args.further_args)
|
return runDiscard genCommand(cmd = "init", repo = repo.path, further_args = nc.args.further_args)
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ import ../model/state_type
|
||||||
import ../notifier/notifier
|
import ../notifier/notifier
|
||||||
import ../model/log_type
|
import ../model/log_type
|
||||||
|
|
||||||
|
import exit_codes
|
||||||
import execute
|
import execute
|
||||||
import prune
|
import prune
|
||||||
|
|
||||||
|
@ -16,33 +17,35 @@ proc genArchiveName(): string =
|
||||||
let ts = getTime().format("yyyy-MM-dd'T'HH:mm:ss'.'ffffff")
|
let ts = getTime().format("yyyy-MM-dd'T'HH:mm:ss'.'ffffff")
|
||||||
return fmt"{hostname}-{ts}"
|
return fmt"{hostname}-{ts}"
|
||||||
|
|
||||||
proc createArchive(nc: NorgConfig, repo: Repository, archivename: string, retry: int = 0): int =
|
proc createArchive(nc: NorgConfig, repo: Repository, archivename: string, retry: int = 0): (EXIT_CODE,string) =
|
||||||
let further_args = nc.args.further_args
|
let further_args = nc.args.further_args
|
||||||
let res = run genCreateCommand(repo = archivename, sources = nc.source_directories, stats=nc.args.stats, exc=nc.exclusions, further_args = further_args)
|
let res = run genCreateCommand(repo = archivename, sources = nc.source_directories, stats=nc.args.stats, exc=nc.exclusions, further_args = further_args)
|
||||||
if res != 0:
|
if res != 0:
|
||||||
info "Failed to run Borg. Waiting 15 seconds and trying again"
|
info "Failed to run Borg. Waiting 15 seconds and trying again"
|
||||||
sleep 15 * 1000 # 15 seconds
|
sleep 15 * 1000 # 15 seconds
|
||||||
if retry == nc.retries:
|
if retry == nc.retries:
|
||||||
return 1
|
return (BORG_ERROR, "Max Retries Reached")
|
||||||
else:
|
else:
|
||||||
return createArchive(nc, repo, archivename, retry + 1)
|
return createArchive(nc, repo, archivename, retry + 1)
|
||||||
return res
|
return (res.toExitCode(),"Success")
|
||||||
|
|
||||||
proc createBackup*(nc: NorgConfig, repo: Repository): int =
|
proc createBackup*(nc: NorgConfig, repo: Repository): EXIT_CODE =
|
||||||
let start_time = now()
|
let start_time = now()
|
||||||
discard notify(nc.notifiers, state=Running)
|
discard notify(nc.notifiers, state=Running)
|
||||||
let archivename = repo.path & "::" & genArchiveName()
|
let archivename = repo.path & "::" & genArchiveName()
|
||||||
debug "Creating Archive: ", archivename
|
debug "Creating Archive: ", archivename
|
||||||
let res = createArchive(nc, repo, archivename)
|
let (res,msg) = createArchive(nc, repo, archivename)
|
||||||
let end_time = now()
|
let end_time = now()
|
||||||
let total = (end_time - start_time).inMilliSeconds()
|
let total = (end_time - start_time).inMilliSeconds()
|
||||||
case res
|
case res
|
||||||
of 0:
|
of BORG_SUCCESS:
|
||||||
if not repo.append_only:
|
if not repo.append_only:
|
||||||
discard pruneRepo(nc, repo)
|
discard pruneRepo(nc, repo)
|
||||||
discard notify(nc.notifiers, state=Success, runtime=total)
|
discard notify(nc.notifiers, state=Success, runtime=total, msg=msg)
|
||||||
of 1:
|
of BORG_WARNING:
|
||||||
discard notify(nc.notifiers, state=Failure, runtime=total)
|
discard notify(nc.notifiers, state=Success, runtime=total, msg="Warning")
|
||||||
|
of BORG_ERROR:
|
||||||
|
discard notify(nc.notifiers, state=Failure, runtime=total, msg=msg)
|
||||||
else:
|
else:
|
||||||
discard notify(nc.notifiers, state=Failure, runtime=total, msg = $res)
|
discard notify(nc.notifiers, state=Failure, runtime=total, msg = $res)
|
||||||
return res
|
return res
|
||||||
|
|
15
norg/borg/exit_codes.nim
Normal file
15
norg/borg/exit_codes.nim
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
|
||||||
|
|
||||||
|
import std/enumutils
|
||||||
|
|
||||||
|
type
|
||||||
|
EXIT_CODE* = enum
|
||||||
|
BORG_SUCCESS = 0
|
||||||
|
BORG_WARNING = 1
|
||||||
|
BORG_ERROR = 2
|
||||||
|
OTHER = 99
|
||||||
|
|
||||||
|
proc toExitCode*(i: int): EXIT_CODE =
|
||||||
|
for code in EXIT_CODE:
|
||||||
|
if i == ord(code): return code
|
||||||
|
return OTHER
|
|
@ -14,6 +14,7 @@ proc parseArgs*() =
|
||||||
arg("command", help="The command to run, defaults to 'create' which will perform a backup.", default=some("create"))
|
arg("command", help="The command to run, defaults to 'create' which will perform a backup.", default=some("create"))
|
||||||
arg("further_args", nargs = -1, help="Any further arguments to send onto borg or restic.")
|
arg("further_args", nargs = -1, help="Any further arguments to send onto borg or restic.")
|
||||||
flag("-v","--version",help="Shows the current norg version.")
|
flag("-v","--version",help="Shows the current norg version.")
|
||||||
|
flag("-u","--update", help="Checks for a Norg update and attempts to install it.")
|
||||||
try:
|
try:
|
||||||
var opts = p.parse(commandLineParams())
|
var opts = p.parse(commandLineParams())
|
||||||
norg_args.config_file = opts.config
|
norg_args.config_file = opts.config
|
||||||
|
@ -24,6 +25,7 @@ proc parseArgs*() =
|
||||||
norg_args.stats = opts.stats
|
norg_args.stats = opts.stats
|
||||||
norg_args.further_args = opts.further_args
|
norg_args.further_args = opts.further_args
|
||||||
norg_args.show_version = opts.version
|
norg_args.show_version = opts.version
|
||||||
|
norg_args.update = opts.update
|
||||||
except ShortCircuit as err:
|
except ShortCircuit as err:
|
||||||
if err.flag == "argparse_help":
|
if err.flag == "argparse_help":
|
||||||
echo err.help
|
echo err.help
|
||||||
|
|
|
@ -4,6 +4,7 @@ export command_type
|
||||||
type
|
type
|
||||||
NorgArgs* = object
|
NorgArgs* = object
|
||||||
show_version*: bool
|
show_version*: bool
|
||||||
|
update*: bool
|
||||||
config_file*: string
|
config_file*: string
|
||||||
extract_destination*: string
|
extract_destination*: string
|
||||||
command*: Command
|
command*: Command
|
||||||
|
|
0
norg/model/exit_codes.nim
Normal file
0
norg/model/exit_codes.nim
Normal file
BIN
norg/norg
Executable file
BIN
norg/norg
Executable file
Binary file not shown.
|
@ -4,6 +4,7 @@ import borg/borg
|
||||||
import restic/restic
|
import restic/restic
|
||||||
import model/encryption_type
|
import model/encryption_type
|
||||||
import utils/actions
|
import utils/actions
|
||||||
|
import utils/update
|
||||||
import model/log_type
|
import model/log_type
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
@ -19,6 +20,8 @@ proc start() =
|
||||||
norg_config.args = norg_args
|
norg_config.args = norg_args
|
||||||
if norg_args.show_version:
|
if norg_args.show_version:
|
||||||
showVersion()
|
showVersion()
|
||||||
|
elif norg_args.update:
|
||||||
|
checkUpdates(VERSION)
|
||||||
elif norg_args.command == GEN_CONF:
|
elif norg_args.command == GEN_CONF:
|
||||||
var config_file = "norg_backup.toml"
|
var config_file = "norg_backup.toml"
|
||||||
if norg_args.config_file != "":
|
if norg_args.config_file != "":
|
||||||
|
|
|
@ -11,7 +11,7 @@ proc run*(cmd: string): int =
|
||||||
return exitcode
|
return exitcode
|
||||||
except:
|
except:
|
||||||
error getCurrentExceptionMsg()
|
error getCurrentExceptionMsg()
|
||||||
return 1
|
return 2
|
||||||
|
|
||||||
proc runDiscard*(cmd: string): int =
|
proc runDiscard*(cmd: string): int =
|
||||||
debug fmt"Trying to run : {cmd}"
|
debug fmt"Trying to run : {cmd}"
|
||||||
|
@ -22,5 +22,5 @@ proc runDiscard*(cmd: string): int =
|
||||||
return exitcode
|
return exitcode
|
||||||
except:
|
except:
|
||||||
error getCurrentExceptionMsg()
|
error getCurrentExceptionMsg()
|
||||||
return 1
|
return 2
|
||||||
|
|
||||||
|
|
93
norg/utils/update.nim
Normal file
93
norg/utils/update.nim
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
##curl -X 'GET' 'https://codeberg.org/api/v1/repos/pswilde/norgbackup/releases/latest -H 'accept: application/json'
|
||||||
|
##
|
||||||
|
import httpclient
|
||||||
|
import json
|
||||||
|
import strformat
|
||||||
|
import strutils
|
||||||
|
import terminal
|
||||||
|
import osproc
|
||||||
|
import os
|
||||||
|
|
||||||
|
import ../model/log_type
|
||||||
|
import version
|
||||||
|
|
||||||
|
const SH = """
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
mv {new} {old}
|
||||||
|
{old} --version
|
||||||
|
rm -r tmp
|
||||||
|
"""
|
||||||
|
const BAT = """
|
||||||
|
move {new} {old}
|
||||||
|
{old} --version
|
||||||
|
rmdir /s tmp
|
||||||
|
"""
|
||||||
|
|
||||||
|
proc extractUpdate(name, file: string) =
|
||||||
|
var client = newHttpClient()
|
||||||
|
try:
|
||||||
|
createDir("tmp")
|
||||||
|
client.downloadFile(file,fmt"tmp/{name}")
|
||||||
|
let cwd = getAppDir()
|
||||||
|
let cwf = getAppFilename()
|
||||||
|
let ok = osproc.execCmd(fmt"tar xf tmp/{name} -C tmp/")
|
||||||
|
copyFile(cwf,fmt"{cwd}/norg_backup")
|
||||||
|
if ok == 0:
|
||||||
|
case hostOS
|
||||||
|
of "linux","freebsd":
|
||||||
|
let content = SH.replace("{new}", "tmp/norg").replace("{old}", cwf)
|
||||||
|
writeFile("tmp/norg_update", content)
|
||||||
|
discard osproc.execCmd("sh tmp/norg_update")
|
||||||
|
quit(0)
|
||||||
|
of "windows":
|
||||||
|
let content = BAT.replace("{new}", "tmp/norg").replace("{old}", cwf)
|
||||||
|
writeFile("tmp/norg_update", content)
|
||||||
|
discard osproc.execCmd("tmp/norg_update")
|
||||||
|
quit(0)
|
||||||
|
except:
|
||||||
|
error getCurrentExceptionMsg()
|
||||||
|
finally:
|
||||||
|
removeDir("tmp")
|
||||||
|
|
||||||
|
proc updateNorg(version: string, j: JsonNode) =
|
||||||
|
let newvers = version[1..^1].replace(".","_")
|
||||||
|
let check_file = fmt"norg_{hostOS}_{hostCPU}-{newvers}.tar.gz"
|
||||||
|
#let check_file = fmt"norg_{hostOS}_{newvers}.tar.gz"
|
||||||
|
var update_found = false
|
||||||
|
for asset in j["assets"].getElems():
|
||||||
|
let name = asset["name"].getStr()
|
||||||
|
if checkfile == name:
|
||||||
|
let file = asset["browser_download_url"].getStr()
|
||||||
|
update_found = true
|
||||||
|
extractUpdate(name,file)
|
||||||
|
if not update_found:
|
||||||
|
info "Unable to find update file for your OS and architecture."
|
||||||
|
info "Please check https://codeberg.org/pswilde/norgbackup/releases/latest for more information"
|
||||||
|
|
||||||
|
|
||||||
|
proc checkUpdates*(cur_vers: string)=
|
||||||
|
initLogger(strfmt = "[$levelname] ")
|
||||||
|
let latest_url = "https://codeberg.org/api/v1/repos/pswilde/norgbackup/releases/latest"
|
||||||
|
var client = newHttpClient()
|
||||||
|
try:
|
||||||
|
let res = client.get(latest_url)
|
||||||
|
if res.code == Http200:
|
||||||
|
let j = res.body.parseJson()
|
||||||
|
let new_vers = j["tag_name"].getStr()
|
||||||
|
if new_vers.newerThan(cur_vers):
|
||||||
|
info "An update is available, would you like to update? (y/N)"
|
||||||
|
let resp = getch()
|
||||||
|
case resp
|
||||||
|
of 'y', 'Y':
|
||||||
|
new_vers.updateNorg(j)
|
||||||
|
else:
|
||||||
|
info "Not updating"
|
||||||
|
else:
|
||||||
|
info "No new Update available."
|
||||||
|
else:
|
||||||
|
debug res.code
|
||||||
|
debug res.body
|
||||||
|
error "Cannot access update URL."
|
||||||
|
except:
|
||||||
|
error getCurrentExceptionMsg()
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import parsecfg
|
import parsecfg
|
||||||
import streams
|
import streams
|
||||||
|
import strutils
|
||||||
|
import sequtils
|
||||||
|
|
||||||
proc getVersion*(): string =
|
proc getVersion*(): string =
|
||||||
let nimble = staticRead("../../norg.nimble")
|
let nimble = staticRead("../../norg.nimble")
|
||||||
|
@ -8,3 +10,11 @@ proc getVersion*(): string =
|
||||||
echo "Compiling version: v", vers
|
echo "Compiling version: v", vers
|
||||||
return "v" & vers
|
return "v" & vers
|
||||||
|
|
||||||
|
proc newerThan*(a,b: string): bool =
|
||||||
|
let new = a[1..^1].split(".").map(proc(s: string): int = s.parseInt())
|
||||||
|
let cur = b[1..^1].split(".").map(proc(s: string): int = s.parseInt())
|
||||||
|
echo "Latest Version: " & a
|
||||||
|
echo "Current Version: " & b
|
||||||
|
for i in countup(0, len(cur) - 1):
|
||||||
|
if new[i] > cur[i]: return true
|
||||||
|
return false
|
||||||
|
|
|
@ -3,36 +3,38 @@
|
||||||
version=$(grep -i version norg.nimble | awk '{print $3}' | sed "s/\"//g" | sed "s/\./_/g")
|
version=$(grep -i version norg.nimble | awk '{print $3}' | sed "s/\"//g" | sed "s/\./_/g")
|
||||||
dir=$(pwd)
|
dir=$(pwd)
|
||||||
echo Building for Linux
|
echo Building for Linux
|
||||||
nimble build -d:linux
|
for cpu in amd64; do
|
||||||
if [ $? != 1 ]; then
|
nimble build -d:linux --cpu:$cpu
|
||||||
|
if [ $? != 1 ]; then
|
||||||
echo "Compressing..."
|
echo "Compressing..."
|
||||||
cd bin || exit
|
cd bin || exit
|
||||||
tar cvzf "norg_linux_$version.tar.gz" norg
|
tar cvzf "norg_linux_$cpu-$version.tar.gz" norg
|
||||||
rm norg
|
rm norg
|
||||||
cd "$dir" || exit
|
cd "$dir" || exit
|
||||||
echo Done.
|
echo Done.
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo Building for FreeBSD
|
echo Building for FreeBSD
|
||||||
nimble build -d:freebsd
|
nimble build -d:freebsd --cpu:$cpu
|
||||||
if [ $? != 1 ]; then
|
if [ $? != 1 ]; then
|
||||||
echo "Compressing..."
|
echo "Compressing..."
|
||||||
cd bin || exit
|
cd bin || exit
|
||||||
tar cvzf "norg_freebsd_$version.tar.gz" norg
|
tar cvzf "norg_freebsd_$cpu-$version.tar.gz" norg
|
||||||
rm norg
|
rm norg
|
||||||
cd "$dir" || exit
|
cd "$dir" || exit
|
||||||
echo Done.
|
echo Done.
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo Building for Windows
|
echo Building for Windows
|
||||||
nimble build -d:mingw
|
nimble build -d:mingw --cpu:$cpu
|
||||||
if [ $? != 1 ]; then
|
if [ $? != 1 ]; then
|
||||||
echo "Zipping..."
|
echo "Zipping..."
|
||||||
cd bin || exit
|
cd bin || exit
|
||||||
cp ../resources/windows/lib* ./
|
cp ../resources/windows/lib* ./
|
||||||
zip "norg_windows_$version.zip" norg.exe lib*
|
zip "norg_windows_$cpu-$version.zip" norg.exe lib*
|
||||||
rm ./lib*
|
rm ./lib*
|
||||||
cd "$dir" || exit
|
cd "$dir" || exit
|
||||||
rm bin/norg.exe
|
rm bin/norg.exe
|
||||||
echo Done.
|
echo Done.
|
||||||
fi
|
fi
|
||||||
|
done
|
||||||
|
|
Loading…
Reference in a new issue