示例#1
0
        private bool TryGetPackagedShim(
            IReadOnlyList <FilePath> packagedShims,
            ToolCommandName commandName,
            out FilePath?packagedShim)
        {
            packagedShim = null;

            if (packagedShims != null && packagedShims.Count > 0)
            {
                FilePath[] candidatepackagedShim =
                    packagedShims
                    .Where(s => string.Equals(
                               Path.GetFileName(s.Value),
                               Path.GetFileName(GetShimPath(commandName).Value))).ToArray();

                if (candidatepackagedShim.Length > 1)
                {
                    throw new ShellShimException(
                              string.Format(
                                  CommonLocalizableStrings.MoreThanOnePackagedShimAvailable,
                                  string.Join(';', candidatepackagedShim)));
                }

                if (candidatepackagedShim.Length == 1)
                {
                    packagedShim = candidatepackagedShim.Single();
                    return(true);
                }
            }

            return(false);
        }
示例#2
0
        private (FilePath, LocalToolsCommandResolver) DefaultSetup(string toolCommand)
        {
            NuGetVersion packageVersionA = NuGetVersion.Parse("1.0.4");

            _fileSystem.File.WriteAllText(Path.Combine(_testDirectoryRoot, ManifestFilename),
                                          _jsonContent.Replace("$TOOLCOMMAND$", toolCommand));
            ToolManifestFinder toolManifest =
                new ToolManifestFinder(new DirectoryPath(_testDirectoryRoot), _fileSystem, new FakeDangerousFileDetector());
            ToolCommandName toolCommandNameA = new ToolCommandName(toolCommand);
            FilePath        fakeExecutable   = _nugetGlobalPackagesFolder.WithFile("fakeExecutable.dll");

            _fileSystem.Directory.CreateDirectory(_nugetGlobalPackagesFolder.Value);
            _fileSystem.File.CreateEmptyFile(fakeExecutable.Value);
            _localToolsResolverCache.Save(
                new Dictionary <RestoredCommandIdentifier, RestoredCommand>
            {
                [new RestoredCommandIdentifier(
                     new PackageId("local.tool.console.a"),
                     packageVersionA,
                     NuGetFramework.Parse(BundledTargetFramework.GetTargetFrameworkMoniker()),
                     Constants.AnyRid,
                     toolCommandNameA)]
                    = new RestoredCommand(toolCommandNameA, "dotnet", fakeExecutable)
            });

            var localToolsCommandResolver = new LocalToolsCommandResolver(
                toolManifest,
                _localToolsResolverCache,
                _fileSystem);

            return(fakeExecutable, localToolsCommandResolver);
        }
示例#3
0
        public void CreateShim(FilePath targetExecutablePath, ToolCommandName commandName, IReadOnlyList <FilePath> packagedShims = null)
        {
            if (string.IsNullOrEmpty(targetExecutablePath.Value))
            {
                throw new ShellShimException(CommonLocalizableStrings.CannotCreateShimForEmptyExecutablePath);
            }

            if (ShimExists(commandName))
            {
                throw new ShellShimException(
                          string.Format(
                              CommonLocalizableStrings.ShellShimConflict,
                              commandName));
            }

            TransactionalAction.Run(
                action: () =>
            {
                try
                {
                    if (!_fileSystem.Directory.Exists(_shimsDirectory.Value))
                    {
                        _fileSystem.Directory.CreateDirectory(_shimsDirectory.Value);
                    }

                    if (TryGetPackagedShim(packagedShims, commandName, out FilePath? packagedShim))
                    {
                        _fileSystem.File.Copy(packagedShim.Value.Value, GetShimPath(commandName).Value);
                        _filePermissionSetter.SetUserExecutionPermission(GetShimPath(commandName).Value);
                    }
                    else
                    {
                        _appHostShellShimMaker.CreateApphostShellShim(
                            targetExecutablePath,
                            GetShimPath(commandName));
                    }
                }
                catch (FilePermissionSettingException ex)
                {
                    throw new ShellShimException(
                        string.Format(CommonLocalizableStrings.FailedSettingShimPermissions, ex.Message));
                }
                catch (Exception ex) when(ex is UnauthorizedAccessException || ex is IOException)
                {
                    throw new ShellShimException(
                        string.Format(
                            CommonLocalizableStrings.FailedToCreateShellShim,
                            commandName,
                            ex.Message
                            ),
                        ex);
                }
            },
                rollback: () => {
                foreach (var file in GetShimFiles(commandName).Where(f => _fileSystem.File.Exists(f.Value)))
                {
                    File.Delete(file.Value);
                }
            });
        }
示例#4
0
        private CommandSpec GetPackageCommandSpecUsingMuxer(CommandResolverArguments arguments,
                                                            ToolCommandName toolCommandName)
        {
            if (!_toolManifest.TryFind(toolCommandName, out var toolManifestPackage))
            {
                return(null);
            }

            if (_localToolsResolverCache.TryLoad(
                    new RestoredCommandIdentifier(
                        toolManifestPackage.PackageId,
                        toolManifestPackage.Version,
                        NuGetFramework.Parse(BundledTargetFramework.GetTargetFrameworkMoniker()),
                        Constants.AnyRid,
                        toolCommandName),
                    _nugetGlobalPackagesFolder,
                    out var restoredCommand))
            {
                if (!_fileSystem.File.Exists(restoredCommand.Executable.Value))
                {
                    throw new GracefulException(string.Format(LocalizableStrings.NeedRunToolRestore,
                                                              toolCommandName.ToString()));
                }

                return(MuxerCommandSpecMaker.CreatePackageCommandSpecUsingMuxer(
                           restoredCommand.Executable.Value,
                           arguments.CommandArguments));
            }

            return(null);
        }
示例#5
0
        public bool TryFind(ToolCommandName toolCommandName, out ToolManifestPackage toolManifestPackage)
        {
            toolManifestPackage = default(ToolManifestPackage);
            foreach (FilePath possibleManifest in EnumerateDefaultAllPossibleManifests())
            {
                if (!_fileSystem.File.Exists(possibleManifest.Value))
                {
                    continue;
                }

                SerializableLocalToolsManifest deserializedManifest =
                    DeserializeLocalToolsManifest(possibleManifest);

                List <ToolManifestPackage> toolManifestPackages =
                    GetToolManifestPackageFromOneManifestFile(deserializedManifest, possibleManifest);

                foreach (var package in toolManifestPackages)
                {
                    if (package.CommandNames.Contains(toolCommandName))
                    {
                        toolManifestPackage = package;
                        return(true);
                    }
                }

                if (deserializedManifest.isRoot.Value)
                {
                    return(false);
                }
            }

            return(false);
        }
示例#6
0
        public void ItShouldFailWhenPackageCommandNameDoesNotMatchManifestCommands()
        {
            ToolCommandName     differentCommandNameA = new ToolCommandName("different-command-nameA");
            ToolCommandName     differentCommandNameB = new ToolCommandName("different-command-nameB");
            IToolManifestFinder manifestFinder        =
                new MockManifestFinder(new[]
            {
                new ToolManifestPackage(_packageIdA, _packageVersionA,
                                        new[] { differentCommandNameA, differentCommandNameB },
                                        new DirectoryPath(_temporaryDirectory)),
            });

            ToolRestoreCommand toolRestoreCommand = new ToolRestoreCommand(_appliedCommand,
                                                                           _parseResult,
                                                                           _toolPackageInstallerMock,
                                                                           manifestFinder,
                                                                           _localToolsResolverCache,
                                                                           _fileSystem,
                                                                           _nugetGlobalPackagesFolder,
                                                                           _reporter
                                                                           );

            toolRestoreCommand.Execute().Should().Be(1);
            _reporter.Lines.Should()
            .Contain(l =>
                     l.Contains(
                         string.Format(LocalizableStrings.CommandsMismatch,
                                       "\"different-command-nameA\" \"different-command-nameB\"", _packageIdA, "\"a\"")));
        }
示例#7
0
 public RestoredCommand(
     ToolCommandName name,
     string runner,
     FilePath executable)
 {
     Name       = name;
     Runner     = runner ?? throw new ArgumentNullException(nameof(runner));
     Executable = executable;
 }
示例#8
0
 private FilePath GetShimPath(ToolCommandName commandName)
 {
     if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
     {
         return(_shimsDirectory.WithFile(commandName.Value + ".exe"));
     }
     else
     {
         return(_shimsDirectory.WithFile(commandName.Value));
     }
 }
示例#9
0
 private FilePath GetShimPath(ToolCommandName commandName)
 {
     if (OperatingSystem.IsWindows())
     {
         return(_shimsDirectory.WithFile(commandName.Value + ".exe"));
     }
     else
     {
         return(_shimsDirectory.WithFile(commandName.Value));
     }
 }
 public RestoredCommandIdentifierVersionRange(
     PackageId packageId,
     VersionRange versionRange,
     NuGetFramework targetFramework,
     string runtimeIdentifier,
     ToolCommandName commandName)
 {
     PackageId         = packageId;
     VersionRange      = versionRange ?? throw new ArgumentException(nameof(versionRange));
     TargetFramework   = targetFramework ?? throw new ArgumentException(nameof(targetFramework));
     RuntimeIdentifier = runtimeIdentifier ?? throw new ArgumentException(nameof(runtimeIdentifier));
     CommandName       = commandName;
 }
示例#11
0
        public void ItCanFindToolExecutable()
        {
            var          toolCommand     = "a";
            NuGetVersion packageVersionA = NuGetVersion.Parse("1.0.4");

            _fileSystem.File.WriteAllText(Path.Combine(_testDirectoryRoot, ManifestFilename),
                                          _jsonContent.Replace("$TOOLCOMMAND$", toolCommand));
            ToolManifestFinder toolManifest =
                new ToolManifestFinder(new DirectoryPath(_testDirectoryRoot), _fileSystem);
            ToolCommandName toolCommandNameA = new ToolCommandName(toolCommand);
            var             fakeExecutable   = _nugetGlobalPackagesFolder.WithFile("fakeExecutable.dll");

            _fileSystem.Directory.CreateDirectory(_nugetGlobalPackagesFolder.Value);
            _fileSystem.File.CreateEmptyFile(fakeExecutable.Value);
            _localToolsResolverCache.Save(
                new Dictionary <RestoredCommandIdentifier, RestoredCommand>
            {
                [new RestoredCommandIdentifier(
                     new PackageId("local.tool.console.a"),
                     packageVersionA,
                     NuGetFramework.Parse(BundledTargetFramework.GetTargetFrameworkMoniker()),
                     Constants.AnyRid,
                     toolCommandNameA)]
                    = new RestoredCommand(toolCommandNameA, "dotnet", fakeExecutable)
            }, _nugetGlobalPackagesFolder);

            var localToolsCommandResolver = new LocalToolsCommandResolver(
                toolManifest,
                _localToolsResolverCache,
                _fileSystem,
                _nugetGlobalPackagesFolder);

            var result = localToolsCommandResolver.Resolve(new CommandResolverArguments()
            {
                CommandName = "dotnet-a",
            });

            result.Should().NotBeNull();

            var commandPath = result.Args.Trim('"');

            _fileSystem.File.Exists(commandPath).Should().BeTrue("the following path exists: " + commandPath);
            commandPath.Should().Be(fakeExecutable.Value);
        }
示例#12
0
        public void WhenNuGetGlobalPackageLocationIsCleanedAfterRestoreItShowError()
        {
            ToolCommandName toolCommandNameA = new ToolCommandName("a");
            NuGetVersion    packageVersionA  = NuGetVersion.Parse("1.0.4");

            _fileSystem.File.WriteAllText(Path.Combine(_testDirectoryRoot, ManifestFilename),
                                          _jsonContent.Replace("$TOOLCOMMAND$", toolCommandNameA.Value));
            ToolManifestFinder toolManifest =
                new ToolManifestFinder(new DirectoryPath(_testDirectoryRoot), _fileSystem);

            var fakeExecutable = _nugetGlobalPackagesFolder.WithFile("fakeExecutable.dll");

            _fileSystem.Directory.CreateDirectory(_nugetGlobalPackagesFolder.Value);
            _fileSystem.File.CreateEmptyFile(fakeExecutable.Value);
            _localToolsResolverCache.Save(
                new Dictionary <RestoredCommandIdentifier, RestoredCommand>
            {
                [new RestoredCommandIdentifier(
                     new PackageId("local.tool.console.a"),
                     packageVersionA,
                     NuGetFramework.Parse(BundledTargetFramework.GetTargetFrameworkMoniker()),
                     Constants.AnyRid,
                     toolCommandNameA)]
                    = new RestoredCommand(toolCommandNameA, "dotnet", fakeExecutable)
            }, _nugetGlobalPackagesFolder);

            var localToolsCommandResolver = new LocalToolsCommandResolver(
                toolManifest,
                _localToolsResolverCache,
                _fileSystem,
                _nugetGlobalPackagesFolder);

            _fileSystem.File.Delete(fakeExecutable.Value);

            Action action = () => localToolsCommandResolver.Resolve(new CommandResolverArguments()
            {
                CommandName = $"dotnet-{toolCommandNameA.ToString()}",
            });

            action.ShouldThrow <GracefulException>(string.Format(CommandFactory.LocalizableStrings.NeedRunToolRestore,
                                                                 toolCommandNameA.ToString()));
        }
示例#13
0
        public void RemoveShim(ToolCommandName commandName)
        {
            var files = new Dictionary <string, string>();

            TransactionalAction.Run(
                action: () => {
                try
                {
                    foreach (var file in GetShimFiles(commandName).Where(f => _fileSystem.File.Exists(f.Value)))
                    {
                        var tempPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
                        FileAccessRetrier.RetryOnMoveAccessFailure(() => _fileSystem.File.Move(file.Value, tempPath));
                        files[file.Value] = tempPath;
                    }
                }
                catch (Exception ex) when(ex is UnauthorizedAccessException || ex is IOException)
                {
                    throw new ShellShimException(
                        string.Format(
                            CommonLocalizableStrings.FailedToRemoveShellShim,
                            commandName.ToString(),
                            ex.Message
                            ),
                        ex);
                }
            },
                commit: () => {
                foreach (var value in files.Values)
                {
                    _fileSystem.File.Delete(value);
                }
            },
                rollback: () => {
                foreach (var kvp in files)
                {
                    FileAccessRetrier.RetryOnMoveAccessFailure(() => _fileSystem.File.Move(kvp.Value, kvp.Key));
                }
            });
        }
示例#14
0
        public void WhenNuGetGlobalPackageLocationIsNotRestoredItThrowsGracefulException()
        {
            ToolCommandName toolCommandNameA = new ToolCommandName("a");
            NuGetVersion    packageVersionA  = NuGetVersion.Parse("1.0.4");

            _fileSystem.File.WriteAllText(Path.Combine(_testDirectoryRoot, ManifestFilename),
                                          _jsonContent.Replace("$TOOLCOMMAND$", toolCommandNameA.Value));
            ToolManifestFinder toolManifest =
                new ToolManifestFinder(new DirectoryPath(_testDirectoryRoot), _fileSystem);

            var localToolsCommandResolver = new LocalToolsCommandResolver(
                toolManifest,
                _localToolsResolverCache,
                _fileSystem);

            Action action = () => localToolsCommandResolver.ResolveStrict(new CommandResolverArguments()
            {
                CommandName = $"dotnet-{toolCommandNameA.ToString()}",
            });

            action.ShouldThrow <GracefulException>(string.Format(CommandFactory.LocalizableStrings.NeedRunToolRestore,
                                                                 toolCommandNameA.ToString()));
        }
示例#15
0
 private IEnumerable <FilePath> GetShimFiles(ToolCommandName commandName)
 {
     yield return(GetShimPath(commandName));
 }
示例#16
0
        private List <ToolManifestPackage> GetToolManifestPackageFromOneManifestFile(
            SerializableLocalToolsManifest deserializedManifest, FilePath path)
        {
            List <ToolManifestPackage> result = new List <ToolManifestPackage>();
            var errors = new List <string>();

            if (deserializedManifest.version == 0)
            {
                errors.Add(string.Format(LocalizableStrings.ManifestVersion0, path.Value));
            }

            if (deserializedManifest.version > SupportedVersion)
            {
                errors.Add(
                    string.Format(
                        LocalizableStrings.ManifestVersionHigherThanSupported,
                        deserializedManifest.version, SupportedVersion, path.Value));
            }

            foreach (KeyValuePair <string, SerializableLocalToolSinglePackage> tools in deserializedManifest.tools)
            {
                var packageLevelErrors = new List <string>();
                var packageIdString    = tools.Key;
                var packageId          = new PackageId(packageIdString);

                string       versionString = tools.Value.version;
                NuGetVersion version       = null;
                if (versionString is null)
                {
                    packageLevelErrors.Add(LocalizableStrings.ToolMissingVersion);
                }
                else
                {
                    if (!NuGetVersion.TryParse(versionString, out version))
                    {
                        packageLevelErrors.Add(string.Format(LocalizableStrings.VersionIsInvalid, versionString));
                    }
                }

                NuGetFramework targetFramework       = null;
                var            targetFrameworkString = tools.Value.targetFramework;
                if (targetFrameworkString != null)
                {
                    targetFramework = NuGetFramework.Parse(
                        targetFrameworkString);

                    if (targetFramework.IsUnsupported)
                    {
                        packageLevelErrors.Add(
                            string.Format(LocalizableStrings.TargetFrameworkIsUnsupported,
                                          targetFrameworkString));
                    }
                }

                if (tools.Value.commands == null ||
                    (tools.Value.commands != null && tools.Value.commands.Length == 0))
                {
                    packageLevelErrors.Add(LocalizableStrings.FieldCommandsIsMissing);
                }

                if (packageLevelErrors.Any())
                {
                    var joinedWithIndentation = string.Join(Environment.NewLine,
                                                            packageLevelErrors.Select(e => "\t\t" + e));
                    errors.Add(string.Format(LocalizableStrings.InPackage, packageId.ToString(), joinedWithIndentation));
                }
                else
                {
                    result.Add(new ToolManifestPackage(
                                   packageId,
                                   version,
                                   ToolCommandName.Convert(tools.Value.commands)));
                }
            }

            if (errors.Any())
            {
                throw new ToolManifestException(
                          string.Format(LocalizableStrings.InvalidManifestFilePrefix,
                                        string.Join(Environment.NewLine, errors.Select(e => "\t" + e))));
            }

            return(result);
        }
示例#17
0
        public IReadOnlyCollection <ToolManifestPackage> Find(FilePath?filePath = null)
        {
            var result = new List <ToolManifestPackage>();

            IEnumerable <FilePath> allPossibleManifests =
                filePath != null
                    ? new[] { filePath.Value }
                    : EnumerateDefaultAllPossibleManifests();

            foreach (FilePath possibleManifest in allPossibleManifests)
            {
                if (_fileSystem.File.Exists(possibleManifest.Value))
                {
                    SerializableLocalToolsManifest deserializedManifest = JsonConvert.DeserializeObject <SerializableLocalToolsManifest>(
                        _fileSystem.File.ReadAllText(possibleManifest.Value), new JsonSerializerSettings
                    {
                        MissingMemberHandling = MissingMemberHandling.Ignore
                    });

                    var errors = new List <string>();

                    if (!deserializedManifest.isRoot)
                    {
                        errors.Add("isRoot is false is not supported.");
                    }

                    if (deserializedManifest.version != 1)
                    {
                        errors.Add(string.Format("Tools manifest format version {0} is not supported.",
                                                 deserializedManifest.version));
                    }

                    foreach (var tools in deserializedManifest.tools)
                    {
                        var packageLevelErrors = new List <string>();
                        var packageIdString    = tools.Key;
                        var packageId          = new PackageId(packageIdString);

                        string       versionString = tools.Value.version;
                        NuGetVersion version       = null;
                        if (versionString is null)
                        {
                            packageLevelErrors.Add(LocalizableStrings.MissingVersion);
                        }
                        else
                        {
                            var versionParseResult = NuGetVersion.TryParse(
                                versionString, out version);

                            if (!versionParseResult)
                            {
                                packageLevelErrors.Add(string.Format(LocalizableStrings.VersionIsInvalid, versionString));
                            }
                        }

                        if (tools.Value.commands == null ||
                            (tools.Value.commands != null && tools.Value.commands.Length == 0))
                        {
                            packageLevelErrors.Add(LocalizableStrings.FieldCommandsIsMissing);
                        }

                        if (packageLevelErrors.Any())
                        {
                            var joined = string.Join(string.Empty, packageLevelErrors.Select(e => Environment.NewLine + "    " + e));
                            errors.Add(string.Format(LocalizableStrings.InPackage, packageId.ToString()) + joined);
                        }
                        else
                        {
                            result.Add(new ToolManifestPackage(
                                           packageId,
                                           version,
                                           ToolCommandName.Convert(tools.Value.commands)));
                        }
                    }

                    if (errors.Any())
                    {
                        throw new ToolManifestException(LocalizableStrings.InvalidManifestFilePrefix +
                                                        string.Join(string.Empty, errors.Select(e => Environment.NewLine + "  " + e)));
                    }

                    return(result);
                }
            }

            throw new ToolManifestCannotFindException(
                      string.Format(LocalizableStrings.CannotFindAnyManifestsFileSearched,
                                    string.Join(Environment.NewLine, allPossibleManifests.Select(f => f.Value))));
        }
示例#18
0
        private List <ToolManifestPackage> GetToolManifestPackageFromOneManifestFile(
            SerializableLocalToolsManifest deserializedManifest,
            FilePath path,
            DirectoryPath correspondingDirectory)
        {
            List <ToolManifestPackage> result = new List <ToolManifestPackage>();
            var errors = new List <string>();

            ValidateVersion(deserializedManifest, errors);

            if (!deserializedManifest.IsRoot.HasValue)
            {
                errors.Add(string.Format(LocalizableStrings.ManifestMissingIsRoot, path.Value));
            }

            foreach (KeyValuePair <string, SerializableLocalToolSinglePackage> tools
                     in (deserializedManifest.Tools ?? new Dictionary <string, SerializableLocalToolSinglePackage>()))
            {
                var packageLevelErrors = new List <string>();
                var packageIdString    = tools.Key;
                var packageId          = new PackageId(packageIdString);

                string       versionString = tools.Value.Version;
                NuGetVersion version       = null;
                if (versionString is null)
                {
                    packageLevelErrors.Add(LocalizableStrings.ToolMissingVersion);
                }
                else
                {
                    if (!NuGetVersion.TryParse(versionString, out version))
                    {
                        packageLevelErrors.Add(string.Format(LocalizableStrings.VersionIsInvalid, versionString));
                    }
                }

                if (tools.Value.Commands == null ||
                    (tools.Value.Commands != null && tools.Value.Commands.Length == 0))
                {
                    packageLevelErrors.Add(LocalizableStrings.FieldCommandsIsMissing);
                }

                if (packageLevelErrors.Any())
                {
                    var joinedWithIndentation = string.Join(Environment.NewLine,
                                                            packageLevelErrors.Select(e => "\t\t" + e));
                    errors.Add(string.Format(LocalizableStrings.InPackage, packageId.ToString(),
                                             joinedWithIndentation));
                }
                else
                {
                    result.Add(new ToolManifestPackage(
                                   packageId,
                                   version,
                                   ToolCommandName.Convert(tools.Value.Commands),
                                   correspondingDirectory));
                }
            }

            if (errors.Any())
            {
                throw new ToolManifestException(
                          string.Format(LocalizableStrings.InvalidManifestFilePrefix,
                                        path.Value,
                                        string.Join(Environment.NewLine, errors.Select(e => "\t" + e))));
            }

            return(result);
        }
示例#19
0
 private bool ShimExists(ToolCommandName commandName)
 {
     return(GetShimFiles(commandName).Any(p => _fileSystem.File.Exists(p.Value)));
 }