< Summary

Information
Class: Dotnet.Installer.Core.Models.Component
Assembly: Dotnet.Installer.Core
File(s): /home/runner/work/dotnet-snap/dotnet-snap/src/Dotnet.Installer.Core/Models/Component.cs
Line coverage
61%
Covered lines: 90
Uncovered lines: 57
Coverable lines: 147
Total lines: 237
Line coverage: 61.2%
Branch coverage
40%
Covered branches: 32
Total branches: 80
Branch coverage: 40%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
get_Key()100%11100%
get_Name()100%11100%
get_Description()100%11100%
get_MajorVersion()100%11100%
get_IsLts()100%11100%
get_EndOfLife()100%11100%
get_Dependencies()100%11100%
get_Installation()100%11100%
get_IsInstalled()100%11100%
Install()71.42%151485.71%
Uninstall()75%4476.92%
PlaceMountUnits()33.33%9658.82%
RemoveMountUnits()33.33%9657.14%
Mount()8.33%761223.52%
Unmount()14.28%771431.57%
PlacePathUnits()50%171266.66%
RemovePathUnits()50%171266.66%

File(s)

/home/runner/work/dotnet-snap/dotnet-snap/src/Dotnet.Installer.Core/Models/Component.cs

#LineLine coverage
 1using System.Text;
 2using System.Text.Json.Serialization;
 3using Dotnet.Installer.Core.Models.Events;
 4using Dotnet.Installer.Core.Services.Contracts;
 5
 6namespace Dotnet.Installer.Core.Models;
 7
 8public class Component
 9{
 7610    public required string Key { get; init; }
 911    public required string Name { get; init; }
 912    public required string Description { get; init; }
 913    public required int MajorVersion { get; init; }
 914    public required bool IsLts { get; init; }
 15    [JsonPropertyName("eol")]
 916    public required DateTime EndOfLife { get; init; }
 3217    public required IEnumerable<string> Dependencies { get; init; }
 918    public Installation? Installation { get; set; }
 719    public bool IsInstalled => Installation is not null;
 20
 21    public event EventHandler<InstallationStartedEventArgs>? InstallationStarted;
 22    public event EventHandler<InstallationFinishedEventArgs>? InstallationFinished;
 23
 24    public async Task Install(IFileService fileService, IManifestService manifestService, ISnapService snapService,
 25        ISystemdService systemdService, ILogger? logger = null)
 526    {
 527        if (IsInstalled)
 028        {
 029            logger?.LogInformation($"{Description} already installed!");
 030            return;
 31        }
 32
 533        InstallationStarted?.Invoke(this, new InstallationStartedEventArgs(Key));
 34
 35        // Install content snap on the machine
 536        if (!snapService.IsSnapInstalled(Key))
 537        {
 538            var result = await snapService.Install(Key);
 539            if (!result.IsSuccess) throw new ApplicationException(result.StandardError);
 540        }
 41
 42        // Place linking file in the content snap's $SNAP_COMMON
 543        await fileService.PlaceLinkageFile(Key);
 44
 45        // Install Systemd mount units
 546        await PlaceMountUnits(fileService, manifestService, systemdService, logger);
 47
 48        // Install update watcher unit
 549        await PlacePathUnits(fileService, systemdService, logger);
 50
 51        // Register the installation of this component in the local manifest file
 552        await manifestService.Add(this);
 53
 1954        foreach (var dependency in Dependencies)
 255        {
 756            var component = manifestService.Remote.First(c => c.Key == dependency);
 257            await component.Install(fileService, manifestService, snapService, systemdService, logger);
 258        }
 59
 560        InstallationFinished?.Invoke(this, new InstallationFinishedEventArgs(Key));
 561    }
 62
 63    public async Task Uninstall(IFileService fileService, IManifestService manifestService, ISnapService snapService,
 64        ISystemdService systemdService, ILogger? logger = default)
 165    {
 166        if (IsInstalled)
 167        {
 68            // Uninstall systemd mount units
 169            await RemoveMountUnits(fileService, manifestService, systemdService, logger);
 70
 71            // Uninstall systemd path units
 172            await RemovePathUnits(fileService, systemdService, logger);
 73
 174            if (snapService.IsSnapInstalled(Key))
 075            {
 076                await snapService.Remove(Key, purge: true);
 077            }
 78
 179            Installation = null;
 180            await manifestService.Remove(this);
 181        }
 182    }
 83
 84    public async Task PlaceMountUnits(IFileService fileService, IManifestService manifestService,
 85        ISystemdService systemdService, ILogger? logger = default)
 586    {
 587        var units = new StringBuilder();
 588        var unitPaths = fileService.EnumerateContentSnapMountFiles(Key);
 89
 1590        foreach (var unitPath in unitPaths)
 091        {
 092            logger?.LogDebug($"Copying {unitPath} to systemd directory.");
 093            fileService.InstallSystemdMountUnit(unitPath);
 094            units.AppendLine(unitPath.Split('/').Last());
 095        }
 96
 97        // Save unit names to component .mounts file
 598        await fileService.PlaceUnitsFile(manifestService.SnapConfigurationLocation, contentSnapName: Key,
 599            units.ToString());
 100
 5101        var result = await systemdService.DaemonReload();
 5102        if (!result.IsSuccess)
 0103        {
 0104            throw new ApplicationException("Could not reload systemd daemon");
 105        }
 5106        await Mount(manifestService, fileService, systemdService, logger);
 5107    }
 108
 109    public async Task RemoveMountUnits(IFileService fileService, IManifestService manifestService,
 110        ISystemdService systemdService, ILogger? logger = default)
 1111    {
 1112        await Unmount(fileService, manifestService, systemdService, logger);
 113
 1114        var units = await fileService.ReadUnitsFile(manifestService.SnapConfigurationLocation, Key);
 115
 3116        foreach (var unit in units)
 0117        {
 0118            logger?.LogDebug($"Removing {unit} from systemd directory.");
 0119            fileService.UninstallSystemdMountUnit(unit);
 0120        }
 121
 1122        fileService.DeleteUnitsFile(manifestService.SnapConfigurationLocation, Key);
 123
 1124        var result = await systemdService.DaemonReload();
 1125        if (!result.IsSuccess)
 0126        {
 0127            throw new ApplicationException("Could not reload systemd daemon");
 128        }
 1129    }
 130
 131    public async Task Mount(IManifestService manifestService, IFileService fileService, ISystemdService systemdService,
 132        ILogger? logger = default)
 5133    {
 5134        var units = await fileService.ReadUnitsFile(manifestService.SnapConfigurationLocation, Key);
 135
 15136        foreach (var unit in units)
 0137        {
 0138            var result = await systemdService.EnableUnit(unit);
 0139            if (!result.IsSuccess)
 0140            {
 0141                throw new ApplicationException($"Could not enable unit {unit}");
 142            }
 0143            logger?.LogDebug($"Enabled {unit}");
 144
 0145            result = await systemdService.StartUnit(unit);
 0146            if (!result.IsSuccess)
 0147            {
 0148                throw new ApplicationException($"Could not start unit {unit}");
 149            }
 0150            logger?.LogDebug($"Started {unit}");
 151
 0152            logger?.LogDebug($"Finished mounting {unit}");
 0153        }
 5154    }
 155
 156    public async Task Unmount(IFileService fileService, IManifestService manifestService,
 157        ISystemdService systemdService, ILogger? logger = default)
 1158    {
 1159        var units = await fileService.ReadUnitsFile(manifestService.SnapConfigurationLocation, Key);
 160
 3161        foreach (var unit in units)
 0162        {
 0163            var result = await systemdService.DisableUnit(unit);
 0164            if (!result.IsSuccess)
 0165            {
 0166                throw new ApplicationException($"Could not disable unit {unit}");
 167            }
 0168            logger?.LogDebug($"Disabled {unit}");
 169
 0170            result = await systemdService.StopUnit(unit);
 0171            if (!result.IsSuccess)
 0172            {
 0173                throw new ApplicationException($"Could not stop unit {unit}");
 174            }
 0175            logger?.LogDebug($"Stopped {unit}");
 176
 0177            logger?.LogDebug($"Finished unmounting {unit}");
 0178        }
 179
 180        // Check for any empty directories
 1181        fileService.RemoveEmptyDirectories(manifestService.DotnetInstallLocation);
 1182        logger?.LogDebug("Removed empty directories.");
 1183    }
 184
 185    private async Task PlacePathUnits(IFileService fileService, ISystemdService systemdService, ILogger? logger = null)
 5186    {
 5187        fileService.InstallSystemdPathUnit(Key);
 5188        logger?.LogDebug($"Placed upgrade watcher path and service units for snap {Key}");
 189
 5190        var result = await systemdService.DaemonReload();
 5191        if (!result.IsSuccess)
 0192        {
 0193            throw new ApplicationException("Could not reload systemd daemon");
 194        }
 195
 5196        result = await systemdService.EnableUnit($"{Key}-update-watcher.path");
 5197        if (!result.IsSuccess)
 0198        {
 0199            throw new ApplicationException($"Could not enable {Key}-update-watcher.path");
 200        }
 5201        logger?.LogDebug($"Enabled {Key}-update-watcher.path");
 202
 5203        result = await systemdService.StartUnit($"{Key}-update-watcher.path");
 5204        if (!result.IsSuccess)
 0205        {
 0206            throw new ApplicationException($"Could not start {Key}-update-watcher.path");
 207        }
 5208        logger?.LogDebug($"Started {Key}-update-watcher.path");
 5209    }
 210
 211    private async Task RemovePathUnits(IFileService fileService, ISystemdService systemdService,
 212        ILogger? logger = default)
 1213    {
 1214        var result = await systemdService.DisableUnit($"{Key}-update-watcher.path");
 1215        if (!result.IsSuccess)
 0216        {
 0217            throw new ApplicationException($"Could not disable {Key}-update-watcher.path");
 218        }
 1219        logger?.LogDebug($"Disabled {Key}-update-watcher.path");
 220
 1221        result = await systemdService.StopUnit($"{Key}-update-watcher.path");
 1222        if (!result.IsSuccess)
 0223        {
 0224            throw new ApplicationException($"Could not stop {Key}-update-watcher.path");
 225        }
 1226        logger?.LogDebug($"Stopped {Key}-update-watcher.path");
 227
 1228        fileService.UninstallSystemdPathUnit(Key);
 1229        logger?.LogDebug($"Removed upgrade watcher path and service units for snap {Key}");
 230
 1231        result = await systemdService.DaemonReload();
 1232        if (!result.IsSuccess)
 0233        {
 0234            throw new ApplicationException("Could not reload systemd daemon");
 235        }
 1236    }
 237}