Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/SenseNet.IO.CLI/AppArgumentModels.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ public enum Verb
{
Export,
Import,
ImportXml,
Copy,
CopyXml,
Sync,
Transfer
};
Expand All @@ -30,13 +32,27 @@ public class ImportArguments : IAppArguments
public RepositoryWriterArgs WriterArgs { get; set; }
}

public class ImportXmlArguments : IAppArguments
{
public Verb Verb => Verb.ImportXml;
public FsXmlReaderArgs ReaderArgs { get; set; }
public RepositoryWriterArgs WriterArgs { get; set; }
}

public class CopyArguments : IAppArguments
{
public Verb Verb => Verb.Copy;
public FsReaderArgs ReaderArgs { get; set; }
public FsWriterArgs WriterArgs { get; set; }
}

public class CopyXmlArguments : IAppArguments
{
public Verb Verb => Verb.CopyXml;
public FsXmlReaderArgs ReaderArgs { get; set; }
public FsWriterArgs WriterArgs { get; set; }
}

public class SyncArguments : IAppArguments
{
public Verb Verb => Verb.Sync;
Expand Down
59 changes: 57 additions & 2 deletions src/SenseNet.IO.CLI/ArgumentParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ public class ArgumentParser
public IAppArguments Parse(string[] args)
{
if (args.Length == 0)
throw new ArgumentParserException("Missing verb (EXPORT, IMPORT, COPY, SYNC or TRANSFER)");
throw new ArgumentParserException("Missing verb (EXPORT, IMPORT, IMPORTXML, COPY, COPYXML, SYNC or TRANSFER)");
if (!Enum.TryParse<Verb>(args[0], true, out var verb))
throw new ArgumentParserException($"Invalid verb '{args[0]}'. Valid values are EXPORT, IMPORT, COPY, SYNC or TRANSFER");
throw new ArgumentParserException($"Invalid verb '{args[0]}'. Valid values are EXPORT, IMPORT, IMPORTXML, COPY, COPYXML, SYNC or TRANSFER");

var sourceSection = args
.SkipWhile(x => !x.Equals("-source", Cmp))
Expand Down Expand Up @@ -46,12 +46,24 @@ protected virtual IAppArguments ParseByVerb(Verb verb, string[] sourceArgs, stri
ReaderArgs = ParseFsReaderArgs(sourceArgs),
WriterArgs = ParseRepositoryWriterArgs(targetArgs)
};
case Verb.ImportXml:
return new ImportXmlArguments
{
ReaderArgs = ParseFsXmlReaderArgs(sourceArgs),
WriterArgs = ParseRepositoryWriterArgs(targetArgs)
};
case Verb.Copy:
return new CopyArguments
{
ReaderArgs = ParseFsReaderArgs(sourceArgs),
WriterArgs = ParseFsWriterArgs(targetArgs)
};
case Verb.CopyXml:
return new CopyXmlArguments
{
ReaderArgs = ParseFsXmlReaderArgs(sourceArgs),
WriterArgs = ParseFsWriterArgs(targetArgs)
};
case Verb.Sync:
return new SyncArguments
{
Expand Down Expand Up @@ -254,6 +266,49 @@ protected virtual RepositoryWriterArgs ParseRepositoryWriterArgs(string[] args)
return result;
}

protected virtual FsXmlReaderArgs ParseFsXmlReaderArgs(string[] args)
{
// [[-PATH] Path] [[-SKIP] PathList] [[-EXCLUDEFIELDS] FieldList]
var result = new FsXmlReaderArgs();
var parsedArgs = ParseSequence(args);

if (parsedArgs.Length > 3)
throw new ArgumentParserException("Too many FsXmlReader arguments.");

foreach (var arg in parsedArgs)
{
if (arg.Key == "0" || arg.Key.Equals("PATH", Cmp))
{
if (result.Path != null)
throw new ArgumentParserException("Invalid FsXmlReader arguments.");
if(arg.Value == null)
throw new ArgumentParserException("Invalid FsXmlReader arguments. Missing path.");
result.Path = arg.Value;
}
else if (arg.Key == "1" || arg.Key.Equals("SKIP", Cmp))
{
if (result.Skip != null)
throw new ArgumentParserException("Invalid FsXmlReader arguments.");
result.Skip = arg.Value
.Split(",;".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)
.Select(x=>x.Trim())
.ToArray();
}
else if (arg.Key == "2" || arg.Key.Equals("EXCLUDEFIELDS", Cmp))
{
if (result.ExcludedFields != null)
throw new ArgumentParserException("Invalid FsXmlReader arguments.");
result.ExcludedFields = arg.Value
.Split(",;".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)
.Select(x=>x.Trim())
.ToArray();
}
else
throw new ArgumentParserException("Unknown FsXmlReader argument: " + arg.Key);
}
return result;
}

private string[] _boolSwitches = new[] {"FLATTEN"};
private KeyValuePair<string, string>[] ParseSequence(string[] args)
{
Expand Down
10 changes: 10 additions & 0 deletions src/SenseNet.IO.CLI/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,16 @@ public static void RewriteSettings(this FsReaderArgs args, FsReaderArgs settings
if (args.Skip != null)
settings.Skip = args.Skip;
}
public static void RewriteSettings(this FsXmlReaderArgs args, FsXmlReaderArgs settings)
{
// rewrite from command line args (they override config file values)
if (args.Path != null)
settings.Path = args.Path;
if (args.Skip != null)
settings.Skip = args.Skip;
if (args.ExcludedFields != null)
settings.ExcludedFields = args.ExcludedFields;
}
public static void RewriteSettings(this FsWriterArgs args, FsWriterArgs settings)
{
// workaround for "Null configuration elements deserialized as empty strings" https://github.com/dotnet/runtime/issues/36510
Expand Down
46 changes: 45 additions & 1 deletion src/SenseNet.IO.CLI/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,30 @@ private static IHost CreateHost(string[] args, Stream settingsFile = null)
})
;
break;
case Verb.ImportXml:
var importXmlArgs = (ImportXmlArguments) appArguments;
serviceCollection
.Configure<FsXmlReaderArgs>(readerArgs =>
{
hostBuilderContext.Configuration.GetSection("fsXmlReader")
.Bind(readerArgs);
importXmlArgs.ReaderArgs.RewriteSettings(readerArgs);
})
.AddTransient<IFilesystemReader, FsXmlReader>()
.AddSenseNetIO(configureRepositoryWriter: writerArgs =>
{
hostBuilderContext.Configuration.GetSection("repositoryWriter").Bind(writerArgs);
importXmlArgs.WriterArgs.RewriteSettings(writerArgs);
})
.AddContentFlow<FsXmlReader, RepositoryWriter>()
.ConfigureSenseNetRepository("target", options =>
{
hostBuilderContext.Configuration.GetSection("repositoryWriter").Bind(options);
//update from command line
importXmlArgs.WriterArgs.RewriteSettings(options);
})
;
break;
case Verb.Copy:
var copyArgs = (CopyArguments) appArguments;
serviceCollection
Expand All @@ -153,6 +177,24 @@ private static IHost CreateHost(string[] args, Stream settingsFile = null)
.AddContentFlow<FsReader, FsWriter>()
;
break;
case Verb.CopyXml:
var copyXmlArgs = (CopyXmlArguments) appArguments;
serviceCollection
.Configure<FsXmlReaderArgs>(readerArgs =>
{
hostBuilderContext.Configuration.GetSection("fsXmlReader")
.Bind(readerArgs);
copyXmlArgs.ReaderArgs.RewriteSettings(readerArgs);
})
.AddTransient<IFilesystemReader, FsXmlReader>()
.AddSenseNetIO(configureFilesystemWriter: writerArgs =>
{
hostBuilderContext.Configuration.GetSection("fsWriter").Bind(writerArgs);
copyXmlArgs.WriterArgs.RewriteSettings(writerArgs);
})
.AddContentFlow<FsXmlReader, FsWriter>()
;
break;
case Verb.Sync:
var syncArgs = (SyncArguments) appArguments;
serviceCollection
Expand Down Expand Up @@ -218,7 +260,9 @@ private static string GetCustomConfigurationPath(ref string[] args)
for (int i = 0; i < args.Length; i++)
{
if (args[i].Equals("-CONFIGURATION", StringComparison.OrdinalIgnoreCase) ||
args[i].Equals("-CONFIG", StringComparison.OrdinalIgnoreCase))
args[i].Equals("-CONFIG", StringComparison.OrdinalIgnoreCase) ||
args[i].Equals("--CONFIGURATION", StringComparison.OrdinalIgnoreCase) ||
args[i].Equals("--CONFIG", StringComparison.OrdinalIgnoreCase))
{
if (i >= args.Length - 1)
throw new ArgumentException("Missing configuration path");
Expand Down
Loading