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.
*/