1package xrpc
2
3import (
4 "encoding/json"
5 "fmt"
6 "net/http"
7 "runtime/debug"
8
9 "tangled.sh/tangled.sh/core/api/tangled"
10 xrpcerr "tangled.sh/tangled.sh/core/xrpc/errors"
11)
12
13// version is set during build time.
14var version string
15
16func (x *Xrpc) Version(w http.ResponseWriter, r *http.Request) {
17 if version == "" {
18 info, ok := debug.ReadBuildInfo()
19 if !ok {
20 http.Error(w, "failed to read build info", http.StatusInternalServerError)
21 return
22 }
23
24 var modVer string
25 var sha string
26 var modified bool
27
28 for _, mod := range info.Deps {
29 if mod.Path == "tangled.sh/tangled.sh/knotserver/xrpc" {
30 modVer = mod.Version
31 break
32 }
33 }
34
35 for _, setting := range info.Settings {
36 switch setting.Key {
37 case "vcs.revision":
38 sha = setting.Value
39 case "vcs.modified":
40 modified = setting.Value == "true"
41 }
42 }
43
44 if modVer == "" {
45 modVer = "unknown"
46 }
47
48 if sha == "" {
49 version = modVer
50 } else if modified {
51 version = fmt.Sprintf("%s (%s with modifications)", modVer, sha)
52 } else {
53 version = fmt.Sprintf("%s (%s)", modVer, sha)
54 }
55 }
56
57 response := tangled.KnotVersion_Output{
58 Version: version,
59 }
60
61 w.Header().Set("Content-Type", "application/json")
62 if err := json.NewEncoder(w).Encode(response); err != nil {
63 x.Logger.Error("failed to encode response", "error", err)
64 writeError(w, xrpcerr.NewXrpcError(
65 xrpcerr.WithTag("InternalServerError"),
66 xrpcerr.WithMessage("failed to encode response"),
67 ), http.StatusInternalServerError)
68 return
69 }
70}