From 89df6e32041bd44ea582a57197ddcb3512cb299f Mon Sep 17 00:00:00 2001 From: Lukas Werner Date: Wed, 20 Aug 2025 08:10:45 -0700 Subject: [PATCH 1/3] codify ~/.lib loading behavior --- store/database.go | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/store/database.go b/store/database.go index d8651ef..582957f 100644 --- a/store/database.go +++ b/store/database.go @@ -8,6 +8,7 @@ import ( "net/url" "os" "path" + "runtime" "strings" "github.com/mattn/go-sqlite3" @@ -77,11 +78,11 @@ END;`, func Open() (*DB, error) { markStoreLocation := os.Getenv("MARK_STORE_LOCATION") + homedir, err := os.UserHomeDir() + if err != nil { + return nil, errors.Join(errors.New("unable to get homedir"), err) + } if markStoreLocation == "" { - homedir, err := os.UserHomeDir() - if err != nil { - return nil, errors.Join(errors.New("unable to get homedir"), err) - } markStoreLocation = path.Join(homedir, ".config", "mark") } @@ -93,8 +94,18 @@ func Open() (*DB, error) { return nil, errors.Join(errors.New("unable to make mark store changes location in: "+markStoreLocation), err) } + var ext string + switch runtime.GOOS { + case "windows": + ext = ".dll" + case "darwin": + ext = ".dylib" + default: + ext = ".so" + } + sql.Register("cr-sqlite", &sqlite3.SQLiteDriver{ - Extensions: []string{"crsqlite"}, + Extensions: []string{path.Join(homedir, ".lib", "crsqlite"+ext)}, }) sqlDB, err := sql.Open("cr-sqlite", path.Join(markStoreLocation, "data.db")) -- 2.51.2 From ee3a3ff7343a25f3ba40b910dde50c36b2740069 Mon Sep 17 00:00:00 2001 From: Lukas Werner Date: Wed, 20 Aug 2025 08:55:53 -0700 Subject: [PATCH 2/3] feat: add auto install crsqlite --- BUILD.md | 3 +- justfile | 38 +++------------------ store/database.go | 11 +++++-- store/util.go | 84 ++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 98 insertions(+), 38 deletions(-) diff --git a/BUILD.md b/BUILD.md index 42d783f..e4cc23e 100644 --- a/BUILD.md +++ b/BUILD.md @@ -1,4 +1,3 @@ # How to build -1. Ensure crsqlite is available in dynamic library loading path -2. `go build --tags "fts5" .` +1. `go build --tags "fts5" .` diff --git a/justfile b/justfile index dde1113..dc2ece1 100644 --- a/justfile +++ b/justfile @@ -2,39 +2,12 @@ default: setup install # Variables home_dir := env_var('HOME') -crsqlite_version := "v0.16.3" -os := `go env GOOS` -shell_rc := if path_exists(home_dir + "/.zshrc") == "true" { ".zshrc" } else { ".bashrc" } - -_arch := `go env GOARCH` -cpu_arch := if _arch == "arm64" { "aarch64" } else { _arch } - -# Show current configuration -vars: - @echo "CRSQLite Version: {{crsqlite_version}}" - @echo "OS: {{os}}" - @echo "CPU Architecture: {{cpu_arch}}" - @echo "Shell RC file: {{shell_rc}}" - -# Setup CRSQLite -setup: - #!/usr/bin/env bash - mkdir -p deps - mkdir -p {{home_dir}}/.lib - curl -L -o deps/crsqlite.zip https://github.com/vlcn-io/cr-sqlite/releases/download/{{crsqlite_version}}/crsqlite-{{os}}-{{cpu_arch}}.zip - unzip -o deps/crsqlite.zip -d deps - cp deps/crsqlite.dylib {{home_dir}}/.lib/ - # Add DYLD_LIBRARY_PATH to RC file if not already present - if ! grep -q "export DYLD_LIBRARY_PATH=" "{{home_dir}}/{{shell_rc}}"; then - echo 'export DYLD_LIBRARY_PATH="$HOME/.lib:$DYLD_LIBRARY_PATH"' >> "{{home_dir}}/{{shell_rc}}" - echo "Added DYLD_LIBRARY_PATH to {{shell_rc}}" - fi # Install the Go application install: setup go install -tags "fts5" . -service-install: setup install +mac-service-install: setup install mkdir -p "{{home_dir}}/Library/LaunchAgents" echo "Installing launch agent..." sed 's|$HOME|{{home_dir}}|g' template.plist > "{{home_dir}}/Library/LaunchAgents/com.lukaswerner.mark.server.plist" @@ -43,26 +16,25 @@ service-install: setup install echo "Launch agent installed and loaded" # Uninstall the launch agent -service-uninstall: +mac-service-uninstall: launchctl unload "{{home_dir}}/Library/LaunchAgents/com.lukaswerner.mark.server.plist" 2>/dev/null || true rm -f "{{home_dir}}/Library/LaunchAgents/com.lukaswerner.mark.server.plist" echo "Launch agent uninstalled" # Check status of the service -status: +mac-status: launchctl list | grep "com.lukaswerner.mark.server" || echo "Service not running" # View logs -logs: +mac-logs: echo "=== STDOUT ===" cat /tmp/mark.server.stdout.log 2>/dev/null || echo "No stdout log found" echo -e "\n=== STDERR ===" cat /tmp/mark.server.stderr.log 2>/dev/null || echo "No stderr log found" # Restart the service -restart: service-uninstall service-install +mac-restart: mac-service-uninstall mac-service-install # Clean up everything clean: - rm -rf deps rm -f {{home_dir}}/.lib/crsqlite.dylib diff --git a/store/database.go b/store/database.go index 582957f..79e0913 100644 --- a/store/database.go +++ b/store/database.go @@ -14,6 +14,8 @@ import ( "github.com/mattn/go-sqlite3" ) +const CRSQLITE_VERSION = "v0.16.3" + type requirement struct { name string definition string @@ -103,9 +105,14 @@ func Open() (*DB, error) { default: ext = ".so" } - + if !DoesFileExist(path.Join(homedir, ".lib", "crsqlite"+ext)) { + err = downloadCrSqlite(path.Join(homedir, ".lib"), "crsqlite"+ext) + if err != nil { + return nil, errors.Join(errors.New("unable to download crsqlite"), err) + } + } sql.Register("cr-sqlite", &sqlite3.SQLiteDriver{ - Extensions: []string{path.Join(homedir, ".lib", "crsqlite"+ext)}, + Extensions: []string{path.Join(homedir, ".lib", "crsqlite")}, }) sqlDB, err := sql.Open("cr-sqlite", path.Join(markStoreLocation, "data.db")) diff --git a/store/util.go b/store/util.go index f6dc2a1..44163e9 100644 --- a/store/util.go +++ b/store/util.go @@ -1,6 +1,15 @@ package store -import "os" +import ( + "archive/zip" + "errors" + "fmt" + "io" + "net/http" + "os" + "path" + "runtime" +) func EnsureDirExists(path string) error { if _, err := os.Stat(path); os.IsNotExist(err) { @@ -8,3 +17,76 @@ func EnsureDirExists(path string) error { } return nil } + +func DoesFileExist(path string) bool { + if _, err := os.Stat(path); os.IsNotExist(err) { + return false + } + return true +} + +func downloadCrSqlite(installPath string, filename string) error { + err := EnsureDirExists(installPath) + if err != nil { + return err + } + platformPair := "" + cpu := "" + switch runtime.GOARCH { + case "arm64": + cpu = "aarch64" + case "amd64": + cpu = "x86_64" + case "386": + cpu = "i686" + default: + return fmt.Errorf("unsupported cpu architecture") + } + platformPair = runtime.GOOS + "-" + cpu + if runtime.GOOS == "android" { + platformPair = "aarch64-linux-android" + } + + resp, err := http.Get(fmt.Sprintf("https://github.com/vlcn-io/cr-sqlite/releases/download/%s/crsqlite-%s.zip", CRSQLITE_VERSION, platformPair)) + if err != nil { + return errors.Join(errors.New("unable to download crsqlite version: "+CRSQLITE_VERSION+" on platform: "+platformPair), err) + } + defer resp.Body.Close() + + f, err := os.Create(path.Join(installPath, filename+".zip")) + if err != nil { + return errors.Join(errors.New("unable to make dynamic lib file"), err) + } + _, err = io.Copy(f, resp.Body) + if err != nil { + return err + } + f.Close() + + zr, err := zip.OpenReader(path.Join(installPath, filename+".zip")) + if err != nil { + return errors.Join(errors.New("unable to open zip"), err) + } + zipFile := zr.File[0] + fileContents, err := zipFile.Open() + if err != nil { + return errors.Join(errors.New("unable to access zip file contents"), err) + } + defer fileContents.Close() + osf, err := os.Create(path.Join(installPath, filename)) + + _, err = io.Copy(osf, fileContents) + if err != nil { + return err + } + osf.Close() + + err = os.Chmod(path.Join(installPath, filename), 0755) + if err != nil { + return err + } + + os.Remove(path.Join(installPath, filename+".zip")) + + return err +} -- 2.51.2 From a05186e8dfdbf28d871979ef5e0e1fcfe3fbc0c7 Mon Sep 17 00:00:00 2001 From: Lukas Werner Date: Wed, 20 Aug 2025 08:57:49 -0700 Subject: [PATCH 3/3] fix: change dynamic lib dir to app data dir --- store/database.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/store/database.go b/store/database.go index 79e0913..fc1d206 100644 --- a/store/database.go +++ b/store/database.go @@ -105,14 +105,14 @@ func Open() (*DB, error) { default: ext = ".so" } - if !DoesFileExist(path.Join(homedir, ".lib", "crsqlite"+ext)) { - err = downloadCrSqlite(path.Join(homedir, ".lib"), "crsqlite"+ext) + if !DoesFileExist(path.Join(markStoreLocation, "crsqlite"+ext)) { + err = downloadCrSqlite(markStoreLocation, "crsqlite"+ext) if err != nil { return nil, errors.Join(errors.New("unable to download crsqlite"), err) } } sql.Register("cr-sqlite", &sqlite3.SQLiteDriver{ - Extensions: []string{path.Join(homedir, ".lib", "crsqlite")}, + Extensions: []string{path.Join(markStoreLocation, "crsqlite")}, }) sqlDB, err := sql.Open("cr-sqlite", path.Join(markStoreLocation, "data.db")) -- 2.51.2