mirror of
https://github.com/Mikescher/kpsync.git
synced 2025-08-25 16:38:06 +02:00
non-functional wip state
This commit is contained in:
commit
e7293464c1
38
.gitignore
vendored
Normal file
38
.gitignore
vendored
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
|
||||||
|
########## GOLAND ##########
|
||||||
|
|
||||||
|
.idea/**/workspace.xml
|
||||||
|
.idea/**/tasks.xml
|
||||||
|
.idea/**/usage.statistics.xml
|
||||||
|
.idea/**/dictionaries
|
||||||
|
.idea/**/shelf
|
||||||
|
.idea/**/aws.xml
|
||||||
|
.idea/**/contentModel.xml
|
||||||
|
.idea/**/dataSources/
|
||||||
|
.idea/**/dataSources.ids
|
||||||
|
.idea/**/dataSources.local.xml
|
||||||
|
.idea/**/sqlDataSources.xml
|
||||||
|
.idea/**/dynamic.xml
|
||||||
|
.idea/**/uiDesigner.xml
|
||||||
|
.idea/**/dbnavigator.xml
|
||||||
|
.idea/**/gradle.xml
|
||||||
|
.idea/**/libraries
|
||||||
|
.idea/**/mongoSettings.xml
|
||||||
|
*.iws
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
.idea/httpRequests
|
||||||
|
.idea/caches/build_file_checksums.ser
|
||||||
|
.idea/$CACHE_FILE$
|
||||||
|
|
||||||
|
########## Linux ##########
|
||||||
|
|
||||||
|
*~
|
||||||
|
.fuse_hidden*
|
||||||
|
.directory
|
||||||
|
.Trash-*
|
||||||
|
.nfs*
|
||||||
|
|
||||||
|
########## Custom ##########
|
||||||
|
|
||||||
|
|
||||||
|
_out/*
|
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
11
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
11
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="LanguageDetectionInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
|
||||||
|
<option name="processCode" value="true" />
|
||||||
|
<option name="processLiterals" value="true" />
|
||||||
|
<option name="processComments" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
</profile>
|
||||||
|
</component>
|
9
.idea/kpsync.iml
generated
Normal file
9
.idea/kpsync.iml
generated
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="WEB_MODULE" version="4">
|
||||||
|
<component name="Go" enabled="true" />
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$" />
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/kpsync.iml" filepath="$PROJECT_DIR$/.idea/kpsync.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
43
Makefile
Normal file
43
Makefile
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
|
||||||
|
# ./firefox-sync-client
|
||||||
|
#########################
|
||||||
|
|
||||||
|
build: enums
|
||||||
|
CGO_ENABLED=0 go build -o _out/kpsync ./cmd/kpsync
|
||||||
|
|
||||||
|
run: build
|
||||||
|
./_out/ffsclient
|
||||||
|
|
||||||
|
clean:
|
||||||
|
go clean
|
||||||
|
rm -rf ./_out/*
|
||||||
|
|
||||||
|
enums:
|
||||||
|
go generate ./...
|
||||||
|
|
||||||
|
package:
|
||||||
|
#
|
||||||
|
# Manually do beforehand:
|
||||||
|
# - Update version in version.go
|
||||||
|
# - Create tag
|
||||||
|
# - Commit
|
||||||
|
#
|
||||||
|
|
||||||
|
go clean
|
||||||
|
rm -rf ./_out/*
|
||||||
|
|
||||||
|
GOARCH=386 GOOS=linux CGO_ENABLED=0 go build -o _out/kpsync_linux-386-static ./cmd/cli # Linux - 32 bit
|
||||||
|
GOARCH=amd64 GOOS=linux CGO_ENABLED=0 go build -o _out/kpsync_linux-amd64-static ./cmd/cli # Linux - 64 bit
|
||||||
|
GOARCH=arm64 GOOS=linux CGO_ENABLED=0 go build -o _out/kpsync_linux-arm64-static ./cmd/cli # Linux - ARM
|
||||||
|
GOARCH=386 GOOS=linux go build -o _out/kpsync_linux-386 ./cmd/cli # Linux - 32 bit
|
||||||
|
GOARCH=amd64 GOOS=linux go build -o _out/kpsync_linux-amd64 ./cmd/cli # Linux - 64 bit
|
||||||
|
GOARCH=arm64 GOOS=linux go build -o _out/kpsync_linux-arm64 ./cmd/cli # Linux - ARM
|
||||||
|
GOARCH=386 GOOS=windows go build -o _out/kpsync_win-386.exe -tags timetzdata -ldflags "-w -s" ./cmd/cli # Windows - 32 bit
|
||||||
|
GOARCH=amd64 GOOS=windows go build -o _out/kpsync_win-amd64.exe -tags timetzdata -ldflags "-w -s" ./cmd/cli # Windows - 64 bit
|
||||||
|
GOARCH=arm64 GOOS=windows go build -o _out/kpsync_win-arm64.exe -tags timetzdata -ldflags "-w -s" ./cmd/cli # Windows - ARM
|
||||||
|
GOARCH=amd64 GOOS=darwin go build -o _out/kpsync_macos-amd64 ./cmd/cli # macOS - 32 bit
|
||||||
|
GOARCH=amd64 GOOS=darwin go build -o _out/kpsync_macos-amd64 ./cmd/cli # macOS - 64 bit
|
||||||
|
GOARCH=amd64 GOOS=openbsd go build -o _out/kpsync_openbsd-amd64 ./cmd/cli # OpenBSD - 64 bit
|
||||||
|
GOARCH=arm64 GOOS=openbsd go build -o _out/kpsync_openbsd-arm64 ./cmd/cli # OpenBSD - ARM
|
||||||
|
GOARCH=amd64 GOOS=freebsd go build -o _out/kpsync_freebsd-amd64 ./cmd/cli # FreeBSD - 64 bit
|
||||||
|
GOARCH=arm64 GOOS=freebsd go build -o _out/kpsync_freebsd-arm64 ./cmd/cli # FreeBSD - ARM
|
19
TODO.md
Normal file
19
TODO.md
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
|
||||||
|
- log to linux fd (pipe) to open terminal
|
||||||
|
|
||||||
|
- show state in tray
|
||||||
|
|
||||||
|
- tray menu
|
||||||
|
- force sync
|
||||||
|
- ~ current Etag
|
||||||
|
- ~ current SHA
|
||||||
|
- ~ last sync ts
|
||||||
|
- check sync
|
||||||
|
- quit
|
||||||
|
- show log (open terminal /w log)
|
||||||
|
|
||||||
|
- config via json + params override
|
||||||
|
|
||||||
|
- colorful log
|
||||||
|
- download/upload progress log
|
73
app/application.go
Normal file
73
app/application.go
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"fyne.io/systray"
|
||||||
|
"mikescher.com/kpsync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Application struct {
|
||||||
|
config kpsync.Config
|
||||||
|
|
||||||
|
trayReady bool
|
||||||
|
sigStopChan chan bool
|
||||||
|
sigErrChan chan error
|
||||||
|
|
||||||
|
dbFile string
|
||||||
|
stateFile string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewApplication() *Application {
|
||||||
|
|
||||||
|
cfg := kpsync.LoadConfig()
|
||||||
|
|
||||||
|
return &Application{
|
||||||
|
config: cfg,
|
||||||
|
trayReady: false,
|
||||||
|
sigStopChan: make(chan bool, 128),
|
||||||
|
sigErrChan: make(chan error, 128),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *Application) Run() {
|
||||||
|
|
||||||
|
go func() { app.initTray() }()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
err := app.initSync()
|
||||||
|
if err != nil {
|
||||||
|
app.sigErrChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = app.runSyncLoop()
|
||||||
|
if err != nil {
|
||||||
|
app.sigErrChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
sigTerm := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(sigTerm, os.Interrupt, syscall.SIGTERM)
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-sigTerm:
|
||||||
|
|
||||||
|
// TODO term
|
||||||
|
|
||||||
|
case _ = <-app.sigErrChan:
|
||||||
|
|
||||||
|
// TODO stop
|
||||||
|
|
||||||
|
case _ = <-app.sigStopChan:
|
||||||
|
|
||||||
|
// TODO stop
|
||||||
|
}
|
||||||
|
|
||||||
|
if app.trayReady {
|
||||||
|
systray.Quit()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
67
app/sync.go
Normal file
67
app/sync.go
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
|
||||||
|
"git.blackforestbytes.com/BlackForestBytes/goext/exerr"
|
||||||
|
"mikescher.com/kpsync/assets"
|
||||||
|
"mikescher.com/kpsync/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (app *Application) initSync() error {
|
||||||
|
|
||||||
|
err := os.MkdirAll(app.config.WorkDir, os.ModePerm)
|
||||||
|
if err != nil {
|
||||||
|
return exerr.Wrap(err, "").Build()
|
||||||
|
}
|
||||||
|
|
||||||
|
app.dbFile = path.Join(app.config.WorkDir, path.Base(app.config.LocalFallback))
|
||||||
|
app.stateFile = path.Join(app.config.WorkDir, "kpsync.state")
|
||||||
|
|
||||||
|
state := app.readState()
|
||||||
|
|
||||||
|
needsDownload := true
|
||||||
|
|
||||||
|
if state != nil && fileExists(app.dbFile) {
|
||||||
|
localCS, err := app.calcLocalChecksum()
|
||||||
|
if err != nil {
|
||||||
|
log.LogError("Failed to calculate local database checksum", err)
|
||||||
|
} else if localCS == state.Checksum {
|
||||||
|
remoteETag, err := app.getRemoteETag()
|
||||||
|
if err != nil {
|
||||||
|
log.LogError("Failed to get remote ETag", err)
|
||||||
|
} else if remoteETag == state.ETag {
|
||||||
|
|
||||||
|
log.LogInfo(fmt.Sprintf("Found local database matching remote database - skip initial download"))
|
||||||
|
log.LogInfo(fmt.Sprintf("Checksum (cached) := %s", state.Checksum))
|
||||||
|
log.LogInfo(fmt.Sprintf("Checksum (local) := %s", localCS))
|
||||||
|
log.LogInfo(fmt.Sprintf("ETag (cached) := %s", state.ETag))
|
||||||
|
log.LogInfo(fmt.Sprintf("ETag (remote) := %s", remoteETag))
|
||||||
|
needsDownload = false
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if needsDownload {
|
||||||
|
func() {
|
||||||
|
fin := app.setTrayState("Downloading database", assets.IconDefault)
|
||||||
|
defer fin()
|
||||||
|
|
||||||
|
log.LogInfo(fmt.Sprintf("Downloading remote database to %s", app.dbFile))
|
||||||
|
|
||||||
|
etag, err := app.downloadDatabase()
|
||||||
|
if err != nil {
|
||||||
|
log.LogError("Failed to download remote database", err)
|
||||||
|
app.sigErrChan <- exerr.Wrap(err, "Failed to download remote database").Build()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *Application) runSyncLoop() error {
|
||||||
|
|
||||||
|
}
|
20
app/tray.go
Normal file
20
app/tray.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fyne.io/systray"
|
||||||
|
"mikescher.com/kpsync/assets"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (app *Application) initTray() {
|
||||||
|
|
||||||
|
trayOnReady := func() {
|
||||||
|
|
||||||
|
systray.SetIcon(assets.IconInit)
|
||||||
|
systray.SetTitle("KeepassXC Sync")
|
||||||
|
systray.SetTooltip("Initializing...")
|
||||||
|
|
||||||
|
app.trayReady = true
|
||||||
|
}
|
||||||
|
|
||||||
|
systray.Run(trayOnReady, nil)
|
||||||
|
}
|
47
app/utils.go
Normal file
47
app/utils.go
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"git.blackforestbytes.com/BlackForestBytes/goext/cryptext"
|
||||||
|
"git.blackforestbytes.com/BlackForestBytes/goext/exerr"
|
||||||
|
)
|
||||||
|
|
||||||
|
func fileExists(p string) bool {
|
||||||
|
_, err := os.Stat(p)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
type State struct {
|
||||||
|
ETag string `json:"etag"`
|
||||||
|
Size int64 `json:"size"`
|
||||||
|
Checksum string `json:"checksum"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *Application) readState() *State {
|
||||||
|
bin, err := os.ReadFile(app.stateFile)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var state State
|
||||||
|
err = json.Unmarshal(bin, &state)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &state
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *Application) calcLocalChecksum() (string, error) {
|
||||||
|
bin, err := os.ReadFile(app.dbFile)
|
||||||
|
if err != nil {
|
||||||
|
return "", exerr.Wrap(err, "").Build()
|
||||||
|
}
|
||||||
|
|
||||||
|
return cryptext.BytesSha256(bin), nil
|
||||||
|
}
|
5
app/webdav.go
Normal file
5
app/webdav.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
func (app *Application) initSync() {
|
||||||
|
|
||||||
|
}
|
14
assets/assets.go
Normal file
14
assets/assets.go
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package assets
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "embed"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed IconInit.png
|
||||||
|
var IconInit []byte
|
||||||
|
|
||||||
|
//go:embed iconDefault.png
|
||||||
|
var IconDefault []byte
|
||||||
|
|
||||||
|
//go:embed iconDownload.png
|
||||||
|
var IconDownload []byte
|
BIN
assets/iconDefault.png
Normal file
BIN
assets/iconDefault.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
17
cmd/cli/main.go
Normal file
17
cmd/cli/main.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.blackforestbytes.com/BlackForestBytes/goext/exerr"
|
||||||
|
"git.blackforestbytes.com/BlackForestBytes/goext/langext"
|
||||||
|
"mikescher.com/kpsync/app"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
exerr.Init(exerr.ErrorPackageConfigInit{
|
||||||
|
ZeroLogErrTraces: langext.PFalse,
|
||||||
|
ZeroLogAllTraces: langext.PFalse,
|
||||||
|
})
|
||||||
|
|
||||||
|
kpApp := app.NewApplication()
|
||||||
|
kpApp.Run()
|
||||||
|
}
|
104
config.go
Normal file
104
config.go
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
package kpsync
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/user"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.blackforestbytes.com/BlackForestBytes/goext/langext"
|
||||||
|
"mikescher.com/kpsync/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
WebDAVURL string `json:"webdav_url"`
|
||||||
|
WebDAVUser string `json:"webdav_user"`
|
||||||
|
WebDAVPass string `json:"webdav_pass"`
|
||||||
|
|
||||||
|
LocalFallback string `json:"local_fallback"`
|
||||||
|
|
||||||
|
WorkDir string `json:"work_dir"`
|
||||||
|
|
||||||
|
Debounce int `json:"debounce"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadConfig() Config {
|
||||||
|
var configPath string
|
||||||
|
flag.StringVar(&configPath, "config", "~/.config/kpsync.json", "Path to the configuration file")
|
||||||
|
|
||||||
|
var webdavURL string
|
||||||
|
flag.StringVar(&webdavURL, "webdav_url", "", "WebDAV URL")
|
||||||
|
|
||||||
|
var webdavUser string
|
||||||
|
flag.StringVar(&webdavUser, "webdav_user", "", "WebDAV User")
|
||||||
|
|
||||||
|
var webdavPass string
|
||||||
|
flag.StringVar(&webdavPass, "webdav_pass", "", "WebDAV Password")
|
||||||
|
|
||||||
|
var localFallback string
|
||||||
|
flag.StringVar(&localFallback, "local_fallback", "", "Local fallback database")
|
||||||
|
|
||||||
|
var workDir string
|
||||||
|
flag.StringVar(&workDir, "work_dir", "", "Temporary working directory")
|
||||||
|
|
||||||
|
var debounce int
|
||||||
|
flag.IntVar(&debounce, "debounce", 0, "Debounce before sync (in seconds)")
|
||||||
|
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
if strings.HasSuffix(configPath, "~") {
|
||||||
|
usr, err := user.Current()
|
||||||
|
if err != nil {
|
||||||
|
log.FatalErr("Failed to query users home directory", err)
|
||||||
|
}
|
||||||
|
fmt.Println(usr.HomeDir)
|
||||||
|
|
||||||
|
configPath = strings.TrimSuffix(configPath, "~")
|
||||||
|
configPath = fmt.Sprintf("%s/%s", usr.HomeDir, configPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := os.Stat(configPath); os.IsNotExist(err) && configPath != "" {
|
||||||
|
_ = os.WriteFile(configPath, langext.Must(json.Marshal(Config{
|
||||||
|
WebDAVURL: "https://your-nextcloud-domain.example/remote.php/dav/files/keepass.kdbx",
|
||||||
|
WebDAVUser: "",
|
||||||
|
WebDAVPass: "",
|
||||||
|
LocalFallback: "",
|
||||||
|
WorkDir: "/tmp/kpsync",
|
||||||
|
Debounce: 3500,
|
||||||
|
})), 0644)
|
||||||
|
}
|
||||||
|
|
||||||
|
cfgBin, err := os.ReadFile(configPath)
|
||||||
|
if err != nil {
|
||||||
|
log.FatalErr("Failed to read config file from "+configPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var cfg Config
|
||||||
|
err = json.Unmarshal(cfgBin, &cfg)
|
||||||
|
if err != nil {
|
||||||
|
log.FatalErr("Failed to parse config file from "+configPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if webdavURL != "" {
|
||||||
|
cfg.WebDAVURL = webdavURL
|
||||||
|
}
|
||||||
|
if webdavUser != "" {
|
||||||
|
cfg.WebDAVUser = webdavUser
|
||||||
|
}
|
||||||
|
if webdavPass != "" {
|
||||||
|
cfg.WebDAVPass = webdavPass
|
||||||
|
}
|
||||||
|
if localFallback != "" {
|
||||||
|
cfg.LocalFallback = localFallback
|
||||||
|
}
|
||||||
|
if workDir != "" {
|
||||||
|
cfg.WorkDir = workDir
|
||||||
|
}
|
||||||
|
if debounce > 0 {
|
||||||
|
cfg.Debounce = debounce
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfg
|
||||||
|
}
|
10
go.mod
Normal file
10
go.mod
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
module mikescher.com/kpsync
|
||||||
|
|
||||||
|
go 1.24.6
|
||||||
|
|
||||||
|
require (
|
||||||
|
fyne.io/systray v1.11.0 // indirect
|
||||||
|
git.blackforestbytes.com/BlackForestBytes/goext v0.0.594 // indirect
|
||||||
|
github.com/godbus/dbus/v5 v5.1.0 // indirect
|
||||||
|
golang.org/x/sys v0.34.0 // indirect
|
||||||
|
)
|
8
go.sum
Normal file
8
go.sum
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fyne.io/systray v1.11.0 h1:D9HISlxSkx+jHSniMBR6fCFOUjk1x/OOOJLa9lJYAKg=
|
||||||
|
fyne.io/systray v1.11.0/go.mod h1:RVwqP9nYMo7h5zViCBHri2FgjXF7H2cub7MAq4NSoLs=
|
||||||
|
git.blackforestbytes.com/BlackForestBytes/goext v0.0.594 h1:tFbvEAe7FMvLuW9/RuXXlxsi8/Ve7xVrFxZnk8e/0yU=
|
||||||
|
git.blackforestbytes.com/BlackForestBytes/goext v0.0.594/go.mod h1:vczjjViG013HjA5Ka3VTE7axDgqMChn1EsvEVg9LZnU=
|
||||||
|
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
|
||||||
|
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
|
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||||
|
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
27
log/logger.go
Normal file
27
log/logger.go
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package log
|
||||||
|
|
||||||
|
//TODO
|
||||||
|
|
||||||
|
func Fatal(msg string) {
|
||||||
|
panic(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func FatalErr(msg string, err error) {
|
||||||
|
if err != nil {
|
||||||
|
panic("ERROR: " + msg + "\n" + err.Error())
|
||||||
|
} else {
|
||||||
|
panic("ERROR: " + msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func LogError(msg string, err error) {
|
||||||
|
if err != nil {
|
||||||
|
println("ERROR: " + msg + "\n" + err.Error())
|
||||||
|
} else {
|
||||||
|
println("ERROR: " + msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func LogInfo(msg string) {
|
||||||
|
println("INFO: " + msg)
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user