فهرست منبع

Bug 2209: Improve behavior when moving/renaming over an existing folder

https://winscp.net/tracker/2209

Source commit: d7a7d5b2efeb6d81bafe7e18f60457fdbd4e11d1
Martin Prikryl 2 سال پیش
والد
کامیت
52cf67f62d

+ 1 - 1
source/core/ScpFileSystem.cpp

@@ -1736,7 +1736,7 @@ void __fastcall TSCPFileSystem::CopyToRemote(TStrings * FilesToCopy,
           unsigned int Answer;
           if (File->IsDirectory)
           {
-            UnicodeString Message = FMTLOAD(DIRECTORY_OVERWRITE, (FileNameOnly));
+            UnicodeString Message = MainInstructions(FMTLOAD(DIRECTORY_OVERWRITE, (FileNameOnly)));
             TQueryParams QueryParams(qpNeverAskAgainCheck);
 
             TSuspendFileOperationProgress Suspend(OperationProgress);

+ 7 - 4
source/core/Terminal.cpp

@@ -4853,18 +4853,21 @@ bool __fastcall TTerminal::DoRenameFile(
     if (DuplicateFile.get() != NULL)
     {
       UnicodeString QuestionFmt;
+      TQueryType QueryType;
       if (DuplicateFile->IsDirectory)
       {
-        QuestionFmt = LoadStr(DIRECTORY_OVERWRITE);
+        QuestionFmt = MainInstructions(LoadStr(DIRECTORY_OVERWRITE)) + LoadStr(DIRECTORY_OVERWRITE_WARNING);
+        QueryType = qtWarning;
       }
       else
       {
-        QuestionFmt = LoadStr(FILE_OVERWRITE);
+        QuestionFmt = MainInstructions(LoadStr(FILE_OVERWRITE));
+        QueryType = qtConfirmation;
       }
       TQueryParams Params(qpNeverAskAgainCheck);
-      UnicodeString Question = MainInstructions(FORMAT(QuestionFmt, (NewName)));
+      UnicodeString Question = FORMAT(QuestionFmt, (NewName));
       unsigned int Answers = qaYes | qaNo | FLAGMASK(OperationProgress != NULL, qaCancel) | FLAGMASK(IsBatchMove, qaYesToAll | qaNoToAll);
-      unsigned int Answer = QueryUser(Question, NULL, Answers, &Params);
+      unsigned int Answer = QueryUser(Question, NULL, Answers, &Params, QueryType);
       switch (Answer)
       {
         case qaNeverAskAgain:

+ 12 - 4
source/forms/Custom.cpp

@@ -802,7 +802,7 @@ bool __fastcall DoShortCutDialog(TShortCut & ShortCut,
 class TRemoteMoveDialog : public TCustomDialog
 {
 public:
-  __fastcall TRemoteMoveDialog(bool Multi);
+  __fastcall TRemoteMoveDialog(bool Multi, TDirectoryExistsEvent OnDirectoryExists);
 
   bool __fastcall Execute(UnicodeString & Target, UnicodeString & FileMask);
 
@@ -814,9 +814,10 @@ protected:
 private:
   THistoryComboBox * Combo;
   bool FMulti;
+  TDirectoryExistsEvent FOnDirectoryExists;
 };
 //---------------------------------------------------------------------------
-__fastcall TRemoteMoveDialog::TRemoteMoveDialog(bool Multi) :
+__fastcall TRemoteMoveDialog::TRemoteMoveDialog(bool Multi, TDirectoryExistsEvent OnDirectoryExists) :
   TCustomDialog(HELP_REMOTE_MOVE)
 {
   Caption = LoadStr(REMOTE_MOVE_TITLE);
@@ -824,6 +825,7 @@ __fastcall TRemoteMoveDialog::TRemoteMoveDialog(bool Multi) :
   ClientWidth = ScaleByTextHeight(this, 420);
 
   FMulti = Multi;
+  FOnDirectoryExists = OnDirectoryExists;
 
   AddImage(L"Move L to R");
 
@@ -860,6 +862,11 @@ void __fastcall TRemoteMoveDialog::DoShow()
 //---------------------------------------------------------------------------
 void __fastcall TRemoteMoveDialog::DoValidate()
 {
+  if (FOnDirectoryExists(NULL, Combo->Text))
+  {
+    Combo->Text = UnixCombinePaths(Combo->Text, AnyMask);
+  }
+
   if (!IsFileNameMask(GetFileMask()) && FMulti)
   {
     UnicodeString Message =
@@ -873,9 +880,10 @@ void __fastcall TRemoteMoveDialog::DoValidate()
   TCustomDialog::DoValidate();
 }
 //---------------------------------------------------------------------------
-bool __fastcall DoRemoteMoveDialog(bool Multi, UnicodeString & Target, UnicodeString & FileMask)
+bool __fastcall DoRemoteMoveDialog(
+  bool Multi, UnicodeString & Target, UnicodeString & FileMask, TDirectoryExistsEvent OnDirectoryExists)
 {
-  std::unique_ptr<TRemoteMoveDialog> Dialog(new TRemoteMoveDialog(Multi));
+  std::unique_ptr<TRemoteMoveDialog> Dialog(new TRemoteMoveDialog(Multi, OnDirectoryExists));
   return Dialog->Execute(Target, FileMask);
 }
 //---------------------------------------------------------------------------

+ 15 - 2
source/forms/CustomScpExplorer.cpp

@@ -4450,6 +4450,18 @@ void __fastcall TCustomScpExplorerForm::LockFiles(TStrings * FileList, bool Lock
   RemoteDirView->RestoreSelection();
 }
 //---------------------------------------------------------------------------
+bool TCustomScpExplorerForm::DoDirectoryExists(void * Session, const UnicodeString & Directory)
+{
+  bool Result = false;
+  TTerminal * ATerminal = (Session == NULL) ? Terminal : reinterpret_cast<TTerminal *>(Session);
+  if (IsActiveTerminal(ATerminal))
+  {
+    std::unique_ptr<TRemoteFile> File(ATerminal->TryReadFile(Directory));
+    Result = File && File->IsDirectory;
+  }
+  return Result;
+}
+//---------------------------------------------------------------------------
 bool __fastcall TCustomScpExplorerForm::RemoteTransferDialog(TManagedTerminal *& Session,
   TStrings * FileList, UnicodeString & Target, UnicodeString & FileMask, bool & DirectCopy,
   bool NoConfirmation, bool Move)
@@ -4501,7 +4513,7 @@ bool __fastcall TCustomScpExplorerForm::RemoteTransferDialog(TManagedTerminal *&
 
     if (Move)
     {
-      Result = DoRemoteMoveDialog(Multi, Target, FileMask);
+      Result = DoRemoteMoveDialog(Multi, Target, FileMask, DoDirectoryExists);
     }
     else
     {
@@ -4537,7 +4549,8 @@ bool __fastcall TCustomScpExplorerForm::RemoteTransferDialog(TManagedTerminal *&
       }
       void * ASession = Session;
       Result = DoRemoteCopyDialog(
-        Sessions.get(), Directories.get(), AllowDirectCopy, Multi, ASession, Target, FileMask, DirectCopy, Terminal);
+        Sessions.get(), Directories.get(), AllowDirectCopy, Multi, ASession, Target, FileMask, DirectCopy, Terminal,
+        DoDirectoryExists);
       Session = static_cast<TManagedTerminal *>(ASession);
     }
   }

+ 1 - 0
source/forms/CustomScpExplorer.h

@@ -755,6 +755,7 @@ protected:
   void __fastcall FileDeleted(TOperationSide Side, const UnicodeString & FileName, bool Success);
   void LoadFilesProperties(TStrings * FileList);
   void PasteFiles();
+  bool DoDirectoryExists(void * Session, const UnicodeString & Directory);
 
 public:
   virtual __fastcall ~TCustomScpExplorerForm();

+ 20 - 7
source/forms/RemoteTransfer.cpp

@@ -16,15 +16,16 @@
 #pragma link "HistoryComboBox"
 #pragma resource "*.dfm"
 //---------------------------------------------------------------------------
-bool __fastcall DoRemoteCopyDialog(TStrings * Sessions, TStrings * Directories,
+bool __fastcall DoRemoteCopyDialog(
+  TStrings * Sessions, TStrings * Directories,
   TDirectRemoteCopy AllowDirectCopy, bool Multi, void *& Session, UnicodeString & Target, UnicodeString & FileMask,
-  bool & DirectCopy, void * CurrentSession)
+  bool & DirectCopy, void * CurrentSession, TDirectoryExistsEvent OnDirectoryExists)
 {
   bool Result;
   TRemoteTransferDialog * Dialog = SafeFormCreate<TRemoteTransferDialog>();
   try
   {
-    Dialog->Init(Multi, Sessions, Directories, AllowDirectCopy, CurrentSession);
+    Dialog->Init(Multi, Sessions, Directories, AllowDirectCopy, CurrentSession, OnDirectoryExists);
     Result = Dialog->Execute(Session, Target, FileMask, DirectCopy);
   }
   __finally
@@ -42,8 +43,9 @@ __fastcall TRemoteTransferDialog::TRemoteTransferDialog(TComponent * Owner)
   Caption = LoadStr(REMOTE_COPY_TITLE);
 }
 //---------------------------------------------------------------------------
-void __fastcall TRemoteTransferDialog::Init(bool Multi, TStrings * Sessions,
-  TStrings * Directories, TDirectRemoteCopy AllowDirectCopy, void * CurrentSession)
+void __fastcall TRemoteTransferDialog::Init(
+  bool Multi, TStrings * Sessions, TStrings * Directories, TDirectRemoteCopy AllowDirectCopy, void * CurrentSession,
+  TDirectoryExistsEvent OnDirectoryExists)
 {
   FMulti = Multi;
   SessionCombo->Items = Sessions;
@@ -52,6 +54,7 @@ void __fastcall TRemoteTransferDialog::Init(bool Multi, TStrings * Sessions,
   DebugAssert(SessionCombo->Items->Count == FDirectories->Count);
   FAllowDirectCopy = AllowDirectCopy;
   FCurrentSession = CurrentSession;
+  FOnDirectoryExists = OnDirectoryExists;
   LoadDialogImage(Image, L"Duplicate L to R");
 }
 //---------------------------------------------------------------------------
@@ -73,7 +76,7 @@ bool __fastcall TRemoteTransferDialog::Execute(void *& Session, UnicodeString &
   bool Result = (ShowModal() == DefaultResult(this));
   if (Result)
   {
-    Session = SessionCombo->Items->Objects[SessionCombo->ItemIndex];
+    Session = GetSelectedSession();
     CustomWinConfiguration->History[L"RemoteTarget"] = DirectoryEdit->Items;
     Target = UnixExtractFilePath(DirectoryEdit->Text);
     FileMask = GetFileMask();
@@ -139,6 +142,11 @@ void __fastcall TRemoteTransferDialog::FormCloseQuery(TObject * /*Sender*/,
 {
   if (ModalResult == DefaultResult(this))
   {
+    if (FOnDirectoryExists(GetSelectedSession(), DirectoryEdit->Text))
+    {
+      DirectoryEdit->Text = UnixCombinePaths(DirectoryEdit->Text, AnyMask);
+    }
+
     if (!IsFileNameMask(GetFileMask()) && FMulti)
     {
       UnicodeString Message =
@@ -178,8 +186,13 @@ void __fastcall TRemoteTransferDialog::NotDirectCopyCheckClick(
   }
 }
 //---------------------------------------------------------------------------
+void * TRemoteTransferDialog::GetSelectedSession()
+{
+  return SessionCombo->Items->Objects[SessionCombo->ItemIndex];
+}
+//---------------------------------------------------------------------------
 bool __fastcall TRemoteTransferDialog::IsCurrentSessionSelected()
 {
-  return (SessionCombo->Items->Objects[SessionCombo->ItemIndex] == FCurrentSession);
+  return (GetSelectedSession() == FCurrentSession);
 }
 //---------------------------------------------------------------------------

+ 5 - 2
source/forms/RemoteTransfer.h

@@ -33,8 +33,9 @@ __published:
 public:
   __fastcall TRemoteTransferDialog(TComponent * Owner);
 
-  void __fastcall Init(bool Multi, TStrings * Sessions, TStrings * Directories,
-    TDirectRemoteCopy AllowDirectCopy, void * CurrentSession);
+  void __fastcall Init(
+    bool Multi, TStrings * Sessions, TStrings * Directories, TDirectRemoteCopy AllowDirectCopy, void * CurrentSession,
+    TDirectoryExistsEvent OnDirectoryExists);
   bool __fastcall Execute(void *& Session, UnicodeString & Target,
     UnicodeString & FileMask, bool & DirectCopy);
 
@@ -42,6 +43,7 @@ protected:
   void __fastcall UpdateControls();
   UnicodeString __fastcall GetFileMask();
   bool __fastcall IsCurrentSessionSelected();
+  void * GetSelectedSession();
   void __fastcall UpdateNotDirectCopyCheck();
 
 private:
@@ -50,6 +52,7 @@ private:
   bool FDirectCopy;
   bool FMulti;
   TDirectRemoteCopy FAllowDirectCopy;
+  TDirectoryExistsEvent FOnDirectoryExists;
 
   INTERFACE_HOOK;
 };

+ 1 - 0
source/resource/TextsCore.h

@@ -346,6 +346,7 @@
 #define PROXY_AUTH_TITLE        363
 #define PROXY_AUTH_USERNAME_PROMPT 364
 #define PROXY_AUTH_PASSWORD_PROMPT 365
+#define DIRECTORY_OVERWRITE_WARNING 366
 
 #define CORE_INFORMATION_STRINGS 400
 #define YES_STR                 401

+ 1 - 0
source/resource/TextsCore1.rc

@@ -315,6 +315,7 @@ BEGIN
   PROXY_AUTH_TITLE, "Proxy authentication"
   PROXY_AUTH_USERNAME_PROMPT, "Proxy &username:"
   PROXY_AUTH_PASSWORD_PROMPT, "Proxy &password:"
+  DIRECTORY_OVERWRITE_WARNING, "All files in the target directory will be deleted!"
 
   CORE_INFORMATION_STRINGS, "CORE_INFORMATION"
   YES_STR, "Yes"

+ 7 - 4
source/windows/WinInterface.h

@@ -324,11 +324,14 @@ bool __fastcall DoPropertiesDialog(TStrings * FileList,
     int AllowedChanges, bool UserGroupByID, TCalculateSizeEvent OnCalculateSize,
     TCalculateChecksumEvent OnCalculateChecksum);
 
-bool __fastcall DoRemoteMoveDialog(bool Multi, UnicodeString & Target, UnicodeString & FileMask);
+typedef bool (__closure * TDirectoryExistsEvent)(void * Session, const UnicodeString & Directory);
+bool __fastcall DoRemoteMoveDialog(
+  bool Multi, UnicodeString & Target, UnicodeString & FileMask, TDirectoryExistsEvent OnDirectoryExists);
 enum TDirectRemoteCopy { drcDisallow, drcAllow, drcConfirmCommandSession };
-bool __fastcall DoRemoteCopyDialog(TStrings * Sessions, TStrings * Directories,
-  TDirectRemoteCopy AllowDirectCopy, bool Multi, void *& Session,
-  UnicodeString & Target, UnicodeString & FileMask, bool & DirectCopy, void * CurrentSession);
+bool __fastcall DoRemoteCopyDialog(
+  TStrings * Sessions, TStrings * Directories,
+  TDirectRemoteCopy AllowDirectCopy, bool Multi, void *& Session, UnicodeString & Target, UnicodeString & FileMask,
+  bool & DirectCopy, void * CurrentSession, TDirectoryExistsEvent OnDirectoryExists);
 
 // forms\SelectMask.cpp
 bool __fastcall DoSelectMaskDialog(TControl * Parent, bool Select, TFileFilter & Filter);