- datekeys.SpecVersion ("0.8.2") names the specification the module
implements. A test ties it to the spec file, its title and
spec/README.md, and TestCatalogueMatchesSpec and the vector files use
it (testkit.SpecVersion now aliases it), so the vectors regenerate
unchanged.
- datekeys.Version() is the version of the module as the go command
recorded it. That is a tag, or for a binary built in a checkout the
pseudo-version of its commit (for example
v0.0.0-20260928105528-9ac9cd952f04), or (devel) when it is unknown, as
in tests or under a replace directive to a directory. It works as the
main module and as a dependency, whatever the module path, which it
reads from the root package.
- `datekeys version` (also -version and --version) prints both and the
Go toolchain.
- README.md and README.es.md explain the three versions (format,
specification, module) and what the code on main covers.
traceability §70 and CHANGELOG follow.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
v0.9
parent
9ac9cd952f
commit
5b342d32dc
@ -0,0 +1,50 @@
|
|||||||
|
package datekeys
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"runtime/debug"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SpecVersion is the version of the DateKeys Protocol Specification that this
|
||||||
|
// module implements: spec/DateKeys_Protocol_Specification_v0.8.2.md, tagged
|
||||||
|
// spec-v0.8.2 in its repository. It is neither the version of the module
|
||||||
|
// (see Version) nor the framing and schema versions inside the objects,
|
||||||
|
// which are 1 (spec §70).
|
||||||
|
const SpecVersion = "0.8.2"
|
||||||
|
|
||||||
|
// modulePath is the path of this module: the import path of its root
|
||||||
|
// package, whatever the module is called.
|
||||||
|
var modulePath = reflect.TypeFor[Error]().PkgPath()
|
||||||
|
|
||||||
|
// Version returns the version of this module in the running program, as the
|
||||||
|
// go command recorded it: a release tag such as v0.1.0; a pseudo-version,
|
||||||
|
// which names the commit, for a program built in a checkout of the module;
|
||||||
|
// or "(devel)" when it is unknown, as in tests or under a replace directive
|
||||||
|
// that points to a directory.
|
||||||
|
func Version() string {
|
||||||
|
info, ok := debug.ReadBuildInfo()
|
||||||
|
if !ok {
|
||||||
|
return "(devel)"
|
||||||
|
}
|
||||||
|
return versionIn(info)
|
||||||
|
}
|
||||||
|
|
||||||
|
func versionIn(info *debug.BuildInfo) string {
|
||||||
|
m := &info.Main
|
||||||
|
if m.Path != modulePath {
|
||||||
|
m = nil
|
||||||
|
for _, d := range info.Deps {
|
||||||
|
if d.Path == modulePath {
|
||||||
|
m = d
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if m != nil && m.Replace != nil {
|
||||||
|
m = m.Replace
|
||||||
|
}
|
||||||
|
if m == nil || m.Version == "" {
|
||||||
|
return "(devel)"
|
||||||
|
}
|
||||||
|
return m.Version
|
||||||
|
}
|
||||||
@ -0,0 +1,60 @@
|
|||||||
|
package datekeys
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"runtime/debug"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SpecVersion names the specification of this repository: its file, its
|
||||||
|
// title and its record in spec/README.md.
|
||||||
|
func TestSpecVersionNamesTheSpecification(t *testing.T) {
|
||||||
|
spec, err := os.ReadFile("spec/DateKeys_Protocol_Specification_v" + SpecVersion + ".md")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !strings.Contains(string(spec), "### Borrador normativo v"+SpecVersion+"\n") {
|
||||||
|
t.Error("the specification is not titled v" + SpecVersion)
|
||||||
|
}
|
||||||
|
readme, err := os.ReadFile("spec/README.md")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !strings.Contains(string(readme), "draft v"+SpecVersion+" (") {
|
||||||
|
t.Error("spec/README.md does not record v" + SpecVersion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestModulePath(t *testing.T) {
|
||||||
|
if modulePath != "g.activething.com/go/DateKeys" {
|
||||||
|
t.Fatalf("module path %q", modulePath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVersion(t *testing.T) {
|
||||||
|
if Version() == "" {
|
||||||
|
t.Fatal("empty version")
|
||||||
|
}
|
||||||
|
other := debug.Module{Path: "example.com/app", Version: "v1.2.3"}
|
||||||
|
for _, tc := range []struct {
|
||||||
|
name string
|
||||||
|
info debug.BuildInfo
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{"the main module, tagged", debug.BuildInfo{Main: debug.Module{Path: modulePath, Version: "v0.1.0"}}, "v0.1.0"},
|
||||||
|
{"the main module, from a checkout", debug.BuildInfo{Main: debug.Module{Path: modulePath, Version: "v0.0.0-20260928125528-9ac9cd952f04"}},
|
||||||
|
"v0.0.0-20260928125528-9ac9cd952f04"},
|
||||||
|
{"the main module in a test", debug.BuildInfo{Main: debug.Module{Path: modulePath}}, "(devel)"},
|
||||||
|
{"a dependency", debug.BuildInfo{Main: other, Deps: []*debug.Module{{Path: modulePath, Version: "v0.2.0"}}}, "v0.2.0"},
|
||||||
|
{"replaced by another version", debug.BuildInfo{Main: other, Deps: []*debug.Module{
|
||||||
|
{Path: modulePath, Version: "v0.2.0", Replace: &debug.Module{Path: modulePath, Version: "v0.2.1"}}}}, "v0.2.1"},
|
||||||
|
{"replaced by a directory", debug.BuildInfo{Main: other, Deps: []*debug.Module{
|
||||||
|
{Path: modulePath, Version: "v0.2.0", Replace: &debug.Module{Path: "../datekeys-go"}}}}, "(devel)"},
|
||||||
|
{"not in the program", debug.BuildInfo{Main: other}, "(devel)"},
|
||||||
|
} {
|
||||||
|
if got := versionIn(&tc.info); got != tc.want {
|
||||||
|
t.Errorf("%s: %q, want %q", tc.name, got, tc.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in new issue