mirror of
https://gitea.com/gitea/tea.git
synced 2026-07-16 02:57:40 +02:00
3b5703177d
Fixes https://gitea.com/gitea/tea/issues/1053 ## What tea hangs forever on Windows when it is started by something that owns a console but redirects tea's stdio: a Windows service, a CI runner, an automation harness. Every command is affected, `tea --version` included. ## Root cause `modules/theme` imported `charm.land/lipgloss/v2/compat` for one struct type, `compat.AdaptiveColor`. But compat detects the terminal background from package-level vars: ```go var ( HasDarkBackground = lipgloss.HasDarkBackground(os.Stdin, os.Stdout) Profile = colorprofile.Detect(os.Stdout, os.Environ()) ) ``` Go initialises every package in the import graph before `main()` runs, and every file in package `cmd` imports `modules/context`, which imports `modules/theme`. So tea queried the terminal on every invocation, before urfave/cli had even looked at the arguments — which is why `--version` hung. On Windows that query opens `CONIN$`/`CONOUT$` and asks the console directly instead of giving up when stdio is redirected, then waits for a reply that never comes. The read has a 2 second timeout, but it does not fire, because the cancel it relies on is a no-op for that handle. Full trace in the issue. ## Changes - `modules/theme/theme.go` — drop the `compat` import and use `lipgloss.LightDark`, a plain function that touches no terminal. `TeaTheme.Theme` is already handed the `isDark` it needs. This also fixes a bug hiding in plain sight: `compat.AdaptiveColor` resolves against a process-wide value detected at init, so the title color ignored the `isDark` argument huh passed in. `Theme(true)` and `Theme(false)` returned the same color. - `modules/theme/background.go` — new `HasDarkBackground()` helper that only asks the terminal when stdin and stdout are both terminals, and otherwise assumes dark, which is the default lipgloss itself falls back to. This is the same rule lipgloss already applies on Unix. - `modules/interact/print.go` — `printTitleAndContent` called `lipgloss.HasDarkBackground(os.Stdin, os.Stdout)` directly, so it hit the same wait on the interactive paths, `tea login add` among them. It now goes through the helper. ## Why fix this in tea The underlying bug is upstream and I have opened PRs for both halves of it: https://github.com/charmbracelet/ultraviolet/pull/138 and https://github.com/charmbracelet/lipgloss/pull/713. But it is not fixed in any released version — lipgloss v2.0.5 is byte-identical to v2.0.4 in the relevant files — so upgrading dependencies does not help, and tea would stay broken on Windows until Charm cuts a release and tea bumps `go.mod`. Separately, these changes stand on their own. tea should not query the terminal in order to print a version string, whatever upstream does. Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: Willem Kokke <mail@willem.net>
32 lines
1.1 KiB
Go
32 lines
1.1 KiB
Go
// Copyright 2026 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package theme
|
|
|
|
import (
|
|
"os"
|
|
|
|
"charm.land/lipgloss/v2"
|
|
"golang.org/x/term"
|
|
)
|
|
|
|
// defaultDarkBackground is the background to assume when we cannot detect one. It
|
|
// matches the default lipgloss falls back to.
|
|
const defaultDarkBackground = true
|
|
|
|
// HasDarkBackground reports whether the terminal has a dark background.
|
|
//
|
|
// It only asks the terminal when stdin and stdout are both terminals. Detection
|
|
// works by writing an escape sequence to the output and waiting for the terminal
|
|
// to answer on the input, and nothing answers when stdio is redirected, so asking
|
|
// means waiting on a reply that never comes. On Windows that wait is unbounded:
|
|
// lipgloss opens the console directly rather than giving up, which is why tea used
|
|
// to hang at start-up under a service or a CI runner.
|
|
func HasDarkBackground() bool {
|
|
if !term.IsTerminal(int(os.Stdin.Fd())) || !term.IsTerminal(int(os.Stdout.Fd())) {
|
|
return defaultDarkBackground
|
|
}
|
|
|
|
return lipgloss.HasDarkBackground(os.Stdin, os.Stdout)
|
|
}
|