import ../model/config_type import ../model/state_type import ../model/borg_type import ../notifier/notifier import ../utils/actions import strutils import strformat import sequtils import osproc import times import os import nativesockets proc genArchiveName(): string = let hostname = getHostname() let ts = getTime().format("yyyy-MM-dd'T'HH:mm:ss'.'ffffff") return fmt"{hostname}-{ts}" proc genCommand(cmd: string, repo: string, others: seq[string]): string = let args = others.join(" ") let cmd = fmt"{BORG_BIN} {cmd} {repo} {args}" return cmd proc run(cmd: string): int = echo fmt"Trying to run : {cmd}" try: let res = execProcess(cmd) echo res except: echo getCurrentExceptionMsg() proc runDiscard(cmd: string): int = echo fmt"Trying to run : {cmd}" try: let res = execCmd(cmd) return res except: echo getCurrentExceptionMsg() return 1 proc initRepo(nc: NorgConfig, repo: Repository): int = return runDiscard genCommand(cmd = "init", repo = repo.path, others = nc.args.others) proc createArchive(nc: NorgConfig, repo: Repository, archivename: string, retry: int = 0): int = let others = concat(nc.source_directories, nc.args.others) let res = run genCommand(cmd = "create", repo = archivename, others = others) if res == 1: sleep 15 * 1000 # 15 seconds if retry == nc.retries: return 1 else: return createArchive(nc, repo, archivename, retry + 1) return res proc backupSources(nc: NorgConfig, repo: Repository): int = let start_time = now() notify(nc.notifiers, state=Running) let end_time = now() let archivename = repo.path & "::" & genArchiveName() let res = createArchive(nc, repo, archivename) let total = (end_time - start_time).inMilliSeconds() case res of 0: notify(nc.notifiers, state=Success, runtime=total) of 1: notify(nc.notifiers, state=Failure, runtime=total) else: notify(nc.notifiers, state=Failure, runtime=total) return res proc listArchives(nc: NorgConfig, repo: Repository): int = return run genCommand(cmd = "list", repo = repo.path, others = nc.args.others) proc mountArchive(nc: NorgConfig, repo: Repository): int = let archive = repo.path & "::" & nc.args.others[0] let others = nc.args.others[1..^1] let ok = runDiscard genCommand(cmd = "mount", repo = archive, others = others) if ok == 0: echo fmt"Mounted {archive} at {others[0]}" else: echo "Failed to mount ", archive proc unmountArchive(nc: NorgConfig): int = let ok = runDiscard genCommand(cmd = "umount", repo = "", others = nc.args.others) if ok == 0: echo "Unmounted ", nc.args.others[0] else: echo "Failed to unmount ", nc.args.others[0] proc isEmpty(dir: string): bool = var count = 0 for idx, f in walkDir(dir): return false #count += 1 return count == 0 proc extractArchive(nc: NorgConfig, repo: Repository): int = let archive = fmt"{repo.path}::{nc.args.others[0]}" var others = nc.args.others[1..^1] if nc.args.extract_destination != "": discard existsOrCreateDir(nc.args.extract_destination) setCurrentDir(nc.args.extract_destination) let dir = getCurrentDir() if dir.isEmpty(): echo "Restoring..." let ok = run(genCommand(cmd = "extract", repo = archive, others = others)) return ok else: echo "Not restoring to non-empty destination\r\nPlease use the --destination flag" proc pruneRepo(nc: NorgConfig, repo: Repository): int = echo "Not Yet Implemented." discard proc compactRepo(nc: NorgConfig, repo: Repository): int = echo "Not Yet Implemented." discard proc checkRepo(nc: NorgConfig, repo: Repository): int = echo "Not Yet Implemented." discard proc execute*(nc: NorgConfig) = run_actions(norg_config.actions.before_everything) for repo in nc.repositories: run_actions(norg_config.actions.before_actions) case nc.args.borg_cmd of INIT: discard initRepo(nc, repo) of CREATE: run_actions(norg_config.actions.before_backup) discard backupSources(nc, repo) run_actions(norg_config.actions.after_backup) of LIST: discard listArchives(nc, repo) of MOUNT: discard mountArchive(nc, repo) of UMOUNT: discard unmountArchive(nc) of EXTRACT: run_actions(norg_config.actions.before_extract) discard extractArchive(nc, repo) run_actions(norg_config.actions.after_extract) of PRUNE: run_actions(norg_config.actions.before_prune) discard pruneRepo(nc, repo) run_actions(norg_config.actions.after_prune) of COMPACT: run_actions(norg_config.actions.before_compact) discard compactRepo(nc, repo) run_actions(norg_config.actions.after_compact) of CHECK: run_actions(norg_config.actions.before_check) discard checkRepo(nc, repo) run_actions(norg_config.actions.after_check) run_actions(norg_config.actions.after_actions) delEncryptionPassphraseInfo() run_actions(norg_config.actions.after_everything)