| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.ComponentModel.Design;
- using System.IO.Abstractions;
- using System.Linq;
- using BO.AppServer.Metadata.Dto;
- using BO.AppServer.Metadata.Enums;
- using BO.Console.Commands.Base;
- using BO.Console.Commands.Workspace.Sync;
- using BO.Console.Commands.Workspace.Sync.Diff;
- using Quadarax.Foundation.Core.Data.Diff;
- using Quadarax.Foundation.Core.IO;
- using Quadarax.Foundation.Core.QConsole;
- using Quadarax.Foundation.Core.QConsole.Argument;
- using Quadarax.Foundation.Core.QConsole.Attributes;
- using Quadarax.Foundation.Core.QConsole.Value;
- using Quadarax.Foundation.Core.Value;
- namespace BO.Console.Commands.Workspace
- {
- [CommandDefinition]
- internal class WorkspaceSyncCommand : AbstractWorkspaceCommand
- {
- #region *** Constants ***
- private const string CS_NEW_IN = ".in";
- private const string CS_NEW_OUT = ".out";
- private const string CS_NOTES = "Directory structure:\n" +
- "["+CS_NEW_IN + "]\t- new artifacts directory for Input type\n" +
- "\t\t<doc_name>.<artifact_name>.<artifact_ext> - new artifacts file\n" +
- "\t\t...\n" +
- "[" +CS_NEW_OUT + "]\t- new artifacts directory for Output type\n" +
- "[<documentId:8>.<document_name_normalized>]\t- document directory\n" +
- "\t\t<arifact_id>.<artifact_type>.<artifact_name>.<artifaxt_ext> - artifact file\n" +
- "\t\t...\n" +
- "...\n" +
- "\n" +
- "Process sequence:\n" +
- "0. If init flag set, sync clean directory\n" +
- "1. Get workspace documents with artifacts -> srv_arts\n" +
- "2. Get sync directory documents with artifacts (skip not well formatted, process incomming also) -> loac_arts\n" +
- "3. Resolve differences srv_arts and loc_ars -> changed_arts\n" +
- "4. Push changes changed_arts to database (if delete flag set removes documents in database)\n" +
- "5. Pull changes changed_arts from database (if delete flag set removes documents in sync directory)\n" +
- "6. Cleanup incommings\n" +
- "7. If repeat set go to step 1.\n";
- private const string CS_CMD_WRKSPSYNC_NAME = "workspace_sync";
- private const string CS_CMD_WRKSPSYNC_DESCR = "Download or upload documents from local directory from/to workspace. Can be run as contignous process.";
- private const string CS_ARG_NAME_DIR = "directory";
- private const string CS_ARG_HINT_DIR = "<sync_directory>";
- private const string CS_ARG_DESC_DIR = "Defines sync directory, if not defined workspace directory will be created as workspace name.";
- private const string CS_ARG_NAME_WD = "repeat";
- private const string CS_ARG_HINT_WD = "<is_repeat>";
- private const string CS_ARG_DESC_WD = "Flag if defined, enables contignous monitoring on sync directory for changes. If not defined process will be run once.";
- private const string CS_ARG_NAME_DELETE = "delete";
- private const string CS_ARG_HINT_DELETE = "<is_delete_allowed>";
- private const string CS_ARG_DESC_DELETE = "Flag if defined, deletes documents in application server when document is deleted in sync directory.";
- private const string CS_ARG_NAME_INIT = "init";
- private const string CS_ARG_HINT_INIT = "<is_initialization>";
- private const string CS_ARG_DESC_INIT = "Flag if defined, reset sync directory during initialization (all content in sync directory will be deleted on start).";
- private const string CS_ARG_NAME_INT = "interval";
- private const string CS_ARG_HINT_INT = "<repeat_interval>";
- private const string CS_ARG_DESC_INT = "Timespan interval between two iterations. Default is 00:30:00.";
- #endregion
- #region *** Properties ***
- public override string Name => CS_CMD_WRKSPSYNC_NAME;
- public override string Description => CS_CMD_WRKSPSYNC_DESCR;
- public override string Notes => CS_NOTES;
- private string SyncDir { get; set; }
- private bool IsRepeat { get; set; }
- private bool IsInit { get; set; }
- private bool IsDeleteAllowed { get; set; }
- private TimeSpan Interval { get; set; }
- #endregion
- #region *** Constructor ***
- public WorkspaceSyncCommand(Engine engine) : base(engine)
- {
- }
- #endregion
- #region *** EXECUTE ***
- protected override Result OnExecute()
- {
- bool isExitSignal = false;
- int nCnt = 0;
- while (!isExitSignal)
- {
- if (!IsRepeat)
- isExitSignal = true;
- var workspace = Client.GetWorkspaceAsync(WorkspaceIdentificationTypeEnum.ApiKey, ApiKey).Result;
- if (workspace == null)
- return new Result(new Exception($"Workspace with API-KEY: {ApiKey} not found."));
- var documents = Client.GetWorkspaceDocumentsAsync(DocumentsScopeEnums.All, ApiKey, ApiKeyPassword, UserName).Result;
- var dirInfo = OpenDirectory(workspace);
- var factory = new DocumentEntryComparer();
- foreach (var dir in dirInfo.EnumerateDirectories())
- {
- if (string.Equals(dir.Name, CS_NEW_IN, StringComparison.CurrentCultureIgnoreCase))
- {
- foreach (var file in dir.GetFiles())
- factory.AddLocalDocumentNew(file.Name,true);
- continue;
- }
- if (string.Equals(dir.Name, CS_NEW_OUT, StringComparison.CurrentCultureIgnoreCase))
- {
- foreach (var file in dir.GetFiles())
- factory.AddLocalDocumentNew(file.Name,false);
- continue;
- }
- if (factory.ValidateDocumentDirectory(dir.Name))
- {
- foreach (var file in dir.GetFiles())
- {
- if (factory.ValidateArtifactFileName(file.Name))
- {
- factory.AddLocalDocument(dir.Name, file.Name, file.Length);
- }
- else
- {
- WriteWarning($"Invalid artifact file '{file.Name}' name format! Expects '<arifact_id>.<artifact_type>.<artifact_name>.<artifaxt_ext>'. Skip");
- }
- }
- }
- else
- {
- WriteWarning($"Invalid document directory '{dir.Name}' name format! Expects '<documentId:8>.<document_name_normalized>'. Skip");
- }
- }
- foreach (var document in documents)
- {
- factory.AddRemoteDocument(document);
- }
- var diff = factory.GetComparator();
- var locals = diff.CompareLeftSide().Where(x => x.CompareState != DiffEntry.CompareStateEnum.Equals);
- foreach (var local in locals)
- {
- var item = local.GetItem<DocumentItem>();
- if (local.CompareState == DiffEntry.CompareStateEnum.CurrentNull ||
- local.CompareState == DiffEntry.CompareStateEnum.CurrentSmaller)
- {
- WriteInfo($"Artifact '{item.ArtName}' will be downloaded");
- }
- else if (local.CompareState == DiffEntry.CompareStateEnum.CurrentGrater ||
- local.CompareState == DiffEntry.CompareStateEnum.OtherNull)
- {
- WriteInfo($"Artifact '{item.ArtName}' will be uploaded");
- }
- }
- }
-
- return new Result();
- }
- private IDirectoryInfo OpenDirectory(WorkspaceRDto workspace)
- {
- if (workspace == null)
- throw new ArgumentNullException(nameof(workspace));
- if (string.IsNullOrEmpty(SyncDir))
- {
- // Current dir
- SyncDir = FileSystem.Path.Combine(FileSystem.Directory.GetCurrentDirectory(), FileUtils.SanitizedFileName(FileSystem, workspace.Name));
- }
- if (IsInit)
- {
- if (FileSystem.Directory.Exists(SyncDir))
- {
- FileSystem.Directory.Delete(SyncDir,true);
- WriteDebugInfo($"Directory '{SyncDir}' deleted due 'init' mode.");
- }
- IsInit = false;
- }
- if (!FileSystem.Directory.Exists(SyncDir))
- {
- FileSystem.Directory.CreateDirectory(SyncDir);
- WriteInfo($"Sync directory '{SyncDir}' created.");
- var inDir = FileSystem.Path.Combine(SyncDir, CS_NEW_IN);
- FileSystem.Directory.CreateDirectory(inDir);
- WriteDebugInfo($"Directory '{inDir}' created.");
- inDir = FileSystem.Path.Combine(SyncDir, CS_NEW_OUT);
- FileSystem.Directory.CreateDirectory(inDir);
- WriteDebugInfo($"Directory '{inDir}' created.");
- }
- var di = FileSystem.DirectoryInfo.FromDirectoryName(SyncDir);
- WriteCaption($"Sync directory '{SyncDir}' opened.");
- return di;
- }
- #endregion
- #region *** Private operations ***
- protected override void OnValidateArguments()
- {
- base.OnValidateArguments();
- SyncDir = GetArgumentValueOrDefault<string>(CS_ARG_NAME_DIR);
- IsRepeat = GetArgumentValueOrDefault<bool>(CS_ARG_NAME_WD);
- IsInit = GetArgumentValueOrDefault<bool>(CS_ARG_NAME_INIT);
- IsDeleteAllowed = GetArgumentValueOrDefault<bool>(CS_ARG_NAME_DELETE);
- Interval = GetArgumentValueOrDefault<TimeSpan>(CS_ARG_NAME_INT);
- }
- protected override IEnumerable<AbstractArgument> OnSetupArguments()
- {
- var args = base.OnSetupArguments().ToList();
- args.Add(new NamedArgument(CS_ARG_NAME_DIR, CS_ARG_DESC_DIR, CS_ARG_HINT_DIR, TypeValuesEnum.String, string.Empty, false));
- args.Add(new FlagArgument(CS_ARG_NAME_WD, CS_ARG_DESC_WD, CS_ARG_HINT_WD, false));
- args.Add(new NamedArgument(CS_ARG_NAME_INT, CS_ARG_DESC_INT, CS_ARG_HINT_INT, TypeValuesEnum.TimeSpan, TimeSpan.FromSeconds(30).ToString(), false));
- args.Add(new FlagArgument(CS_ARG_NAME_DELETE, CS_ARG_DESC_DELETE, CS_ARG_HINT_DELETE, false));
- args.Add(new FlagArgument(CS_ARG_NAME_INIT, CS_ARG_DESC_INIT, CS_ARG_HINT_INIT, false));
- return args;
- }
- #endregion
- }
- }
|