Browse Source

Convenience methods Session.PutFileToDirectory, Session.PutFilesToDirectory, Session.GetFileToDirectory and Session.GetFilesToDirectory

Source commit: 0f89d088a94eeeaecbc4af11862542df9ea28667
Martin Prikryl 6 years ago
parent
commit
fe24c90abb
2 changed files with 150 additions and 2 deletions
  1. 138 2
      dotnet/Session.cs
  2. 12 0
      source/core/Script.cpp

+ 138 - 2
dotnet/Session.cs

@@ -758,6 +758,66 @@ namespace WinSCP
             }
         }
 
+        public TransferOperationResult PutFilesToDirectory(
+            string localDirectory, string remoteDirectory, string filemask = null, bool remove = false, TransferOptions options = null)
+        {
+            // Not locking, locked in PutFiles
+            using (Logger.CreateCallstack())
+            {
+                if (localDirectory == null)
+                {
+                    throw Logger.WriteException(new ArgumentNullException("localDirectory"));
+                }
+                if (remoteDirectory == null)
+                {
+                    throw Logger.WriteException(new ArgumentNullException("remoteDirectory"));
+                }
+                if (string.IsNullOrEmpty(filemask))
+                {
+                    filemask = "*";
+                }
+                string localPath = Path.Combine(localDirectory, filemask);
+                const string remoteSeparator = "/";
+                string remotePath =
+                    remoteDirectory +
+                    (remoteDirectory.EndsWith(remoteSeparator, StringComparison.Ordinal) ? string.Empty : remoteSeparator);
+                return PutFiles(localPath, remotePath, remove, options);
+            }
+        }
+
+        public TransferEventArgs PutFileToDirectory(string localFilePath, string remoteDirectory, bool remove = false, TransferOptions options = null)
+        {
+            // Not locking, locked in PutFiles (within PutFilesToDirectory)
+            using (Logger.CreateCallstack())
+            {
+                if (string.IsNullOrEmpty(localFilePath))
+                {
+                    throw Logger.WriteException(new ArgumentException("File to path cannot be empty", "localFilePath"));
+                }
+
+                if (!File.Exists(localFilePath))
+                {
+                    throw Logger.WriteException(new FileNotFoundException($"File {localFilePath} does not exist", localFilePath));
+                }
+                string localDirectory = Path.GetDirectoryName(localFilePath);
+                string filemask = RemotePath.EscapeFileMask(Path.GetFileName(localFilePath));
+
+                TransferOperationResult operationResult =
+                    PutFilesToDirectory(localDirectory, remoteDirectory, filemask, remove, options);
+                operationResult.Check();
+                // Should not happen
+                if (operationResult.Transfers.Count == 0)
+                {
+                    throw Logger.WriteException(new FileNotFoundException("File not found"));
+                }
+                if (operationResult.Transfers.Count > 1)
+                {
+                    throw Logger.WriteException(new InvalidOperationException("More then one file has been unexpectedly found"));
+                }
+                return operationResult.Transfers[0];
+            }
+        }
+
         private void AddTransfer(TransferOperationResult result, TransferEventArgs args)
         {
             if (args != null)
@@ -770,6 +830,15 @@ namespace WinSCP
         public TransferOperationResult GetFiles(string remotePath, string localPath, bool remove = false, TransferOptions options = null)
         {
             using (Logger.CreateCallstackAndLock())
+            {
+                return DoGetFiles(remotePath, localPath, remove, options, string.Empty);
+            }
+        }
+
+        private TransferOperationResult DoGetFiles(
+            string remotePath, string localPath, bool remove, TransferOptions options, string additionalParams)
+        {
+            using (Logger.CreateCallstack())
             {
                 if (options == null)
                 {
@@ -779,8 +848,8 @@ namespace WinSCP
                 CheckOpened();
 
                 WriteCommand(
-                    string.Format(CultureInfo.InvariantCulture, "get {0} {1} -- \"{2}\" \"{3}\"",
-                        BooleanSwitch(remove, "delete"), options.ToSwitches(),
+                    string.Format(CultureInfo.InvariantCulture, "get {0} {1} {2} -- \"{3}\" \"{4}\"",
+                        BooleanSwitch(remove, "delete"), options.ToSwitches(), additionalParams,
                         Tools.ArgumentEscape(remotePath), Tools.ArgumentEscape(localPath)));
 
                 TransferOperationResult result = new TransferOperationResult();
@@ -818,6 +887,73 @@ namespace WinSCP
             }
         }
 
+        public TransferOperationResult GetFilesToDirectory(
+            string remoteDirectory, string localDirectory, string filemask = null, bool remove = false, TransferOptions options = null)
+        {
+            using (Logger.CreateCallstackAndLock())
+            {
+                return DoGetFilesToDirectory(remoteDirectory, localDirectory, filemask, remove, options, null);
+            }
+        }
+
+        private TransferOperationResult DoGetFilesToDirectory(
+            string remoteDirectory, string localDirectory, string filemask, bool remove, TransferOptions options, string additionalParams)
+        {
+            using (Logger.CreateCallstack())
+            {
+                if (remoteDirectory == null)
+                {
+                    throw Logger.WriteException(new ArgumentNullException("remoteDirectory"));
+                }
+                if (localDirectory == null)
+                {
+                    throw Logger.WriteException(new ArgumentNullException("localDirectory"));
+                }
+                if (string.IsNullOrEmpty(filemask))
+                {
+                    filemask = "*";
+                }
+                string remotePath = RemotePath.Combine(remoteDirectory, filemask);
+                if (!Directory.Exists(localDirectory))
+                {
+                    throw Logger.WriteException(new DirectoryNotFoundException(localDirectory));
+                }
+                string localSeparator = Path.DirectorySeparatorChar.ToString();
+                string localPath =
+                    localDirectory +
+                    (localDirectory.EndsWith(localSeparator, StringComparison.Ordinal) ? string.Empty : localSeparator);
+                return DoGetFiles(remotePath, localPath, remove, options, additionalParams);
+            }
+        }
+
+        public TransferEventArgs GetFileToDirectory(string remoteFilePath, string localDirectory, bool remove = false, TransferOptions options = null)
+        {
+            using (Logger.CreateCallstackAndLock())
+            {
+                if (string.IsNullOrEmpty(remoteFilePath))
+                {
+                    throw Logger.WriteException(new ArgumentException("File to path cannot be empty", "remoteDirectory"));
+                }
+
+                string remoteDirectory = RemotePath.GetDirectoryName(remoteFilePath);
+                string filemask = RemotePath.EscapeFileMask(RemotePath.GetFileName(remoteFilePath));
+
+                TransferOperationResult operationResult =
+                    DoGetFilesToDirectory(remoteDirectory, localDirectory, filemask, remove, options, "-onlyfile");
+                operationResult.Check();
+                // Should happen only when the filename is mask-like, otherwise "get" throws straight away
+                if (operationResult.Transfers.Count == 0)
+                {
+                    throw Logger.WriteException(new FileNotFoundException("File not found"));
+                }
+                if (operationResult.Transfers.Count > 1)
+                {
+                    throw Logger.WriteException(new InvalidOperationException("More then one file has been unexpectedly found"));
+                }
+                return operationResult.Transfers[0];
+            }
+        }
+
         public RemovalOperationResult RemoveFiles(string path)
         {
             using (Logger.CreateCallstackAndLock())

+ 12 - 0
source/core/Script.cpp

@@ -1453,6 +1453,18 @@ void __fastcall TScript::GetProc(TScriptProcParams * Parameters)
     (TFileListType)(fltQueryServer | fltMask | FLAGMASK(Latest, fltLatest)));
   try
   {
+    // For internal use by .NET Session.GetFileToDirectory
+    if (Parameters->FindSwitch(L"onlyfile"))
+    {
+      for (int Index = 0; Index < FileList->Count; Index++)
+      {
+        TRemoteFile * File = dynamic_cast<TRemoteFile *>(FileList->Objects[Index]);
+        if (File->IsDirectory)
+        {
+          throw Exception(FMTLOAD(NOT_FILE_ERROR, (File->FileName)));
+        }
+      }
+    }
 
     UnicodeString TargetDirectory;
     if (Parameters->ParamCount == 1)