Esempio n. 1
0
        static async Task Main(string[] args)
        {
            var host = HostUtilities.BuildAndRunHost(args, x => x.AddSingleton <IProcessUtility, ProcessUtility>().AddSingleton <IComparer <string>, WinStringComparer>());

            var logger     = host.Services.GetService <ILogger <Program> >();
            var sourcePath = args?.Length == 1 ? Path.GetFullPath(args[0]) : AppDomain.CurrentDomain.BaseDirectory;

            _ = sourcePath ?? throw new InvalidOperationException("sourcePath is null");
            if (!Directory.Exists(sourcePath))
            {
                throw new InvalidOperationException($"Directory does not exist: {sourcePath}");
            }

            var destinationPath = Path.Combine(sourcePath, ProjectBuiltinNugetDirectoryName);

            if (!Directory.Exists(destinationPath))
            {
                Directory.CreateDirectory(destinationPath);
            }

            var csprojFiles        = Directory.EnumerateFiles(sourcePath, "*.csproj", SearchOption.AllDirectories);
            var packages           = new HashSet <string>(StringComparer.OrdinalIgnoreCase);
            var nugetCacheRootPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".nuget", "packages");
            var processUtility     = host.Services.GetService <IProcessUtility>();
            var tempPath           = PathExtensions.CreateTempDirectory();

            logger.LogTrace("Using temp path {TempPath}...", tempPath);

            async Task CopyAllPackageDependenciesAsync(string packageFilePath)
            {
                await NugetUtilities.ExtractPackageAndApplyActionAsync(
                    packageFilePath,
                    processUtility ?? throw new InvalidOperationException("processUtility is null"),
                    tempPath ?? throw new InvalidOperationException("tempPath is null"),
                    async (dllFilePath, nuspecFilePath) =>
                {
                    var dependencies = await GetScarPackageReferencesFromNuspecFileAsync(nuspecFilePath).ConfigureAwait(false);
                    foreach (var nugetPackageInfo in dependencies)
                    {
                        logger.LogTrace("Trying to clone {PackageName} which is a dependency of {DependentPackageName}...", nugetPackageInfo.ToString(), NugetUtilities.ParseNugetPackageInfoForPath(packageFilePath)?.ToString());
                        await ClonePackageIfExistsInCacheAsync(
                            logger ?? throw new InvalidOperationException("logger is null"),
                            packages ?? throw new InvalidOperationException("packages is null"),
                            nugetPackageInfo,
                            nugetCacheRootPath ?? throw new InvalidOperationException("nugetCacheRootPath is null"),
                            destinationPath ?? throw new InvalidOperationException("destinationPath is null"),
                            CopyAllPackageDependenciesAsync)
                        .ConfigureAwait(false);
                    }
                })
                .ConfigureAwait(false);
            }

            var tasks = csprojFiles.Select(
                async csprojFilePath =>
            {
                var scarPackageReferences = await GetScarPackageReferencesFromProjectFileAsync(csprojFilePath).ConfigureAwait(false);
                foreach (var nugetPackageInfo in scarPackageReferences)
                {
                    logger.LogTrace("Trying to clone {PackageName}...", nugetPackageInfo.ToString());
                    await ClonePackageIfExistsInCacheAsync(logger, packages, nugetPackageInfo, nugetCacheRootPath, destinationPath, CopyAllPackageDependenciesAsync).ConfigureAwait(false);
                }
            });

            await Task.WhenAll(tasks).ConfigureAwait(false);

            DeleteNonExistingPackages(logger, packages, destinationPath);

            var fileNameComparer = host.Services.GetService <IComparer <string> >();

            DeleteOutdatedPackagesFromCache(logger, nugetCacheRootPath, fileNameComparer);
            DeleteOutdatedPackagesFromCache(logger, ScarLocalNugetPath, fileNameComparer);
            Directory.Delete(tempPath, true);
            logger.LogInformation("Deleted {TempPath}", tempPath);
        }
Esempio n. 2
0
        static async Task Main(string[] args)
        {
            var host = HostUtilities.BuildAndRunHost(
                args,
                x => x.AddSingleton <IProcessUtility, ProcessUtility>().AddSingleton <IFileHasher, FileHasher>().AddSingleton <IComparer <string>, WinStringComparer>());

            var sourceDirectoryPath = args?.Length == 1 ? args[0] : AppDomain.CurrentDomain.BaseDirectory;
            var logger = host.Services.GetService <ILogger <Program> >();

            logger.LogTrace("Processing packages in {SourceDirectoryPath}...", sourceDirectoryPath);
            _ = sourceDirectoryPath ?? throw new InvalidOperationException("sourcePath is null");
            if (!Directory.Exists(sourceDirectoryPath))
            {
                throw new InvalidOperationException($"Directory {sourceDirectoryPath} does not exist");
            }

            var orderedNupkgFiles = Directory.GetFiles(sourceDirectoryPath, "*.nupkg", SearchOption.AllDirectories).OrderByDescending(x => x, host.Services.GetService <IComparer <string> >()).ToArray();

            if (orderedNupkgFiles.Length >= 2)
            {
                var    lastTwoPackages = orderedNupkgFiles.Take(2).ToArray();
                var    lastPackagePath = lastTwoPackages[0];
                var    previousPackagePath = lastTwoPackages[1];
                var    processUtility = host.Services.GetService <IProcessUtility>();
                var    fileHasher = host.Services.GetService <IFileHasher>();
                string?previousPackageNuspecText = null, lastPackageNuspecText = null;
                byte[]? lastPackageDllHash = null, previousPackageDllHash = null;

                async Task ExtractLastPackageDetails(string dllFilePath, string nuspecFilePath)
                {
                    var(dllHash, nuspecText) = await ExtractPackageHashAndNuspecTextWithoutVersionAsync(
                        fileHasher ?? throw new InvalidOperationException(nameof(fileHasher)),
                        dllFilePath,
                        nuspecFilePath)
                                               .ConfigureAwait(false);

                    lastPackageDllHash    = dllHash;
                    lastPackageNuspecText = nuspecText;
                }

                async Task ExtractPreviousPackageDetails(string dllFilePath, string nuspecFilePath)
                {
                    var(dllHash, nuspecText) = await ExtractPackageHashAndNuspecTextWithoutVersionAsync(
                        fileHasher ?? throw new InvalidOperationException(nameof(fileHasher)),
                        dllFilePath,
                        nuspecFilePath)
                                               .ConfigureAwait(false);

                    previousPackageDllHash    = dllHash;
                    previousPackageNuspecText = nuspecText;
                }

                await Task.WhenAll(
                    NugetUtilities.ExtractPackageAndApplyActionAsync(lastPackagePath, processUtility, sourceDirectoryPath, ExtractLastPackageDetails),
                    NugetUtilities.ExtractPackageAndApplyActionAsync(previousPackagePath, processUtility, sourceDirectoryPath, ExtractPreviousPackageDetails))
                .ConfigureAwait(false);

                var lastPackageName     = NugetUtilities.ParseNugetPackageInfoForPath(lastPackagePath)?.ToString();
                var previousPackageName = NugetUtilities.ParseNugetPackageInfoForPath(previousPackagePath)?.ToString();

                var dllHashesAreEqual = lastPackageDllHash.SequenceEqual(previousPackageDllHash);
                var nuspecDifference  = CompareStrings(lastPackageNuspecText, previousPackageNuspecText);

                var packagesAreEqual = dllHashesAreEqual && nuspecDifference == 0;
                if (!packagesAreEqual)
                {
                    logger.LogInformation(
                        @"Nuget packages {LastPackageName} is different from previous {PreviousPackageName} Nuspec: {NuspecDifference}, Dll: {DllsAreEqual}
Current dll hash: {CurrentDllHash}
Previous dll hash: {PreviousDllHash}
Current nuspec: {CurrentNuspec}
Previous nuspec: {PreviousNuspec}",
                        lastPackageName,
                        previousPackageName,
                        nuspecDifference,
                        !dllHashesAreEqual,
                        lastPackageDllHash?.GetHashString(),
                        previousPackageDllHash?.GetHashString(),
                        lastPackageNuspecText,
                        previousPackageNuspecText);
                    await PushNugetAsync(logger, processUtility, lastPackagePath).ConfigureAwait(false);
                }
                else
                {
                    logger.LogInformation("Nuget package {LastPackageName} is identical to previous {PreviousPackageName}. Push is skipped", lastPackageName, previousPackageName);
                }

                // Leave 2 last files
                DeleteFiles(orderedNupkgFiles.Skip(2), logger);
            }
            else if (orderedNupkgFiles.Length == 1)
            {
                var lastPackagePath = orderedNupkgFiles.Single();
                logger.LogInformation("There is only one nuget package {LastPackageName}", NugetUtilities.ParseNugetPackageInfoForPath(lastPackagePath)?.ToString());
                var processUtility = host.Services.GetService <IProcessUtility>();
                await PushNugetAsync(logger, processUtility, lastPackagePath).ConfigureAwait(false);
            }
            else
            {
                logger.LogInformation("Nothing to compare");
            }
        }