myxce/src/frontend/xcecli/cmd/main.go
Rongsong Shen d65d18ad5f
feat(dirty-content-fingerprint): xcecli shows fingerprint in --version
Adds DirtyFingerprint var and composeVersionDisplay() helper to
xcecli/cmd/main.go, a logical duplicate of apiserver's just-approved
implementation (task 4.4, same anchored strings.TrimSuffix strip-and-
append rule). Applied at the sole consumption point: the version string
fed into router.Execute(cm, version), which sets Cobra's rootCmd.Version.
router.go is untouched -- xcecli has no startup log to protect, already
established out of scope by the original build-time-versioning feature.

New main_test.go covers the same 6 cases as apiserver's tests. Verified
independently by review (including a second, independent mutation test)
with real builds across all 3 required scenarios and a full xcecli module
test suite run showing no regressions.

This completes all Go binary work (tasks 4.1-4.5) for this spec.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-21 08:21:18 +00:00

111 lines
4.3 KiB
Go
Executable file

/*
The MIT License (MIT)
Copyright © 2025 xce
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package main
import (
"fmt"
"os"
"strings"
"xcecli/config"
logger "xcecli/config"
cmd "xcecli/router"
"go.uber.org/zap"
)
// GitCommit and BuildTime are injected at link time via
// `-ldflags "-X main.GitCommit=... -X main.BuildTime=..."` (see
// src/tools/go_build and src/frontend/Makefile's build-cli target). The
// "unknown" defaults matter: a bare `go build`/`go run` that bypasses that
// ldflags injection must still report "unknown" rather than an empty
// string, matching this feature's unknown-fallback requirement (see
// xce_version_field() in src/lib/utils.c for the equivalent C-side
// convention).
//
// DirtyFingerprint is injected the same way (`-X main.DirtyFingerprint=...`,
// see src/tools/go_build task 4.1) but its default is a deliberately EMPTY
// string, not "unknown" -- matching dirty_fingerprint's convention
// everywhere else in the dirty-content-fingerprint feature (empty means
// "no fingerprint available", distinct from GitCommit/BuildTime's
// "unknown" sentinel for "not injected at all").
var (
GitCommit = "unknown"
BuildTime = "unknown"
DirtyFingerprint = ""
)
// composeVersionDisplay applies the dirty-content-fingerprint feature's
// strip-and-append rule to gitCommit: if dirtyFingerprint is non-empty, a
// trailing "-dirty" suffix on gitCommit is stripped (an anchored suffix
// check via strings.TrimSuffix, not a blind substring replace) and
// "-<dirtyFingerprint>" is appended in its place; otherwise gitCommit is
// returned exactly as-is (already correctly showing "-dirty" or not, per
// the original build-time-versioning feature). Mirrors
// xce_compose_version_ex() in src/lib/utils.c (task 3.1) and apiserver's
// own composeVersionDisplay (task 4.4), the equivalent implementations
// already approved for the other version-displaying components.
//
// xcecli has no startup log to protect (already established as out of
// scope by the original build-time-versioning feature, see that feature's
// own task 4.5 commit fb09afe), so this result feeds the ONLY consumption
// point below: the version string passed into router.Execute(cm, version),
// which sets rootCmd.Version for Cobra's native --version/-v handling.
func composeVersionDisplay(gitCommit, dirtyFingerprint string) string {
if dirtyFingerprint == "" {
return gitCommit
}
return strings.TrimSuffix(gitCommit, "-dirty") + "-" + dirtyFingerprint
}
func main() {
// init logger
if err := logger.InitLogger(); err != nil {
fmt.Println(strings.ToLower(err.Error()))
os.Exit(1)
}
logger.Info("********** Initialize Logger on client side done!")
// initialize the config manager
configManager, err := config.NewConfigManager()
if err != nil {
fmt.Println("failed to initialize the config manager", zap.Error(err))
os.Exit(1)
}
// ensure the config manager is initialized correctly
if configManager == nil {
fmt.Println("failed to initialize the config manager")
os.Exit(1)
}
// execute the command
version := fmt.Sprintf("%s built %s", composeVersionDisplay(GitCommit, DirtyFingerprint), BuildTime)
if err := cmd.Execute(configManager, version); err != nil {
fmt.Println(strings.ToLower(err.Error()))
os.Exit(1)
}
}