Files
bjarneo--cliamp/pluginmgr/resolve.go
T
wehub-resource-sync ead81af521
Deploy to GitHub Pages / deploy (push) Failing after 0s
CI / go (push) Has been cancelled
CI / build (darwin, macos-14) (push) Has been cancelled
CI / build (windows, windows-2025) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:31:13 +08:00

97 lines
2.5 KiB
Go

package pluginmgr
import (
"fmt"
"net/url"
"path"
"strings"
)
// resolveSource parses a plugin source string into a download URL and plugin name.
//
// Supported formats:
//
// user/repo → GitHub (HEAD)
// user/repo@v1.0 → GitHub (tag)
// gitlab:user/repo → GitLab (HEAD)
// gitlab:user/repo@v1.0 → GitLab (tag)
// codeberg:user/repo → Codeberg (main)
// codeberg:user/repo@v1 → Codeberg (tag)
// https://example.com/plugin.lua → raw URL
func resolveSource(source string) (urls []string, name string, err error) {
// Raw URL.
if strings.HasPrefix(source, "http://") || strings.HasPrefix(source, "https://") {
u, err := url.Parse(source)
if err != nil {
return nil, "", fmt.Errorf("invalid URL: %w", err)
}
base := path.Base(u.Path)
name = strings.TrimSuffix(base, ".lua")
if name == "" || name == "." || name == "/" {
return nil, "", fmt.Errorf("cannot derive a plugin name from URL %q; it should end in <name>.lua", source)
}
return []string{source}, name, nil
}
// Detect forge prefix.
forge := "github"
repo := source
if prefix, rest, ok := strings.Cut(source, ":"); ok {
switch prefix {
case "gitlab", "codeberg":
forge = prefix
repo = rest
default:
return nil, "", fmt.Errorf("unknown forge prefix %q (supported: gitlab, codeberg)", prefix)
}
}
// Split repo@tag.
ref := ""
if r, tag, ok := strings.Cut(repo, "@"); ok {
repo = r
ref = tag
}
// Validate user/repo format.
parts := strings.SplitN(repo, "/", 3)
if len(parts) != 2 || parts[0] == "" || parts[1] == "" {
return nil, "", fmt.Errorf("invalid source %q (expected user/repo)", source)
}
name = parts[1]
// Convention: repos are named cliamp-plugin-<name> with entry point <name>.lua.
short := strings.TrimPrefix(name, "cliamp-plugin-")
u, err := buildForgeURL(forge, repo, ref, short)
if err != nil {
return nil, "", err
}
return []string{u}, short, nil
}
func buildForgeURL(forge, repo, ref, entrypoint string) (string, error) {
var base string
switch forge {
case "github":
if ref == "" {
ref = "HEAD"
}
base = fmt.Sprintf("https://raw.githubusercontent.com/%s/%s", repo, ref)
case "gitlab":
if ref == "" {
ref = "HEAD"
}
base = fmt.Sprintf("https://gitlab.com/%s/-/raw/%s", repo, ref)
case "codeberg":
if ref == "" {
base = fmt.Sprintf("https://codeberg.org/%s/raw/branch/main", repo)
} else {
base = fmt.Sprintf("https://codeberg.org/%s/raw/tag/%s", repo, ref)
}
default:
return "", fmt.Errorf("unsupported forge %q", forge)
}
return base + "/" + entrypoint + ".lua", nil
}