diff --git a/app.go b/app.go index 3a3fff3..50aff01 100644 --- a/app.go +++ b/app.go @@ -4,9 +4,10 @@ import ( "context" "embed" "os" - "sync" "time" + "github.com/ad-on-is/resticity/internal" + "github.com/charmbracelet/log" "github.com/energye/systray" "github.com/go-co-op/gocron/v2" @@ -18,117 +19,19 @@ import ( // App struct type App struct { ctx context.Context - scheduler *Scheduler - restic *Restic - settings *Settings + scheduler *internal.Scheduler + restic *internal.Restic + settings *internal.Settings assets *embed.FS } -type Settings struct { - file string - Config Config `json:"config"` - mux sync.Mutex -} - -type S3Options struct { - S3Key string `json:"s3_key"` - S3Secret string `json:"s3_secret"` -} - -type AzureOptions struct { - AzureAccountName string `json:"azure_account_name"` - AzureAccountKey string `json:"azure_account_key"` - AzureAccountSas string `json:"azure_account_sas"` -} - -type GcsOptions struct { - GoogleProjectId string `json:"google_project_id"` - GoogleApplicationCredentials string `json:"google_application_credentials"` -} - -type Options struct { - S3Options - AzureOptions - GcsOptions -} - -type GroupKey struct { - Hostname string `json:"hostname"` - Paths []string `json:"paths"` - Tags []string `json:"tags"` -} - -type SnapshotGroup struct { - GroupKey GroupKey `json:"group_key"` - Snapshots []Snapshot `json:"snapshots"` -} - -type Snapshot struct { - Id string `json:"id"` - Time time.Time `json:"time"` - Paths []string `json:"paths"` - Hostname string `json:"hostname"` - Username string `json:"username"` - UID uint32 `json:"uid"` - GID uint32 `json:"gid"` - ShortId string `json:"short_id"` - Tags []string `json:"tags"` - ProgramVersion string `json:"program_version"` -} - -type FileDescriptor struct { - Name string `json:"name"` - Type string `json:"type"` - Path string `json:"path"` - Size uint32 `json:"size"` - Mtime string `json:"mtime"` -} - -type Mount struct { - RepositoryId string `json:"repository_id"` - Path string `json:"path"` -} - -type Repository struct { - Id string `json:"id"` - Name string `json:"name"` - Type string `json:"type"` - PruneParams [][]string `json:"prune_params"` - Path string `json:"path"` - Password string `json:"password"` - Options Options `json:"options"` -} - -type Backup struct { - Id string `json:"id"` - Path string `json:"path"` - Name string `json:"name"` - Cron string `json:"cron"` - BackupParams [][]string `json:"backup_params"` - Targets []string `json:"targets"` -} - -type Schedule struct { - Id string `json:"id"` - Action string `json:"action"` - BackupId string `json:"backup_id"` - ToRepositoryId string `json:"to_repository_id"` - FromRepositoryId string `json:"from_repository_id"` - Cron string `json:"cron"` - Active bool `json:"active"` - LastRun string `json:"last_run"` - LastError string `json:"last_error"` -} - -type Config struct { - Mounts []Mount `json:"mounts"` - Repositories []Repository `json:"repositories"` - Backups []Backup `json:"backups"` - Schedules []Schedule `json:"schedules"` -} - // NewApp creates a new App application struct -func NewApp(restic *Restic, scheduler *Scheduler, settings *Settings, assets *embed.FS) *App { +func NewApp( + restic *internal.Restic, + scheduler *internal.Scheduler, + settings *internal.Settings, + assets *embed.FS, +) *App { return &App{restic: restic, scheduler: scheduler, settings: settings} } @@ -140,13 +43,13 @@ func (a *App) toggleSysTrayIcon() { "/home/adonis/Development/Go/resticity/frontend/public/appicon_active.png", ) - _, err := a.scheduler.gocron.NewJob( + _, err := a.scheduler.Gocron.NewJob( gocron.DurationJob(500*time.Millisecond), gocron.NewTask(func() { running := funk.Filter( a.scheduler.Jobs, - func(j Job) bool { return j.Running == true }, - ).([]Job) + func(j internal.Job) bool { return j.Running == true }, + ).([]internal.Job) if len(running) > 0 { systray.SetIcon(active_icon) } else { @@ -223,6 +126,6 @@ func (a *App) SelectFile(title string) string { return "" } -func (a *App) FakeCreateForModels() (SnapshotGroup, Repository, Backup, Config, Schedule, FileDescriptor) { - return SnapshotGroup{}, Repository{}, Backup{}, Config{}, Schedule{}, FileDescriptor{} +func (a *App) FakeCreateForModels() (internal.SnapshotGroup, internal.Repository, internal.Backup, internal.Config, internal.Schedule, internal.FileDescriptor) { + return internal.SnapshotGroup{}, internal.Repository{}, internal.Backup{}, internal.Config{}, internal.Schedule{}, internal.FileDescriptor{} } diff --git a/cmd/server/main.go b/cmd/server/main.go new file mode 100644 index 0000000..8df0389 --- /dev/null +++ b/cmd/server/main.go @@ -0,0 +1,32 @@ +package main + +import ( + "bytes" + "flag" + + "github.com/ad-on-is/resticity/internal" + + "github.com/charmbracelet/log" +) + +func main() { + log.SetLevel(log.DebugLevel) + flagConfigFile := "" + flag.StringVar(&flagConfigFile, "config", "", "Specify a config file") + flag.StringVar(&flagConfigFile, "c", "", "Specify a config file") + flag.Parse() + log.Info("settings file", flagConfigFile) + errb := bytes.NewBuffer([]byte{}) + outb := bytes.NewBuffer([]byte{}) + outputChan := make(chan internal.ChanMsg) + settings := internal.NewSettings(flagConfigFile) + restic := internal.NewRestic(errb, outb, settings) + if scheduler, err := internal.NewScheduler(settings, restic, &outputChan); err == nil { + (scheduler).RescheduleBackups() + internal.RunServer(scheduler, restic, settings, errb, outb, &outputChan) + + } else { + log.Error("Init scheduler", "error", err) + } + +} diff --git a/com.adisdurakovic.Resticity.yml b/com.adisdurakovic.Resticity.yml deleted file mode 100644 index a130df5..0000000 --- a/com.adisdurakovic.Resticity.yml +++ /dev/null @@ -1,13 +0,0 @@ -id: com.adisdurakovic.Resticity -runtime: org.freedesktop.Platform -runtime-version: '23.08' -sdk: org.freedesktop.Sdk -command: resticity -modules: - - name: resticity - buildsystem: simple - build-commands: - - install -D resticity /app/bin/resticity - sources: - - type: file - path: resticity \ No newline at end of file diff --git a/frontend/wailsjs/go/main/App.d.ts b/frontend/wailsjs/go/main/App.d.ts index 62d1e2f..6a54b7f 100755 --- a/frontend/wailsjs/go/main/App.d.ts +++ b/frontend/wailsjs/go/main/App.d.ts @@ -1,9 +1,9 @@ // Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL // This file is automatically generated. DO NOT EDIT -import {main} from '../models'; +import {internal} from '../models'; import {uuid} from '../models'; -export function FakeCreateForModels():Promise; +export function FakeCreateForModels():Promise; export function SelectDirectory(arg1:string):Promise; diff --git a/frontend/wailsjs/go/models.ts b/frontend/wailsjs/go/models.ts index ba83b47..dcaba6d 100755 --- a/frontend/wailsjs/go/models.ts +++ b/frontend/wailsjs/go/models.ts @@ -1,4 +1,4 @@ -export namespace main { +export namespace internal { export interface Backup { id: string; diff --git a/go.mod b/go.mod index ebea38e..36a1785 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module resticity +module github.com/ad-on-is/resticity go 1.21 diff --git a/helpers.go b/helpers.go deleted file mode 100644 index d3a54dd..0000000 --- a/helpers.go +++ /dev/null @@ -1,14 +0,0 @@ -package main - -func StringArrayContains(alpha []string, str string) bool { - - // iterate using the for loop - for i := 0; i < len(alpha); i++ { - // check - if alpha[i] == str { - // return true - return true - } - } - return false -} diff --git a/restic.go b/internal/restic.go similarity index 99% rename from restic.go rename to internal/restic.go index 017f39a..53ba8ce 100644 --- a/restic.go +++ b/internal/restic.go @@ -1,4 +1,4 @@ -package main +package internal import ( "bufio" diff --git a/scheduler.go b/internal/scheduler.go similarity index 97% rename from scheduler.go rename to internal/scheduler.go index 69388c8..bbe41fe 100644 --- a/scheduler.go +++ b/internal/scheduler.go @@ -1,4 +1,4 @@ -package main +package internal import ( "context" @@ -23,7 +23,7 @@ type Job struct { } type Scheduler struct { - gocron gocron.Scheduler + Gocron gocron.Scheduler restic *Restic Jobs []Job jmu sync.Mutex @@ -38,8 +38,8 @@ func NewScheduler(settings *Settings, restic *Restic, ch *chan ChanMsg) (*Schedu s.restic = restic s.outputCh = ch if gc, err := gocron.NewScheduler(); err == nil { - s.gocron = gc - s.gocron.Start() + s.Gocron = gc + s.Gocron.Start() return s, nil } else { return nil, err @@ -142,7 +142,7 @@ func (s *Scheduler) RescheduleBackups() { jobDef = gocron.CronJob(schedule.Cron, false) } - j, err := s.gocron.NewJob( + j, err := s.Gocron.NewJob( jobDef, gocron.NewTask(func() { diff --git a/server.go b/internal/server.go similarity index 93% rename from server.go rename to internal/server.go index f17bb7e..3252cd4 100644 --- a/server.go +++ b/internal/server.go @@ -1,4 +1,4 @@ -package main +package internal import ( "bytes" @@ -15,32 +15,6 @@ import ( "github.com/thoas/go-funk" ) -type BrowseData struct { - Path string `json:"path"` -} - -type MountData struct { - Path string `json:"path"` -} - -type RestoreData struct { - RootPath string `json:"root_path"` - FromPath string `json:"from_path"` - ToPath string `json:"to_path"` -} - -type Output struct { - Id string `json:"id"` - Out any `json:"out"` -} - -type MsgJob struct { - Id string `json:"id"` - Schedule Schedule `json:"schedule"` - Running bool `json:"running"` - Force bool `json:"force"` -} - func RunServer( scheduler *Scheduler, restic *Restic, diff --git a/settings.go b/internal/settings.go similarity index 99% rename from settings.go rename to internal/settings.go index d7986b5..1a71db3 100644 --- a/settings.go +++ b/internal/settings.go @@ -1,4 +1,4 @@ -package main +package internal import ( "encoding/json" diff --git a/internal/types.go b/internal/types.go new file mode 100644 index 0000000..8183e41 --- /dev/null +++ b/internal/types.go @@ -0,0 +1,141 @@ +package internal + +import ( + "sync" + "time" +) + +type Settings struct { + file string + Config Config `json:"config"` + mux sync.Mutex +} + +type S3Options struct { + S3Key string `json:"s3_key"` + S3Secret string `json:"s3_secret"` +} + +type AzureOptions struct { + AzureAccountName string `json:"azure_account_name"` + AzureAccountKey string `json:"azure_account_key"` + AzureAccountSas string `json:"azure_account_sas"` +} + +type GcsOptions struct { + GoogleProjectId string `json:"google_project_id"` + GoogleApplicationCredentials string `json:"google_application_credentials"` +} + +type Options struct { + S3Options + AzureOptions + GcsOptions +} + +type GroupKey struct { + Hostname string `json:"hostname"` + Paths []string `json:"paths"` + Tags []string `json:"tags"` +} + +type SnapshotGroup struct { + GroupKey GroupKey `json:"group_key"` + Snapshots []Snapshot `json:"snapshots"` +} + +type Snapshot struct { + Id string `json:"id"` + Time time.Time `json:"time"` + Paths []string `json:"paths"` + Hostname string `json:"hostname"` + Username string `json:"username"` + UID uint32 `json:"uid"` + GID uint32 `json:"gid"` + ShortId string `json:"short_id"` + Tags []string `json:"tags"` + ProgramVersion string `json:"program_version"` +} + +type FileDescriptor struct { + Name string `json:"name"` + Type string `json:"type"` + Path string `json:"path"` + Size uint32 `json:"size"` + Mtime string `json:"mtime"` +} + +type Mount struct { + RepositoryId string `json:"repository_id"` + Path string `json:"path"` +} + +type Repository struct { + Id string `json:"id"` + Name string `json:"name"` + Type string `json:"type"` + PruneParams [][]string `json:"prune_params"` + Path string `json:"path"` + Password string `json:"password"` + Options Options `json:"options"` +} + +type Backup struct { + Id string `json:"id"` + Path string `json:"path"` + Name string `json:"name"` + Cron string `json:"cron"` + BackupParams [][]string `json:"backup_params"` + Targets []string `json:"targets"` +} + +type Schedule struct { + Id string `json:"id"` + Action string `json:"action"` + BackupId string `json:"backup_id"` + ToRepositoryId string `json:"to_repository_id"` + FromRepositoryId string `json:"from_repository_id"` + Cron string `json:"cron"` + Active bool `json:"active"` + LastRun string `json:"last_run"` + LastError string `json:"last_error"` +} + +type Config struct { + Mounts []Mount `json:"mounts"` + Repositories []Repository `json:"repositories"` + Backups []Backup `json:"backups"` + Schedules []Schedule `json:"schedules"` +} + +type BrowseData struct { + Path string `json:"path"` +} + +type MountData struct { + Path string `json:"path"` +} + +type RestoreData struct { + RootPath string `json:"root_path"` + FromPath string `json:"from_path"` + ToPath string `json:"to_path"` +} + +type Output struct { + Id string `json:"id"` + Out any `json:"out"` +} + +type MsgJob struct { + Id string `json:"id"` + Schedule Schedule `json:"schedule"` + Running bool `json:"running"` + Force bool `json:"force"` +} + +type ChanMsg struct { + Id string `json:"id"` + Out string `json:"out"` + Schedule Schedule `json:"schedule"` +} diff --git a/main.go b/main.go index 7edccb5..bcf2b40 100644 --- a/main.go +++ b/main.go @@ -5,6 +5,8 @@ import ( "embed" "flag" + "github.com/ad-on-is/resticity/internal" + "github.com/charmbracelet/log" "github.com/wailsapp/wails/v2" "github.com/wailsapp/wails/v2/pkg/logger" @@ -15,45 +17,38 @@ import ( //go:embed all:frontend/.output/public var assets embed.FS -type ChanMsg struct { - Id string `json:"id"` - Out string `json:"out"` - Schedule Schedule `json:"schedule"` -} - func main() { log.SetLevel(log.DebugLevel) flagConfigFile := "" - flagServer := false flagBackground := false flag.StringVar(&flagConfigFile, "config", "", "Specify a config file") flag.StringVar(&flagConfigFile, "c", "", "Specify a config file") - flag.BoolVar(&flagServer, "server", false, "Run as server") - flag.BoolVar(&flagServer, "s", false, "Run as server") flag.BoolVar(&flagBackground, "background", false, "Run in background mode") flag.BoolVar(&flagBackground, "b", false, "Run in background mode") flag.Parse() log.Info("settings file", flagConfigFile) errb := bytes.NewBuffer([]byte{}) outb := bytes.NewBuffer([]byte{}) - outputChan := make(chan ChanMsg) - settings := NewSettings(flagConfigFile) - restic := NewRestic(errb, outb, settings) - if scheduler, err := NewScheduler(settings, restic, &outputChan); err == nil { + outputChan := make(chan internal.ChanMsg) + settings := internal.NewSettings(flagConfigFile) + restic := internal.NewRestic(errb, outb, settings) + if scheduler, err := internal.NewScheduler(settings, restic, &outputChan); err == nil { (scheduler).RescheduleBackups() - if flagServer { - RunServer(scheduler, restic, settings, errb, outb, &outputChan) - } else { - go RunServer(scheduler, restic, settings, errb, outb, &outputChan) - Desktop(scheduler, restic, settings, flagBackground) - } + + go internal.RunServer(scheduler, restic, settings, errb, outb, &outputChan) + Desktop(scheduler, restic, settings, flagBackground) } else { log.Error("Init scheduler", "error", err) } } -func Desktop(scheduler *Scheduler, restic *Restic, settings *Settings, isHidden bool) { +func Desktop( + scheduler *internal.Scheduler, + restic *internal.Restic, + settings *internal.Settings, + isHidden bool, +) { // Create an instance of the app structure app := NewApp(restic, scheduler, settings, &assets) // Create application with options