/// <summary> /// Copies files or directories from another implementation fetched by an external 0install process. /// </summary> /// <param name="builder">The builder.</param> /// <param name="metadata">The path of the source and destination file or directory.</param> /// <param name="handler">A callback object used when the the user needs to be informed about IO tasks.</param> /// <exception cref="UnauthorizedAccessException">Access to a resource was denied.</exception> /// <exception cref="IOException">An IO operation failed.</exception> public static void CopyFrom(this IBuilder builder, CopyFromStep metadata, ITaskHandler handler) { if (metadata.Implementation == null) { throw new ArgumentException($"Must call {nameof(IRecipeStep.Normalize)}() first.", nameof(metadata)); } handler.RunTask(new SimpleTask(string.Format(Resources.FetchingExternal, metadata.ID), () => ZeroInstallClient.Detect.FetchAsync(metadata.Implementation).Wait())); string path = ImplementationStores.Default().GetPath(metadata.Implementation); builder.CopyFrom(metadata, path, handler); }
/// <summary> /// Copies files or directories from another implementation. /// </summary> /// <param name="builder">The builder.</param> /// <param name="metadata">The path of the source and destination file or directory.</param> /// <param name="path">The path of the implementation referenced by <paramref name="metadata"/>.</param> /// <param name="handler">A callback object used when the the user needs to be informed about IO tasks.</param> /// <exception cref="UnauthorizedAccessException">Access to a resource was denied.</exception> /// <exception cref="IOException">An IO operation failed.</exception> public static void CopyFrom(this IBuilder builder, CopyFromStep metadata, string path, ITaskHandler handler) => handler.RunTask(new ReadDirectory(path, builder.BuildDirectory(metadata.Destination)));
/// <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)); } }