< Summary

Information
Class: Dotnet.Installer.Core.Services.Implementations.FileService
Assembly: Dotnet.Installer.Core
File(s): /home/runner/work/dotnet-snap/dotnet-snap/src/Dotnet.Installer.Core/Services/Implementations/FileService.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 93
Coverable lines: 93
Total lines: 168
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 22
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

/home/runner/work/dotnet-snap/dotnet-snap/src/Dotnet.Installer.Core/Services/Implementations/FileService.cs

#LineLine coverage
 1using System.Text;
 2using Dotnet.Installer.Core.Services.Contracts;
 3using Dotnet.Installer.Core.Types;
 4
 5namespace Dotnet.Installer.Core.Services.Implementations;
 6
 7public class FileService : IFileService
 8{
 9    /// <summary>
 10    /// Enumerates the .mount unit files for a .NET content snap by looking at the files present in the directory
 11    /// <c>$SNAP/mounts</c>.
 12    /// </summary>
 13    /// <param name="contentSnapName">The .NET content snap name.</param>
 14    /// <returns>A list of absolute paths of the .mount unit files for <c>contentSnapName</c>.</returns>
 15    public IEnumerable<string> EnumerateContentSnapMountFiles(string contentSnapName)
 016    {
 017        return Directory.EnumerateFiles(Path.Join("/", "snap", contentSnapName, "current", "mounts"));
 018    }
 19
 20    /// <inheritdoc cref="File.Exists"/>
 21    public bool FileExists(string path)
 022    {
 023        return File.Exists(path);
 024    }
 25
 26    public void InstallSystemdMountUnit(string unitPath)
 027    {
 028        var destination = Path.Join("/", "usr", "lib", "systemd", "system");
 29
 030        File.Copy(unitPath,Path.Join(destination, unitPath.Split('/').Last()), overwrite: true);
 031    }
 32
 33    public void UninstallSystemdMountUnit(string unitName)
 034    {
 035        var unitPath = Path.Join("/", "usr", "lib", "systemd", "system", unitName);
 36
 037        if (File.Exists(unitPath)) File.Delete(unitPath);
 038    }
 39
 40    public void InstallSystemdPathUnit(string snapName)
 041    {
 042        var destination = Path.Join("/", "usr", "lib", "systemd", "system");
 043        var unitsLocation = Path.Join("/", "snap", "dotnet", "current", "Scripts");
 044        var unitFilesInLocation = Directory.GetFiles(unitsLocation, "{SNAP}*");
 045        foreach (var unitFile in unitFilesInLocation)
 046        {
 047            var originFilePath = unitFile.Replace("{SNAP}", snapName);
 048            var fileContent = File.ReadAllText(unitFile).Replace("{SNAP}", snapName);
 049            File.WriteAllText(Path.Join(destination, originFilePath.Split('/').Last()), fileContent, Encoding.UTF8);
 050        }
 051    }
 52
 53    public void UninstallSystemdPathUnit(string snapName)
 054    {
 055        var destination = Path.Join("/", "usr", "lib", "systemd", "system");
 056        var unitsLocation = Path.Join("/", "snap", "dotnet", "current", "Scripts");
 057        var unitFilesInLocation = Directory.GetFiles(unitsLocation, "{SNAP}*");
 058        foreach (var unitFile in unitFilesInLocation)
 059        {
 060            var originFilePath = unitFile.Replace("{SNAP}", snapName);
 061            File.Delete(Path.Join(destination, originFilePath.Split('/').Last()));
 062        }
 063    }
 64
 65    /// <summary>
 66    /// The linkage file is a flag that marks that a .NET content snap is present in a system
 67    /// and the .NET installer tool is tracking its updates for eventual .mount path updates
 68    /// on content snap refreshes. Check each .NET content snap's refresh hook for the code that
 69    /// checks for the present of the <c>$SNAP_COMMON/dotnet-installer</c> file.
 70    /// </summary>
 71    /// <param name="contentSnapName">The name of the .NET content snap.</param>
 72    /// <returns></returns>
 73    public Task PlaceLinkageFile(string contentSnapName)
 074    {
 075        return File.WriteAllTextAsync(
 076            Path.Join("/", "var", "snap", contentSnapName, "common", "dotnet-installer"),
 077            "installer linkage ok\n",
 078            Encoding.UTF8);
 079    }
 80
 81    public Task PlaceUnitsFile(string snapConfigDirLocation, string contentSnapName, string units)
 082    {
 083        var mountsFileName = $"{contentSnapName}.mounts";
 084        return File.WriteAllTextAsync(
 085            Path.Join(snapConfigDirLocation, mountsFileName),
 086            contents: units,
 087            Encoding.UTF8);
 088    }
 89
 90    public Task<string[]> ReadUnitsFile(string snapConfigDirLocation, string contentSnapName)
 091    {
 092        var mountsFileName = $"{contentSnapName}.mounts";
 093        return File.ReadAllLinesAsync(Path.Join(snapConfigDirLocation, mountsFileName));
 094    }
 95
 96    public void DeleteUnitsFile(string snapConfigDirLocation, string contentSnapName)
 097    {
 098        var mountsFileName = $"{contentSnapName}.mounts";
 099        File.Delete(Path.Join(snapConfigDirLocation, mountsFileName));
 0100    }
 101
 102    /// <summary>
 103    /// Reads a .version file and returns the .NET version in it.
 104    /// </summary>
 105    /// <param name="dotNetRoot">The root of the .NET directory hive.</param>
 106    /// <param name="componentPath">The relative path to the .NET shared component,
 107    /// e.g. <c>shared/Microsoft.NETCore.App</c>, <c>shared/Microsoft.AspNetCore.App</c> or <c>sdk</c>.</param>
 108    /// <param name="majorVersion">The .NET major version of the component being analyzed.</param>
 109    /// <returns>The .NET version in the .version file.</returns>
 110    public DotnetVersion ReadDotVersionFile(string dotNetRoot, string componentPath, int majorVersion)
 0111    {
 0112        var location = Path.Join(dotNetRoot, componentPath);
 0113        foreach (var directory in Directory.EnumerateDirectories(location))
 0114        {
 0115            if (directory.Split(Path.DirectorySeparatorChar).Last().StartsWith(majorVersion.ToString()))
 0116            {
 0117                location = Path.Join(directory, ".version");
 0118                break;
 119            }
 0120        }
 121
 122        // Search files matching the pattern
 0123        if (File.Exists(location))
 0124        {
 0125            var lines = File.ReadAllLines(location);
 126            // Ensure there are enough lines to read the version string
 0127            if (lines.Length > 1)
 0128            {
 0129                return DotnetVersion.Parse(lines[1]);
 130            }
 0131        }
 132
 0133        throw new FileNotFoundException($".version file not found at {location}");
 0134    }
 135
 136    /// <summary>
 137    /// Iterates recursively through all the directories within <c>root</c> and deletes any empty directories found.
 138    /// <c>root</c> will NOT be deleted even if it ends up being an empty directory itself.
 139    /// </summary>
 140    /// <param name="root">A path to the top-level directory.</param>
 141    /// <exception cref="DirectoryNotFoundException">When <c>root</c> does not exist.</exception>
 142    public void RemoveEmptyDirectories(string root)
 0143    {
 0144        var dir = new DirectoryInfo(root);
 145
 0146        if (!dir.Exists)
 0147        {
 0148            throw new DirectoryNotFoundException(
 0149                $"The directory does not exist ({root})."
 0150            );
 151        }
 152
 0153        foreach (var directory in dir.GetDirectories())
 0154        {
 0155            RemoveEmptyDirectories(directory.FullName);
 156
 0157            if (IsDirectoryEmpty(directory.FullName))
 0158            {
 0159                directory.Delete();
 0160            }
 0161        }
 0162    }
 163
 164    private static bool IsDirectoryEmpty(string path)
 0165    {
 0166        return Directory.GetFiles(path).Length == 0 && Directory.GetDirectories(path).Length == 0;
 0167    }
 168}