/// <summary> /// TODO: description /// </summary> /// <param name="context"></param> public void Run(ActionContext context) { if (!SourcePath.IsAbsolute && context?.BasePath == null) { throw new ArgumentException("The context BasePath must be specified when the SourcePath is relative.", nameof(context)); } if (!TargetPath.IsAbsolute && context?.BasePath == null) { throw new ArgumentException("The context BasePath must be specified when the TargetPath is relative.", nameof(context)); } if (Content != null && context?.ContentBasePath == null) { throw new ArgumentException("The context ContentBasePath must be specified when working with Content.", nameof(context)); } if (SourcePath.IsDirectory || TargetPath.IsDirectory) { throw new NotSupportedException("Both the source and target paths must be files."); } string tempPatchPath = Utility.GetTempFilePath(); string tempTargetCopyPath = Utility.GetTempFilePath(); try { // get the absolute paths, rooted off of the context base path if necessary Path sourcePath = SourcePath.IsAbsolute ? SourcePath : Path.Combine(context.BasePath, SourcePath); Path targetPath = TargetPath.IsAbsolute ? TargetPath : Path.Combine(context.BasePath, TargetPath); Logger?.Info("Patching {0} against {1} to {2} using the {3} algorithm", sourcePath, tempPatchPath, targetPath, Algorithm); IPatcher patcher = Utility.GetPatcher(Algorithm); // write the patch file to a temp location Content.Save(Path.Combine(context.ContentBasePath, Content.Id + "\\"), tempPatchPath, Overwrite); // TODO: specify remote content path format as part of context // if source and target paths are the same, copy source to temp location first to patch against if (SourcePath.Equals(TargetPath)) { File.Copy(sourcePath, tempTargetCopyPath); // TODO: support for remote paths patcher.Apply(tempTargetCopyPath, tempPatchPath, targetPath); // TODO: support for remote paths } else { patcher.Apply(sourcePath, tempPatchPath, targetPath); // TODO: support for remote paths } } catch (Exception ex) { // swallow the exception and log a warning if optional, otherwise propagate upwards if (Optional) { Logger?.Warn(ex, "Optional action failure."); } else { throw; } } finally { File.Delete(tempPatchPath); File.Delete(tempTargetCopyPath); } }