Пример #1
0
        /// <summary>
        /// Returns the names of the files in a plugin package.
        /// </summary>
        /// <param name="packagePath"></param>
        /// <returns></returns>
        internal static List <string> FilesInPackage(string packagePath)
        {
            List <string> files    = new List <string>();
            string        fileType = Path.GetExtension(packagePath);

            if (fileType == ".xml")
            {
                var pkg = PackageDef.FromXml(packagePath);
                return(pkg.Files.Select(f => f.FileName).ToList());
            }

            try
            {
                using (var fileStream = File.OpenRead(packagePath))
                    using (var zip = new ZipArchive(fileStream, ZipArchiveMode.Read))
                    {
                        foreach (var part in zip.Entries)
                        {
                            if (part.Name == "[Content_Types].xml" || part.Name == ".rels" || part.FullName.StartsWith("package/services/metadata/core-properties"))
                            {
                                continue; // skip strange extra files that are created by System.IO.Packaging.Package (TAP 7.x)
                            }
                            string path = Uri.UnescapeDataString(part.FullName);
                            files.Add(path);
                        }
                    }
            }
            catch (InvalidDataException)
            {
                log.Error($"Could not unpackage '{packagePath}'.");
                throw;
            }
            return(files);
        }
Пример #2
0
        /// <summary>
        /// Load the input as a PackageDef, saves it again and compares the saved output to the original input
        /// </summary>
        /// <param name="input"></param>
        private static void LoadSaveCompare(string input, string expectedOutput)
        {
            PackageDef pkg;

            byte[] inputArray = System.Text.Encoding.ASCII.GetBytes(input);
            using (MemoryStream inputStream = new MemoryStream(inputArray))
            {
                pkg = PackageDef.FromXml(inputStream);
            }
            string output = "";

            using (Stream str = new MemoryStream())
            {
                pkg.SaveTo(str);
                using (StreamReader reader = new StreamReader(str))
                {
                    reader.BaseStream.Seek(0, 0);
                    output = reader.ReadToEnd();
                }
            }
            XDocument inputDoc  = XDocument.Parse(expectedOutput);
            XDocument outputDoc = XDocument.Parse(output);

            AssertElementEquals(inputDoc.Root, outputDoc.Root);
            AssertElementEquals(outputDoc.Root, inputDoc.Root);
        }
Пример #3
0
        public void CheckDependencies_AllDepsInstalled()
        {
            var xseries = PackageDef.FromXml(PackageDef.GetDefaultPackageMetadataPath("XSeries"));

            //var test2 = PackageDef.FromXmlFile(PackageDef.GetDefaultPackageMetadataPath("Test2"));
            File.Copy(PackageDef.GetDefaultPackageMetadataPath("CheckDependencies_AllDepsInstalled"), "CheckDependencies_AllDepsInstalled.xml", true);
            PackageDef.ValidateXml("CheckDependencies_AllDepsInstalled.xml");
            var alldeps = PackageDef.FromXml("CheckDependencies_AllDepsInstalled.xml");
            //var tree = DependencyAnalyzer.BuildAnalyzerContext(new List<PackageDef> { xseries, test2, alldeps });
            //Assert.AreEqual(tree.BrokenPackages.Count, 1);
            //PackageDependencyExt.CheckDependencies(inputFilename);
        }
Пример #4
0
        public void LoadPackageFile()
        {
            var        packageString = Resources.GetEmbedded("ExamplePackage.xml");
            PackageDef package;

            using (var str = new MemoryStream(Encoding.UTF8.GetBytes(packageString)))
            {
                package = PackageDef.FromXml(str);
            }
            Assert.AreEqual(package.Dependencies.Count, 1);
            Assert.AreEqual("Tap", package.Dependencies[0].Name);
            Assert.AreEqual(package.Files.Count, 2);
            Assert.IsNotNull(package.Description);
        }
Пример #5
0
        public void CheckDependencies_MissingDep()
        {
            string inputFilename = "Packages/CheckDependencies_MissingDep/package.xml";

            //PackageDependencyExt.CheckDependencies(inputFilename);
            var xseries = PackageDef.FromXml(PackageDef.GetDefaultPackageMetadataPath("XSeries"));

            PackageDef.ValidateXml(inputFilename);
            var missing = PackageDef.FromXml(inputFilename);
            var tree    = DependencyAnalyzer.BuildAnalyzerContext(new List <PackageDef> {
                xseries, missing
            });

            Assert.IsTrue(tree.GetIssues(missing).Any(issue => issue.IssueType == DependencyIssueType.Missing));
            //Assert.Fail("CheckDependencies should have thrown an exception");
        }
Пример #6
0
 static PackageDef loadPackageDef(string file)
 {
     try
     {
         using (var f = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
             return(PackageDef.FromXml(f));
     }
     catch (Exception e)
     {
         log.Warning("Unable to read package file '{0}'. Moving it to '.broken'", file);
         log.Debug(e);
         var brokenfile = file + ".broken";
         if (File.Exists(brokenfile))
         {
             File.Delete(brokenfile);
         }
         File.Move(file, brokenfile);
     }
     return(null);
 }
Пример #7
0
        public void SaveTo_Simple()
        {
            string inputFilename     = "Packages/Package/package.xml"; // this package contains the old XML Schema URL
            string outputFileContent = "";

            PackageDef pkg = PackageDef.FromXml(inputFilename);

            using (Stream str = new MemoryStream())
            {
                pkg.SaveTo(str);
                using (StreamReader reader = new StreamReader(str))
                {
                    reader.BaseStream.Seek(0, 0);
                    outputFileContent = reader.ReadToEnd();
                }
            }
            string inputContent = File.ReadAllText(inputFilename);

            // check that the package now contains the new XML Schema URL
            StringAssert.Contains("xmlns=\"http://opentap.io/schemas/package\"", outputFileContent);
        }
Пример #8
0
        /// <summary>
        /// Load from an XML package definition file.
        /// This file is not expected to have info about the plugins in it, so this method will enumerate the plugins inside each dll by loading them.
        /// </summary>
        /// <param name="xmlFilePath">The Package Definition xml file. Usually named package.xml</param>
        /// <param name="projectDir">Directory used byt GitVersionCalculator to expand any $(GitVersion) macros in the XML file.</param>
        /// <returns></returns>
        public static PackageDef FromInputXml(string xmlFilePath, string projectDir)
        {
            PackageDef.ValidateXml(xmlFilePath);
            var pkgDef = PackageDef.FromXml(xmlFilePath);

            if (pkgDef.Files.Any(f => f.HasCustomData <UseVersionData>() && f.HasCustomData <SetAssemblyInfoData>()))
            {
                throw new InvalidDataException("A file cannot specify <SetAssemblyInfo/> and <UseVersion/> at the same time.");
            }

            pkgDef.Files = expandGlobEntries(pkgDef.Files);

            var excludeAdd = pkgDef.Files.Where(file => file.IgnoredDependencies != null).SelectMany(file => file.IgnoredDependencies).Distinct().ToList();

            List <Exception> exceptions = new List <Exception>();

            foreach (PackageFile item in pkgDef.Files)
            {
                string fullPath = Path.GetFullPath(item.FileName);
                if (!File.Exists(fullPath))
                {
                    string fileName = Path.GetFileName(item.FileName);
                    if (File.Exists(fileName) && item.SourcePath == null)
                    {
                        // this is to support building everything to the root folder. This way the developer does not have to specify SourcePath.
                        log.Warning("Specified file '{0}' was not found, using file '{1}' as source instead. Consider setting SourcePath to remove this warning.", item.FileName, fileName);
                        item.SourcePath = fileName;
                    }
                    else
                    {
                        exceptions.Add(new FileNotFoundException("Missing file for package.", fullPath));
                    }
                }
            }
            if (exceptions.Count > 0)
            {
                throw new AggregateException("Missing files", exceptions);
            }

            pkgDef.Date = DateTime.UtcNow;

            // Copy to output directory first
            foreach (var file in pkgDef.Files)
            {
                if (file.RelativeDestinationPath != file.FileName)
                {
                    try
                    {
                        var destPath = Path.GetFullPath(file.RelativeDestinationPath);
                        if (!File.Exists(destPath))
                        {
                            Directory.CreateDirectory(Path.GetDirectoryName(destPath));
                            ProgramHelper.FileCopy(file.FileName, destPath);
                        }
                    }
                    catch
                    {
                        // Catching here. The files might be used by themselves
                    }
                }
            }

            var searcher = new PluginSearcher(PluginSearcher.Options.IncludeSameAssemblies);

            searcher.Search(Directory.GetCurrentDirectory());
            List <AssemblyData> assemblies = searcher.Assemblies.ToList();

            // Enumerate plugins if this has not already been done.
            if (!pkgDef.Files.SelectMany(pfd => pfd.Plugins).Any())
            {
                EnumeratePlugins(pkgDef, assemblies);
            }

            log.Info("Updating package version.");
            pkgDef.updateVersion(projectDir);
            log.Info("Package version is {0}", pkgDef.Version);

            pkgDef.findDependencies(excludeAdd, assemblies);

            return(pkgDef);
        }
Пример #9
0
        private void waitForPackageFilesFree(string tapDir, List <string> PackagePaths)
        {
            // ignore tap.exe as it is not meant to be overwritten.
            bool exclude(string filename) => filename.ToLower() == "tap" || filename.ToLower() == "tap.exe";

            List <FileInfo> filesInUse = new List <FileInfo>();

            foreach (string packageFileName in PackagePaths)
            {
                foreach (string file in PluginInstaller.FilesInPackage(packageFileName))
                {
                    string fullPath = Path.Combine(tapDir, file);
                    string filename = Path.GetFileName(file);
                    if (exclude(filename))
                    {
                        continue;
                    }
                    if (IsFileLocked(new FileInfo(fullPath)))
                    {
                        filesInUse.Add(new FileInfo(fullPath));
                    }
                }
            }

            // Check if the files that are in use are used by any other package
            var packages = PackagePaths.Select(p => p.EndsWith("TapPackage") ? PackageDef.FromPackage(p) : PackageDef.FromXml(p));
            var remainingInstalledPlugins = new Installation(tapDir).GetPackages().Where(i => packages.Any(p => p.Name == i.Name) == false);
            var filesToRemain             = remainingInstalledPlugins.SelectMany(p => p.Files).Select(f => f.RelativeDestinationPath).Distinct(StringComparer.InvariantCultureIgnoreCase);

            filesInUse = filesInUse.Where(f => filesToRemain.Contains(f.Name, StringComparer.InvariantCultureIgnoreCase) == false).ToList();

            if (filesInUse.Count > 0)
            {
                log.Info("Following files cannot be modified because they are in use:");
                foreach (var file in filesInUse)
                {
                    log.Info("- " + file.FullName);

                    var loaded_asm = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(x => x.IsDynamic == false && x.Location == file.FullName);
                    if (loaded_asm != null)
                    {
                        throw new InvalidOperationException($"The file '{file.FullName}' is being used by this process.");
                    }
                }

                var allProcesses = Process.GetProcesses().Where(p =>
                                                                p.ProcessName.ToLowerInvariant().Contains("opentap") &&
                                                                p.ProcessName.ToLowerInvariant().Contains("vshost") == false &&
                                                                p.ProcessName != Assembly.GetExecutingAssembly().GetName().Name).ToArray();
                if (allProcesses.Any())
                {
                    // The file could be locked by someone other than OpenTAP processes. We should not assume it's OpenTAP holding the file.
                    log.Warning(Environment.NewLine + "To continue, try closing applications that could be using the files.");
                    foreach (var process in allProcesses)
                    {
                        log.Warning("- " + process.ProcessName);
                    }
                }

                log.Warning(Environment.NewLine + "Waiting for files to become unlocked...");

                while (isPackageFilesInUse(tapDir, PackagePaths, exclude))
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        return;
                    }
                    if (!isTapRunning())
                    {
                        OnError(new IOException("One or more plugin files are in use. View log for more information."));
                    }
                    Thread.Sleep(300);
                }
            }
        }
Пример #10
0
        internal bool RunCommand(string command, bool force, bool modifiesPackageFiles)
        {
            var verb = System.Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(command.ToLower()) + "ed";

            try
            {
                if (modifiesPackageFiles)
                {
                    waitForPackageFilesFree(TapDir, PackagePaths);
                }

                if (cancellationToken.IsCancellationRequested)
                {
                    log.Debug("Received abort while waiting for package files to be unlocked.");
                    return(false);
                }

                double progressPercent = 10;
                OnProgressUpdate((int)progressPercent, "");

                PluginInstaller pi = new PluginInstaller();

                foreach (string fileName in PackagePaths)
                {
                    PackageDef pkg = PackageDef.FromXml(fileName);
                    OnProgressUpdate((int)progressPercent, string.Format("Running command '{0}' on '{1}'", command, pkg.Name));
                    Stopwatch timer = Stopwatch.StartNew();
                    var       res   = pi.ExecuteAction(pkg, command, force, TapDir);

                    if (res == ActionResult.Error)
                    {
                        OnProgressUpdate(100, "Done");
                        return(false);
                    }
                    else if (res == ActionResult.NothingToDo)
                    {
                        log.Info(string.Format("Tried to {0} {1}, but there was nothing to do.", command, pkg.Name));
                    }
                    else
                    {
                        log.Info(timer, string.Format("{1} {0} version {2}.", pkg.Name, verb, pkg.Version));
                    }

                    progressPercent += (double)80 / PackagePaths.Count();
                }
                OnProgressUpdate(90, "");

                if (DoSleep)
                {
                    Thread.Sleep(100);
                }

                OnProgressUpdate(100, "Done");
                Thread.Sleep(50); // Let Eventhandler get the last OnProgressUpdate
            }
            catch (Exception ex)
            {
                OnError(ex);
                return(false);
            }

            new Installation(TapDir).AnnouncePackageChange();

            return(true);
        }