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

mcasters 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 b3f7cc8971 Issue #6317 (git GUI plugin options) (#6318)
b3f7cc8971 is described below

commit b3f7cc8971b78858b409612ab5688162f7c67f2b
Author: Matt Casters <[email protected]>
AuthorDate: Fri Jan 9 09:26:12 2026 +0100

    Issue #6317 (git GUI plugin options) (#6318)
    
    Too annoying, so I'm going to merge this.
---
 .../modules/ROOT/pages/hop-gui/hop-gui-git.adoc    |  12 ++
 .../main/java/org/apache/hop/git/GitGuiPlugin.java |  32 ++--
 .../java/org/apache/hop/git/config/GitConfig.java  |  40 +++++
 .../hop/git/config/GitConfigOptionPlugin.java      | 168 +++++++++++++++++++++
 .../apache/hop/git/config/GitConfigSingleton.java  |  76 ++++++++++
 .../git/config/messages/messages_en_US.properties  |  22 +++
 6 files changed, 337 insertions(+), 13 deletions(-)

diff --git a/docs/hop-user-manual/modules/ROOT/pages/hop-gui/hop-gui-git.adoc 
b/docs/hop-user-manual/modules/ROOT/pages/hop-gui/hop-gui-git.adoc
index 20687b2697..2069df7c0f 100644
--- a/docs/hop-user-manual/modules/ROOT/pages/hop-gui/hop-gui-git.adoc
+++ b/docs/hop-user-manual/modules/ROOT/pages/hop-gui/hop-gui-git.adoc
@@ -89,3 +89,15 @@ For workflows and pipelines, click 'Visual diff' to open the 
file in the Data Or
 Hop will show an additional icon in the upper right corner of the action or 
transform icon to indicate the git change that was made (green for added or 
yellow for changed)
 
 image::hop-gui/git-visual-diff.png[Git visual diff,width="65%"]
+
+== Git Configuration options
+
+There are a few global configuration options available for the git GUI plugin.
+You can find these in the configuration perspective under the "Plugins" tab 
and the "git" section.
+
+[options="header", cols="1,2"]
+|===
+|Option|Description
+|Enable the git plugin|If disabled the plugin will be loaded but will not try 
to detect a git repository in the project folder.
+|Search parent folders for git repository|this option will search for a git 
repository (`.git/config` file detection) not just in the project folder but 
also in all parent folders. Please note that enabling this option can lead to 
the git plugin having to consider large amounts of files not always associated 
with the Hop project you're working with.  For this reason the option is 
disabled by default.
+|===
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 6815b69c51..de9f6e77c7 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
@@ -39,6 +39,8 @@ import 
org.apache.hop.core.gui.plugin.toolbar.GuiToolbarElementType;
 import org.apache.hop.core.logging.LogChannel;
 import org.apache.hop.core.util.Utils;
 import org.apache.hop.core.vfs.HopVfs;
+import org.apache.hop.git.config.GitConfig;
+import org.apache.hop.git.config.GitConfigSingleton;
 import org.apache.hop.git.info.GitInfoExplorerFileType;
 import org.apache.hop.git.info.GitInfoExplorerFileTypeHandler;
 import org.apache.hop.git.model.UIFile;
@@ -658,29 +660,33 @@ public class GitGuiPlugin
   public void rootChanged(String rootFolder, String rootName) {
     // OK, let's see if we can determine the current git instance...
     //
-    try (FileObject folder = findGitConfig(rootFolder)) {
-      if (folder != null) {
-        git = new UIGit();
-        git.openRepo(HopVfs.getFilename(folder));
-        setBranchLabel(git.getBranch());
-      } else {
+    GitConfig config = GitConfigSingleton.getConfig();
+
+    git = null;
+    setBranchLabel(null);
+
+    if (config.isEnabled()) {
+      try (FileObject folder = findGitConfig(rootFolder, 
config.isSearchingParentFolders())) {
+        if (folder != null) {
+          git = new UIGit();
+          git.openRepo(HopVfs.getFilename(folder));
+          setBranchLabel(git.getBranch());
+        }
+      } catch (Exception e) {
+        // This is not a git project...
         git = null;
-        setBranchLabel(null);
+        LogChannel.UI.logBasic("No git project found in " + rootFolder);
       }
-    } catch (Exception e) {
-      // This is not a git project...
-      git = null;
-      LogChannel.UI.logBasic("No git project found in " + rootFolder);
     }
     refreshChangedFiles();
     enableButtons();
   }
 
-  private FileObject findGitConfig(String rootFolderName)
+  private FileObject findGitConfig(String rootFolderName, boolean 
searchParentFolders)
       throws HopFileException, FileSystemException {
     FileObject folder = HopVfs.getFileObject(rootFolderName);
     FileObject fileObject = folder.resolveFile(".git/config");
-    while (!fileObject.exists() && folder.getParent() != null) {
+    while (searchParentFolders && !fileObject.exists() && folder.getParent() 
!= null) {
       folder = folder.getParent();
       fileObject = folder.resolveFile(".git/config");
     }
diff --git 
a/plugins/misc/git/src/main/java/org/apache/hop/git/config/GitConfig.java 
b/plugins/misc/git/src/main/java/org/apache/hop/git/config/GitConfig.java
new file mode 100644
index 0000000000..561e39284a
--- /dev/null
+++ b/plugins/misc/git/src/main/java/org/apache/hop/git/config/GitConfig.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.hop.git.config;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class GitConfig {
+  public static final String HOP_CONFIG_GIT_CONFIG_KEY = "gitConfig";
+  private boolean enabled;
+  private boolean searchingParentFolders;
+
+  public GitConfig() {
+    this.enabled = true;
+    this.searchingParentFolders = false;
+  }
+
+  public GitConfig(GitConfig config) {
+    this.enabled = config.enabled;
+    this.searchingParentFolders = config.searchingParentFolders;
+  }
+}
diff --git 
a/plugins/misc/git/src/main/java/org/apache/hop/git/config/GitConfigOptionPlugin.java
 
b/plugins/misc/git/src/main/java/org/apache/hop/git/config/GitConfigOptionPlugin.java
new file mode 100644
index 0000000000..c4b411e3fb
--- /dev/null
+++ 
b/plugins/misc/git/src/main/java/org/apache/hop/git/config/GitConfigOptionPlugin.java
@@ -0,0 +1,168 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.hop.git.config;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.hop.core.config.plugin.ConfigPlugin;
+import org.apache.hop.core.config.plugin.IConfigOptions;
+import org.apache.hop.core.exception.HopException;
+import org.apache.hop.core.gui.plugin.GuiElementType;
+import org.apache.hop.core.gui.plugin.GuiPlugin;
+import org.apache.hop.core.gui.plugin.GuiWidgetElement;
+import org.apache.hop.core.logging.ILogChannel;
+import org.apache.hop.core.variables.IVariables;
+import org.apache.hop.i18n.BaseMessages;
+import org.apache.hop.metadata.api.IHasHopMetadataProvider;
+import org.apache.hop.ui.core.dialog.ErrorDialog;
+import org.apache.hop.ui.core.gui.GuiCompositeWidgets;
+import org.apache.hop.ui.core.gui.IGuiPluginCompositeWidgetsListener;
+import org.apache.hop.ui.hopgui.HopGui;
+import 
org.apache.hop.ui.hopgui.perspective.configuration.tabs.ConfigPluginOptionsTab;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Control;
+import picocli.CommandLine;
+
+@ConfigPlugin(
+    id = "GitConfigOptionPlugin",
+    description = "Configuration options for the git GUI plugin")
+@GuiPlugin(
+    description = "i18n::GitConfig.Tab.Name" // label in options dialog
+    )
+@Getter
+@Setter
+public class GitConfigOptionPlugin implements IConfigOptions, 
IGuiPluginCompositeWidgetsListener {
+  protected static final Class<?> PKG = GitConfigOptionPlugin.class;
+
+  private static final String WIDGET_ID_GIT_ENABLE = "10000-git-enable-plugin";
+  private static final String WIDGET_ID_GIT_SEARCH_PARENT_FOLDERS =
+      "10010-git-search-parent-folders";
+
+  @GuiWidgetElement(
+      id = WIDGET_ID_GIT_ENABLE,
+      parentId = ConfigPluginOptionsTab.GUI_WIDGETS_PARENT_ID,
+      type = GuiElementType.CHECKBOX,
+      label = "i18n::GitConfig.EnableGitPlugin.Message")
+  @CommandLine.Option(
+      names = {"--git-gui-enabled"},
+      description = "Enable or disable the git GUI plugin")
+  private Boolean gitEnabled;
+
+  @GuiWidgetElement(
+      id = WIDGET_ID_GIT_SEARCH_PARENT_FOLDERS,
+      parentId = ConfigPluginOptionsTab.GUI_WIDGETS_PARENT_ID,
+      type = GuiElementType.CHECKBOX,
+      label = "i18n::GitConfig.SearchParentFolders.Message")
+  @CommandLine.Option(
+      names = {"--git-gui-search-parent-folders"},
+      description = "The git GUI searches the parent folders for a repository")
+  private Boolean searchingParentFolders;
+
+  public static GitConfigOptionPlugin getInstance() {
+    GitConfigOptionPlugin instance = new GitConfigOptionPlugin();
+    GitConfig config = GitConfigSingleton.getConfig();
+    instance.gitEnabled = config.isEnabled();
+    instance.searchingParentFolders = config.isSearchingParentFolders();
+    return instance;
+  }
+
+  @Override
+  public boolean handleOption(
+      ILogChannel log, IHasHopMetadataProvider hasHopMetadataProvider, 
IVariables variables)
+      throws HopException {
+    GitConfig config = GitConfigSingleton.getConfig();
+    try {
+      boolean changed = false;
+      if (gitEnabled != null) {
+        config.setEnabled(gitEnabled);
+        if (gitEnabled) {
+          log.logBasic("Enabled the git GUI plugin");
+        } else {
+          log.logBasic("Disabled the git GUI plugin");
+        }
+        changed = true;
+      }
+      if (searchingParentFolders != null) {
+        config.setSearchingParentFolders(searchingParentFolders);
+        if (searchingParentFolders) {
+          log.logBasic("The git GUI plugin is searching parent folders for a 
repository.");
+        } else {
+          log.logBasic(
+              "The git GUI plugin only looks at the project home folder for a 
repository.");
+        }
+        changed = true;
+      }
+
+      // Save to file if anything changed
+      //
+      if (changed) {
+        GitConfigSingleton.saveConfig();
+      }
+      return changed;
+    } catch (Exception e) {
+      throw new HopException("Error handling git plugin configuration 
options", e);
+    }
+  }
+
+  @Override
+  public void widgetsCreated(GuiCompositeWidgets compositeWidgets) {
+    // Do nothing
+  }
+
+  @Override
+  public void widgetsPopulated(GuiCompositeWidgets compositeWidgets) {
+    // Do nothing
+  }
+
+  @Override
+  public void widgetModified(
+      GuiCompositeWidgets compositeWidgets, Control changedWidget, String 
widgetId) {
+    persistContents(compositeWidgets);
+  }
+
+  @Override
+  public void persistContents(GuiCompositeWidgets compositeWidgets) {
+    for (String widgetId : compositeWidgets.getWidgetsMap().keySet()) {
+      Control control = compositeWidgets.getWidgetsMap().get(widgetId);
+      switch (widgetId) {
+        case WIDGET_ID_GIT_ENABLE:
+          gitEnabled = ((Button) control).getSelection();
+          GitConfigSingleton.getConfig().setEnabled(gitEnabled);
+          break;
+        case WIDGET_ID_GIT_SEARCH_PARENT_FOLDERS:
+          searchingParentFolders = ((Button) control).getSelection();
+          
GitConfigSingleton.getConfig().setSearchingParentFolders(searchingParentFolders);
+          break;
+        default:
+          break;
+      }
+    }
+    // Save the project...
+    //
+    try {
+      GitConfigSingleton.saveConfig();
+    } catch (Exception e) {
+      new ErrorDialog(
+          HopGui.getInstance().getShell(),
+          BaseMessages.getString(PKG, 
"GitConfig.SavingOption.ErrorDialog.Header"),
+          BaseMessages.getString(PKG, 
"GitConfig.SavingOption.ErrorDialog.Message"),
+          e);
+    }
+  }
+}
diff --git 
a/plugins/misc/git/src/main/java/org/apache/hop/git/config/GitConfigSingleton.java
 
b/plugins/misc/git/src/main/java/org/apache/hop/git/config/GitConfigSingleton.java
new file mode 100644
index 0000000000..124852af3d
--- /dev/null
+++ 
b/plugins/misc/git/src/main/java/org/apache/hop/git/config/GitConfigSingleton.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.git.config;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.gson.Gson;
+import org.apache.hop.core.config.HopConfig;
+import org.apache.hop.core.exception.HopException;
+import org.apache.hop.core.json.HopJson;
+import org.apache.hop.core.logging.LogChannel;
+
+public class GitConfigSingleton {
+
+  private static GitConfigSingleton configSingleton;
+
+  private GitConfig gitConfig;
+
+  private GitConfigSingleton() {
+    // Load from the HopConfig store
+    //
+    Object configObject =
+        
HopConfig.getInstance().getConfigMap().get(GitConfig.HOP_CONFIG_GIT_CONFIG_KEY);
+    if (configObject == null) {
+      gitConfig = new GitConfig();
+    } else {
+      // The way Jackson stores these simple POJO is with a map per default...
+      // So we don't really need to mess around with Deserializer and so on.
+      // This way we can keep the class name out of the JSON as well.
+      //
+      try {
+        ObjectMapper mapper = HopJson.newMapper();
+        gitConfig = mapper.readValue(new Gson().toJson(configObject), 
GitConfig.class);
+      } catch (Exception e) {
+        LogChannel.GENERAL.logError(
+            "Error reading git configuration, check property '"
+                + GitConfig.HOP_CONFIG_GIT_CONFIG_KEY
+                + "' in the Hop config json file",
+            e);
+        gitConfig = new GitConfig();
+      }
+    }
+    
HopConfig.getInstance().getConfigMap().put(GitConfig.HOP_CONFIG_GIT_CONFIG_KEY, 
gitConfig);
+  }
+
+  public static GitConfigSingleton getInstance() {
+    return configSingleton;
+  }
+
+  public static GitConfig getConfig() {
+    if (configSingleton == null) {
+      configSingleton = new GitConfigSingleton();
+    }
+    return configSingleton.gitConfig;
+  }
+
+  public static void saveConfig() throws HopException {
+    HopConfig.getInstance()
+        .saveOption(GitConfig.HOP_CONFIG_GIT_CONFIG_KEY, 
configSingleton.gitConfig);
+    HopConfig.getInstance().saveToFile();
+  }
+}
diff --git 
a/plugins/misc/git/src/main/resources/org/apache/hop/git/config/messages/messages_en_US.properties
 
b/plugins/misc/git/src/main/resources/org/apache/hop/git/config/messages/messages_en_US.properties
new file mode 100644
index 0000000000..733677a60c
--- /dev/null
+++ 
b/plugins/misc/git/src/main/resources/org/apache/hop/git/config/messages/messages_en_US.properties
@@ -0,0 +1,22 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+GitConfig.Tab.Name=git
+GitConfig.EnableGitPlugin.Message=Enable the git GUI plugin
+GitConfig.SearchParentFolders.Message=Search parent folders for git repository
+GitConfig.SavingOption.ErrorDialog.Header=Error
+GitConfig.SavingOption.ErrorDialog.Message=Error saving option

Reply via email to