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
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ bld init Add the Build submodule (defaults to the latest ta
bld init --tag v1.2.3 Add the Build submodule pinned to a specific tag
bld update Move an existing submodule to the latest tag
bld update --tag v1.2.3 Move an existing submodule to a specific tag
bld self-update Reinstall the bld CLI from the latest main
bld self-update --ref v0.2.0 Install a specific BuildCLI branch or tag
bld upgrade Alias for self-update
bld status Show the current submodule path, commit, and tags
bld tags List tags advertised by the Build remote
bld repair --strategy stash Stash local submodule changes, then restore the parent HEAD
Expand Down Expand Up @@ -47,6 +50,8 @@ Common options:

`init` and `update` stage `.gitmodules` and the submodule gitlink. They do not create a commit, so you can review the change in the parent repository first.

`self-update` (alias `upgrade`) republishes this CLI from [IngeniumSE/BuildCLI](https://github.com/IngeniumSE/BuildCLI) and replaces the installed `bld` binary. It does not change the Build submodule; use `update` for that. By default it clones `main` over HTTPS. Pass `--source` to publish an existing checkout, or `--ref` for a branch or tag. The install location matches `scripts/install.sh` / `scripts/install.ps1` (`~/.local/share/ingenium/bld` on Unix, `%LOCALAPPDATA%\Ingenium\bld` on Windows) and can be overridden with `BLD_INSTALL_DIR` or `--install-dir`.

Existing Ingenium repositories that already use `build` or `Build` as the submodule path are detected automatically.

`repair` can prompt for a strategy when run interactively. `reset` and `reinit` are destructive and require `--yes` in non-interactive use.
Expand Down Expand Up @@ -82,6 +87,12 @@ curl -sSL https://raw.githubusercontent.com/IngeniumSE/BuildCLI/main/scripts/ins

The default install location is `~/.local/share/ingenium/bld`, with a symlink at `~/.local/bin/bld`. Add `~/.local/bin` to `PATH` if the installer reports that the command is not visible yet.

After `bld` is on PATH, later versions can be installed with:

```bash
bld self-update
```

### Windows

From a clone:
Expand All @@ -96,7 +107,7 @@ Or later:
irm https://raw.githubusercontent.com/IngeniumSE/BuildCLI/main/scripts/install.ps1 | iex
```

The default install location is `%LOCALAPPDATA%\Ingenium\bld`. That directory is added to the user `PATH`. Open a new terminal before running `bld`.
The default install location is `%LOCALAPPDATA%\Ingenium\bld`. That directory is added to the user `PATH`. Open a new terminal before running `bld`. After `bld` is on PATH, later versions can be installed with `bld self-update`.

### .NET tool

Expand Down
12 changes: 12 additions & 0 deletions apps/Ingenium.BuildCli/BuildCliApplication.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Ingenium.BuildCli.Infrastructure;
using Ingenium.BuildCli.Execution;
using Ingenium.BuildCli.Rendering;
using Ingenium.BuildCli.SelfUpdate;
using Ingenium.BuildCli.Submodule;

using Microsoft.Extensions.DependencyInjection;
Expand Down Expand Up @@ -35,6 +36,7 @@ public static CommandApp Create(IAnsiConsole? console = null, Action<IServiceCol
services.AddSingleton<IBuildSubmoduleService, BuildSubmoduleService>();
services.AddSingleton<IBuildHostService, BuildHostService>();
services.AddSingleton<IBuildExtensionService, BuildExtensionService>();
services.AddSingleton<ISelfUpdateService, SelfUpdateService>();
configureServices?.Invoke(services);

var app = new CommandApp(new TypeRegistrar(services));
Expand Down Expand Up @@ -90,6 +92,16 @@ public static void Configure(IConfigurator config)
.WithExample("update")
.WithExample("update", "--tag", "v1.2.3");

config.AddCommand<SelfUpdateCommand>("self-update")
.WithDescription("Update the installed bld CLI from the BuildCLI repository. Does not change the Build submodule.")
.WithExample("self-update")
.WithExample("self-update", "--ref", "main")
.WithExample("self-update", "--source", ".");

config.AddCommand<SelfUpdateCommand>("upgrade")
.WithDescription("Alias for self-update.")
.WithExample("upgrade");

config.AddCommand<StatusCommand>("status")
.WithDescription("Show the current Build submodule state.")
.WithExample("status");
Expand Down
11 changes: 9 additions & 2 deletions apps/Ingenium.BuildCli/CommandLineDefaults.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ public static class CommandLineDefaults
{
"init",
"update",
"self-update",
"upgrade",
"status",
"tags",
"repair",
Expand All @@ -43,7 +45,11 @@ public static class CommandLineDefaults
"-t",
"--tag",
"-s",
"--strategy"
"--strategy",
"--ref",
"--source",
"--install-dir",
"--bin-dir"
};

private static readonly HashSet<string> CliFlagOptions = new(StringComparer.OrdinalIgnoreCase)
Expand All @@ -53,7 +59,8 @@ public static class CommandLineDefaults
"-f",
"--force",
"-y",
"--yes"
"--yes",
"--framework-dependent"
};

/// <summary>
Expand Down
103 changes: 103 additions & 0 deletions apps/Ingenium.BuildCli/Commands/SelfUpdateCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// This work is licensed under the terms of the MIT license.
// For a copy, see <https://opensource.org/licenses/MIT>.

using System.ComponentModel;

using Ingenium.BuildCli.Git;
using Ingenium.BuildCli.Rendering;
using Ingenium.BuildCli.SelfUpdate;

using Spectre.Console;
using Spectre.Console.Cli;

namespace Ingenium.BuildCli.Commands;

/// <summary>
/// Republishes and reinstalls the <c>bld</c> CLI itself.
/// </summary>
public sealed class SelfUpdateCommand : AsyncCommand<SelfUpdateCommand.Settings>
{
private readonly IAnsiConsole _console;
private readonly ISelfUpdateService _service;
private readonly IGitTrace _trace;

/// <summary>
/// Initializes a new instance of the <see cref="SelfUpdateCommand"/> class.
/// </summary>
public SelfUpdateCommand(IAnsiConsole console, ISelfUpdateService service, IGitTrace trace)
{
_console = console;
_service = service;
_trace = trace;
}

/// <inheritdoc />
public override async Task<int> ExecuteAsync(CommandContext context, Settings settings)
{
_trace.Enabled = settings.Verbose;
ConsoleWriter.WriteHeader(_console, "self-update");

var request = settings.ToRequest();
var result = settings.Verbose
? await _service.UpdateAsync(request)
: await _console.Status()
.Spinner(Spinner.Known.Dots)
.StartAsync("Updating the installed bld CLI...", async _ => await _service.UpdateAsync(request));

_console.MarkupLine("[green]Updated[/] the installed bld CLI.");
_console.WriteLine();
ConsoleWriter.WriteSelfUpdate(_console, result);
return ExitCodes.Success;
}

/// <summary>
/// Settings for <see cref="SelfUpdateCommand"/>.
/// </summary>
public sealed class Settings : CommandSettings
{
[CommandOption("--ref <REF>")]
[Description("Git branch or tag of BuildCLI to install. Defaults to main.")]
public string? Ref { get; init; }

[CommandOption("--source <PATH>")]
[Description("Existing BuildCLI checkout to publish instead of cloning.")]
public string? Source { get; init; }

[CommandOption("--url <URL>")]
[Description("BuildCLI git URL used when cloning. Defaults to the public HTTPS repository.")]
public string? Url { get; init; }

[CommandOption("--install-dir <PATH>")]
[Description("Directory that receives the published bld binary.")]
public string? InstallDirectory { get; init; }

[CommandOption("--bin-dir <PATH>")]
[Description("Directory that receives the bld symlink on macOS and Linux.")]
public string? BinDirectory { get; init; }

[CommandOption("--framework-dependent")]
[Description("Publish a framework-dependent binary instead of a self-contained single file.")]
public bool FrameworkDependent { get; init; }

[CommandOption("--verbose")]
[Description("Write the git and dotnet commands that are executed.")]
public bool Verbose { get; init; }

/// <summary>
/// Creates a service request from these settings.
/// </summary>
public SelfUpdateRequest ToRequest()
{
return new SelfUpdateRequest
{
Ref = Ref,
Source = Source,
Url = Url,
FrameworkDependent = FrameworkDependent,
Verbose = Verbose,
InstallDirectory = InstallDirectory,
BinDirectory = BinDirectory
};
}
}
}
33 changes: 33 additions & 0 deletions apps/Ingenium.BuildCli/Rendering/ConsoleWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// For a copy, see <https://opensource.org/licenses/MIT>.

using Ingenium.BuildCli.Extensions;
using Ingenium.BuildCli.SelfUpdate;
using Ingenium.BuildCli.Submodule;

using Spectre.Console;
Expand Down Expand Up @@ -135,6 +136,38 @@ public static void WriteExtension(IAnsiConsole console, BuildExtensionScaffold s
console.MarkupLine("[grey]The Build host imports every project under build-extensions/ automatically.[/]");
}

/// <summary>
/// Writes a successful self-update summary.
/// </summary>
public static void WriteSelfUpdate(IAnsiConsole console, SelfUpdateResult result)
{
var table = new Table()
.Border(TableBorder.Rounded)
.HideHeaders()
.AddColumn(new TableColumn("Key").PadRight(2))
.AddColumn("Value");

table.AddRow("[grey]Version[/]", Markup.Escape(result.Version));
table.AddRow("[grey]Runtime[/]", Markup.Escape(result.RuntimeIdentifier));
table.AddRow("[grey]Ref[/]", Markup.Escape(result.Ref));
table.AddRow("[grey]Installed[/]", Markup.Escape(result.ExecutablePath));
if (!string.IsNullOrEmpty(result.BinLink))
{
table.AddRow("[grey]Link[/]", Markup.Escape(result.BinLink));
}

console.Write(table);

if (!result.BinDirectoryOnPath)
{
var hint = OperatingSystem.IsWindows()
? Path.GetDirectoryName(result.ExecutablePath) ?? result.ExecutablePath
: Path.GetDirectoryName(result.BinLink ?? result.ExecutablePath) ?? result.ExecutablePath;
console.WriteLine();
console.MarkupLine($"[yellow]bld may not be on PATH.[/] Add {Markup.Escape(hint)} to PATH and reopen the terminal.");
}
}

/// <summary>
/// Writes advertised remote tags.
/// </summary>
Expand Down
15 changes: 15 additions & 0 deletions apps/Ingenium.BuildCli/SelfUpdate/ISelfUpdateService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// This work is licensed under the terms of the MIT license.
// For a copy, see <https://opensource.org/licenses/MIT>.

namespace Ingenium.BuildCli.SelfUpdate;

/// <summary>
/// Republishes and reinstalls the <c>bld</c> CLI.
/// </summary>
public interface ISelfUpdateService
{
/// <summary>
/// Clones or uses a local checkout, publishes <c>bld</c>, and replaces the installed binary.
/// </summary>
Task<SelfUpdateResult> UpdateAsync(SelfUpdateRequest request, CancellationToken cancellationToken = default);
}
Loading
Loading