Reconcile Gitea distribution with current alpha behavior and release tooling

Hop-State: A_06FN55REVAR7VQG4BWJBCD8
Hop-Proposal: R_06FN55QTEWKH16NSR59YJYG
Hop-Task: T_06FN3MBF98GWD4NA5PA1RWG
Hop-Attempt: AT_06FN55BQ80H2S8WHNDD24G0
This commit is contained in:
Hop
2026-07-11 12:10:59 -07:00
parent 23a4891099
commit de99aad4d4
28 changed files with 1565 additions and 21 deletions
+17 -3
View File
@@ -8,6 +8,7 @@ import (
"fmt"
"io"
"os"
"runtime/debug"
"strings"
)
@@ -39,7 +40,19 @@ Usage:
Add --json anywhere for machine-readable output.
`
const Version = "0.1.0-alpha.4"
// Version is replaced by GoReleaser through -ldflags. Source installs made by
// `go install module@version` fall back to the module version in Go build info.
var Version = "dev"
func effectiveVersion() string {
if Version != "" && Version != "dev" {
return strings.TrimPrefix(Version, "v")
}
if info, ok := debug.ReadBuildInfo(); ok && info.Main.Version != "" && info.Main.Version != "(devel)" {
return strings.TrimPrefix(info.Main.Version, "v")
}
return "dev"
}
func RunCLI(args []string, stdout, stderr io.Writer) int {
return RunCLIWithInput(args, os.Stdin, stdout, stderr)
@@ -56,10 +69,11 @@ func RunCLIWithInput(args []string, stdin io.Reader, stdout, stderr io.Writer) i
command := args[0]
commandArgs := args[1:]
if command == "version" || command == "--version" {
version := effectiveVersion()
if jsonOutput {
writeJSON(stdout, map[string]any{"ok": true, "version": Version})
writeJSON(stdout, map[string]any{"ok": true, "version": version})
} else {
fmt.Fprintf(stdout, "hop %s\n", Version)
fmt.Fprintf(stdout, "hop %s\n", version)
}
return 0
}
+67
View File
@@ -0,0 +1,67 @@
package hop
import (
"os"
"path/filepath"
"regexp"
"strings"
"testing"
)
var markdownLink = regexp.MustCompile(`\[[^]]+\]\(([^)]+)\)`)
func TestDocumentationLinksResolve(t *testing.T) {
root := filepath.Clean(filepath.Join("..", ".."))
files := []string{filepath.Join(root, "README.md")}
wiki, err := filepath.Glob(filepath.Join(root, "wiki", "*.md"))
if err != nil {
t.Fatal(err)
}
files = append(files, wiki...)
if len(wiki) < 10 {
t.Fatalf("wiki contains %d pages, want at least 10", len(wiki))
}
for _, file := range files {
contents, err := os.ReadFile(file)
if err != nil {
t.Fatal(err)
}
for _, match := range markdownLink.FindAllStringSubmatch(string(contents), -1) {
target := match[1]
if strings.HasPrefix(target, "http://") || strings.HasPrefix(target, "https://") ||
strings.HasPrefix(target, "#") || strings.HasPrefix(target, "mailto:") {
continue
}
if anchor := strings.IndexByte(target, '#'); anchor >= 0 {
target = target[:anchor]
}
if target == "" {
continue
}
resolved := filepath.Clean(filepath.Join(filepath.Dir(file), filepath.FromSlash(target)))
if filepath.Dir(file) == filepath.Join(root, "wiki") && filepath.Ext(resolved) == "" {
resolved += ".md"
}
if _, err := os.Stat(resolved); err != nil {
t.Errorf("%s links to missing %s: %v", file, target, err)
}
}
}
}
func TestProductDocumentationUsesCanonicalGiteaHost(t *testing.T) {
for _, relative := range []string{"README.md", "wiki/Home.md", "wiki/Installation.md"} {
contents, err := os.ReadFile(filepath.Join("..", "..", filepath.FromSlash(relative)))
if err != nil {
t.Fatal(err)
}
text := string(contents)
if !strings.Contains(text, "githop.xyz") {
t.Errorf("%s does not name the canonical distribution host", relative)
}
if strings.Contains(text, "raw.githubusercontent.com/hop-vcs/hop") ||
strings.Contains(text, "github.com/hop-vcs/hop") {
t.Errorf("%s still points installation at GitHub", relative)
}
}
}
+18
View File
@@ -458,6 +458,24 @@ func TestCLILandConflictReturnsAutomaticReconciliation(t *testing.T) {
}
}
func TestCLIVersionUsesReleaseLinkerValue(t *testing.T) {
previous := Version
Version = "v1.2.3"
t.Cleanup(func() { Version = previous })
var stdout, stderr bytes.Buffer
if code := RunCLI([]string{"version", "--json"}, &stdout, &stderr); code != 0 {
t.Fatalf("version exited %d: %s", code, stderr.String())
}
var response map[string]any
if err := json.Unmarshal(stdout.Bytes(), &response); err != nil {
t.Fatal(err)
}
if got, _ := response["version"].(string); got != "1.2.3" {
t.Fatalf("version = %q, want 1.2.3", got)
}
}
func TestOpenProjectInsideFinalValidationDoesNotReacquireAcceptanceLock(t *testing.T) {
ctx := context.Background()
service, _ := newTestProject(t, map[string]string{"base.txt": "base\n"})
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"path/filepath"
"strings"
hopskill "github.com/hop-vcs/hop/skills/hop"
hopskill "githop.xyz/hop/hop/skills/hop"
)
type SkillInstallResult struct {