Пример #1
0
        public void TestApplyRecipeCopyFrom()
        {
            using var existingImplDir = new TemporaryDirectory("0install-unit-tests");
            using var archiveFile     = new TemporaryFile("0install-unit-tests");
            new TestRoot
            {
                new TestDirectory("source")
                {
                    new TestFile("file"),
                    new TestFile("executable")
                    {
                        IsExecutable = true
                    },
                    new TestSymlink("symlink", "target")
                }
            }.Build(existingImplDir);

            typeof(ArchiveExtractorTest).CopyEmbeddedToFile("testArchive.zip", archiveFile);

            var downloadedFiles = new[] { archiveFile };
            var recipe          = new Recipe
            {
                Steps =
                {
                    new CopyFromStep
                    {
                        Source         = "source",
                        Destination    = "dest",
                        Implementation = new Implementation
                        {
                            ManifestDigest = new ManifestDigest(sha1New: "123")
                        }
                    },
                    new CopyFromStep
                    {
                        Source         = "source/file",
                        Destination    = "dest/symlink", // Overwrite existing symlink with regular file
                        Implementation = new Implementation
                        {
                            ManifestDigest = new ManifestDigest(sha1New: "123")
                        }
                    }
                }
            };

            using (FetchHandle.Register(_ => existingImplDir))
            {
                using var recipeDir = recipe.Apply(downloadedFiles, new SilentTaskHandler());
                new TestRoot
                {
                    new TestDirectory("dest")
                    {
                        new TestFile("file"),
                        new TestFile("executable")
                        {
                            IsExecutable = true
                        },
                        new TestFile("symlink")
                    }
                }.Verify(recipeDir);
            }

            FileUtils.DisableWriteProtection(existingImplDir);
            Directory.Delete(existingImplDir, recursive: true);
        }
Пример #2
0
        /// <summary>
        /// Applies a <see cref="CopyFromStep"/> to a <see cref="TemporaryDirectory"/>. <see cref="FetchHandle.Register"/> must be called first on the same thread.
        /// </summary>
        /// <param name="step">The <see cref="Archive"/> to apply.</param>
        /// <param name="workingDir">The <see cref="TemporaryDirectory"/> to apply the changes to.</param>
        /// <param name="handler">A callback object used when the the user needs to be informed about progress.</param>
        /// <param name="tag">A tag used to associate composite task with a specific operation; can be null.</param>
        /// <exception cref="IOException">A path specified in <paramref name="step"/> is illegal.</exception>
        /// <exception cref="ArgumentException"><see cref="CopyFromStep.Implementation"/> is <c>null</c>. Please call <see cref="Feed.ResolveInternalReferences"/> first.</exception>
        /// <exception cref="InvalidOperationException"><see cref="FetchHandle.Register"/> was not called first.</exception>
        public static void Apply(this CopyFromStep step, TemporaryDirectory workingDir, ITaskHandler handler, object?tag = null)
        {
            #region Sanity checks
            if (step == null)
            {
                throw new ArgumentNullException(nameof(step));
            }
            if (workingDir == null)
            {
                throw new ArgumentNullException(nameof(workingDir));
            }
            if (handler == null)
            {
                throw new ArgumentNullException(nameof(handler));
            }
            #endregion

            string source      = FileUtils.UnifySlashes(step.Source ?? "");
            string destination = FileUtils.UnifySlashes(step.Destination ?? "");
            if (FileUtils.IsBreakoutPath(source))
            {
                throw new IOException(string.Format(Resources.RecipeInvalidPath, source));
            }
            if (FileUtils.IsBreakoutPath(destination))
            {
                throw new IOException(string.Format(Resources.RecipeInvalidPath, destination));
            }

            if (step.Implementation == null)
            {
                throw new ArgumentException(string.Format(Resources.UnableToResolveRecipeReference, step, ""));
            }

            string sourcePath = Path.Combine(FetchHandle.Use(step.Implementation), source);
            if (Directory.Exists(sourcePath))
            {
                handler.RunTask(new CloneDirectory(sourcePath, workingDir)
                {
                    TargetSuffix = destination,
                    UseHardlinks = true,
                    Tag          = tag
                });
            }
            else if (File.Exists(sourcePath))
            {
                if (string.IsNullOrEmpty(destination))
                {
                    throw new IOException(string.Format(Resources.RecipeCopyFromDestinationMissing, step));
                }
                handler.RunTask(new CloneFile(sourcePath, workingDir)
                {
                    TargetSuffix   = Path.GetDirectoryName(destination),
                    TargetFileName = Path.GetFileName(destination),
                    UseHardlinks   = true,
                    Tag            = tag
                });
            }
            else
            {
                throw new IOException(string.Format(Resources.RecipeCopyFromSourceMissing, step));
            }
        }