using ClaudeDo.Releases;
namespace ClaudeDo.Installer.Core;
public sealed record DetectedState(
InstallerMode Mode,
InstallManifest? Existing,
GiteaRelease? LatestRelease,
string? LatestVersion)
{
/// True when a release was returned but its tag isn't a parseable
/// System.Version (e.g. "0.2.0-beta") — so we couldn't decide if it's newer.
public bool LatestTagUnparseable { get; init; }
}
public sealed class InstallModeDetector
{
private readonly IReleaseClient _releases;
public InstallModeDetector(IReleaseClient releases)
{
_releases = releases;
}
public async Task DetectAsync(string installDir, CancellationToken ct)
{
var manifest = InstallManifestStore.TryRead(installDir);
if (manifest is null)
return new DetectedState(InstallerMode.FreshInstall, null, null, null);
var release = await _releases.GetLatestReleaseAsync(ct);
if (release is null)
return new DetectedState(InstallerMode.Config, manifest, null, null);
var latestVersion = release.TagName.TrimStart('v', 'V');
var cmp = VersionComparer.Compare(latestVersion, manifest.Version);
var newer = cmp.IsNewer;
var unparseable = cmp.Unparseable;
if (newer)
return new DetectedState(InstallerMode.Update, manifest, release, latestVersion);
return new DetectedState(InstallerMode.Config, manifest, release, latestVersion)
{
LatestTagUnparseable = unparseable,
};
}
}