turbo-editors/turbo-pythonpublic Fork 0
bbfc62fe52548e4712c66104331c9a4de0cff21e
Commits
Clone
git clone https://git.rickub.com/turbo-editors/turbo-python.git
git clone ssh://git@rickub.com/turbo-editors/turbo-python.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

📦 Turbo Python 6fc62ea · on bbfc62fe52548e4712c66104331c9a4de0cff21e · k33g · 10h ago
versioning.md · 150 lines · 6.2 KBmarkdown
Blame HistoryOpen raw

Reference: the version number

Neutral description of where the version Turbo Python reports comes from, and what each way of building it produces.

Where the number comes from

Three sources, consulted in this order. The first that answers wins.

Order Source Set by
1 Linker stamps make build, make install, scripts/install.sh
2 Go build information The Go tool, automatically
3 unknown Nothing — the value reported when no source could name the build

There is no version constant in the source. A number written into a .go file has to be edited as part of releasing, and is wrong the moment someone forgets.

Linker stamps

Three package-level variables in internal/version, set with -ldflags -X.

Variable Filled from Example
stamp git describe --tags --dirty v0.1.0-14-g88a4c38
commit git rev-parse --short HEAD 88a4c38
built date -u +%Y-%m-%dT%H:%M:%SZ 2026-08-31T18:04:05Z
go build -ldflags "\
  -X 'rickub.com/turbo-editors/turbo-python/internal/version.stamp=v0.2.0' \
  -X 'rickub.com/turbo-editors/turbo-python/internal/version.commit=88a4c38' \
  -X 'rickub.com/turbo-editors/turbo-python/internal/version.built=2026-08-31T18:04:05Z'" .

A leading v is dropped for display: the tag is v0.2.0, the About box says 0.2.0.

Go build information

Read from runtime/debug.ReadBuildInfo() when nothing was stamped.

Field read Used for
Main.Version The number, unless it is empty, (devel), or a pseudo-version
vcs.revision The commit, abbreviated to seven characters
vcs.modified Whether -dirty is appended

vcs.time is not used. It records when the commit was made, not when the binary was linked, so reporting it as a build date would be wrong on every binary built later than its own commit.

A pseudo-versionv0.1.1-0.20260831165958-88a4c3859bf3 — is the Go tool naming a commit that no tag names. It is reported as devel, not shown as written: its 0.1.1 is a patch release that does not exist.

What each build reports

Built by Number Commit Built
make build, make install, scripts/install.sh 0.1.0-14-g88a4c38 yes yes
The same, on a tagged commit 0.2.0 yes yes
The same, with uncommitted changes 0.1.0-14-g88a4c38-dirty yes yes
go install rickub.com/turbo-editors/turbo-python@v0.2.0 0.2.0 no no
go build . in a checkout devel yes no
go build . in a checkout with uncommitted changes devel-dirty yes no
uv run unknown no no
A checkout with no git, and no stamps unknown no no

Only the stamped rows can report a tag: the Go build system does not read git tags.

Checked at build time

A linker stamp is a string, and a wrong one is not an error. -X naming a symbol that does not exist links happily and stamps nothing; the binary then falls back to Go build information and reports a version the build never meant — often devel, on a binary attached to a release. Nothing but running the binary catches it, so every build that produces one runs it.

scripts/check-version.sh is what runs.

Called by On A failure fails
make build bin/turbo-python, with $(VERSION) and $(COMMIT) the build
scripts/install.sh the staged binary, before it is installed the install, leaving the binary already there untouched
03-build-releases.sh the one staged asset this machine can run, with the tag the release build
scripts/check-version.sh bin/turbo-python v0.2.0 88a4c38   # a stamped build
scripts/check-version.sh bin/turbo-python                  # nothing to expect
Arguments Passes when
binary, version, commit the reported number equals the version with its leading v dropped, and the commit appears in the output
binary, version the number equals it
binary the number is anything but unknown

The version comparison is an equality, not a search. 0.2.0 is a substring of 10.2.0, and of a commit hash that happens to contain it; a stamp that is nearly right is exactly what this exists to catch.

Exit Meaning
0 The binary reports what the build meant. The line it printed is echoed.
1 It does not run, is not there, or reports something else.
2 No binary was named.

Where it is shown

-version

One line, carrying every part that is known.

Turbo Python 0.2.0 (88a4c38, built 2026-08-31T18:04:05Z)
Turbo Python 0.2.0 (88a4c38)
Turbo Python 0.2.0

Help ▸ About

One line per known fact. A fact the build did not record has no line, rather than an empty one.

Turbo Python 0.2.0

A Turbo C-style editor for Python,
written in Go.

Commit: 88a4c38
Built:  2026-08-31 18:04 UTC
Theme:  Turbo Classic

Built is rendered in UTC as YYYY-MM-DD HH:MM UTC. A stamp that is not valid RFC 3339 is shown exactly as it was given, rather than dropped.

make version

Prints what this checkout would stamp, without building.

$ make version
v0.1.0-14-g88a4c38 (88a4c38)

make ldflags

Prints the linker flags a stamped build uses, so a script can reuse them instead of repeating the -X paths.

$ make ldflags
-X 'rickub.com/turbo-editors/turbo-python/internal/version.stamp=v0.2.0' -X '….commit=7f8b36a' -X '….built=2026-08-31T19:02:03Z'

03-build-releases.sh reads it for its cross-compiles, overriding the version with the tag it is releasing — make ldflags VERSION=v0.2.0 — so the binaries say what the release says rather than what git describe says. A binary cross-compiled without it reports devel, whatever the release it is attached to says.

See also

  • Cutting a release so the number is right: How to make a release
  • What -version is not for: it is written for a person. A script that needs the number should compare with grep -F, or ask git, rather than reading a field out of it.
  • Why there is no version constant: Design decisions
  • The -version flag among the others: Command line
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# Reference: the version number

> Neutral description of where the version Turbo Python reports comes from, and what each way of building it produces.

## Where the number comes from

Three sources, consulted in this order. The first that answers wins.

| Order | Source | Set by |
| --- | --- | --- |
| 1 | Linker stamps | `make build`, `make install`, `scripts/install.sh` |
| 2 | Go build information | The Go tool, automatically |
| 3 | `unknown` | Nothing — the value reported when no source could name the build |

There is **no version constant in the source**. A number written into a `.go` file has to be edited as part of releasing, and is wrong the moment someone forgets.

## Linker stamps

Three package-level variables in `internal/version`, set with `-ldflags -X`.

| Variable | Filled from | Example |
| --- | --- | --- |
| `stamp` | `git describe --tags --dirty` | `v0.1.0-14-g88a4c38` |
| `commit` | `git rev-parse --short HEAD` | `88a4c38` |
| `built` | `date -u +%Y-%m-%dT%H:%M:%SZ` | `2026-08-31T18:04:05Z` |

```sh
go build -ldflags "\
  -X 'rickub.com/turbo-editors/turbo-python/internal/version.stamp=v0.2.0' \
  -X 'rickub.com/turbo-editors/turbo-python/internal/version.commit=88a4c38' \
  -X 'rickub.com/turbo-editors/turbo-python/internal/version.built=2026-08-31T18:04:05Z'" .
```

A leading `v` is dropped for display: the tag is `v0.2.0`, the About box says `0.2.0`.

## Go build information

Read from `runtime/debug.ReadBuildInfo()` when nothing was stamped.

| Field read | Used for |
| --- | --- |
| `Main.Version` | The number, unless it is empty, `(devel)`, or a pseudo-version |
| `vcs.revision` | The commit, abbreviated to seven characters |
| `vcs.modified` | Whether `-dirty` is appended |

`vcs.time` is **not** used. It records when the commit was made, not when the binary was linked, so reporting it as a build date would be wrong on every binary built later than its own commit.

A **pseudo-version**`v0.1.1-0.20260831165958-88a4c3859bf3` — is the Go tool naming a commit that no tag names. It is reported as `devel`, not shown as written: its `0.1.1` is a patch release that does not exist.

## What each build reports

| Built by | Number | Commit | Built |
| --- | --- | --- | --- |
| `make build`, `make install`, `scripts/install.sh` | `0.1.0-14-g88a4c38` | yes | yes |
| The same, on a tagged commit | `0.2.0` | yes | yes |
| The same, with uncommitted changes | `0.1.0-14-g88a4c38-dirty` | yes | yes |
| `go install rickub.com/turbo-editors/turbo-python@v0.2.0` | `0.2.0` | no | no |
| `go build .` in a checkout | `devel` | yes | no |
| `go build .` in a checkout with uncommitted changes | `devel-dirty` | yes | no |
| `uv run` | `unknown` | no | no |
| A checkout with no git, and no stamps | `unknown` | no | no |

Only the stamped rows can report a tag: the Go build system does not read git tags.

## Checked at build time

A linker stamp is a string, and a wrong one is not an error. `-X` naming a symbol that does not exist links happily and stamps nothing; the binary then falls back to Go build information and reports a version the build never meant — often `devel`, on a binary attached to a release. Nothing but running the binary catches it, so every build that produces one runs it.

`scripts/check-version.sh` is what runs.

| Called by | On | A failure fails |
| --- | --- | --- |
| `make build` | `bin/turbo-python`, with `$(VERSION)` and `$(COMMIT)` | the build |
| `scripts/install.sh` | the staged binary, **before** it is installed | the install, leaving the binary already there untouched |
| `03-build-releases.sh` | the one staged asset this machine can run, with the tag | the release build |

```sh
scripts/check-version.sh bin/turbo-python v0.2.0 88a4c38   # a stamped build
scripts/check-version.sh bin/turbo-python                  # nothing to expect
```

| Arguments | Passes when |
| --- | --- |
| binary, version, commit | the reported number **equals** the version with its leading `v` dropped, and the commit appears in the output |
| binary, version | the number equals it |
| binary | the number is anything but `unknown` |

The version comparison is an equality, not a search. `0.2.0` is a substring of `10.2.0`, and of a commit hash that happens to contain it; a stamp that is nearly right is exactly what this exists to catch.

| Exit | Meaning |
| --- | --- |
| `0` | The binary reports what the build meant. The line it printed is echoed. |
| `1` | It does not run, is not there, or reports something else. |
| `2` | No binary was named. |

## Where it is shown

### `-version`

One line, carrying every part that is known.

```
Turbo Python 0.2.0 (88a4c38, built 2026-08-31T18:04:05Z)
Turbo Python 0.2.0 (88a4c38)
Turbo Python 0.2.0
```

### Help ▸ About

One line per known fact. A fact the build did not record has **no line**, rather than an empty one.

```
Turbo Python 0.2.0

A Turbo C-style editor for Python,
written in Go.

Commit: 88a4c38
Built:  2026-08-31 18:04 UTC
Theme:  Turbo Classic
```

`Built` is rendered in UTC as `YYYY-MM-DD HH:MM UTC`. A stamp that is not valid RFC 3339 is shown exactly as it was given, rather than dropped.

### `make version`

Prints what this checkout would stamp, without building.

```
$ make version
v0.1.0-14-g88a4c38 (88a4c38)
```

### `make ldflags`

Prints the linker flags a stamped build uses, so a script can reuse them instead of repeating the `-X` paths.

```
$ make ldflags
-X 'rickub.com/turbo-editors/turbo-python/internal/version.stamp=v0.2.0' -X '….commit=7f8b36a' -X '….built=2026-08-31T19:02:03Z'
```

`03-build-releases.sh` reads it for its cross-compiles, overriding the version with the tag it is releasing — `make ldflags VERSION=v0.2.0` — so the binaries say what the release says rather than what `git describe` says. A binary cross-compiled without it reports `devel`, whatever the release it is attached to says.

## See also

- Cutting a release so the number is right: [How to make a release](../how-to/make-a-release.md)
- What `-version` is **not** for: it is written for a person. A script that needs the number should compare with `grep -F`, or ask git, rather than reading a field out of it.
- Why there is no version constant: [Design decisions](../explanation/design-decisions.md#the-version-is-a-property-of-the-build-not-of-the-source)
- The `-version` flag among the others: [Command line](cli.md)