Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [1.0.0-beta.5] - 2026-09-28

### Added

- `sourceant update` replaces this command, the agent and the core, or the parts
named. Each download is checked against the release's own checksums, and the
replacement is renamed over the old file, so an interrupted update leaves a
working install
- `sourceant start` starts the agent and the indexer without opening a browser

### Changed

- A command that needs the agent starts one, on the next free port when
something else holds the usual one, and writes that address down so later
commands and the view agree on it
- `sourceant setup` starts what it installed

## [1.0.0-beta.4] - 2026-09-27

### Added
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.0-beta.4
1.0.0-beta.5
6 changes: 2 additions & 4 deletions internal/agent/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,11 @@ func New(baseURL string, timeout time.Duration) *Client {
// Starter brings the agent up and answers with the address it listens on.
type Starter func(ctx context.Context) (string, error)

// StartWith gives this client something to run when nothing answers. Without
// it, a call to an agent that is not running fails as it always did.
// StartWith gives this client something to run when nothing answers.
func StartWith(client *Client, start Starter) { client.revive.start = start }

// reviving starts the agent once, for the first call that finds it absent, and
// sends that call again. The agent may come up somewhere else, so the retry
// follows the address it answers on.
// sends that call again.
type reviving struct {
client *Client
start Starter
Expand Down
9 changes: 4 additions & 5 deletions internal/command/lifecycle.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ func ensureAgent(ctx context.Context, opts *options, out io.Writer) (string, err
if _, err := agent.New(opts.agentURL, opts.timeout).Status(ctx); err == nil {
return opts.agentURL, nil
}
// An address somebody named is the address they meant, so it is started
// there or not at all. Only the default moves when something holds it.
// An address somebody named is the address they meant, so it is started there
// or not at all.
listen, err := address(opts.agentURL, !opts.agentNamed)
if err != nil {
return "", err
Expand All @@ -46,8 +46,7 @@ func ensureAgent(ctx context.Context, opts *options, out io.Writer) (string, err
return target, nil
}

// address is what to listen on. With move, a port something else holds is
// passed over for the next one up.
// address is what to listen on, passing over a port something else holds.
func address(from string, move bool) (string, error) {
parsed, err := url.Parse(from)
if err != nil {
Expand Down Expand Up @@ -105,7 +104,7 @@ func run(listen string, out io.Writer) error {
}

// answering waits for the agent to serve, which means waiting for the core it
// starts first. A first run pulls or builds one.
// starts first.
func answering(ctx context.Context, target string, timeout time.Duration) error {
client := agent.New(target, timeout)
deadline := time.Now().Add(90 * time.Second)
Expand Down
4 changes: 1 addition & 3 deletions internal/command/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,7 @@ func agentDefault() string {
return DefaultAgent
}

// client talks to the agent, starting one where nothing answers. Anything that
// needs the agent is something somebody asked for, and asking them to run a
// second command first is a step the command can take itself.
// client talks to the agent, starting one where nothing answers.
func (o *options) client() *agent.Client {
client := agent.New(o.agentURL, o.timeout)
agent.StartWith(client, func(ctx context.Context) (string, error) {
Expand Down
3 changes: 1 addition & 2 deletions internal/update/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ type Asset struct {
// Fetcher reads a URL.
type Fetcher func(ctx context.Context, url string) ([]byte, error)

// Latest is the newest release of a repository. Prereleases are included when
// asked for, which is what a machine already running one wants.
// Latest is the newest release of a repository.
func Latest(ctx context.Context, get Fetcher, repo string, prerelease bool) (Release, error) {
base := api(repo)
if !prerelease {
Expand Down
Loading