diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index f74c440..cc2d7b8 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -59,7 +59,7 @@ jobs:
- name: "GoReleaser"
id: go
- uses: goreleaser/goreleaser-action@e435ccd777264be153ace6237001ef4d979d3a7a # v6.4.0
+ uses: goreleaser/goreleaser-action@ec59f474b9834571250b370d4735c50f8e2d1e29 # v7.0.0
env:
#GITHUB_TOKEN: ${{ steps.app.outputs.token }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/README.md b/README.md
index f32b8d6..0ff6f9b 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
[](https://github.com/smashedr/install-release/releases)
[](https://github.com/smashedr/install-release/releases/latest)
-[](https://github.com/smashedr/install-release/releases/latest)
-[](https://github.com/smashedr/install-release/pkgs/container/install-release)
+[](https://github.com/smashedr/install-release/releases/latest)
+[](https://github.com/smashedr/install-release/pkgs/container/install-release)
[](https://github.com/smashedr/install-release/blob/master/go.mod)
[](https://sonarcloud.io/summary/new_code?id=smashedr_install-release)
[](https://github.com/smashedr/install-release/deployments/docs)
@@ -125,18 +125,33 @@ Install a specific version/tag.
ir owner/repo v1.0.0
```
-Install using many formats:
+Specify repo in any format:
```shell
-ir owner repo
-ir owner/repo
-ir owner repo tag
-ir owner/repo tag
-ir owner/repo/tag
-ir owner/repo:tag
-ir owner/repo@tag
+ir owner[/ ]repo
+ir owner[/ ]repo[@:/ ]tag
+ir github.com/owner[/ ]repo[@:/ ]tag
+ir https://github.com/owner[/ ]repo[@:/ ]tag
+```
+
+View Examples
+
+```shell
+ir smashedr bup
+ir smashedr/bup
+ir smashedr bup latest
+ir smashedr/bup latest
+ir smashedr/bup/latest
+ir smashedr/bup:latest
+ir smashedr/bup@latest
+ir github.com/smashedr/bup
+ir github.com/smashedr/bup/latest
+ir https://github.com/smashedr/bup
+ir https://github.com/smashedr/bup@latest
```
+
+
Skip the asset and name prompts.
```shell
diff --git a/Taskfile.yml b/Taskfile.yml
index b606a91..77593cc 100644
--- a/Taskfile.yml
+++ b/Taskfile.yml
@@ -16,6 +16,10 @@ tasks:
- go get -u
- task: tidy
+ actions:
+ desc: Actions Up
+ cmd: actions-up --exclude "cssnr/.*,actions/.*,docker/.*" --yes
+
lint:
desc: Lint
cmds:
diff --git a/cmd/info.go b/cmd/info.go
index 5e5ea9c..53697b6 100644
--- a/cmd/info.go
+++ b/cmd/info.go
@@ -24,14 +24,14 @@ var infoCmd = &cobra.Command{
log.Debug("infoCmd", "args", args, "binPath", binPath, "preRelease", preRelease)
if len(args) >= 1 && strings.Contains(args[0], "/") {
- owner, repo, tag, err := parseRepository(args)
+ repo, err := parseRepository(args)
if err != nil {
_ = cmd.Help()
log.Fatal(err)
}
- log.Info("Repository", "owner", owner, "repo", repo, "tag", tag)
+ log.Info("Repository", "repo", repo)
client := getClient()
- release, err := getRelease(client, owner, repo, tag, preRelease, true)
+ release, err := getRelease(client, repo, preRelease, true)
if err != nil {
log.Fatalf("Error getting release: %v", err)
}
diff --git a/cmd/install.go b/cmd/install.go
index 6cd48ba..4250012 100644
--- a/cmd/install.go
+++ b/cmd/install.go
@@ -17,6 +17,7 @@ import (
"io"
"io/fs"
"net/http"
+ "net/url"
"os"
"path/filepath"
"runtime"
@@ -30,6 +31,12 @@ var archAliases = map[string][]string{
"arm64": {"arm64", "aarch64"},
}
+type Repository struct {
+ Owner string
+ Name string
+ Tag string
+}
+
func runInstall(cmd *cobra.Command, args []string) error { // NOSONAR
cmd.SilenceUsage = true // set here so subcommands do not silence usage
binPath := viper.GetString("bin")
@@ -45,28 +52,29 @@ func runInstall(cmd *cobra.Command, args []string) error { // NOSONAR
return fmt.Errorf("repository must be in format: owner/repo")
}
- owner, repo, tag, err := parseRepository(args)
+ repo, err := parseRepository(args)
if err != nil {
+ log.Debugf("parseRepository err: %v", err)
_ = cmd.Help()
return err
}
- log.Info("Repository", "owner", owner, "repo", repo, "tag", tag)
+ log.Info("Repository", "repo", repo)
log.Info("runtime", "GOOS", runtime.GOOS, "GOARCH", runtime.GOARCH)
- tagDisplay := tag
- if tag == "" {
+ tagDisplay := repo.Tag
+ if repo.Tag == "" {
if preRelease {
tagDisplay = "pre-release"
} else {
tagDisplay = "latest"
}
}
- styles.PrintKV("Repository", fmt.Sprintf("%s/%s:%s", owner, repo, tagDisplay))
+ styles.PrintKV("Repository", fmt.Sprintf("%s/%s:%s", repo.Owner, repo.Name, tagDisplay))
client := getClient()
- release, err := getRelease(client, owner, repo, tag, preRelease, skipPrompts)
+ release, err := getRelease(client, repo, preRelease, skipPrompts)
if err != nil {
return fmt.Errorf("get release error: %w", err)
}
@@ -120,7 +128,7 @@ func runInstall(cmd *cobra.Command, args []string) error { // NOSONAR
styles.PrintKV("Asset Name", asset.GetName())
rc, _, err := client.Repositories.DownloadReleaseAsset(
- context.Background(), owner, repo, asset.GetID(), http.DefaultClient,
+ context.Background(), repo.Owner, repo.Name, asset.GetID(), http.DefaultClient,
)
if err != nil {
return err
@@ -395,22 +403,22 @@ func getClient() *github.Client {
return github.NewClient(httpClient)
}
-func getRelease(client *github.Client, owner, repo, tag string, pre, skip bool) (*github.RepositoryRelease, error) {
+func getRelease(client *github.Client, repo Repository, pre, skip bool) (*github.RepositoryRelease, error) {
ctx := context.Background()
var release *github.RepositoryRelease
var err error
- if tag != "" {
- log.Debugf("client.Repositories.GetReleaseByTag: %v", tag)
- release, _, err = client.Repositories.GetReleaseByTag(ctx, owner, repo, tag)
+ if repo.Tag != "" {
+ log.Debugf("client.Repositories.GetReleaseByTag: %v", repo.Tag)
+ release, _, err = client.Repositories.GetReleaseByTag(ctx, repo.Owner, repo.Name, repo.Tag)
} else if pre {
log.Debugf("GetLatestRelease")
- release, err = getLatestRelease(client, owner, repo)
+ release, err = getLatestRelease(client, repo)
} else if skip {
log.Debugf("client.Repositories.GetLatestRelease")
- release, _, err = client.Repositories.GetLatestRelease(ctx, owner, repo)
+ release, _, err = client.Repositories.GetLatestRelease(ctx, repo.Owner, repo.Name)
} else {
log.Debugf("chooseRelease")
- release, err = chooseRelease(client, owner, repo, 30)
+ release, err = chooseRelease(client, repo, 30)
}
if err != nil {
return nil, fmt.Errorf("get release error: %w", err)
@@ -418,8 +426,8 @@ func getRelease(client *github.Client, owner, repo, tag string, pre, skip bool)
return release, nil
}
-func getLatestRelease(client *github.Client, owner, repo string) (*github.RepositoryRelease, error) {
- releases, err := getReleases(client, owner, repo, 1)
+func getLatestRelease(client *github.Client, repo Repository) (*github.RepositoryRelease, error) {
+ releases, err := getReleases(client, repo, 1)
if err != nil {
return nil, err
}
@@ -429,17 +437,17 @@ func getLatestRelease(client *github.Client, owner, repo string) (*github.Reposi
return releases[0], nil
}
-func getReleases(client *github.Client, owner, repo string, number int) ([]*github.RepositoryRelease, error) {
+func getReleases(client *github.Client, repo Repository, number int) ([]*github.RepositoryRelease, error) {
ctx := context.Background()
- releases, _, err := client.Repositories.ListReleases(ctx, owner, repo, &github.ListOptions{PerPage: number})
+ releases, _, err := client.Repositories.ListReleases(ctx, repo.Owner, repo.Name, &github.ListOptions{PerPage: number})
if err != nil {
return nil, err
}
return releases, nil
}
-func chooseRelease(client *github.Client, owner, repo string, number int) (*github.RepositoryRelease, error) {
- releases, err := getReleases(client, owner, repo, number)
+func chooseRelease(client *github.Client, repo Repository, number int) (*github.RepositoryRelease, error) {
+ releases, err := getReleases(client, repo, number)
if err != nil {
return nil, fmt.Errorf("error getting releases: %w", err)
}
@@ -477,52 +485,84 @@ func ensureWinExt(destName string) string {
return destName
}
-func parseRepository(args []string) (owner, repo, tag string, err error) {
+func parseRepository(args []string) (repo Repository, err error) {
helpErr := errors.New("repository format: owner/repo[:tag]")
log.Debugf("parseRepository %v: %v", len(args), args)
+
switch len(args) {
case 0:
- return "", "", "", helpErr
+ return repo, helpErr
case 1:
- repository := args[0]
+ // Parse URL
+ parsed := parseURL(args[0])
+ log.Debug("URL", "args[0]", args[0], "parsed", parsed)
+ fullName := parsed
// Check for :tag @tag /tag
- if idx := strings.IndexAny(args[0], ":@"); idx != -1 {
+ if idx := strings.IndexAny(parsed, ":@"); idx != -1 {
log.Debugf("idx: %v", idx)
- repository = args[0][:idx]
- tag = args[0][idx+1:]
- } else if strings.Count(args[0], "/") == 2 {
- split := strings.Split(args[0], "/")
+ fullName = parsed[:idx]
+ repo.Tag = parsed[idx+1:]
+ } else if strings.Count(parsed, "/") == 2 {
+ split := strings.Split(parsed, "/")
if split[2] != "" {
- repository = split[0] + "/" + split[1]
- tag = split[2]
+ fullName = split[0] + "/" + split[1]
+ repo.Tag = split[2]
}
}
// Set owner/repo
- split := strings.Split(repository, "/")
+ split := strings.Split(fullName, "/")
if len(split) != 2 {
- return "", "", "", helpErr
+ return repo, helpErr
}
- owner = split[0]
- repo = split[1]
+ repo.Owner = split[0]
+ repo.Name = split[1]
case 2:
if strings.Contains(args[0], "/") {
split := strings.Split(args[0], "/")
- owner = split[0]
- repo = split[1]
- tag = args[1]
+ repo.Owner = split[0]
+ repo.Name = split[1]
+ repo.Tag = args[1]
} else {
- owner = args[0]
- repo = args[1]
+ repo.Owner = args[0]
+ repo.Name = args[1]
}
default:
- owner = args[0]
- repo = args[1]
- tag = args[2]
+ repo.Owner = args[0]
+ repo.Name = args[1]
+ repo.Tag = args[2]
}
- if owner == "" || repo == "" {
+ if repo.Owner == "" || repo.Name == "" {
log.Infof("owner/repo are blank")
- return "", "", "", helpErr
+ return repo, helpErr
}
return
}
+
+func parseURL(original string) string {
+ log.Debugf("parseURL: %v", original)
+ u, err := url.Parse(original)
+ if err != nil {
+ log.Debug(err)
+ return original
+ }
+ u.Path = strings.TrimLeft(u.Path, "/")
+ log.Debug("Original", "Host", u.Host, "Path", u.Path)
+
+ if u.Host == "" && strings.HasPrefix(strings.ToLower(u.Path), "github.com/") {
+ u.Scheme = "https"
+ u.Host = "github.com"
+ u.Path = u.Path[11:]
+ }
+
+ log.Debug("Updated", "Host", u.Host, "Path", u.Path)
+
+ split := strings.Split(strings.TrimRight(u.Path, "/"), "/")
+ log.Debugf("split: %v", split)
+ count := len(split)
+ log.Debugf("count: %v", count)
+ if count < 2 {
+ return original
+ }
+ return u.Path
+}
diff --git a/docs/index.md b/docs/index.md
index 83293d0..4eacbc8 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -10,8 +10,8 @@ icon: lucide/rocket
[](https://github.com/smashedr/install-release/releases)
[](https://github.com/smashedr/install-release/releases/latest)
-[](https://github.com/smashedr/install-release/releases/latest)
-[](https://github.com/smashedr/install-release/pkgs/container/install-release)
+[](https://github.com/smashedr/install-release/releases/latest)
+[](https://github.com/smashedr/install-release/pkgs/container/install-release)
[](https://github.com/smashedr/install-release/blob/master/go.mod)
[](https://github.com/smashedr/install-release/pulse)
[](https://github.com/smashedr/install-release?tab=readme-ov-file#readme)
@@ -56,8 +56,8 @@ If you run into any issues or have any questions, [support](support.md) is avail
--8<-- "docs/snippets/install.md"
-[](https://github.com/smashedr/install-release/releases/latest)
-[](https://github.com/smashedr/install-release/releases)
+[](https://github.com/smashedr/install-release/releases/latest)
+[](https://github.com/smashedr/install-release/releases)
## :lucide-terminal-square: Usage
@@ -79,18 +79,33 @@ Install a specific version/tag.
ir owner/repo v1.0.0
```
-Install using many formats:
+Specify repo in any format:
```shell
-ir owner repo
-ir owner/repo
-ir owner repo tag
-ir owner/repo tag
-ir owner/repo/tag
-ir owner/repo:tag
-ir owner/repo@tag
+ir owner[/ ]repo
+ir owner[/ ]repo[@:/ ]tag
+ir github.com/owner[/ ]repo[@:/ ]tag
+ir https://github.com/owner[/ ]repo[@:/ ]tag
+```
+
+View Examples
+
+```shell
+ir smashedr bup
+ir smashedr/bup
+ir smashedr bup latest
+ir smashedr/bup latest
+ir smashedr/bup/latest
+ir smashedr/bup:latest
+ir smashedr/bup@latest
+ir github.com/smashedr/bup
+ir github.com/smashedr/bup/latest
+ir https://github.com/smashedr/bup
+ir https://github.com/smashedr/bup@latest
```
+
+
Skip the asset and name prompts.
```shell
diff --git a/go.mod b/go.mod
index a0addc0..56adb92 100644
--- a/go.mod
+++ b/go.mod
@@ -31,7 +31,7 @@ require (
github.com/charmbracelet/x/cellbuf v0.0.15 // indirect
github.com/charmbracelet/x/exp/strings v0.1.0 // indirect
github.com/charmbracelet/x/term v0.2.2 // indirect
- github.com/clipperhouse/displaywidth v0.10.0 // indirect
+ github.com/clipperhouse/displaywidth v0.11.0 // indirect
github.com/clipperhouse/uax29/v2 v2.7.0 // indirect
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 // indirect
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
diff --git a/go.sum b/go.sum
index 9a85dd8..15e6061 100644
--- a/go.sum
+++ b/go.sum
@@ -50,8 +50,8 @@ github.com/charmbracelet/x/termios v0.1.1 h1:o3Q2bT8eqzGnGPOYheoYS8eEleT5ZVNYNy8
github.com/charmbracelet/x/termios v0.1.1/go.mod h1:rB7fnv1TgOPOyyKRJ9o+AsTU/vK5WHJ2ivHeut/Pcwo=
github.com/charmbracelet/x/xpty v0.1.2 h1:Pqmu4TEJ8KeA9uSkISKMU3f+C1F6OGBn8ABuGlqCbtI=
github.com/charmbracelet/x/xpty v0.1.2/go.mod h1:XK2Z0id5rtLWcpeNiMYBccNNBrP2IJnzHI0Lq13Xzq4=
-github.com/clipperhouse/displaywidth v0.10.0 h1:GhBG8WuerxjFQQYeuZAeVTuyxuX+UraiZGD4HJQ3Y8g=
-github.com/clipperhouse/displaywidth v0.10.0/go.mod h1:XqJajYsaiEwkxOj4bowCTMcT1SgvHo9flfF3jQasdbs=
+github.com/clipperhouse/displaywidth v0.11.0 h1:lBc6kY44VFw+TDx4I8opi/EtL9m20WSEFgwIwO+UVM8=
+github.com/clipperhouse/displaywidth v0.11.0/go.mod h1:bkrFNkf81G8HyVqmKGxsPufD3JhNl3dSqnGhOoSD/o0=
github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk=
github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM=
github.com/confluentinc/go-editor v0.11.0 h1:fcEALYHj7xV/fRSp54/IHi2DS4GlZMJWVgrYvi/llvU=