< 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: 92
Coverable lines: 92
Total lines: 146
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 20
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
DeleteFile(...)100%210%
DownloadFile()0%2040%
FileExists(...)100%210%
ExtractDeb()100%210%
GetFileHash()100%210%
MoveDirectory(...)0%7280%
OpenRead(...)100%210%
ReadAllLines(...)100%210%
RemoveEmptyDirectories(...)0%4260%
IsDirectoryEmpty(...)0%620%
SavePackageContentToFile()100%210%

File(s)

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

#LineLine coverage
 1using System.Security.Cryptography;
 2using CliWrap;
 3using Dotnet.Installer.Core.Exceptions;
 4using Dotnet.Installer.Core.Services.Contracts;
 5
 6namespace Dotnet.Installer.Core.Services.Implementations;
 7
 8public class FileService : IFileService
 9{
 10    public void DeleteFile(string path)
 011    {
 012        File.Delete(path);
 013    }
 14
 15    public async Task<string> DownloadFile(Uri url, string destinationDirectory)
 016    {
 017        using var client = new HttpClient();
 018        await using var remoteFileStream = await client.GetStreamAsync(url);
 19
 020        var fileName = Path.Combine(destinationDirectory, url.Segments.Last());
 21
 22        try
 023        {
 024            if (File.Exists(fileName)) File.Delete(fileName);
 025            await using var writerStream = File.OpenWrite(fileName);
 026            await remoteFileStream.CopyToAsync(writerStream);
 027        }
 028        catch (UnauthorizedAccessException)
 029        {
 030            throw new NeedsSudoException(fileName);
 31        }
 32
 033        return fileName;
 034    }
 35
 36    public bool FileExists(string path)
 037    {
 038        return File.Exists(path);
 039    }
 40
 41    public async Task ExtractDeb(string debPath, string destinationDirectory, string snapConfigurationDirectory)
 042    {
 043        var scratchDirectory = Path.Combine(destinationDirectory, "scratch");
 44
 045        await Cli.Wrap("dpkg")
 046            .WithArguments([ "--extract", debPath, scratchDirectory ])
 047            .WithWorkingDirectory(destinationDirectory)
 048            .ExecuteAsync();
 49
 050        var files = MoveDirectory($"{scratchDirectory}/usr/lib/dotnet", destinationDirectory);
 51
 052        var packageName = Path.GetFileNameWithoutExtension(debPath);
 053        await SavePackageContentToFile(files, snapConfigurationDirectory, packageName);
 54
 055        Directory.Delete(scratchDirectory, recursive: true);
 056    }
 57
 58    public async Task<string> GetFileHash(string filePath)
 059    {
 060        await using var readerStream = File.OpenRead(filePath);
 061        var result = await SHA256.HashDataAsync(readerStream);
 062        return Convert.ToHexString(result).ToLower();
 063    }
 64
 65    public IEnumerable<string> MoveDirectory(string sourceDirectory, string destinationDirectory)
 066    {
 067        var result = new List<string>();
 068        var dir = new DirectoryInfo(sourceDirectory);
 69
 070        if (!dir.Exists)
 071        {
 072            throw new DirectoryNotFoundException(
 073                $"The source directory does not exist ({sourceDirectory})."
 074            );
 75        }
 76
 77        // If the destination directory does not exist, create it.
 078        if (!Directory.Exists(destinationDirectory))
 079        {
 080            Directory.CreateDirectory(destinationDirectory);
 081        }
 82
 83        // Get the files in the directory and copy them to the new location.
 084        var files = dir.GetFiles();
 085        foreach (var file in files)
 086        {
 087            var path = Path.Combine(destinationDirectory, file.Name);
 088            result.Add(path);
 089            file.MoveTo(path, overwrite: true);
 090        }
 91
 92        // Copy subdirectories and their contents to the new location.
 093        var subDirs = dir.GetDirectories();
 094        foreach (var subDir in subDirs)
 095        {
 096            var path = Path.Combine(destinationDirectory, subDir.Name);
 097            result.AddRange(MoveDirectory(subDir.FullName, path));
 098        }
 99
 0100        return result;
 0101    }
 102
 103    public Stream OpenRead(string path)
 0104    {
 0105        return File.OpenRead(path);
 0106    }
 107
 108    public Task<string[]> ReadAllLines(string fileName)
 0109    {
 0110        return File.ReadAllLinesAsync(fileName);
 0111    }
 112
 113    public void RemoveEmptyDirectories(string root)
 0114    {
 0115        var dir = new DirectoryInfo(root);
 116
 0117        if (!dir.Exists)
 0118        {
 0119            throw new DirectoryNotFoundException(
 0120                $"The directory does not exist ({root})."
 0121            );
 122        }
 123
 124        // Recursively search for empty directories and remove them
 0125        foreach (var directory in dir.GetDirectories())
 0126        {
 0127            RemoveEmptyDirectories(directory.FullName);
 128
 0129            if (IsDirectoryEmpty(directory.FullName))
 0130            {
 0131                directory.Delete();
 0132            }
 0133        }
 0134    }
 135
 136    private static bool IsDirectoryEmpty(string path)
 0137    {
 0138        return Directory.GetFiles(path).Length == 0 && Directory.GetDirectories(path).Length == 0;
 0139    }
 140
 141    private static async Task SavePackageContentToFile(IEnumerable<string> files, string snapConfigurationDirectory, str
 0142    {
 0143        var registrationFile = Path.Combine(snapConfigurationDirectory, $"{packageName}.files");
 0144        await File.WriteAllLinesAsync(registrationFile, files);
 0145    }
 146}