예제 #1
0
        /// <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);
            }
        }