コード例 #1
0
        protected override int LockedExecute(CancellationToken cancellationToken)
        {
            if (Packages == null)
            {
                throw new Exception("No packages specified.");
            }

            if (Force == false && Packages.Any(p => p == "OpenTAP") && Target == ExecutorClient.ExeDir)
            {
                log.Error("Aborting request to uninstall the OpenTAP package that is currently executing as that would brick this installation. Use --force to uninstall anyway.");
                return(-4);
            }

            Installer installer = new Installer(Target, cancellationToken)
            {
                DoSleep = false
            };

            installer.ProgressUpdate += RaiseProgressUpdate;
            installer.Error          += RaiseError;

            var installedPackages = new Installation(Target).GetPackages();

            bool anyUnrecognizedPlugins = false;

            foreach (string pack in Packages)
            {
                PackageDef package = installedPackages.FirstOrDefault(p => p.Name == pack);

                if (package != null && package.PackageSource is InstalledPackageDefSource source)
                {
                    installer.PackagePaths.Add(source.PackageDefFilePath);
                }
                else if (!IgnoreMissing)
                {
                    log.Error("Package '{0}' is not installed", pack);
                    anyUnrecognizedPlugins = true;
                }
            }

            if (anyUnrecognizedPlugins)
            {
                return(-2);
            }

            if (!Force)
            {
                if (!CheckPackageAndDependencies(installedPackages, installer.PackagePaths))
                {
                    return(-3);
                }
            }

            return(installer.RunCommand("uninstall", Force, true) ? 0 : -1);
        }
コード例 #2
0
ファイル: Test.cs プロジェクト: ZHJEE/OpenTAP
        public override int Execute(CancellationToken cancellationToken)
        {
            if (Packages == null)
            {
                throw new Exception("No packages specified.");
            }

            var target = LockingPackageAction.GetLocalInstallationDir();


            Installer installer = new Installer(target, cancellationToken)
            {
                DoSleep = false
            };

            installer.ProgressUpdate += RaiseProgressUpdate;
            installer.Error          += RaiseError;

            var installedPackages = new Installation(target).GetPackages();

            bool anyUnrecognizedPlugins = false;

            foreach (string pack in Packages)
            {
                PackageDef package = installedPackages.FirstOrDefault(p => p.Name == pack);

                if (package != null && package.PackageSource is InstalledPackageDefSource source)
                {
                    installer.PackagePaths.Add(source.PackageDefFilePath);
                }
                else if (!IgnoreMissing)
                {
                    log.Error("Package '{0}' is not installed", pack);
                    anyUnrecognizedPlugins = true;
                }
            }

            if (anyUnrecognizedPlugins)
            {
                return(-2);
            }

            return(installer.RunCommand("test", false, false) ? 0 : -1);
        }
コード例 #3
0
ファイル: List.cs プロジェクト: ZHJEE/OpenTAP
        protected override int LockedExecute(CancellationToken cancellationToken)
        {
            if (OS == null)
            {
                switch (Environment.OSVersion.Platform)
                {
                case PlatformID.MacOSX:
                    OS = "OSX";
                    break;

                case PlatformID.Unix:
                    OS = "Linux";
                    break;

                default:
                    OS = "Windows";
                    break;
                }
            }

            List <IPackageRepository> repositories = new List <IPackageRepository>();

            if (Installed == false)
            {
                if (Repository == null)
                {
                    repositories.AddRange(PackageManagerSettings.Current.Repositories.Where(p => p.IsEnabled).Select(s => s.Manager));
                }
                else
                {
                    repositories.AddRange(Repository.Select(s => PackageRepositoryHelpers.DetermineRepositoryType(s)));
                }
            }

            if (Target == null)
            {
                Target = FileSystemHelper.GetCurrentInstallationDirectory();
            }

            HashSet <PackageDef> installed = new Installation(Target).GetPackages().ToHashSet();


            VersionSpecifier versionSpec = VersionSpecifier.Parse("^");

            if (!String.IsNullOrWhiteSpace(Version))
            {
                versionSpec = VersionSpecifier.Parse(Version);
            }

            if (string.IsNullOrEmpty(Name))
            {
                var packages = installed.ToList();
                packages.AddRange(PackageRepositoryHelpers.GetPackageNameAndVersionFromAllRepos(repositories, new PackageSpecifier("", versionSpec, Architecture, OS)));

                if (Installed)
                {
                    packages = packages.Where(p => installed.Any(i => i.Name == p.Name)).ToList();
                }

                PrintReadable(packages, installed);
            }
            else
            {
                IPackageIdentifier package = installed.FirstOrDefault(p => p.Name == Name);

                if (Installed)
                {
                    if (package is null)
                    {
                        log.Info($"{Name} is not installed");
                        return(-1);
                    }

                    log.Info(package.Version.ToString());
                    return(0);
                }


                List <PackageVersion> versions = null;

                if (All)
                {
                    versions = PackageRepositoryHelpers.GetAllVersionsFromAllRepos(repositories, Name).Distinct().ToList();
                    var versionsCount = versions.Count;
                    if (versionsCount == 0) // No versions
                    {
                        log.Info($"No versions of '{Name}'.");
                        return(0);
                    }

                    if (Version != null) // Version is specified by user
                    {
                        versions = versions.Where(v => versionSpec.IsCompatible(v.Version)).ToList();
                    }

                    if (versions.Any() == false && versionsCount > 0)
                    {
                        log.Info($"Package '{Name}' does not exists with version '{Version}'.");
                        log.Info($"Package '{Name}' exists in {versionsCount} other versions, please specify a different version.");
                        return(0);
                    }
                }
                else
                {
                    var opentap = new Installation(Target).GetOpenTapPackage();
                    versions = PackageRepositoryHelpers.GetAllVersionsFromAllRepos(repositories, Name, opentap).Distinct().ToList();

                    versions = versions.Where(s => s.IsPlatformCompatible(Architecture, OS)).ToList();

                    if (versions.Any() == false) // No compatible versions
                    {
                        versions = PackageRepositoryHelpers.GetAllVersionsFromAllRepos(repositories, Name).ToList();
                        if (versions.Any())
                        {
                            log.Warning($"There are no compatible versions of '{Name}'.");
                            log.Info($"There are {versions.Count} incompatible versions available. Use '--all' to show these.");
                        }
                        else
                        {
                            log.Warning($"Package '{Name}' could not be found in any repository.");
                        }

                        return(0);
                    }


                    versions = versions.Where(v => versionSpec.IsCompatible(v.Version)).ToList();
                    if (versions.Any() == false) // No versions that are compatible
                    {
                        if (string.IsNullOrEmpty(Version))
                        {
                            log.Warning($"There are no released versions of '{Name}'.");
                        }
                        else
                        {
                            log.Warning($"Package '{Name}' does not exists with version '{Version}'.");
                        }

                        var anyPrereleaseSpecifier = new VersionSpecifier(versionSpec.Major, versionSpec.Minor, versionSpec.Patch, versionSpec.PreRelease, versionSpec.BuildMetadata, VersionMatchBehavior.AnyPrerelease | versionSpec.MatchBehavior);
                        versions = versions.Where(v => anyPrereleaseSpecifier.IsCompatible(v.Version)).ToList();
                        if (versions.Any())
                        {
                            log.Info($"There are {versions.Count} pre-released versions available. Use '--version <pre-release>' (e.g. '--version rc') or '--all' to show these.");
                        }

                        return(0);
                    }
                }
                PrintVersionsReadable(package, versions);
            }
            return(0);
        }
コード例 #4
0
        internal static void findDependencies(this PackageDef pkg, List <string> excludeAdd, List <AssemblyData> searchedFiles)
        {
            bool foundNew = false;

            var notFound = new HashSet <string>();

            // First update the pre-entered dependencies
            var installed = new Installation(Directory.GetCurrentDirectory()).GetPackages().Where(p => p.Name != pkg.Name).ToList();

            List <string> brokenPackageNames = new List <string>();

            List <AssemblyData> getPackageAssemblues(PackageDef pkgDef)
            {
                List <AssemblyData> output = new List <AssemblyData>();

                foreach (var f in pkgDef.Files)
                {
                    var asms = searchedFiles.Where(sf => PathUtils.AreEqual(f.FileName, sf.Location))
                               .Where(sf => IsDotNetAssembly(sf.Location)).ToList();
                    if (asms.Count == 0 && (Path.GetExtension(f.FileName).Equals(".dll", StringComparison.OrdinalIgnoreCase) || Path.GetExtension(f.FileName).Equals(".exe", StringComparison.OrdinalIgnoreCase)))
                    {
                        if (File.Exists(f.FileName))
                        {
                            // If the pluginSearcher found assemblies that are located somewhere not expected by the package definition, the package might appear broken.
                            // But if the file found by the pluginSearcher is the same as the one expected by the package definition we should not count it as broken.
                            // This could cause a package to not be added as a dependencies.
                            // E.g. when debugging and the OpenTAP.Cli.dll is both in the root build dir and in "Packages/OpenTAP"
                            var asmsIdenticalFilename = searchedFiles.Where(sf => Path.GetFileName(f.FileName) == Path.GetFileName(sf.Location));
                            var asmsIdentical         = asmsIdenticalFilename.Where(sf => PathUtils.CompareFiles(f.FileName, sf.Location));
                            output.AddRange(asmsIdentical);
                            continue;
                        }

                        if (!brokenPackageNames.Contains(pkgDef.Name) && IsDotNetAssembly(f.FileName))
                        {
                            brokenPackageNames.Add(pkgDef.Name);
                            log.Warning($"Package '{pkgDef.Name}' is not installed correctly?  Referenced file '{f.FileName}' was not found.");
                        }
                    }
                    output.AddRange(asms);
                }
                return(output);
            };

            var packageAssemblies = new Memorizer <PackageDef, List <AssemblyData> >(getPackageAssemblues);

            // check versions of any hardcoded dependencies against what is currently installed
            foreach (PackageDependency dep in pkg.Dependencies)
            {
                var installedPackage = installed.FirstOrDefault(ip => ip.Name == dep.Name);
                if (installedPackage != null)
                {
                    if (dep.Version == null)
                    {
                        dep.Version = new VersionSpecifier(installedPackage.Version, VersionMatchBehavior.Compatible);
                        log.Info("A version was not specified for package dependency {0}. Using installed version ({1}).", dep.Name, dep.Version);
                    }
                    else
                    {
                        if (!dep.Version.IsCompatible(installedPackage.Version))
                        {
                            throw new ExitCodeException((int)PackageCreateAction.ExitCodes.PackageDependencyError, $"Installed version of {dep.Name} ({installedPackage.Version}) is incompatible with dependency specified in package definition ({dep.Version}).");
                        }
                    }
                }
                else
                {
                    throw new ExitCodeException((int)PackageCreateAction.ExitCodes.PackageDependencyError,
                                                $"Package dependency '{dep.Name}' specified in package definition is not installed. Please install a compatible version first.");
                }
            }

            // Find additional dependencies
            do
            {
                foundNew = false;

                // Find everything we already know about
                var offeredByDependencies = AssembliesOfferedBy(installed, pkg.Dependencies, false, packageAssemblies).ToList();
                var offeredByThis         = packageAssemblies[pkg]
                                            .Where(f => f != null)
                                            .ToList();

                var anyOffered = offeredByDependencies.Concat(offeredByThis).ToList();

                // Find our dependencies and subtract the above two lists
                var dependentAssemblyNames = pkg.Files
                                             .SelectMany(fs => fs.DependentAssemblies)
                                             .Where(r => r.Name != "mscorlib") // Special case. We should not bundle the framework assemblies.
                                             .Where(r => !anyOffered.Any(of => AssemblyRefUtils.IsCompatibleReference(of, r)))
                                             .Distinct().Where(x => !excludeAdd.Contains(x.Name)).ToList();

                // If there's anything left we start resolving
                if (dependentAssemblyNames.Any())
                {
                    // First look in installed packages
                    var packageCandidates = new Dictionary <PackageDef, int>();
                    foreach (var f in installed)
                    {
                        var candidateAsms = packageAssemblies[f].Where(asm => dependentAssemblyNames.Any(dep => (dep.Name == asm.Name))).ToList();

                        // Don't consider a package that only matches assemblies in the Dependencies subfolder
                        candidateAsms.RemoveAll(asm => asm.Location.Contains("Dependencies")); // TODO: less lazy check for Dependencies subfolder would be good.

                        if (candidateAsms.Count > 0)
                        {
                            packageCandidates[f] = candidateAsms.Count;
                        }
                    }

                    // Look at the most promising candidate (i.e. the one containing most assemblies with the same names as things we need)
                    PackageDef candidatePkg = packageCandidates.OrderByDescending(k => k.Value).FirstOrDefault().Key;

                    if (candidatePkg != null)
                    {
                        foreach (AssemblyData candidateAsm in packageAssemblies[candidatePkg])
                        {
                            var requiredAsm = dependentAssemblyNames.FirstOrDefault(dep => dep.Name == candidateAsm.Name);
                            if (requiredAsm != null)
                            {
                                if (OpenTap.Utils.Compatible(candidateAsm.Version, requiredAsm.Version))
                                {
                                    log.Info($"Satisfying assembly reference to {requiredAsm.Name} by adding dependency on package {candidatePkg.Name}");
                                    if (candidateAsm.Version != requiredAsm.Version)
                                    {
                                        log.Warning($"Version of {requiredAsm.Name} in {candidatePkg.Name} is different from the version referenced in this package ({requiredAsm.Version} vs {candidateAsm.Version}).");
                                        log.Warning($"Consider changing your version of {requiredAsm.Name} to {candidateAsm.Version} to match that in {candidatePkg.Name}.");
                                    }
                                    foundNew = true;
                                }
                                else
                                {
                                    var depender = pkg.Files.FirstOrDefault(f => f.DependentAssemblies.Contains(requiredAsm));
                                    if (depender == null)
                                    {
                                        log.Error($"This package require assembly {requiredAsm.Name} in version {requiredAsm.Version} while that assembly is already installed through package '{candidatePkg.Name}' in version {candidateAsm.Version}.");
                                    }
                                    else
                                    {
                                        log.Error($"{Path.GetFileName(depender.FileName)} in this package require assembly {requiredAsm.Name} in version {requiredAsm.Version} while that assembly is already installed through package '{candidatePkg.Name}' in version {candidateAsm.Version}.");
                                    }
                                    //log.Error($"Please align the version of {requiredAsm.Name} to ensure interoperability with package '{candidate.Key.Name}' or uninstall that package.");
                                    throw new ExitCodeException((int)PackageCreateAction.ExitCodes.AssemblyDependencyError,
                                                                $"Please align the version of {requiredAsm.Name} ({candidateAsm.Version} vs {requiredAsm.Version})  to ensure interoperability with package '{candidatePkg.Name}' or uninstall that package.");
                                }
                            }
                        }
                        if (foundNew)
                        {
                            log.Info("Adding dependency on package '{0}' version {1}", candidatePkg.Name, candidatePkg.Version);

                            PackageDependency pd = new PackageDependency(candidatePkg.Name, new VersionSpecifier(candidatePkg.Version, VersionMatchBehavior.Compatible));
                            pkg.Dependencies.Add(pd);
                        }
                    }
                    else
                    {
                        // No installed package can offer any of the remaining referenced assemblies.
                        // add them as payload in this package in the Dependencies subfolder
                        foreach (var unknown in dependentAssemblyNames)
                        {
                            var foundAsms = searchedFiles.Where(asm => (asm.Name == unknown.Name) && OpenTap.Utils.Compatible(asm.Version, unknown.Version)).ToList();
                            var foundAsm  = foundAsms.FirstOrDefault();

                            if (foundAsm != null)
                            {
                                AddFileDependencies(pkg, unknown, foundAsm);
                                packageAssemblies.Invalidate(pkg);
                                foundNew = true;
                            }
                            else if (!notFound.Contains(unknown.Name))
                            {
                                log.Debug("'{0}' could not be found in any of {1} searched assemblies, or is already added.", unknown.Name, searchedFiles.Count);
                                notFound.Add(unknown.Name);
                            }
                        }
                    }
                }
            }while (foundNew);
        }
コード例 #5
0
        internal static void RunIsolated(string application = null, string target = null, IsolatedPackageAction isolatedAction = null)
        {
            using (var tpmClient = new ExecutorClient())
            {
                var packages = new Installation(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)).GetPackages();
                PackageDef findPackageWithFile(string file)
                {
                    foreach (var package in packages)
                    {
                        foreach (var pkgfile in package.Files)
                        {
                            var filePath = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), pkgfile.FileName);

                            if (string.Equals(NormalizePath(filePath), NormalizePath(file), StringComparison.OrdinalIgnoreCase))
                            {
                                return(package);
                            }
                        }
                    }
                    return(null);
                }

                var        exec = application ?? Assembly.GetEntryAssembly().Location;
                PackageDef pkg  = findPackageWithFile(Path.GetFullPath(exec));
                if (pkg == null)
                {
                    throw new InvalidOperationException($"{Path.GetFileName(exec)} was not installed through a package.");
                }
                var dependencies = pkg.Dependencies.ToList();

                if (isolatedAction != null)
                {
                    // If the executing IsolatedPackageAction does not origin from OpenTAP package, we need to include it when we copy and run isolated
                    var        actionAsm             = isolatedAction.GetType().Assembly.Location;
                    PackageDef isolatedActionPackage = findPackageWithFile(Path.GetFullPath(actionAsm));
                    if (isolatedActionPackage == null)
                    {
                        throw new InvalidOperationException($"{Path.GetFileName(actionAsm)} was not installed through a package.");
                    }
                    if (pkg.Name != isolatedActionPackage.Name)
                    {
                        if (!dependencies.Any(p => p.Name == isolatedActionPackage.Name))
                        {
                            dependencies.Add(new PackageDependency(isolatedActionPackage.Name, new VersionSpecifier(isolatedActionPackage.Version, VersionMatchBehavior.Compatible)));
                        }
                    }
                }

                // when installing/uninstalling packages we might need to use custom package actions as well.
                var extraDependencies = PluginManager.GetPlugins <ICustomPackageAction>().Select(t => t.Assembly.Location).Distinct().ToList();
                foreach (var exDep in extraDependencies)
                {
                    var package = findPackageWithFile(exDep);
                    if (package != null && !dependencies.Any(p => p.Name == package.Name))
                    {
                        dependencies.Add(new PackageDependency(package.Name, new VersionSpecifier(package.Version, VersionMatchBehavior.Compatible)));
                    }
                }

                var deps = OpenTap.Utils.FlattenHeirarchy(dependencies, dep => (IEnumerable <PackageDependency>)packages.FirstOrDefault(x => x.Name == dep.Name)?.Dependencies ?? Array.Empty <PackageDependency>(), distinct: true);

                if (false == deps.Any(x => x.Name == pkg.Name))
                {
                    deps.Add(new PackageDependency(pkg.Name, new VersionSpecifier(pkg.Version, VersionMatchBehavior.Compatible)));
                }

                bool force = isolatedAction?.Force ?? false;

                List <string> allFiles = new List <string>();
                foreach (var d in deps)
                {
                    var availPackages = packages.Where(p => p.Name == d.Name);
                    var package       = availPackages.FirstOrDefault(p => d.Version.IsCompatible(p.Version));
                    if (package == null)
                    {
                        package = availPackages.FirstOrDefault();
                        if (!force)
                        {
                            if (package != null)
                            {
                                throw new Exception($"Cannot find compatible dependency '{d.Name}' {d.Version}. Version {package.Version} is installed.");
                            }
                            throw new Exception($"Cannot find needed dependency '{d.Name}'.");
                        }

                        log.Warning("Unable to find compatible package, using {0} v{1} instead.", package.Name, package.Version);
                    }

                    var defPath = String.Join("/", PackageDef.PackageDefDirectory, package.Name, PackageDef.PackageDefFileName);
                    if (File.Exists(defPath))
                    {
                        allFiles.Add(defPath);
                    }

                    var fs             = package.Files;
                    var brokenPackages = new HashSet <string>();
                    foreach (var file in fs)
                    {
                        string loc = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), file.FileName);
                        if (!File.Exists(loc))
                        {
                            brokenPackages.Add(package.Name);
                            log.Debug($"Could not find file '{loc}' part of package '{package.Name}'.");
                            continue;
                        }

                        allFiles.Add(file.FileName);
                    }

                    foreach (var name in brokenPackages)
                    {
                        log.Warning($"Package '{name}' has missing files and is broken.");
                    }
                }

                string tempFolder = Path.GetFullPath(FileSystemHelper.CreateTempDirectory());

                foreach (var _loc in allFiles.Distinct())
                {
                    string loc = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), _loc);

                    var newloc = Path.Combine(tempFolder, _loc);
                    OpenTap.FileSystemHelper.EnsureDirectory(newloc);
                    if (File.Exists(newloc))
                    {
                        continue;
                    }
                    File.Copy(loc, newloc);
                }

                { // tell TPM Server to start new app.
                    var loc = application ?? Assembly.GetEntryAssembly().Location;
                    if (string.Equals(".dll", Path.GetExtension(loc), StringComparison.OrdinalIgnoreCase))
                    {  //.netcore wierdness.
                        loc = Path.ChangeExtension(loc, "exe");
                        if (File.Exists(loc) == false)
                        {
                            loc = loc.Substring(0, loc.Length - ".exe".Length);
                        }
                    }

                    var newname = Path.Combine(tempFolder, Path.GetFileName(loc));

                    newname = $"\"{newname}\"";  // there could be whitespace in the name.

                    // now that we start from a different dir, we need to supply a --target argument
                    if (target != null)
                    {
                        newname = $"{newname} --target \"{target}\"";
                    }

                    tpmClient.MessageServer("run " + newname);
                    tpmClient.Dispose();
                }
            }
        }