diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b6a6dbd..cf3718e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -23,3 +23,4 @@ jobs: shell: nix develop --command bash -e {0} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CHOCOLATEY_API_KEY: ${{ secrets.CHOCOLATEY_API_KEY }} diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 6138f51..6d21564 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -121,10 +121,17 @@ builds: # name_template: "armaria" archives: - - id: w/version + - id: armaria-linux-archive builds: - armaria-linux-amd64 - armaria-host-linux-amd64 + name_template: "armaria_{{ .Version }}_{{ .Os }}_{{ .Arch }}" + wrap_in_directory: false + format: zip + files: + - none* + - id: armaria-windows-archive + builds: - armaria-windows-amd64 - armaria-host-windows-amd64 name_template: "armaria_{{ .Version }}_{{ .Os }}_{{ .Arch }}" @@ -158,7 +165,7 @@ snapcrafts: title: Armaria icon: ./art/icon-light.svg # publish: true - summary: Armaria is a fast local-first bookmark manager. + summary: Armaria is a fast, open, and local first bookmarks manager. description: Armaria is a FOSS bookmarks manager that keeps all of your local bookmarks in a SQLite database. You can use many different frontends to manage your bookmarks including browsers, and back them up and/or sync them however you see fit. confinement: strict license: MIT @@ -182,3 +189,27 @@ snapcrafts: interface: personal-files write: - $HOME/.config/chromium/NativeMessagingHosts + +chocolateys: + - name: armaria + owners: Jonathan Hope + authors: Jonathan Hope + title: Armaria + project_url: https://github.com/JonathanHope/armaria + url_template: "https://github.com/JonathanHope/armaria/releases/download/{{ .Tag }}/{{ .ArtifactName }}" + icon_url: "https://github.com/JonathanHope/armaria/blob/main/art/cabinet-light-128.svg" + copyright: Jonathan Hope + license_url: https://github.com/JonathanHope/armaria/blob/main/LICENSE + require_license_acceptance: false + project_source_url: https://github.com/JonathanHope/armaria + docs_url: https://github.com/JonathanHope/armaria/README.org + bug_tracker_url: https://github.com/JonathanHope/armaria/issues + tags: "bookmarks" + summary: Armaria is a fast, open, and local first bookmarks manager . + description: | + Armaria is a FOSS bookmarks manager that keeps all of your local bookmarks in a SQLite database. You can use many different frontends to manage your bookmarks including browsers, and back them up and/or sync them however you see fit. + release_notes: "https://github.com/JonathanHope/armaria/releases/tag/{{ .Tag }}" + source_repo: "https://push.chocolatey.org/" + ids: + - armaria-windows-archive + api_key: "{{ .Env.CHOCOLATEY_API_KEY }}" diff --git a/cmd/cli/cmd/formatters.go b/cmd/cli/cmd/formatters.go index 423d241..561b8ad 100644 --- a/cmd/cli/cmd/formatters.go +++ b/cmd/cli/cmd/formatters.go @@ -5,15 +5,14 @@ import ( "errors" "fmt" "io" - "os" "strings" "github.com/charmbracelet/lipgloss" "github.com/charmbracelet/lipgloss/table" "github.com/jonathanhope/armaria/internal/null" "github.com/jonathanhope/armaria/pkg/model" + "github.com/nathan-fiscaletti/consolesize-go" "github.com/samber/lo" - "golang.org/x/term" ) // The Armaria CLI can format its output in multiple ways. @@ -148,10 +147,7 @@ func formatBookResults(writer io.Writer, formatter Formatter, books []armaria.Bo fmt.Fprintln(writer, string(json)) case FormatterPretty: - width, _, err := term.GetSize(int(os.Stdin.Fd())) - if err != nil { - panic(err) - } + width, _ := consolesize.GetConsoleSize() headerStyle := lipgloss. NewStyle(). @@ -210,10 +206,7 @@ func formatTagResults(writer io.Writer, formatter Formatter, tags []string) { fmt.Fprintln(writer, string(json)) case FormatterPretty: - width, _, err := term.GetSize(int(os.Stdin.Fd())) - if err != nil { - panic(err) - } + width, _ := consolesize.GetConsoleSize() style := lipgloss. NewStyle(). @@ -237,10 +230,7 @@ func formatConfigResult(writer io.Writer, formatter Formatter, value string) { fmt.Fprintf(writer, "\"%s\"\n", value) case FormatterPretty: - width, _, err := term.GetSize(int(os.Stdin.Fd())) - if err != nil { - panic(err) - } + width, _ := consolesize.GetConsoleSize() style := lipgloss. NewStyle(). diff --git a/go.mod b/go.mod index 9f25a02..1a31985 100644 --- a/go.mod +++ b/go.mod @@ -15,10 +15,10 @@ require ( github.com/knadh/koanf/providers/structs v0.1.0 github.com/knadh/koanf/v2 v2.0.1 github.com/mattn/go-sqlite3 v1.14.18 + github.com/nathan-fiscaletti/consolesize-go v0.0.0-20220204101620-317176b6684d github.com/nullism/bqb v1.7.1 github.com/pressly/goose/v3 v3.16.0 github.com/samber/lo v1.38.1 - golang.org/x/term v0.14.0 gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0 ) diff --git a/go.sum b/go.sum index f5ffa07..1a946fe 100644 --- a/go.sum +++ b/go.sum @@ -142,6 +142,8 @@ github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo= github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8= +github.com/nathan-fiscaletti/consolesize-go v0.0.0-20220204101620-317176b6684d h1:NqRhLdNVlozULwM1B3VaHhcXYSgrOAv8V5BE65om+1Q= +github.com/nathan-fiscaletti/consolesize-go v0.0.0-20220204101620-317176b6684d/go.mod h1:cxIIfNMTwff8f/ZvRouvWYF6wOoO7nj99neWSx2q/Es= github.com/nullism/bqb v1.7.1 h1:n2BOwqJ3qggm/Z2CrNpzy9lWUqhyq7gy50xGVh+rdBw= github.com/nullism/bqb v1.7.1/go.mod h1:4Z4vvPss9ms9dtLHpI4tUPtysmCAZfbm44lbsP3VDBY= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= @@ -227,8 +229,6 @@ golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8= -golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8= diff --git a/internal/paths/paths.go b/internal/paths/paths.go index 1735be3..9dfd6b0 100644 --- a/internal/paths/paths.go +++ b/internal/paths/paths.go @@ -72,16 +72,20 @@ func databaseInternal(inputPath null.NullString, configPath string, goos string, // Config gets the path to the config file. // The config file is a TOML file located at getFolderPath() + "bookmarks.db". func Config() (string, error) { - return configInternal(runtime.GOOS, os.UserHomeDir, filepath.Join, os.Getenv) + return configInternal(runtime.GOOS, os.UserHomeDir, filepath.Join, os.Getenv, os.MkdirAll) } // configInternal allows DI for GetConfigPath. -func configInternal(goos string, userHome userHomeFn, join joinFn, getenv getenvFn) (string, error) { +func configInternal(goos string, userHome userHomeFn, join joinFn, getenv getenvFn, mkDirAll mkDirAllFn) (string, error) { folder, err := folderInternal(goos, userHome, join, getenv) if err != nil { return "", fmt.Errorf("error getting folder path while getting config path: %w", err) } + if err = mkDirAll(folder, os.ModePerm); err != nil { + return "", fmt.Errorf("error creating folder while getting config path: %w", err) + } + return join(folder, configFilename), nil } diff --git a/internal/paths/paths_test.go b/internal/paths/paths_test.go index 79145cb..1b9071e 100644 --- a/internal/paths/paths_test.go +++ b/internal/paths/paths_test.go @@ -13,26 +13,36 @@ func TestGetConfigPath(t *testing.T) { type test struct { goos string configPath string + folderPath string + folderCreated bool snapCommonDir string } tests := []test{ { - goos: "windows", - configPath: "~/AppData/Local/Armaria/armaria.toml", + goos: "windows", + configPath: "~/AppData/Local/Armaria/armaria.toml", + folderPath: "~/AppData/Local/Armaria", + folderCreated: true, }, { - goos: "linux", - configPath: "~/.armaria/armaria.toml", + goos: "linux", + configPath: "~/.armaria/armaria.toml", + folderPath: "~/.armaria", + folderCreated: true, }, { goos: "linux", configPath: "~/snap/.armaria/armaria.toml", + folderPath: "~/snap/.armaria", snapCommonDir: "~/snap", + folderCreated: true, }, { - goos: "darwin", - configPath: "~/Library/Application Support/Armaria/armaria.toml", + goos: "darwin", + configPath: "~/Library/Application Support/Armaria/armaria.toml", + folderPath: "~/Library/Application Support/Armaria", + folderCreated: true, }, } @@ -41,16 +51,31 @@ func TestGetConfigPath(t *testing.T) { } for _, tc := range tests { + folderCreated := false + t.Run(fmt.Sprintf("GOOS: %s, SNAP_USER_COMMON: %s", tc.goos, tc.snapCommonDir), func(t *testing.T) { + mkDirAll := func(path string, perm os.FileMode) error { + folderCreated = true + if path != tc.folderPath { + t.Errorf("folder: got %+v; want %+v", path, tc.folderPath) + } + + return nil + } + getenv := func(key string) string { return tc.snapCommonDir } - got, err := configInternal(tc.goos, userHome, path.Join, getenv) + got, err := configInternal(tc.goos, userHome, path.Join, getenv, mkDirAll) if err != nil { t.Fatalf("unexpected error: %+v", err) } + if folderCreated != tc.folderCreated { + t.Fatalf("folder created: got %+v; want %+v", folderCreated, tc.folderCreated) + } + if got != tc.configPath { t.Errorf("configPath: got %+v; want %+v", got, tc.configPath) } diff --git a/pkg/api/get_config.go b/pkg/api/get_config.go index b15dda2..9bd2332 100644 --- a/pkg/api/get_config.go +++ b/pkg/api/get_config.go @@ -1,7 +1,9 @@ package armariaapi import ( + "errors" "fmt" + "os" "strings" "github.com/jonathanhope/armaria/internal/paths" @@ -21,6 +23,10 @@ func GetConfig() (armaria.Config, error) { return config, fmt.Errorf("error getting config path while getting config: %w", err) } + if _, err := os.Stat(configPath); errors.Is(err, os.ErrNotExist) { + return config, nil + } + var k = koanf.New(".") if err := k.Load(file.Provider(configPath), toml.Parser()); err != nil { if strings.Contains(err.Error(), "no such file or directory") { diff --git a/tools/choco b/tools/choco new file mode 100755 index 0000000..25b5968 --- /dev/null +++ b/tools/choco @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +echo $@ + +docker run -v $PWD:/build -w /build chocolatey/choco:v2.2.2-linux choco $@