• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2024 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package telemetry
6
7import (
8	"os"
9	"path/filepath"
10	"runtime/debug"
11	"strings"
12)
13
14// IsToolchainProgram reports whether a program with the given path is a Go
15// toolchain program.
16func IsToolchainProgram(progPath string) bool {
17	return strings.HasPrefix(progPath, "cmd/")
18}
19
20// ProgramInfo extracts the go version, program package path, and program
21// version to use for counter files.
22//
23// For programs in the Go toolchain, the program version will be the same as
24// the Go version, and will typically be of the form "go1.2.3", not a semantic
25// version of the form "v1.2.3". Go versions may also include spaces and
26// special characters.
27func ProgramInfo(info *debug.BuildInfo) (goVers, progPath, progVers string) {
28	goVers = info.GoVersion
29	if strings.Contains(goVers, "devel") || strings.Contains(goVers, "-") {
30		goVers = "devel"
31	}
32
33	progPath = info.Path
34	if progPath == "" {
35		progPath = strings.TrimSuffix(filepath.Base(os.Args[0]), ".exe")
36	}
37
38	// Main module version information is not populated for the cmd module, but
39	// we can re-use the Go version here.
40	if IsToolchainProgram(progPath) {
41		progVers = goVers
42	} else {
43		progVers = info.Main.Version
44		if strings.Contains(progVers, "devel") || strings.Count(progVers, "-") > 1 {
45			// Heuristically mark all pseudo-version-like version strings as "devel"
46			// to avoid creating too many counter files.
47			// We should not use regexp that pulls in large dependencies.
48			// Pseudo-versions have at least three parts (https://go.dev/ref/mod#pseudo-versions).
49			// This heuristic still allows use to track prerelease
50			// versions (e.g. gopls@v0.16.0-pre.1, vscgo@v0.42.0-rc.1).
51			progVers = "devel"
52		}
53	}
54
55	return goVers, progPath, progVers
56}
57