This is an automated email from the ASF dual-hosted git repository.

hansva pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git


The following commit(s) were added to refs/heads/main by this push:
     new bc2983625e Add git clean when doing revert, fixes #6489 (#6490)
bc2983625e is described below

commit bc2983625e26ac7f9d1fadc69949ef8545bb479a
Author: Hans Van Akelyen <[email protected]>
AuthorDate: Wed Feb 4 14:04:49 2026 +0100

    Add git clean when doing revert, fixes #6489 (#6490)
---
 .../main/java/org/apache/hop/git/GitGuiPlugin.java | 66 +++++++++++++++++++
 .../main/java/org/apache/hop/git/model/UIGit.java  | 48 ++++++++++++++
 .../hop/git/messages/messages_en_US.properties     |  2 +
 .../hop/ui/core/dialog/EnterSelectionDialog.java   | 77 ++--------------------
 .../perspective/explorer/ExplorerPerspective.java  | 41 ++++++++++++
 5 files changed, 161 insertions(+), 73 deletions(-)

diff --git 
a/plugins/misc/git/src/main/java/org/apache/hop/git/GitGuiPlugin.java 
b/plugins/misc/git/src/main/java/org/apache/hop/git/GitGuiPlugin.java
index 3f538405f8..bc8124f053 100644
--- a/plugins/misc/git/src/main/java/org/apache/hop/git/GitGuiPlugin.java
+++ b/plugins/misc/git/src/main/java/org/apache/hop/git/GitGuiPlugin.java
@@ -21,6 +21,7 @@ package org.apache.hop.git;
 import java.io.File;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -467,11 +468,76 @@ public class GitGuiPlugin
         String selection = selectionDialog.open();
         if (selection != null) {
           int[] selectedNrs = selectionDialog.getSelectionIndeces();
+
+          // Only close tabs for files that will be deleted (untracked/added); 
reload the rest
+          Set<String> pathsThatWillBeDeleted =
+              git.getRevertPathFilesThatWillBeDeleted(relativePath);
+          List<String> filenamesToClose = new ArrayList<>();
+          List<String> filenamesToReload = new ArrayList<>();
+          for (int selectedNr : selectedNrs) {
+            String filePath = files[selectedNr];
+            String fullFilename;
+            try {
+              FileObject fileObj =
+                  HopVfs.getFileObject(new File(git.getDirectory(), 
filePath).getAbsolutePath());
+              fullFilename =
+                  fileObj.exists()
+                      ? HopVfs.getFilename(fileObj)
+                      : new File(git.getDirectory(), 
filePath).getAbsolutePath();
+            } catch (Exception ignored) {
+              fullFilename = new File(git.getDirectory(), 
filePath).getAbsolutePath();
+            }
+            if (pathsThatWillBeDeleted.contains(filePath)) {
+              filenamesToClose.add(fullFilename);
+            } else {
+              filenamesToReload.add(fullFilename);
+            }
+          }
+
           for (int selectedNr : selectedNrs) {
             String file = files[selectedNr];
             git.revertPath(file);
           }
 
+          // Close tabs for reverted files that were deleted (untracked/added)
+          
ExplorerPerspective.getInstance().closeTabsForFilenames(filenamesToClose);
+          // Reload tabs for reverted files that still exist 
(changed/missing/uncommitted)
+          
ExplorerPerspective.getInstance().reloadTabsForFilenames(filenamesToReload);
+
+          // When a folder was selected, ask if user wants to run git clean 
(yes/no)
+          boolean isFolder = false;
+          try {
+            isFolder = 
HopVfs.getFileObject(explorerFile.getFilename()).isFolder();
+          } catch (Exception ignored) {
+            // not a folder
+          }
+          if (isFolder) {
+            MessageBox cleanBox =
+                new MessageBox(
+                    HopGui.getInstance().getShell(), SWT.YES | SWT.NO | 
SWT.ICON_QUESTION);
+            cleanBox.setText(
+                BaseMessages.getString(PKG, 
"GitGuiPlugin.Dialog.CleanConfirm.Header"));
+            cleanBox.setMessage(
+                BaseMessages.getString(PKG, 
"GitGuiPlugin.Dialog.CleanConfirm.Message"));
+            if ((cleanBox.open() & SWT.YES) != 0) {
+              Set<String> foldersToClean = new HashSet<>();
+              foldersToClean.add(relativePath);
+              for (int selectedNr : selectedNrs) {
+                String filePath = files[selectedNr];
+                int lastSlash = Math.max(filePath.lastIndexOf('/'), 
filePath.lastIndexOf('\\'));
+                String parentFolder = (lastSlash <= 0) ? "" : 
filePath.substring(0, lastSlash);
+                foldersToClean.add(parentFolder);
+              }
+              for (String folder : foldersToClean) {
+                try {
+                  git.cleanPath(folder);
+                } catch (Exception cleanEx) {
+                  LogChannel.UI.logError("Git clean failed for " + folder, 
cleanEx);
+                }
+              }
+            }
+          }
+
           // Show confirmation message once after all files have been reverted
           MessageBox box =
               new MessageBox(HopGui.getInstance().getShell(), SWT.OK | 
SWT.ICON_INFORMATION);
diff --git a/plugins/misc/git/src/main/java/org/apache/hop/git/model/UIGit.java 
b/plugins/misc/git/src/main/java/org/apache/hop/git/model/UIGit.java
index 197381f654..5e26ed5d2d 100644
--- a/plugins/misc/git/src/main/java/org/apache/hop/git/model/UIGit.java
+++ b/plugins/misc/git/src/main/java/org/apache/hop/git/model/UIGit.java
@@ -46,6 +46,7 @@ import org.apache.hop.i18n.BaseMessages;
 import org.apache.hop.ui.core.dialog.EnterSelectionDialog;
 import org.apache.hop.ui.core.dialog.ErrorDialog;
 import org.apache.hop.ui.hopgui.HopGui;
+import org.eclipse.jgit.api.CleanCommand;
 import org.eclipse.jgit.api.CloneCommand;
 import org.eclipse.jgit.api.DiffCommand;
 import org.eclipse.jgit.api.Git;
@@ -867,6 +868,28 @@ public class UIGit extends VCS {
     }
   }
 
+  /**
+   * Clean untracked files and directories under the given path (e.g. a 
folder).
+   *
+   * @param path The path to clean (relative to repo root)
+   * @throws HopException when the clean operation fails
+   */
+  public void cleanPath(String path) throws HopException {
+    try {
+      String normalizedPath = normalizePathForJGit(path);
+      if (normalizedPath == null || ".".equals(normalizedPath)) {
+        normalizedPath = "";
+      }
+      CleanCommand cleanCommand = git.clean();
+      if (!normalizedPath.isEmpty()) {
+        cleanCommand.setPaths(Collections.singleton(normalizedPath));
+      }
+      cleanCommand.setCleanDirectories(true).setForce(true).call();
+    } catch (Exception e) {
+      throw new HopException("Git: error cleaning path '" + path + "'", e);
+    }
+  }
+
   /**
    * Get the list of files which will be reverted.
    *
@@ -897,6 +920,31 @@ public class UIGit extends VCS {
     }
   }
 
+  /**
+   * Get the subset of revert-path files that will be deleted by revert 
(untracked or added). For
+   * these files revert removes the file; for others (changed, missing, 
uncommitted) the file stays
+   * and only content is reset.
+   *
+   * @param path The path to revert (same as for getRevertPathFiles)
+   * @return Paths that will be deleted (untracked + added)
+   */
+  public Set<String> getRevertPathFilesThatWillBeDeleted(String path) throws 
HopException {
+    try {
+      Set<String> files = new HashSet<>();
+      String normalizedPath = normalizePathForJGit(path);
+      StatusCommand statusCommand = git.status();
+      if (normalizedPath != null && !".".equals(normalizedPath)) {
+        statusCommand = statusCommand.addPath(normalizedPath);
+      }
+      Status status = statusCommand.call();
+      files.addAll(status.getUntracked());
+      files.addAll(status.getAdded());
+      return files;
+    } catch (Exception e) {
+      throw new HopException("Git: error getting revert path files for '" + 
path + "'", e);
+    }
+  }
+
   public boolean createBranch(String value) {
     try {
       git.branchCreate().setName(value).call();
diff --git 
a/plugins/misc/git/src/main/resources/org/apache/hop/git/messages/messages_en_US.properties
 
b/plugins/misc/git/src/main/resources/org/apache/hop/git/messages/messages_en_US.properties
index dee9a017c6..24690c1c18 100644
--- 
a/plugins/misc/git/src/main/resources/org/apache/hop/git/messages/messages_en_US.properties
+++ 
b/plugins/misc/git/src/main/resources/org/apache/hop/git/messages/messages_en_US.properties
@@ -57,6 +57,8 @@ GitGuiPlugin.Dialog.RevertError.Header=GIT Revert Error
 GitGuiPlugin.Dialog.RevertError.Message=There was an error doing a git revert
 GitGuiPlugin.Dialog.RevertFiles.Header=Select files to revert
 GitGuiPlugin.Dialog.RevertFiles.Message=Please select the files to revert
+GitGuiPlugin.Dialog.CleanConfirm.Header=Git Clean
+GitGuiPlugin.Dialog.CleanConfirm.Message=Should we also run git clean to 
remove untracked files in this folder and subfolders?
 GitGuiPlugin.Dialog.SelectFilesToCommit.Header=Commit Message
 GitGuiPlugin.Dialog.SelectFilesToCommit.Message=Please enter a commit message:
 GitGuiPlugin.Dialog.StageFiles.Header=Select files to commit
diff --git 
a/ui/src/main/java/org/apache/hop/ui/core/dialog/EnterSelectionDialog.java 
b/ui/src/main/java/org/apache/hop/ui/core/dialog/EnterSelectionDialog.java
index 74026defb1..40e70b2802 100644
--- a/ui/src/main/java/org/apache/hop/ui/core/dialog/EnterSelectionDialog.java
+++ b/ui/src/main/java/org/apache/hop/ui/core/dialog/EnterSelectionDialog.java
@@ -20,6 +20,8 @@ package org.apache.hop.ui.core.dialog;
 import java.util.ArrayList;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import lombok.Getter;
+import lombok.Setter;
 import org.apache.hop.core.Const;
 import org.apache.hop.core.Props;
 import org.apache.hop.core.util.Utils;
@@ -48,6 +50,8 @@ import org.eclipse.swt.widgets.ToolBar;
 import org.eclipse.swt.widgets.ToolItem;
 
 /** Allows the user to make a selection from a list of values. */
+@Getter
+@Setter
 public class EnterSelectionDialog extends Dialog {
   private static final Class<?> PKG = EnterSelectionDialog.class;
 
@@ -61,10 +65,6 @@ public class EnterSelectionDialog extends Dialog {
   private Button wOk;
   private Shell shell;
 
-  public Shell getShell() {
-    return shell;
-  }
-
   private String[] choices;
   private String selection;
   private int selectionNr;
@@ -134,10 +134,6 @@ public class EnterSelectionDialog extends Dialog {
     quickSearch = false;
   }
 
-  public void setCurrentValue(String currentValue) {
-    this.currentValue = currentValue;
-  }
-
   public void clearModal() {
     modal = false;
   }
@@ -470,43 +466,10 @@ public class EnterSelectionDialog extends Dialog {
     return -1;
   }
 
-  public int getSelectionNr() {
-    return selectionNr;
-  }
-
-  public boolean isMulti() {
-    return multi;
-  }
-
-  public void setMulti(boolean multi) {
-    this.multi = multi;
-  }
-
   public int[] getSelectionIndeces() {
     return indices;
   }
 
-  /**
-   * @return the fixed
-   */
-  public boolean isFixed() {
-    return fixed;
-  }
-
-  /**
-   * @param fixed the fixed to set
-   */
-  public void setFixed(boolean fixed) {
-    this.fixed = fixed;
-  }
-
-  /**
-   * @return the selectedNrs
-   */
-  public int[] getSelectedNrs() {
-    return selectedNrs;
-  }
-
   /**
    * @param selectedNrs the selectedNrs to set
    */
@@ -570,36 +533,4 @@ public class EnterSelectionDialog extends Dialog {
     }
     wSelection.redraw();
   }
-
-  /**
-   * Gets addNoneOption
-   *
-   * @return value of addNoneOption
-   */
-  public boolean isAddNoneOption() {
-    return addNoneOption;
-  }
-
-  /**
-   * @param addNoneOption The addNoneOption to set
-   */
-  public void setAddNoneOption(boolean addNoneOption) {
-    this.addNoneOption = addNoneOption;
-  }
-
-  /**
-   * Gets noneClicked
-   *
-   * @return value of noneClicked
-   */
-  public boolean isNoneClicked() {
-    return noneClicked;
-  }
-
-  /**
-   * @param noneClicked The noneClicked to set
-   */
-  public void setNoneClicked(boolean noneClicked) {
-    this.noneClicked = noneClicked;
-  }
 }
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/ExplorerPerspective.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/ExplorerPerspective.java
index d33c083e29..0d9d3c87cc 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/ExplorerPerspective.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/ExplorerPerspective.java
@@ -1131,6 +1131,47 @@ public class ExplorerPerspective implements 
IHopPerspective, TabClosable {
     return null;
   }
 
+  /**
+   * Close tabs for the given filenames (e.g. after files are deleted by 
revert or external delete).
+   * Only tabs whose handler filename exactly matches one of the given 
filenames are closed.
+   *
+   * @param filenames filenames as stored in the tab handlers (e.g. from 
HopVfs.getFilename)
+   */
+  public void closeTabsForFilenames(java.util.Collection<String> filenames) {
+    if (filenames == null) {
+      return;
+    }
+    for (String filename : filenames) {
+      TabItemHandler handler = findTabItemHandler(filename);
+      if (handler != null) {
+        removeTabItem(handler);
+      }
+    }
+  }
+
+  /**
+   * Reload content from disk for tabs matching the given filenames (e.g. 
after revert that did not
+   * delete the file). Only tabs whose handler filename exactly matches one of 
the given filenames
+   * are reloaded; handlers that support {@link IHopFileTypeHandler#reload()} 
will refresh content.
+   *
+   * @param filenames filenames as stored in the tab handlers (e.g. from 
HopVfs.getFilename)
+   */
+  public void reloadTabsForFilenames(java.util.Collection<String> filenames) {
+    if (filenames == null) {
+      return;
+    }
+    for (String filename : filenames) {
+      TabItemHandler handler = findTabItemHandler(filename);
+      if (handler != null) {
+        try {
+          handler.getTypeHandler().reload();
+        } catch (Exception e) {
+          hopGui.getLog().logError("Error reloading file '" + filename + "'", 
e);
+        }
+      }
+    }
+  }
+
   /**
    * Get an existing tab item handler, can be used when the 
IHopeFileTypeHandler has no file name.
    */

Reply via email to