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

mattcasters 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 6e13af56a5 Fix pipeline marked dirty after opening a transform dialog 
and clicking OK without changes (#7428)
6e13af56a5 is described below

commit 6e13af56a50ce4313bf4ebe848e53ed02e2a9d43
Author: Lance <[email protected]>
AuthorDate: Sun Jul 5 05:51:35 2026 +0800

    Fix pipeline marked dirty after opening a transform dialog and clicking OK 
without changes (#7428)
    
    Signed-off-by: lance <[email protected]>
---
 .../delegates/HopGuiPipelineTransformDelegate.java | 92 ++++++++++++++--------
 1 file changed, 61 insertions(+), 31 deletions(-)

diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/delegates/HopGuiPipelineTransformDelegate.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/delegates/HopGuiPipelineTransformDelegate.java
index c15dcf3d6d..a33e6e0164 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/delegates/HopGuiPipelineTransformDelegate.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/delegates/HopGuiPipelineTransformDelegate.java
@@ -26,6 +26,7 @@ import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import org.apache.hop.core.Const;
 import org.apache.hop.core.exception.HopException;
 import org.apache.hop.core.extension.ExtensionPointHandler;
 import org.apache.hop.core.extension.HopExtensionPoint;
@@ -193,22 +194,21 @@ public class HopGuiPipelineTransformDelegate {
         return null;
       }
 
-      // Before we do anything, let's store the situation the way it
-      // was...
-      //
-      TransformMeta before = (TransformMeta) transformMeta.clone();
       dialog = getTransformDialog(transformMeta.getTransform(), pipelineMeta, 
name);
+      TransformMeta before = null;
       if (dialog != null) {
         dialogs.put(name, dialog);
 
         dialog.setMetadataProvider(hopGui.getMetadataProvider());
         transformMeta.getTransform().convertIOMetaToTransformNames();
+        // Snapshot after IO-meta normalization so OK-without-edits is not 
treated as a change.
+        before = (TransformMeta) transformMeta.clone();
         transformName = dialog.open();
 
         dialogs.remove(name);
       }
 
-      if (!Utils.isEmpty(transformName)) {
+      if (!Utils.isEmpty(transformName) && before != null) {
         // Force the recreation of the transform IO metadata object. (cached 
by default)
         //
         transformMeta.getTransform().resetTransformIoMeta();
@@ -227,11 +227,6 @@ public class HopGuiPipelineTransformDelegate {
         //
         
transformMeta.getTransform().searchInfoAndTargetTransforms(pipelineMeta.getTransforms());
 
-        // Mark the TransformMeta wrapper as changed since the dialog was 
closed with OK
-        // This ensures that changes are properly tracked regardless of inner 
metadata object
-        // identity
-        transformMeta.setChanged();
-
         //
         // See if the new name the user enter, doesn't collide with
         // another transform.
@@ -261,17 +256,17 @@ public class HopGuiPipelineTransformDelegate {
         pipelineMeta.notifyAllListeners(transformMeta, newTransformMeta);
         transformMeta.setName(transformName);
 
-        //
-        // OK, so the transform has changed...
-        // Backup the situation for undo/redo
-        //
         TransformMeta after = (TransformMeta) transformMeta.clone();
-
-        hopGui.undoDelegate.addUndoChange(
-            pipelineMeta,
-            new TransformMeta[] {before},
-            new TransformMeta[] {after},
-            new int[] {pipelineMeta.indexOfTransform(transformMeta)});
+        if (hasTransformMetaChanged(before, after)) {
+          transformMeta.setChanged();
+          hopGui.undoDelegate.addUndoChange(
+              pipelineMeta,
+              new TransformMeta[] {before},
+              new TransformMeta[] {after},
+              new int[] {pipelineMeta.indexOfTransform(transformMeta)});
+        } else {
+          transformMeta.setChanged(before.hasChanged());
+        }
       }
       pipelineGraph.updateGui();
 
@@ -603,16 +598,23 @@ public class HopGuiPipelineTransformDelegate {
                 return dialog.open();
               });
         }
-        transformMeta.setChanged();
-        hopGui.undoDelegate.addUndoChange(
-            partitionSettings.getPipelineMeta(),
-            new TransformMeta[] {partitionSettings.getBefore()},
-            new TransformMeta[] {partitionSettings.getAfter()},
-            new int[] {
-              partitionSettings
-                  .getPipelineMeta()
-                  .indexOfTransform(partitionSettings.getTransformMeta())
-            });
+
+        TransformMeta partitionBefore = partitionSettings.getBefore();
+        TransformMeta partitionAfter = partitionSettings.getAfter();
+        if (hasTransformMetaChanged(partitionBefore, partitionAfter)) {
+          transformMeta.setChanged();
+          hopGui.undoDelegate.addUndoChange(
+              partitionSettings.getPipelineMeta(),
+              new TransformMeta[] {partitionBefore},
+              new TransformMeta[] {partitionAfter},
+              new int[] {
+                partitionSettings
+                    .getPipelineMeta()
+                    .indexOfTransform(partitionSettings.getTransformMeta())
+              });
+        } else {
+          transformMeta.setChanged(partitionBefore.hasChanged());
+        }
         pipelineGraph.redraw();
       }
     } catch (Exception e) {
@@ -677,6 +679,7 @@ public class HopGuiPipelineTransformDelegate {
       List<TransformMeta> targetTransforms = 
pipelineMeta.findNextTransforms(transformMeta, true);
 
       // now edit this transformErrorMeta object:
+      TransformMeta before = (TransformMeta) transformMeta.clone();
       TransformErrorMetaDialog dialog =
           new TransformErrorMetaDialog(
               hopGui.getActiveShell(),
@@ -686,12 +689,39 @@ public class HopGuiPipelineTransformDelegate {
               targetTransforms);
       if (dialog.open()) {
         transformMeta.setTransformErrorMeta(transformErrorMeta);
-        transformMeta.setChanged();
+        TransformMeta after = (TransformMeta) transformMeta.clone();
+        if (hasTransformMetaChanged(before, after)) {
+          transformMeta.setChanged();
+        } else {
+          transformMeta.setChanged(before.hasChanged());
+        }
         pipelineGraph.redraw();
       }
     }
   }
 
+  /**
+   * Returns {@code true} if two transform snapshots differ in persisted 
configuration (transform
+   * body, partitioning, GUI placement, and error handling).
+   */
+  private static boolean hasTransformMetaChanged(TransformMeta before, 
TransformMeta after) {
+    try {
+      if (!before.getXml().equals(after.getXml())) {
+        return true;
+      }
+
+      return !getErrorMetaXml(before).equals(getErrorMetaXml(after));
+    } catch (HopException e) {
+      // If comparison fails, treat as changed to avoid losing edits.
+      return true;
+    }
+  }
+
+  private static String getErrorMetaXml(TransformMeta transformMeta) throws 
HopException {
+    TransformErrorMeta errorMeta = transformMeta.getTransformErrorMeta();
+    return errorMeta == null ? Const.EMPTY_STRING : errorMeta.getXml();
+  }
+
   public void delTransforms(PipelineMeta pipelineMeta, List<TransformMeta> 
transforms) {
     if (Utils.isEmpty(transforms)) {
       return; // nothing to do

Reply via email to