Esempio n. 1
0
        /// <summary>
        /// Exports all implementations listed in a <see cref="Selections"/> document as archives.
        /// </summary>
        /// <param name="implementationStore">Used to get cached implementations.</param>
        /// <param name="handler">A callback object used when the the user needs to be asked questions or informed about download and IO tasks.</param>
        /// <exception cref="OperationCanceledException">The user canceled the task.</exception>
        /// <exception cref="UnauthorizedAccessException">The file could not be read or written.</exception>
        /// <exception cref="UnauthorizedAccessException">Write access to the directory is not permitted.</exception>
        /// <exception cref="IOException">An implementation archive could not be creates.</exception>
        public void ExportImplementations(IImplementationStore implementationStore, ITaskHandler handler)
        {
            if (implementationStore == null)
            {
                throw new ArgumentNullException(nameof(implementationStore));
            }
            if (handler == null)
            {
                throw new ArgumentNullException(nameof(handler));
            }

            string contentDir = Path.Combine(_destination, "content");

            Directory.CreateDirectory(contentDir);

            foreach (var digest in _selections.Implementations.Select(x => x.ManifestDigest).Where(x => x.Best != null).Distinct())
            {
                string?sourcePath = implementationStore.GetPath(digest);
                if (sourcePath == null)
                {
                    Log.Warn("Implementation " + digest + " missing from cache");
                    continue;
                }

                using var generator = ArchiveGenerator.Create(sourcePath, Path.Combine(contentDir, digest.Best + ".tbz2"), Archive.MimeTypeTarBzip);
                handler.RunTask(generator);
            }
        }
Esempio n. 2
0
    /// <summary>
    /// Exports all implementations listed in a <see cref="Selections"/> document as archives.
    /// </summary>
    /// <param name="implementationStore">Used to get cached implementations.</param>
    /// <param name="handler">A callback object used when the the user needs to be asked questions or informed about download and IO tasks.</param>
    /// <exception cref="OperationCanceledException">The user canceled the task.</exception>
    /// <exception cref="IOException">An implementation archive could not be created.</exception>
    /// <exception cref="UnauthorizedAccessException">Read or access to a file is not permitted.</exception>
    public void ExportImplementations(IImplementationStore implementationStore, ITaskHandler handler)
    {
        #region Sanity checks
        if (implementationStore == null)
        {
            throw new ArgumentNullException(nameof(implementationStore));
        }
        if (handler == null)
        {
            throw new ArgumentNullException(nameof(handler));
        }
        #endregion

        foreach (var digest in _selections.Implementations.Select(x => x.ManifestDigest).Where(x => x.Best != null).Distinct())
        {
            string?sourcePath = implementationStore.GetPath(digest);
            if (sourcePath == null)
            {
                Log.Warn($"Implementation {digest} missing from cache");
                continue;
            }

            using var builder = ArchiveBuilder.Create(Path.Combine(_contentDir, digest.Best + ".tgz"), Archive.MimeTypeTarGzip);
            handler.RunTask(new ReadDirectory(sourcePath, builder));
        }
    }
        /// <summary>
        /// Determines the local path of an implementation.
        /// </summary>
        /// <param name="implementationStore">The store to get the implementation from.</param>
        /// <param name="implementation">The implementation to be located.</param>
        /// <returns>A fully qualified path to the directory containing the implementation.</returns>
        /// <exception cref="ImplementationNotFoundException">The <paramref name="implementation"/> is not cached yet.</exception>
        /// <exception cref="UnauthorizedAccessException">Read access to the store is not permitted.</exception>
        public static string GetPath(this IImplementationStore implementationStore, ImplementationBase implementation)
        {
            #region Sanity checks
            if (implementationStore == null)
            {
                throw new ArgumentNullException(nameof(implementationStore));
            }
            if (implementation == null)
            {
                throw new ArgumentNullException(nameof(implementation));
            }
            #endregion

            if (string.IsNullOrEmpty(implementation.LocalPath))
            {
                string?path = implementationStore.GetPath(implementation.ManifestDigest);
                if (path == null)
                {
                    throw new ImplementationNotFoundException(implementation.ManifestDigest);
                }
                return(path);
            }
            else
            {
                return(implementation.LocalPath);
            }
        }
        /// <summary>
        /// Determines the command-line needed to execute an <see cref="ImplementationSelection"/>. Recursively handles <see cref="Runner"/>s.
        /// </summary>
        /// <param name="implementation">The implementation to launch.</param>
        /// <param name="commandName">The name of the <see cref="Command"/> within the <paramref name="implementation"/> to launch.</param>
        /// <exception cref="KeyNotFoundException"><see cref="Selections"/> points to missing <see cref="Dependency"/>s.</exception>
        /// <exception cref="ImplementationNotFoundException">An <see cref="Implementation"/> is not cached yet.</exception>
        /// <exception cref="ExecutorException">A <see cref="Command"/> contained invalid data.</exception>
        /// <exception cref="IOException">A problem occurred while writing a file.</exception>
        /// <exception cref="UnauthorizedAccessException">Write access to a file is not permitted.</exception>
        private List <ArgBase> GetCommandLine(ImplementationSelection implementation, string commandName)
        {
            #region Sanity checks
            if (implementation == null)
            {
                throw new ArgumentNullException(nameof(implementation));
            }
            if (commandName == null)
            {
                throw new ArgumentNullException(nameof(commandName));
            }
            #endregion

            Debug.Assert(_selections != null);

            if (commandName.Length == 0)
            {
                throw new ExecutorException(string.Format(Resources.CommandNotSpecified, implementation.InterfaceUri));
            }
            var command = implementation[commandName];
            Debug.Assert(command != null);

            // Apply bindings implementations use to find themselves and their dependencies
            ApplyBindings(command, implementation);
            if (command.WorkingDir != null)
            {
                ApplyWorkingDir(command.WorkingDir, implementation);
            }
            ApplyDependencyBindings(command);

            List <ArgBase> commandLine;
            var            runner = command.Runner;
            if (runner == null)
            {
                commandLine = new List <ArgBase>();
            }
            else
            {
                commandLine = GetCommandLine(_selections[runner.InterfaceUri], runner.Command ?? Command.NameRun);
                commandLine.AddRange(runner.Arguments);
            }

            if (!string.IsNullOrEmpty(command.Path))
            {
                string path = FileUtils.UnifySlashes(command.Path);

                // Fully qualified paths are used by package/native implementations, usually relative to the implementation
                commandLine.Add(Path.IsPathRooted(path) ? path : Path.Combine(_implementationStore.GetPath(implementation), path));
            }
            commandLine.AddRange(command.Arguments);

            return(commandLine);
        }
Esempio n. 5
0
        /// <summary>
        /// Determines the local path of an implementation.
        /// </summary>
        /// <param name="implementation">The implementation to be located.</param>
        /// <returns>A fully qualified path to the directory containing the implementation; <c>null</c> if the requested implementation could not be found in the store or is a package implementation.</returns>
        protected string?GetPathSafe(ImplementationBase implementation)
        {
            #region Sanity checks
            if (implementation == null)
            {
                throw new ArgumentNullException(nameof(implementation));
            }
            #endregion

            if (implementation.ID.StartsWith(ExternalImplementation.PackagePrefix))
            {
                return(null);
            }

            _implementationStore.Flush();
            return(_implementationStore.GetPath(implementation.ManifestDigest));
        }
        /// <summary>
        /// Wrapper for <see cref="IImplementationStore.GetPath"/>, handling exceptions.
        /// </summary>
        public static string?GetPathSafe(this IImplementationStore implementationStore, ManifestDigest manifestDigest)
        {
            #region Sanity checks
            if (implementationStore == null)
            {
                throw new ArgumentNullException(nameof(implementationStore));
            }
            #endregion

            try
            {
                return(implementationStore.GetPath(manifestDigest));
            }
            #region Error handling
            catch (UnauthorizedAccessException)
            {
                return(null);
            }
            #endregion
        }
Esempio n. 7
0
    /// <summary>
    /// Creates a new implementation node.
    /// </summary>
    /// <param name="digest">The digest identifying the implementation.</param>
    /// <param name="implementationStore">The <see cref="IImplementationStore"/> the implementation is located in.</param>
    /// <exception cref="FormatException">The manifest file is not valid.</exception>
    /// <exception cref="IOException">The manifest file could not be read.</exception>
    /// <exception cref="UnauthorizedAccessException">Read access to the file is not permitted.</exception>
    protected ImplementationNode(ManifestDigest digest, IImplementationStore implementationStore)
        : base(implementationStore)
    {
        #region Sanity checks
        if (implementationStore == null)
        {
            throw new ArgumentNullException(nameof(implementationStore));
        }
        #endregion

        _digest = digest;

        // Determine the total size of an implementation via its manifest file
        string?path = implementationStore.GetPath(digest);
        if (path == null)
        {
            return;
        }
        string manifestPath = System.IO.Path.Combine(path, Manifest.ManifestFile);
        Size = Manifest.Load(manifestPath, ManifestFormat.FromPrefix(digest.AvailableDigests.First())).TotalSize;
    }
    /// <inheritdoc/>
    public NamedCollection <SelectionsTreeNode> GetTree(Selections selections)
    {
        #region Sanity checks
        if (selections == null)
        {
            throw new ArgumentNullException(nameof(selections));
        }
        #endregion

        var visited = new HashSet <FeedUri>();
        var result  = new NamedCollection <SelectionsTreeNode>();

        ImplementationSelection?TryGetImplementation(IInterfaceUri target)
        {
            try
            {
                return(selections[target.InterfaceUri]);
            }
            catch (KeyNotFoundException)
            {
                return(null);
            }
        }

        string?GetPath(ImplementationBase implementation)
        => implementation.LocalPath
        ?? (implementation.ID.StartsWith(ExternalImplementation.PackagePrefix)
                   ? "(" + implementation.ID + ")"
                   : _implementationStore.GetPath(implementation.ManifestDigest));

        void AddNodes(IInterfaceUri target, SelectionsTreeNode?parent)
        {
            // Prevent infinite recursion
            if (visited.Contains(target.InterfaceUri))
            {
                return;
            }
            visited.Add(target.InterfaceUri);

            var implementation = TryGetImplementation(target);

            var node = new SelectionsTreeNode(
                target.InterfaceUri,
                implementation?.Version,
                (implementation == null) ? null : GetPath(implementation),
                parent);

            result.Add(node);
            if (implementation == null)
            {
                return;
            }

            // Recurse into regular dependencies
            foreach (var dependency in implementation.Dependencies)
            {
                AddNodes(dependency, parent: node);
            }

            foreach (var command in implementation.Commands)
            {
                // Recurse into command dependencies
                foreach (var dependency in command.Dependencies)
                {
                    AddNodes(dependency, parent: node);
                }

                // Recurse into runner dependency
                if (command.Runner != null)
                {
                    AddNodes(command.Runner, parent: node);
                }
            }
        }

        AddNodes(selections, parent: null);
        return(result);
    }