예제 #1
0
        private IEnumerable <CsprojInfo> EnumerateDebugifiableProjects(DebugCommand cmd)
        {
            var path         = cmd.Path;
            var isCsprojFile = File.Exists(path) && string.Equals(Path.GetExtension(path), ".csproj", StringComparison.InvariantCultureIgnoreCase);

            if (isCsprojFile)
            {
                var csproj = path;
                if (TryGetVersion(csproj, out string version) || !string.IsNullOrWhiteSpace(cmd.Version))
                {
                    // to be sure that the csproj is nuget-compatible, ensure it is the new csproj format
                    if (!File.ReadLines(csproj).First().Trim().StartsWith("<Project Sdk="))
                    {
                        _logger.Warning($"Project file {Path.GetFileName(csproj)} is not supported: Only latest csproj format is supported");
                    }
                    else
                    {
                        var packageId = GetPackageId(csproj);

                        yield return(new CsprojInfo(packageId, version ?? cmd.Version, csproj));
                    }
                }
                else
                {
                    _logger.Warning($"Project file  {Path.GetFileName(csproj)} does not contain a <Version> element. Please specify a version using the -v commandline argument.");
                }
            }
            else
            {
                // ensure path is a directory
                path = Directory.Exists(path) ? path : Path.GetDirectoryName(path);
                foreach (var csproj in Directory.EnumerateFiles(path, "*.csproj", SearchOption.AllDirectories))
                {
                    if (TryGetVersion(csproj, out string version) || !string.IsNullOrWhiteSpace(cmd.Version))
                    {
                        // to be sure that the csproj is nuget-compatible, ensure it is the new csproj format
                        if (!File.ReadLines(csproj).First().Trim().StartsWith("<Project Sdk="))
                        {
                            _logger.Warning($"Project file {Path.GetFileName(csproj)} is not supported: Only latest csproj format is supported");
                        }
                        else
                        {
                            var packageId = GetPackageId(csproj);

                            yield return(new CsprojInfo(packageId, version ?? cmd.Version, csproj));
                        }
                    }
                    else
                    {
                        _logger.Warning($"Project file  {Path.GetFileName(csproj)} does not contain a <Version> element. Please specify a version using the -v commandline argument.");
                    }
                }
            }
        }
예제 #2
0
        private bool DotnetPack(CsprojInfo projectFile, DebugCommand cmd)
        {
            bool verbose    = cmd.Verbose;
            var  csprojPath = projectFile.Path;

            if (!Path.IsPathRooted(csprojPath))
            {
                throw new ArgumentException($"{nameof(csprojPath)} must be rooted");
            }

            // dotnet pack --include-symbols --include-source -c Debug
            // see: https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-pack
            var name = "dotnet";
            //var args = $"pack '{csprojPath}' --include-symbols --include-source -c Debug";
            var args = $"pack --include-symbols --include-source -c Debug {cmd.PackArguments}";

            _logger.Info($"creating {projectFile.NugetPackageName}");

            var output = ExecuteProcess(name, args, csprojPath, verbose);


            const string fallbackTraceMessage =
                "error : If you are building projects that require targets from full MSBuild or MSBuildFrameworkToolsPath, you need to use desktop msbuild ('msbuild.exe') instead of 'dotnet build' or 'dotnet msbuild'";
            var fallbackToMsBuildRequired = output.Output.Any(l => l.Contains(fallbackTraceMessage));

            if (verbose)
            {
                foreach (var line in output.Output)
                {
                    _logger.Debug(line);
                }
                _logger.Debug($"dotnet pack returned {output.ExitCode}");
            }

            if (fallbackToMsBuildRequired)
            {
                if (verbose)
                {
                    _logger.Debug("falling back to full MSBuild as advanced targets are required...");
                }

                return(MsBuildPack(projectFile, verbose));
            }

            // only iif dotnet pack returns 0, everything is fine
            return(output.ExitCode == 0);
        }
예제 #3
0
        private void ExtractNupkg(DebugCommand cmd, string extractPath, string packagePath)
        {
            // add pseudo file to know when do delete such a folder
            if (cmd.Verbose)
            {
                _logger.Debug($"Writing .debugified.txt to {extractPath}");
            }
            File.WriteAllText(Path.Combine(extractPath, ".debugified.txt"), "this package was debugified");

            using var archive = new ZipArchive(File.OpenRead(packagePath));
            foreach (var entry in archive.Entries)
            {
                if (entry.FullName.StartsWith("lib") || entry.FullName.StartsWith("src"))
                {
                    if (cmd.Verbose)
                    {
                        _logger.Debug($"Extracting {entry.FullName}");
                    }

                    // Gets the full path to ensure that relative segments are removed.
                    string destinationPath = Path.GetFullPath(Path.Combine(extractPath, entry.FullName));

                    // Ordinal match is safest, case-sensitive volumes can be mounted within volumes that
                    // are case-insensitive.
                    if (destinationPath.StartsWith(extractPath, StringComparison.Ordinal))
                    {
                        // ensure the subdirectories exist
                        Directory.CreateDirectory(Path.GetDirectoryName(destinationPath));
                        entry.ExtractToFile(destinationPath, true);
                    }
                }
                else
                {
                    if (cmd.Verbose)
                    {
                        _logger.Debug($"Skipping {entry.FullName} as it does not start with 'src' or 'lib'");
                    }
                }
            }
        }
예제 #4
0
        public void Debugify(DebugCommand cmd)
        {
            if (!string.IsNullOrWhiteSpace(cmd.Version))
            {
                var versionValidator = new Regex(@"\d+\.\d+\.\d+(\.\d+)?[\d\w_-]*?");
                if (!versionValidator.IsMatch(cmd.Version))
                {
                    _logger.Error($"Error: '{cmd.Version}' is not a valid nuget package version");
                    return;
                }
            }

            if (string.IsNullOrEmpty(cmd.Path))
            {
                if (cmd.Verbose)
                {
                    _logger.Debug($"No path provided. Will run in current directory: {Environment.CurrentDirectory}");
                }
                cmd.Path = Environment.CurrentDirectory;
            }
            else
            {
                if (!Path.IsPathRooted(cmd.Path))
                {
                    cmd.Path = Path.GetFullPath(cmd.Path);
                }

                if (cmd.Verbose)
                {
                    _logger.Debug($"Path: {cmd.Path}");
                }
            }

            // find it within the current solution
            var solutionDir = File.Exists(cmd.Path) && string.Equals(Path.GetExtension(cmd.Path), ".sln",
                                                                     StringComparison.InvariantCultureIgnoreCase)
                ? Path.GetDirectoryName(cmd.Path)
                : RecursivelyFindSolutionDir(cmd.Path, cmd.Verbose);

            if (solutionDir is null)
            {
                _logger.Warning($"Could not find any solution in '{(File.Exists(cmd.Path) ? Path.GetDirectoryName(cmd.Path) : cmd.Path)}'");
                return;
            }
            if (cmd.Verbose)
            {
                _logger.Debug($"Found sln directory: {solutionDir}");
            }

            // find all compatible project files
            var projectFiles = EnumerateDebugifiableProjects(cmd).ToList();

            if (!projectFiles.Any())
            {
                _logger.Warning($"Could not find any debugifiable *.csproj files in '{(File.Exists(cmd.Path) ? Path.GetDirectoryName(cmd.Path) : cmd.Path)}'");
                return;
            }

            // make sur the version files are restored afterwards
            using (var cd = new CompositeDisposable(_logger))
            {
                // pack the thing up
                var packFailedCount    = 0;
                var erroredCsprojInfos = new List <CsprojInfo>();
                // replace version in csproj files
                if (!string.IsNullOrWhiteSpace(cmd.Version))
                {
                    foreach (var projectFile in projectFiles)
                    {
                        try
                        {
                            if (cmd.Verbose)
                            {
                                _logger.Debug($"changing package version of {Path.GetFileName(projectFile.Path)}");
                            }

                            cd.Add(projectFile.ReplaceVersion(cmd.Version));
                        }
                        catch (Exception x)
                        {
                            erroredCsprojInfos.Add(projectFile);
                            packFailedCount++;

                            _logger.Error(x.Message);
                        }
                    }
                }

                foreach (var projectFile in projectFiles.Except(erroredCsprojInfos))
                {
                    if (!DotnetPack(projectFile, cmd))
                    {
                        _logger.Error($"dotnet pack failed for {Path.GetFileName(projectFile.Path)}");
                        packFailedCount++;
                    }
                }

                if (packFailedCount != 0)
                {
                    _logger.Warning(
                        $"WARNING: Failed to create {packFailedCount} of {projectFiles.Count} *.nupkg files");
                }
            }

            // resolve nuget package cache
            var pathWithEnv      = $@"%USERPROFILE%\.nuget\packages\";
            var packageCachePath = Environment.ExpandEnvironmentVariables(pathWithEnv);

            if (cmd.Verbose)
            {
                _logger.Info($"nuget package cache fount at '{packageCachePath}'");
            }

            // find each nupkg and extract it to cache
            foreach (var projectFile in projectFiles)
            {
                var packageName = projectFile.NugetPackageName;
                var packagePath = Directory.EnumerateFiles(solutionDir, "*.nupkg", SearchOption.AllDirectories)
                                  .FirstOrDefault(p => string.Equals(packageName, Path.GetFileName(p), StringComparison.InvariantCultureIgnoreCase));
                if (packagePath is null)
                {
                    _logger.Error($"Could not find package {packageName}");
                    continue;
                }

                // verify, that there is a nuget package with the same id and version in the cache
                var extractPath = Path.Combine(packageCachePath, projectFile.PackageId, projectFile.ActualVersion);
                if (!Directory.Exists(extractPath))
                {
                    _logger.Warning($"Cannot debugify {packageName} as the package cannot be found in the cache: {extractPath}");
                    continue;
                }

                // extract nupkg contents into package cache
                ExtractNupkg(cmd, extractPath, packagePath);

                _logger.Success($"Successfully debugified {projectFile.PackageId} version {projectFile.ActualVersion}");
            }
        }