mirror of
https://github.com/winscp/winscp.git
synced 2026-10-24 02:28:55 +03:00
Remote file duplication in scripting, .NET assembly and XML log + Scripting command mv and .NET assembly function Session.MoveFile report when the server does not support file renaming/moving.
Source commit: 974f6dff9af8f3bb1e39a7b2ef453af0c7b2d0ec
This commit is contained in:
@@ -1054,6 +1054,35 @@ namespace WinSCP
|
||||
}
|
||||
}
|
||||
|
||||
public void DuplicateFile(string sourcePath, string targetPath)
|
||||
{
|
||||
using (Logger.CreateCallstackAndLock())
|
||||
{
|
||||
CheckOpened();
|
||||
|
||||
string sourceArgument = Tools.ArgumentEscape(EscapeFileMask(sourcePath));
|
||||
string targetArgument = Tools.ArgumentEscape(targetPath);
|
||||
string command = string.Format(CultureInfo.InvariantCulture, "cp \"{0}\" \"{1}\"", sourceArgument, targetArgument);
|
||||
WriteCommand(command);
|
||||
|
||||
using (ElementLogReader groupReader = _reader.WaitForGroupAndCreateLogReader())
|
||||
{
|
||||
if (!groupReader.TryWaitForNonEmptyElement("cp", LogReadFlags.ThrowFailures))
|
||||
{
|
||||
throw Logger.WriteException(new SessionRemoteException(this, string.Format(CultureInfo.CurrentCulture, "{0} not found.", sourcePath)));
|
||||
}
|
||||
else
|
||||
{
|
||||
using (ElementLogReader cpReader = groupReader.CreateLogReader())
|
||||
{
|
||||
ReadElement(cpReader, 0);
|
||||
groupReader.ReadToEnd(LogReadFlags.ThrowFailures);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This is not static method only to make it visible to COM
|
||||
public string EscapeFileMask(string fileMask)
|
||||
{
|
||||
|
||||
@@ -365,6 +365,7 @@ void __fastcall TScript::Init()
|
||||
FCommands->Register(L"rmdir", SCRIPT_RMDIR_DESC, SCRIPT_RMDIR_HELP, &RmDirProc, 1, -1, false);
|
||||
FCommands->Register(L"mv", SCRIPT_MV_DESC, SCRIPT_MV_HELP2, &MvProc, 2, -1, false);
|
||||
FCommands->Register(L"rename", 0, SCRIPT_MV_HELP2, &MvProc, 2, -1, false);
|
||||
FCommands->Register(L"cp", SCRIPT_CP_DESC, SCRIPT_CP_HELP, &CpProc, 2, -1, false);
|
||||
FCommands->Register(L"chmod", SCRIPT_CHMOD_DESC, SCRIPT_CHMOD_HELP2, &ChModProc, 2, -1, false);
|
||||
FCommands->Register(L"ln", SCRIPT_LN_DESC, SCRIPT_LN_HELP, &LnProc, 2, 2, false);
|
||||
FCommands->Register(L"symlink", 0, SCRIPT_LN_HELP, &LnProc, 2, 2, false);
|
||||
@@ -1331,10 +1332,15 @@ void __fastcall TScript::RmDirProc(TScriptProcParams * Parameters)
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
void __fastcall TScript::MvProc(TScriptProcParams * Parameters)
|
||||
void __fastcall TScript::DoMvOrCp(TScriptProcParams * Parameters, TFSCapability Capability, bool Cp)
|
||||
{
|
||||
CheckSession();
|
||||
|
||||
if (!FTerminal->IsCapable[Capability])
|
||||
{
|
||||
NotSupported();
|
||||
}
|
||||
|
||||
TStrings * FileList = CreateFileList(Parameters, 1, Parameters->ParamCount - 1,
|
||||
fltMask);
|
||||
try
|
||||
@@ -1346,7 +1352,14 @@ void __fastcall TScript::MvProc(TScriptProcParams * Parameters)
|
||||
|
||||
Target = UnixIncludeTrailingBackslash(TargetDirectory) + FileMask;
|
||||
CheckMultiFilesToOne(FileList, Target, true);
|
||||
FTerminal->MoveFiles(FileList, TargetDirectory, FileMask);
|
||||
if (Cp)
|
||||
{
|
||||
FTerminal->CopyFiles(FileList, TargetDirectory, FileMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
FTerminal->MoveFiles(FileList, TargetDirectory, FileMask);
|
||||
}
|
||||
}
|
||||
__finally
|
||||
{
|
||||
@@ -1354,6 +1367,16 @@ void __fastcall TScript::MvProc(TScriptProcParams * Parameters)
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
void __fastcall TScript::MvProc(TScriptProcParams * Parameters)
|
||||
{
|
||||
DoMvOrCp(Parameters, fcRemoteMove, false);
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
void __fastcall TScript::CpProc(TScriptProcParams * Parameters)
|
||||
{
|
||||
DoMvOrCp(Parameters, fcRemoteCopy, true);
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
void __fastcall TScript::ChModProc(TScriptProcParams * Parameters)
|
||||
{
|
||||
CheckSession();
|
||||
|
||||
@@ -136,6 +136,7 @@ protected:
|
||||
void __fastcall RmProc(TScriptProcParams * Parameters);
|
||||
void __fastcall RmDirProc(TScriptProcParams * Parameters);
|
||||
void __fastcall MvProc(TScriptProcParams * Parameters);
|
||||
void __fastcall CpProc(TScriptProcParams * Parameters);
|
||||
void __fastcall ChModProc(TScriptProcParams * Parameters);
|
||||
void __fastcall LnProc(TScriptProcParams * Parameters);
|
||||
void __fastcall MkDirProc(TScriptProcParams * Parameters);
|
||||
@@ -179,6 +180,7 @@ private:
|
||||
void __fastcall NotSupported();
|
||||
void __fastcall CheckMultiFilesToOne(TStrings * FileList, const UnicodeString & Target, bool Unix);
|
||||
void __fastcall LogOption(const UnicodeString & LogStr);
|
||||
void __fastcall DoMvOrCp(TScriptProcParams * Parameters, TFSCapability Capability, bool Cp);
|
||||
};
|
||||
//---------------------------------------------------------------------------
|
||||
typedef void __fastcall (__closure *TScriptInputEvent)(TScript * Script, const UnicodeString Prompt, UnicodeString & Str);
|
||||
|
||||
@@ -296,6 +296,7 @@ protected:
|
||||
case laMkdir: return L"mkdir";
|
||||
case laRm: return L"rm";
|
||||
case laMv: return L"mv";
|
||||
case laCp: return L"cp";
|
||||
case laCall: return L"call";
|
||||
case laLs: return L"ls";
|
||||
case laStat: return L"stat";
|
||||
@@ -532,6 +533,13 @@ __fastcall TMvSessionAction::TMvSessionAction(TActionLog * Log,
|
||||
Destination(ADestination);
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
__fastcall TCpSessionAction::TCpSessionAction(TActionLog * Log,
|
||||
const UnicodeString & FileName, const UnicodeString & ADestination) :
|
||||
TFileLocationSessionAction(Log, laCp, FileName)
|
||||
{
|
||||
Destination(ADestination);
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
__fastcall TCallSessionAction::TCallSessionAction(TActionLog * Log,
|
||||
const UnicodeString & Command, const UnicodeString & Destination) :
|
||||
TSessionAction(Log, laCall)
|
||||
|
||||
@@ -80,7 +80,7 @@ public:
|
||||
enum TLogLineType { llOutput, llInput, llStdError, llMessage, llException };
|
||||
enum TLogAction
|
||||
{
|
||||
laUpload, laDownload, laTouch, laChmod, laMkdir, laRm, laMv, laCall, laLs,
|
||||
laUpload, laDownload, laTouch, laChmod, laMkdir, laRm, laMv, laCp, laCall, laLs,
|
||||
laStat, laChecksum, laCwd
|
||||
};
|
||||
//---------------------------------------------------------------------------
|
||||
@@ -180,6 +180,13 @@ public:
|
||||
const UnicodeString & Destination);
|
||||
};
|
||||
//---------------------------------------------------------------------------
|
||||
class TCpSessionAction : public TFileLocationSessionAction
|
||||
{
|
||||
public:
|
||||
__fastcall TCpSessionAction(TActionLog * Log, const UnicodeString & FileName,
|
||||
const UnicodeString & Destination);
|
||||
};
|
||||
//---------------------------------------------------------------------------
|
||||
class TCallSessionAction : public TSessionAction
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -4485,6 +4485,7 @@ void __fastcall TTerminal::DoCopyFile(const UnicodeString FileName,
|
||||
TRetryOperationLoop RetryLoop(this);
|
||||
do
|
||||
{
|
||||
TCpSessionAction Action(ActionLog, AbsolutePath(FileName, true), AbsolutePath(NewName, true));
|
||||
try
|
||||
{
|
||||
DebugAssert(FFileSystem);
|
||||
@@ -4503,7 +4504,7 @@ void __fastcall TTerminal::DoCopyFile(const UnicodeString FileName,
|
||||
}
|
||||
catch(Exception & E)
|
||||
{
|
||||
RetryLoop.Error(E, FMTLOAD(COPY_FILE_ERROR, (FileName, NewName)));
|
||||
RetryLoop.Error(E, Action, FMTLOAD(COPY_FILE_ERROR, (FileName, NewName)));
|
||||
}
|
||||
}
|
||||
while (RetryLoop.Retry());
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#define SCRIPT_ECHO_HELP 27
|
||||
#define SCRIPT_STAT_HELP 28
|
||||
#define SCRIPT_CHECKSUM_HELP 29
|
||||
#define SCRIPT_CP_HELP 30
|
||||
|
||||
#define CORE_ERROR_STRINGS 100
|
||||
#define KEY_NOT_VERIFIED 101
|
||||
@@ -320,6 +321,7 @@
|
||||
#define S3_ACCESS_KEY_ID_PROMPT 357
|
||||
#define S3_SECRET_ACCESS_KEY_TITLE 358
|
||||
#define S3_SECRET_ACCESS_KEY_PROMPT 359
|
||||
#define DUPLICATE_FOLDER_NOT_SUPPORTED 360
|
||||
|
||||
#define CORE_INFORMATION_STRINGS 400
|
||||
#define YES_STR 401
|
||||
@@ -468,6 +470,7 @@
|
||||
#define AND_STR 556
|
||||
#define AUTH_CHANGING_PASSWORD 557
|
||||
#define PASTE_KEY_BUTTON 558
|
||||
#define SCRIPT_CP_DESC 559
|
||||
|
||||
#define CORE_VARIABLE_STRINGS 600
|
||||
#define PUTTY_BASED_ON 601
|
||||
|
||||
@@ -237,6 +237,7 @@ BEGIN
|
||||
S3_ERROR_FURTHER_DETAILS, "Further details: %s"
|
||||
S3_ERROR_EXTRA_DETAILS, "Extra Details: "
|
||||
S3_STATUS_ACCESS_DENIED, "Access denied."
|
||||
DUPLICATE_FOLDER_NOT_SUPPORTED, "Direct duplication of folders is not supported. Use a duplication via a local temporary copy."
|
||||
|
||||
CORE_CONFIRMATION_STRINGS, "CORE_CONFIRMATION"
|
||||
CONFIRM_PROLONG_TIMEOUT3, "Host is not communicating for %d seconds.\n\nWait for another %0:d seconds?"
|
||||
@@ -438,6 +439,7 @@ BEGIN
|
||||
AND_STR, "%s and %s"
|
||||
AUTH_CHANGING_PASSWORD, "Changing password."
|
||||
PASTE_KEY_BUTTON, "&Paste key"
|
||||
SCRIPT_CP_DESC, "Duplicates remote file"
|
||||
|
||||
CORE_VARIABLE_STRINGS, "CORE_VARIABLE"
|
||||
PUTTY_BASED_ON, "SSH and SCP code based on PuTTY %s"
|
||||
|
||||
@@ -376,4 +376,18 @@ BEGIN
|
||||
" Calculates checksum of remote file.\n"
|
||||
"example:\n"
|
||||
" checksum sha-1 index.html\n"
|
||||
SCRIPT_CP_HELP,
|
||||
"cp <file> [ <file2> ... ] [ <directory>/ ][ <newname> ]\n"
|
||||
" Duplicates one or more remote files. Destination directory or new\n"
|
||||
" name or both must be specified. Destination directory must end with\n"
|
||||
" slash. Operation mask can be used instead of new name.\n"
|
||||
" Filename can be replaced with wildcard to select multiple files.\n"
|
||||
"effective option:\n"
|
||||
" failonnomatch\n"
|
||||
"examples:\n"
|
||||
" cp index.html public_html/\n"
|
||||
" cp index.html about.*\n"
|
||||
" cp index.html public_html/about.*\n"
|
||||
" cp public_html/index.html public_html/about.html /home/martin/*.bak\n"
|
||||
" cp *.html /home/backup/*.bak\n"
|
||||
END
|
||||
|
||||
Reference in New Issue
Block a user