/// <summary> /// TODO: description /// </summary> /// <param name="targetPath"></param> /// <param name="content"></param> /// <param name="overwrite"></param> /// <param name="optional"></param> public AddAction(Path targetPath, Content content = null, bool overwrite = false, bool optional = false) { TargetPath = targetPath ?? throw new ArgumentNullException(nameof(targetPath)); Content = content; Overwrite = overwrite; Optional = optional; }
/// <summary> /// TODO: description /// </summary> /// <param name="context"></param> public void Run(ActionContext context = null) { if (!TargetPath.IsAbsolute && context?.BasePath == null) { throw new ArgumentException("The context BasePath must be specified when the TargetPath is relative.", nameof(context)); } try { // get the absolute path, rooted off of the context base path if necessary Path path = TargetPath.IsAbsolute ? TargetPath : Path.Combine(context.BasePath, TargetPath); Logger.Info("Deleting {0}", path); if (TargetPath.IsDirectory) { Directory.Delete(path, true); // TODO: support for remote paths } else { File.Delete(path); // 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; } } }
public void RelativePathTest() { Path path; path = new Path("file"); Assert.IsFalse(path.IsDirectory); Assert.IsFalse(path.IsAbsolute); path = new Path("/file"); Assert.IsFalse(path.IsDirectory); Assert.IsFalse(path.IsAbsolute); path = new Path("file.ext"); Assert.IsFalse(path.IsDirectory); Assert.IsFalse(path.IsAbsolute); path = new Path("/file.ext"); Assert.IsFalse(path.IsDirectory); Assert.IsFalse(path.IsAbsolute); path = new Path("directory/"); Assert.IsTrue(path.IsDirectory); Assert.IsFalse(path.IsAbsolute); path = new Path("/directory/"); Assert.IsTrue(path.IsDirectory); Assert.IsFalse(path.IsAbsolute); }
public void LocalPathTest() { Path path; path = new Path(@"C:\"); Assert.IsTrue(path.IsDirectory); Assert.IsTrue(path.IsAbsolute); path = new Path(@"C:\file"); Assert.IsFalse(path.IsDirectory); Assert.IsTrue(path.IsAbsolute); path = new Path(@"C:\file.ext"); Assert.IsFalse(path.IsDirectory); Assert.IsTrue(path.IsAbsolute); path = new Path(@"C:\directory\"); Assert.IsTrue(path.IsDirectory); Assert.IsTrue(path.IsAbsolute); // alternate separators are fine path = new Path(@"C:/directory/"); Assert.IsTrue(path.IsDirectory); Assert.IsTrue(path.IsAbsolute); }
/// <summary> /// TODO: description /// </summary> /// <param name="sourcePath"></param> /// <param name="targetPath"></param> /// <param name="overwrite"></param> /// <param name="optional"></param> public CopyAction(Path sourcePath, Path targetPath, bool overwrite = false, bool optional = false) { SourcePath = sourcePath ?? throw new ArgumentException(nameof(sourcePath)); TargetPath = targetPath ?? throw new ArgumentException(nameof(targetPath)); Overwrite = overwrite; Optional = optional; }
public void PackageCreateApplySerializeTest() { // create temp directories to be used during patching Path tempDirectory = Utility.GetTempDirectory(); Directory.CreateDirectory(tempDirectory); Path tempSourceCopyDirectory = Utility.GetTempDirectory(); Directory.CreateDirectory(tempSourceCopyDirectory); try { // create a new repo var repo = new Repository(); repo.Name = "Test Repo Name"; repo.Description = "Test Repo Description"; // generate package content Path sourceContentPath = Path.Combine(Environment.CurrentDirectory + "\\", "content\\source\\"); Path targetContentPath = Path.Combine(Environment.CurrentDirectory + "\\", "content\\target\\"); var settings = new PackageSettings(partSize: 40); // test multipart logic var package = new Package(repo, sourceContentPath, targetContentPath, tempDirectory, settings); package.Name = "Initial Update"; // update the source snapshot info package.SourceSnapshot.Name = "Test Original Name"; package.SourceSnapshot.Version = new Version("1.0.0.0"); // update the target snapshot info package.TargetSnapshot.Name = "Test Updated Name"; package.TargetSnapshot.Version = new Version("1.1.0.0"); // bind the new package to the repo repo.Packages.Add(package); // test serialization string json = repo.Serialize(); Repository testRepo = Repository.Deserialize(json); string json2 = testRepo.Serialize(); Assert.AreEqual(json, json2); // copy source directory to temp directory to patch against new Microsoft.VisualBasic.Devices.Computer().FileSystem.CopyDirectory(sourceContentPath, tempSourceCopyDirectory, true); // run the actions targeting the temp package directory package.Apply(Path.Combine(tempDirectory, package.Id + "\\"), tempSourceCopyDirectory); // find method tests (not comprehensive) Assert.AreEqual(repo.FindSnapshotFromDirectory(sourceContentPath), package.SourceSnapshot); Assert.AreEqual(repo.FindSnapshotFromDirectory(targetContentPath), package.TargetSnapshot); } finally { // clean up temp directories Directory.Delete(tempDirectory, true); Directory.Delete(tempSourceCopyDirectory, true); } }
/// <summary> /// TODO: description /// </summary> /// <param name="sourcePath"></param> /// <param name="targetPath"></param> /// <param name="algorithm"></param> /// <param name="content"></param> /// <param name="overwrite"></param> /// <param name="optional"></param> public PatchAction(Path sourcePath, Path targetPath, PatchAlgorithmType algorithm, Content content, bool overwrite = true, bool optional = false) { SourcePath = sourcePath ?? throw new ArgumentException(nameof(sourcePath)); TargetPath = targetPath ?? throw new ArgumentException(nameof(targetPath)); Algorithm = algorithm; Content = content ?? throw new ArgumentException(nameof(content)); Overwrite = overwrite; Optional = optional; }
/// <summary> /// TODO: description /// </summary> /// <param name="inputFile"></param> /// <param name="outputDirectory"></param> /// <param name="settings"></param> public Content(Path inputFile, Path outputDirectory, PackageSettings settings = null) { if (!File.Exists(inputFile)) { throw new FileNotFoundException("Unable to create content.", inputFile); } PackageSettings pkgSettings = settings ?? new PackageSettings(); Compressed = pkgSettings.CompressionEnabled; Path contentDirectory = Path.Combine(outputDirectory, Id + "\\"); Directory.CreateDirectory(contentDirectory); try { if (pkgSettings.CompressionEnabled) { string origPath = inputFile; inputFile = Utility.GetTempFilePath(); Utility.Compress(origPath, inputFile); } // break the file up into parts of specified chunk size using (FileStream fs = File.OpenRead(inputFile)) { long bytesCopied = 0; int fileIndex = 0; do { string fileName = $"{fileIndex}{pkgSettings.PartExtension}"; string path = Path.Combine(contentDirectory, fileName); long bytesToCopy = Math.Min(fs.Length - bytesCopied, pkgSettings.PartSize); using (var file = File.OpenWrite(path)) { fs.CopyToCount(file, bytesToCopy); } Parts.Add(new FileInformation(fileName, Utility.ComputeHash(path))); bytesCopied += bytesToCopy; fileIndex++; } while (bytesCopied < fs.Length); } } finally { if (pkgSettings.CompressionEnabled) { File.Delete(inputFile); } } }
/// <summary> /// TODO: description /// </summary> /// <param name="context"></param> public void Run(ActionContext context = null) { 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 (SourcePath.Equals(TargetPath)) { throw new NotSupportedException("The SourcePath cannot equal the TargetPath."); } if (SourcePath.IsDirectory != TargetPath.IsDirectory) { throw new NotSupportedException("Both the source and target paths must be of the same type."); } 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); // ensure that target directory path exists Directory.CreateDirectory(Path.GetDirectoryName(targetPath)); // TODO: support for remote paths Logger?.Info("Moving {0} to {1}", sourcePath, targetPath); if (SourcePath.IsDirectory) { Directory.Move(sourcePath, targetPath); // TODO: support for remote paths } else { File.Move(sourcePath, 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; } } }
/// <summary> /// TODO: description /// </summary> /// <param name="context"></param> public void Run(ActionContext context = null) { 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)); } try { // get the absolute path, rooted off of the context base path if necessary Path path = TargetPath.IsAbsolute ? TargetPath : Path.Combine(context.BasePath, TargetPath); Logger?.Info("Adding {0}", path); if (path.IsDirectory) { Directory.CreateDirectory(path); // TODO: support for remote paths } else if (File.Exists(path) && !Overwrite) { throw new IOException("File already exists and cannot be overwritten."); } else if (Content != null) { // TODO: remove trailing slash requirement for caller, handle that internally Content.Save(Path.Combine(context.ContentBasePath, Content.Id + "\\"), path, Overwrite); // TODO: specify remote content path format as part of context } else { // create an empty file File.Create(path).Dispose(); // 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; } } }
public void PathCombineTest() { Assert.AreEqual(Path.Combine("http://example.com/", "file"), new Path("http://example.com/file")); Assert.AreEqual(Path.Combine("http://example.com/directory/", "file"), new Path("http://example.com/directory/file")); Assert.AreEqual(Path.Combine("http://example.com/", "file.ext"), new Path("http://example.com/file.ext")); Assert.AreEqual(Path.Combine("http://example.com/directory/", "file.ext"), new Path("http://example.com/directory/file.ext")); // should assume first argument is a directory, even if no trailing slash is specified Assert.AreEqual(Path.Combine("http://example.com", "file"), new Path("http://example.com/file")); Assert.AreEqual(Path.Combine("http://example.com/directory", "file"), new Path("http://example.com/directory/file")); Assert.AreEqual(Path.Combine("http://example.com", "file.ext"), new Path("http://example.com/file.ext")); Assert.AreEqual(Path.Combine("http://example.com/directory", "file.ext"), new Path("http://example.com/directory/file.ext")); // TODO: null second arg }
/// <summary> /// Combines and saves content files into a single file. /// </summary> /// <param name="sourceDirectory">The directory which contains the content file(s).</param> /// <param name="outputFilePath">The path of the file to be created.</param> /// <param name="overwrite">Indicates whether or not overwriting an existing file is supported.</param> public void Save(Path sourceDirectory, Path outputFilePath, bool overwrite = false) { if (!Directory.Exists(sourceDirectory)) { throw new DirectoryNotFoundException("Invalid source directory."); } if (string.IsNullOrWhiteSpace(outputFilePath)) { throw new ArgumentException(nameof(outputFilePath)); } if (Parts.Count == 0) { throw new InvalidOperationException(); } if (File.Exists(outputFilePath) && !overwrite) { throw new IOException("Unable to overwrite file."); } // make sure output directory exists Directory.CreateDirectory(Path.GetDirectoryName(outputFilePath)); if (Compressed) { var compressedFile = Utility.GetTempFilePath(); try { // must assemble compressed file first, can't decompress against individual parts Utility.JoinFiles(sourceDirectory, compressedFile); Utility.Decompress(compressedFile, outputFilePath); } finally { File.Delete(compressedFile); } } else { Utility.JoinFiles(sourceDirectory, outputFilePath); } }
public void PathDirectoryNameTest() { Assert.IsNull(Path.GetDirectoryName(@"file")); Assert.IsNull(Path.GetDirectoryName(@"file.ext")); Assert.AreEqual(Path.GetDirectoryName(@"directory\"), new Path(@"directory\")); Assert.AreEqual(Path.GetDirectoryName(@"directory\file"), new Path(@"directory\")); Assert.AreEqual(Path.GetDirectoryName(@"directory\file.ext"), new Path(@"directory\")); Assert.AreEqual(Path.GetDirectoryName(@"C:\file"), new Path(@"C:\")); Assert.AreEqual(Path.GetDirectoryName(@"C:\file.ext"), new Path(@"C:\")); Assert.AreEqual(Path.GetDirectoryName(@"C:\directory\"), new Path(@"C:\directory\")); Assert.AreEqual(Path.GetDirectoryName(@"C:\directory\file"), new Path(@"C:\directory\")); Assert.AreEqual(Path.GetDirectoryName(@"C:\directory\file.ext"), new Path(@"C:\directory\")); Assert.AreEqual(Path.GetDirectoryName(@"http://example.com/file"), new Path(@"http://example.com/")); Assert.AreEqual(Path.GetDirectoryName(@"http://example.com/file.ext"), new Path(@"http://example.com/")); Assert.AreEqual(Path.GetDirectoryName(@"http://example.com/directory/"), new Path(@"http://example.com/directory/")); Assert.AreEqual(Path.GetDirectoryName(@"http://example.com/directory/file"), new Path(@"http://example.com/directory/")); Assert.AreEqual(Path.GetDirectoryName(@"http://example.com/directory/file.ext"), new Path(@"http://example.com/directory/")); }
public void PathFileNameTest() { Assert.AreEqual(Path.GetFileName(@"file"), new Path(@"file")); Assert.AreEqual(Path.GetFileName(@"file.ext"), new Path(@"file.ext")); Assert.IsNull(Path.GetFileName(@"directory\")); Assert.AreEqual(Path.GetFileName(@"directory\file"), new Path(@"file")); Assert.AreEqual(Path.GetFileName(@"directory\file.ext"), new Path(@"file.ext")); Assert.AreEqual(Path.GetFileName(@"C:\file"), new Path(@"file")); Assert.AreEqual(Path.GetFileName(@"C:\file.ext"), new Path(@"file.ext")); Assert.IsNull(Path.GetFileName(@"C:\directory\")); Assert.AreEqual(Path.GetFileName(@"C:\directory\file"), new Path(@"file")); Assert.AreEqual(Path.GetFileName(@"C:\directory\file.ext"), new Path(@"file.ext")); // TODO: convert the others to this format Assert.AreEqual("file", Path.GetFileName(@"http://example.com/file").Name); Assert.AreEqual("file.ext", Path.GetFileName(@"http://example.com/file.ext").Name); Assert.IsNull(Path.GetFileName(@"http://example.com/directory/")); Assert.AreEqual("file", Path.GetFileName(@"http://example.com/directory/file").Name); Assert.AreEqual("file.ext", Path.GetFileName(@"http://example.com/directory/file.ext").Name); }
public void UncPathTest() { Path path; path = new Path(@"\\localhost"); Assert.IsTrue(path.IsDirectory); Assert.IsTrue(path.IsAbsolute); path = new Path(@"\\localhost\"); Assert.IsTrue(path.IsDirectory); Assert.IsTrue(path.IsAbsolute); path = new Path(@"\\localhost\file"); Assert.IsFalse(path.IsDirectory); Assert.IsTrue(path.IsAbsolute); path = new Path(@"\\localhost\file.ext"); Assert.IsFalse(path.IsDirectory); Assert.IsTrue(path.IsAbsolute); path = new Path(@"\\localhost\directory\"); Assert.IsTrue(path.IsDirectory); Assert.IsTrue(path.IsAbsolute); }
public void HttpPathTest() { Path path; path = new Path(@"http://localhost"); Assert.IsTrue(path.IsDirectory); Assert.IsTrue(path.IsAbsolute); path = new Path(@"http://localhost/"); Assert.IsTrue(path.IsDirectory); Assert.IsTrue(path.IsAbsolute); path = new Path(@"http://localhost/file"); Assert.IsFalse(path.IsDirectory); Assert.IsTrue(path.IsAbsolute); path = new Path(@"http://localhost/file.ext"); Assert.IsFalse(path.IsDirectory); Assert.IsTrue(path.IsAbsolute); path = new Path(@"http://localhost/directory/"); Assert.IsTrue(path.IsDirectory); Assert.IsTrue(path.IsAbsolute); }
/// <summary> /// TODO: description /// </summary> /// <param name="targetPath"></param> /// <param name="optional"></param> public RemoveAction(Path targetPath, bool optional = false) { TargetPath = targetPath ?? throw new ArgumentException(nameof(targetPath)); Optional = optional; }
/// <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); } }