Skip to content

Commit

Permalink
Merge pull request #225 from NoxOrg/feature/copy-file-plugin
Browse files Browse the repository at this point in the history
Feature/copy file plugin
  • Loading branch information
jan-schutte committed May 8, 2024
2 parents bb7d96d + e4e8f82 commit 3205a31
Show file tree
Hide file tree
Showing 10 changed files with 333 additions and 11 deletions.
116 changes: 116 additions & 0 deletions src/Nox.Cli.Plugins/Nox.Cli.Plugin.File/FileCopyFile_v1.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
using Nox.Cli.Abstractions;
using Nox.Cli.Abstractions.Extensions;

namespace Nox.Cli.Plugin.File;

public class FileCopyFile_v1: INoxCliAddin
{
public NoxActionMetaData Discover()
{
return new NoxActionMetaData
{
Name = "file/copy-file@v1",
Author = "Jan Schutte",
Description = "Copy a file from one folder to another.",

Inputs =
{
["source-path"] = new NoxActionInput {
Id = "source-path",
Description = "The path to the file to copy",
Default = string.Empty,
IsRequired = true
},

["target-path"] = new NoxActionInput {
Id = "target-path",
Description = "The path of the folder into which to copy the source file",
Default = string.Empty,
IsRequired = true
},
["is-overwrite"] = new NoxActionInput {
Id = "is-overwrite",
Description = "Indicate whether the copy must overwrite the target file, if it exists.",
Default = false,
IsRequired = false
}
}
};
}

private string? _sourcePath;
private string? _targetPath;
private bool? _isOverwrite;

public Task BeginAsync(IDictionary<string,object> inputs)
{
_sourcePath = inputs.Value<string>("source-path");
_targetPath = inputs.Value<string>("target-path");
_isOverwrite = inputs.ValueOrDefault<bool>("is-overwrite", this);
return Task.CompletedTask;
}

public Task<IDictionary<string, object>> ProcessAsync(INoxWorkflowContext ctx)
{
var outputs = new Dictionary<string, object>();

ctx.SetState(ActionState.Error);

if (string.IsNullOrEmpty(_sourcePath) ||
string.IsNullOrEmpty(_targetPath))
{
ctx.SetErrorMessage("The File copy-file action was not initialized");
}
else
{
try
{
var fullSourcePath = Path.GetFullPath(_sourcePath);
var filename = Path.GetFileName(fullSourcePath);
if (!System.IO.File.Exists(fullSourcePath))
{
ctx.SetErrorMessage($"Source file: {fullSourcePath} does not exist!");
}
else
{
var isValid = true;
var fullTargetPath = Path.Combine(Path.GetFullPath(_targetPath), filename);
Directory.CreateDirectory(Path.GetDirectoryName(fullTargetPath)!);
var createDate = DateTime.Now;
if (System.IO.File.Exists(fullTargetPath))
{
if (_isOverwrite!.Value)
{
createDate = System.IO.File.GetCreationTime(fullTargetPath);
System.IO.File.Delete(fullTargetPath);
}
else
{
ctx.SetErrorMessage($"File: {fullTargetPath} already exists, and is-overwrite was not specified.");
isValid = false;
}

}
if (isValid)
{
System.IO.File.Copy(fullSourcePath, fullTargetPath);
System.IO.File.SetCreationTime(fullTargetPath, createDate);
ctx.SetState(ActionState.Success);
}
}

}
catch (Exception ex)
{
ctx.SetErrorMessage(ex.Message);
}
}

return Task.FromResult<IDictionary<string, object>>(outputs);
}

public Task EndAsync()
{
return Task.CompletedTask;
}
}
54 changes: 50 additions & 4 deletions src/Nox.Cli.Plugins/Nox.Cli.Plugin.File/FileCopyFolder_v1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,25 +35,34 @@ public NoxActionMetaData Discover()
Default = true,
IsRequired = false
},
["is-overwrite"] = new NoxActionInput {
Id = "is-overwrite",
Description = "Indicate whether the copy must overwrite the target path.",
Default = false,
IsRequired = false
}
}
};
}

private string? _sourcePath;
private string? _targetPath;
private bool? _isRecursive;
private bool? _isOverwrite;

public Task BeginAsync(IDictionary<string,object> inputs)
{
_sourcePath = inputs.Value<string>("source-path");
_targetPath = inputs.Value<string>("target-path");
_isRecursive = inputs.ValueOrDefault<bool>("is-recursive", this);
_isOverwrite = inputs.ValueOrDefault<bool>("is-overwrite", this);
return Task.CompletedTask;
}

public Task<IDictionary<string, object>> ProcessAsync(INoxWorkflowContext ctx)
{
var outputs = new Dictionary<string, object>();
var isValid = true;

ctx.SetState(ActionState.Error);

Expand All @@ -70,6 +79,7 @@ public Task<IDictionary<string, object>> ProcessAsync(INoxWorkflowContext ctx)
if (!Directory.Exists(fullSourcePath))
{
ctx.SetErrorMessage($"Folder {fullSourcePath} does not exist!");
isValid = false;
}
else
{
Expand All @@ -78,8 +88,24 @@ public Task<IDictionary<string, object>> ProcessAsync(INoxWorkflowContext ctx)
{
Directory.CreateDirectory(fullTargetPath);
}
CopyFiles(fullSourcePath, fullTargetPath);
ctx.SetState(ActionState.Success);
else
{
if (_isOverwrite!.Value)
{
PurgeFolder(fullTargetPath);
}
else
{
ctx.SetErrorMessage($"Folder {fullTargetPath} already exists, and is-overwrite was not specified.");
isValid = false;
}
}

if (isValid)
{
CopyFiles(fullSourcePath, fullTargetPath);
ctx.SetState(ActionState.Success);
}
}

}
Expand All @@ -103,10 +129,16 @@ private void CopyFiles(string sourceFolder, string targetFolder)

foreach (var file in di.GetFiles())
{
var targetFilePath = Path.Combine(targetFolder, file.Name);
if (System.IO.File.Exists(targetFilePath)) System.IO.File.Delete(targetFilePath);
var targetFilePath = Path.Combine(targetFolder, file.Name);
var createDate = DateTime.Now;
if (System.IO.File.Exists(targetFilePath))
{
createDate = System.IO.File.GetCreationTime(targetFilePath);
System.IO.File.Delete(targetFilePath);
}
Directory.CreateDirectory(targetFolder);
file.CopyTo(targetFilePath);
System.IO.File.SetCreationTime(targetFilePath, createDate);
}

if (_isRecursive == true)
Expand All @@ -117,4 +149,18 @@ private void CopyFiles(string sourceFolder, string targetFolder)
}
}
}

private void PurgeFolder(string path)
{
var di = new DirectoryInfo(path);
foreach (var file in di.GetFiles())
{
file.Delete();
}

foreach (var dir in di.GetDirectories())
{
dir.Delete(true);
}
}
}
11 changes: 6 additions & 5 deletions src/Nox.Cli.Variables/ClientVariableProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -217,15 +217,18 @@ private object ReplaceVariable(object value, bool isIfCondition = false, bool is
{
var result = value;

var match = _variableRegex.Match(result.ToString()!);
var matches = _variableRegex.Matches(result.ToString()!);

while (match.Success)
foreach (var match in matches.ToList())
{
var fullPhrase = match.Groups[0].Value;

var variable = match.Groups["variable"].Value;

if (isServer && _serverVariables.Contains(variable)) return result;
if (isServer && _serverVariables.Contains(variable))
{
continue;
}

var resolvedValue = LookupValue(variable);

Expand Down Expand Up @@ -259,8 +262,6 @@ private object ReplaceVariable(object value, bool isIfCondition = false, bool is
}
result = result.ToString()!.Replace(fullPhrase, "NULL");
}

match = _variableRegex.Match(result.ToString()!);
}

return result;
Expand Down
12 changes: 11 additions & 1 deletion src/Nox.Cli.Variables/ServerVariableProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,17 @@ private void ResolveServerVariables()
{
//Find the variable value
var lookupValue = LookupValue(match.Groups[2].Value);
if (lookupValue != null) item.Value = lookupValue;
if (lookupValue != null)
{
if (lookupValue is string)
{
item.Value = item.Value.ToString()!.Replace(match.Value, lookupValue.ToString());
}
else
{
item.Value = lookupValue;
}
}
}
}
}
Expand Down
102 changes: 102 additions & 0 deletions src/Plugin.File.Tests/CopyFileTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
using Moq;
using Nox.Cli.Abstractions.Caching;
using Nox.Cli.Actions;
using Nox.Cli.Configuration;
using Nox.Cli.Plugin.File;
using Nox.Cli.Variables.Secrets;
using Nox.Secrets.Abstractions;
using Nox.Solution;
using Xunit;

namespace Plugin.File.Tests;

public class CopyFileTests
{
[Fact]
public async Task Can_copy_a_File_if_destination_folder_does_not_exist()
{
var path = "./files/copy-file";
//Ensure the target folder does not exist
Helpers.PurgeFolderRecursive(Path.Combine(path, "new-target"), true);

var plugin = new FileCopyFile_v1();
var inputs = new Dictionary<string, object>
{
{"source-path", Path.Combine(path, "source/Sample.txt")},
{"target-path", Path.Combine(path, "new-target")}
};
await plugin.BeginAsync(inputs);
var wfConfig = new WorkflowConfiguration();
var sln = Mock.Of<NoxSolution>();
var orgResolver = Mock.Of<IOrgSecretResolver>();
var cacheMan = Mock.Of<INoxCliCacheManager>();
var lteConfig = Mock.Of<LocalTaskExecutorConfiguration>();
var secretsResolver = Mock.Of<INoxSecretsResolver>();
var ctx = new NoxWorkflowContext(wfConfig, sln, orgResolver, cacheMan, lteConfig, secretsResolver);
await plugin.ProcessAsync(ctx);
Assert.True(System.IO.File.Exists(Path.Combine(path, "new-target/Sample.txt")));
}

[Fact]
public async Task Must_not_copy_if_destination_folder_exists_and_overwrite_not_specified()
{
var path = "./files/copy-file";
//Ensure the target folder exists
Helpers.PurgeFolderRecursive(Path.Combine(path, "new-target"), true);
Directory.CreateDirectory(Path.Combine(path, "new-target"));
await System.IO.File.WriteAllTextAsync(Path.Combine(path, "new-target/Sample.txt"), "Hello World");

var plugin = new FileCopyFile_v1();
var inputs = new Dictionary<string, object>
{
{"source-path", Path.Combine(path, "source/Sample.txt")},
{"target-path", Path.Combine(path, "new-target")}
};
await plugin.BeginAsync(inputs);
var wfConfig = new WorkflowConfiguration();
var sln = Mock.Of<NoxSolution>();
var orgResolver = Mock.Of<IOrgSecretResolver>();
var cacheMan = Mock.Of<INoxCliCacheManager>();
var lteConfig = Mock.Of<LocalTaskExecutorConfiguration>();
var secretsResolver = Mock.Of<INoxSecretsResolver>();
var ctx = new NoxWorkflowContext(wfConfig, sln, orgResolver, cacheMan, lteConfig, secretsResolver);
await plugin.ProcessAsync(ctx);
await plugin.EndAsync();
Assert.True(System.IO.File.Exists(Path.Combine(path, "new-target/Sample.txt")));
var fileSize = new FileInfo(Path.Combine(path, "new-target/Sample.txt")).Length;
Assert.Equal(11, fileSize);
}

[Fact]
public async Task Can_copy_a_File_if_destination_folder_exists_and_overwrite_specified()
{
var path = "./files/copy-file";
//Ensure the target folder exists
Helpers.PurgeFolderRecursive(Path.Combine(path, "new-target"), true);
Directory.CreateDirectory(Path.Combine(path, "new-target"));
await System.IO.File.WriteAllTextAsync(Path.Combine(path, "new-target/Sample.txt"), "Hello World");

var plugin = new FileCopyFile_v1();
var inputs = new Dictionary<string, object>
{
{"source-path", Path.Combine(path, "source/Sample.txt")},
{"target-path", Path.Combine(path, "new-target")},
{"is-overwrite", true}
};
await plugin.BeginAsync(inputs);
var wfConfig = new WorkflowConfiguration();
var sln = Mock.Of<NoxSolution>();
var orgResolver = Mock.Of<IOrgSecretResolver>();
var cacheMan = Mock.Of<INoxCliCacheManager>();
var lteConfig = Mock.Of<LocalTaskExecutorConfiguration>();
var secretsResolver = Mock.Of<INoxSecretsResolver>();
var ctx = new NoxWorkflowContext(wfConfig, sln, orgResolver, cacheMan, lteConfig, secretsResolver);
await plugin.ProcessAsync(ctx);
await plugin.EndAsync();
Assert.True(System.IO.File.Exists(Path.Combine(path, "new-target/Sample.txt")));
var fileSize = new FileInfo(Path.Combine(path, "new-target/Sample.txt")).Length;
Assert.Equal(0, fileSize);
}


}
2 changes: 1 addition & 1 deletion src/Plugin.File.Tests/FolderRenameTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public async Task Can_Rename_a_Folder()

if (Directory.Exists(Path.Combine(path, "Sample-After")))
{
Directory.Delete(Path.Combine(path, "Sample-After"));
Helpers.PurgeFolderRecursive(Path.Combine(path, "Sample-After"), true);
}

CopyRecursively(Path.Combine(path, "Sample"), Path.Combine(path, "Sample-Before"));
Expand Down
Loading

0 comments on commit 3205a31

Please sign in to comment.