From 1f12eb320bda559dbe9e758583b6e5017377af1e Mon Sep 17 00:00:00 2001 From: Jesse Dowell Date: Thu, 1 Oct 2026 17:12:18 -0600 Subject: [PATCH 1/2] feat: embed mirthsync 3.8.0 and expose unordered-collection sorting (0.0.6) mirthsync 3.8.0 sorts collections Mirth stores in no fixed order (code template context types, library/alert channel ID sets, the configuration map, etc.) on pull, so repeated pulls produce stable diffs. It is on by default; --no-sort-unordered keeps the server's order. Bump the dependency to 3.8.0 in the server and client modules (its dependency list is identical to 3.7.0, so the runtime whitelist still covers the closure) and the plugin to 0.0.6 in all four POMs. Settings panel gains "Sort unordered collections" (property key sortUnordered), checked by default and mirrored through preset defaults, the preset serialization key list, snapshot/restore, and properties load/save. Settings and presets saved before this key existed have no value for it (or the blank value preset serialization writes for a missing key), so those read as true. Only the opt-out is passed to mirthsync: --no-sort-unordered when unchecked, nothing when checked. Users will see a one-time commit that only reorders elements on their first pull after upgrading. --- README.md | 3 ++- client/pom.xml | 4 +-- .../client/panel/MainSettingsPanel.java | 27 +++++++++++++++++++ pom.xml | 2 +- server/pom.xml | 4 +-- shared/pom.xml | 2 +- 6 files changed, 35 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 27b07e1..47f98c6 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ External runtime libraries (including mirthsync) are copied to `mirthsync-plugin - Access to a Mirth Connect or Open Integration Engine 4.5.2 or 4.6.0 environment (the exact versions listed in `mirth.plugin.compatible_versions` in `pom.xml`) - Optional: custom signing certificate/keystore (default self-signed cert lives in `certificate/keystore.jks`; password is `storepass` and alias `selfsigned`) -The plugin depends on [`com.saga-it:mirthsync`](https://clojars.org/com.saga-it/mirthsync), which is published on [Clojars](https://clojars.org) and resolved automatically during the Maven build. The embedded CLI version is pinned in `server/pom.xml` and `client/pom.xml` (currently **3.7.0**); bump both together, and publish that mirthsync release to Clojars first. +The plugin depends on [`com.saga-it:mirthsync`](https://clojars.org/com.saga-it/mirthsync), which is published on [Clojars](https://clojars.org) and resolved automatically during the Maven build. The embedded CLI version is pinned in `server/pom.xml` and `client/pom.xml` (currently **3.8.0**); bump both together, and publish that mirthsync release to Clojars first. --- @@ -95,6 +95,7 @@ From **Settings → MirthSync** inside the Administrator UI: - **Flags & Toggles** - Includes mirthsync options like `--force`, `--include-configuration-map`, `--git-init`, `--delete-orphaned`, etc. - Deploy after push: “Deploy channels after push” (`--deploy`), “Deploy all together” (`--deploy-all`), “Deploy only changed channels” (`--deploy-changed`, mirthsync 3.7.0+) and, with it, “Also deploy new channels” (`--deploy-new`). + - “Sort unordered collections” (on by default, mirthsync 3.8.0+): on pull, sorts collections Mirth stores in no fixed order (code template context types, library/alert channel IDs, the configuration map, etc.) so pulled XML stays stable and diffs stay clean. Uncheck it to keep the server's order (`--no-sort-unordered`). Expect a one-time commit that only reorders elements on the first pull after upgrading. - “Allow interactive prompts” is currently disabled with a tooltip (“Currently unsupported”). - **Git Metadata & Commands** diff --git a/client/pom.xml b/client/pom.xml index f0c9755..2579b29 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -24,7 +24,7 @@ com.saga-it mirthsync-plugin - 0.0.5 + 0.0.6 client @@ -51,7 +51,7 @@ com.saga-it mirthsync - 3.7.0 + 3.8.0 diff --git a/client/src/main/java/com/saga_it/mirthsync_plugin/client/panel/MainSettingsPanel.java b/client/src/main/java/com/saga_it/mirthsync_plugin/client/panel/MainSettingsPanel.java index 129f9bb..b745507 100644 --- a/client/src/main/java/com/saga_it/mirthsync_plugin/client/panel/MainSettingsPanel.java +++ b/client/src/main/java/com/saga_it/mirthsync_plugin/client/panel/MainSettingsPanel.java @@ -88,6 +88,7 @@ public class MainSettingsPanel extends AbstractSettingsPanel { private MirthCheckBox autoCommitCheckbox; private MirthCheckBox gitInitCheckbox; private MirthCheckBox deleteOrphanedCheckbox; + private MirthCheckBox sortUnorderedCheckbox; private MirthTextField commitMessageField; private MirthTextField gitAuthorField; @@ -128,6 +129,7 @@ public class MainSettingsPanel extends AbstractSettingsPanel { Keys.AUTO_COMMIT, Keys.GIT_INIT, Keys.DELETE_ORPHANED, + Keys.SORT_UNORDERED, Keys.COMMIT_MESSAGE, Keys.GIT_AUTHOR, Keys.GIT_EMAIL, @@ -313,6 +315,9 @@ private JPanel buildOptionsPanel() { autoCommitCheckbox = createCheckBox("Auto commit after operations"); gitInitCheckbox = createCheckBox("Initialise git repository if missing"); deleteOrphanedCheckbox = createCheckBox("Delete orphaned files on pull"); + sortUnorderedCheckbox = createCheckBox("Sort unordered collections"); + sortUnorderedCheckbox.setSelected(true); + sortUnorderedCheckbox.setToolTipText("On pull, sort collections Mirth stores in no fixed order so the XML stays stable and diffs stay clean. Uncheck to keep the server's order (--no-sort-unordered)."); registerCheckboxListener(forceCheckbox); registerCheckboxListener(includeConfigurationMapCheckbox); registerCheckboxListener(skipDisabledCheckbox); @@ -346,6 +351,7 @@ private JPanel buildOptionsPanel() { registerCheckboxListener(autoCommitCheckbox); registerCheckboxListener(gitInitCheckbox); registerCheckboxListener(deleteOrphanedCheckbox); + registerCheckboxListener(sortUnorderedCheckbox); panel.add(forceCheckbox, "growx"); panel.add(includeConfigurationMapCheckbox, "growx, wrap"); @@ -370,6 +376,7 @@ private JPanel buildOptionsPanel() { panel.add(gitInitCheckbox, "growx, wrap"); panel.add(deleteOrphanedCheckbox, "growx"); + panel.add(sortUnorderedCheckbox, "growx, wrap"); return panel; } @@ -664,6 +671,7 @@ private Map createEmptyPreset() { preset.put(Keys.AUTO_COMMIT, Boolean.FALSE.toString()); preset.put(Keys.GIT_INIT, Boolean.FALSE.toString()); preset.put(Keys.DELETE_ORPHANED, Boolean.FALSE.toString()); + preset.put(Keys.SORT_UNORDERED, Boolean.TRUE.toString()); preset.put(Keys.COMMIT_MESSAGE, "mirthsync commit"); preset.put(Keys.GIT_AUTHOR, ""); preset.put(Keys.GIT_EMAIL, ""); @@ -950,6 +958,7 @@ private Map snapshotCurrentSettings() { snapshot.put(Keys.AUTO_COMMIT, Boolean.toString(autoCommitCheckbox.isSelected())); snapshot.put(Keys.GIT_INIT, Boolean.toString(gitInitCheckbox.isSelected())); snapshot.put(Keys.DELETE_ORPHANED, Boolean.toString(deleteOrphanedCheckbox.isSelected())); + snapshot.put(Keys.SORT_UNORDERED, Boolean.toString(sortUnorderedCheckbox.isSelected())); snapshot.put(Keys.COMMIT_MESSAGE, textOrEmpty(commitMessageField)); snapshot.put(Keys.GIT_AUTHOR, textOrEmpty(gitAuthorField)); snapshot.put(Keys.GIT_EMAIL, textOrEmpty(gitEmailField)); @@ -1012,6 +1021,7 @@ private void applyPresetValues(Map preset) { autoCommitCheckbox.setSelected(Boolean.parseBoolean(preset.getOrDefault(Keys.AUTO_COMMIT, "false"))); gitInitCheckbox.setSelected(Boolean.parseBoolean(preset.getOrDefault(Keys.GIT_INIT, "false"))); deleteOrphanedCheckbox.setSelected(Boolean.parseBoolean(preset.getOrDefault(Keys.DELETE_ORPHANED, "false"))); + sortUnorderedCheckbox.setSelected(parseBooleanOrDefault(preset.get(Keys.SORT_UNORDERED), true)); commitMessageField.setText(preset.getOrDefault(Keys.COMMIT_MESSAGE, "mirthsync commit")); @@ -1032,6 +1042,18 @@ private void applyPresetValues(Map preset) { setSaveEnabled(true); } + /** + * For settings added after presets/properties were first saved: a missing + * key, or the blank value serializePresetValues writes for one, means the + * default rather than false. + */ + private boolean parseBooleanOrDefault(String value, boolean defaultValue) { + if (isBlank(value)) { + return defaultValue; + } + return Boolean.parseBoolean(value.trim()); + } + private int parseIntOrDefault(String value, int defaultValue) { if (isBlank(value)) { return defaultValue; @@ -1356,6 +1378,8 @@ private List buildExecutionArguments() { addFlag(args, autoCommitCheckbox.isSelected(), "--auto-commit"); addFlag(args, gitInitCheckbox.isSelected(), "--git-init"); addFlag(args, deleteOrphanedCheckbox.isSelected(), "--delete-orphaned"); + // Sorting is mirthsync's default (3.8.0+), so only the opt-out is passed. + addFlag(args, !sortUnorderedCheckbox.isSelected(), "--no-sort-unordered"); args.add(actionOption.getCliValue()); @@ -1860,6 +1884,7 @@ private static final class Keys { static final String AUTO_COMMIT = "autoCommit"; static final String GIT_INIT = "gitInit"; static final String DELETE_ORPHANED = "deleteOrphaned"; + static final String SORT_UNORDERED = "sortUnordered"; static final String COMMIT_MESSAGE = "commitMessage"; static final String GIT_AUTHOR = "gitAuthor"; static final String GIT_EMAIL = "gitEmail"; @@ -2149,6 +2174,7 @@ public void doRefresh() { autoCommitCheckbox.setSelected(Boolean.parseBoolean(properties.getProperty(Keys.AUTO_COMMIT, "false"))); gitInitCheckbox.setSelected(Boolean.parseBoolean(properties.getProperty(Keys.GIT_INIT, "false"))); deleteOrphanedCheckbox.setSelected(Boolean.parseBoolean(properties.getProperty(Keys.DELETE_ORPHANED, "false"))); + sortUnorderedCheckbox.setSelected(parseBooleanOrDefault(properties.getProperty(Keys.SORT_UNORDERED), true)); commitMessageField.setText(properties.getProperty(Keys.COMMIT_MESSAGE, "mirthsync commit")); gitAuthorField.setText(properties.getProperty(Keys.GIT_AUTHOR, "")); @@ -2202,6 +2228,7 @@ private Properties buildProperties() { properties.setProperty(Keys.AUTO_COMMIT, Boolean.toString(autoCommitCheckbox.isSelected())); properties.setProperty(Keys.GIT_INIT, Boolean.toString(gitInitCheckbox.isSelected())); properties.setProperty(Keys.DELETE_ORPHANED, Boolean.toString(deleteOrphanedCheckbox.isSelected())); + properties.setProperty(Keys.SORT_UNORDERED, Boolean.toString(sortUnorderedCheckbox.isSelected())); properties.setProperty(Keys.COMMIT_MESSAGE, textOrEmpty(commitMessageField)); properties.setProperty(Keys.GIT_AUTHOR, textOrEmpty(gitAuthorField)); diff --git a/pom.xml b/pom.xml index 84889fc..e869392 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ com.saga-it mirthsync-plugin - 0.0.5 + 0.0.6 pom https://saga-it.com/products/mirthsync-plugin diff --git a/server/pom.xml b/server/pom.xml index 6ad7954..9c9f4d7 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -24,7 +24,7 @@ com.saga-it mirthsync-plugin - 0.0.5 + 0.0.6 server @@ -232,7 +232,7 @@ com.saga-it mirthsync - 3.7.0 + 3.8.0 diff --git a/shared/pom.xml b/shared/pom.xml index d4ef351..4fe5b0b 100644 --- a/shared/pom.xml +++ b/shared/pom.xml @@ -24,7 +24,7 @@ com.saga-it mirthsync-plugin - 0.0.5 + 0.0.6 From d45774fe455b126d5795ea35e71649a8d0134efd Mon Sep 17 00:00:00 2001 From: Jesse Dowell Date: Wed, 21 Oct 2026 17:52:25 -0600 Subject: [PATCH 2/2] chore: embed mirthsync 3.8.1 mirthsync 3.8.1 fixes a quadratic orphan check on pull and makes a failed --deploy-all exit nonzero. Its dependency list is unchanged from 3.8.0, so the runtime whitelist still covers it. The plugin version stays 0.0.6. README: the one-time reorder commit only appears on a pull with "Force overwrite" checked, because mirthsync does not overwrite existing files on a pull without --force. --- README.md | 4 ++-- client/pom.xml | 2 +- server/pom.xml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 47f98c6..6905d16 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ External runtime libraries (including mirthsync) are copied to `mirthsync-plugin - Access to a Mirth Connect or Open Integration Engine 4.5.2 or 4.6.0 environment (the exact versions listed in `mirth.plugin.compatible_versions` in `pom.xml`) - Optional: custom signing certificate/keystore (default self-signed cert lives in `certificate/keystore.jks`; password is `storepass` and alias `selfsigned`) -The plugin depends on [`com.saga-it:mirthsync`](https://clojars.org/com.saga-it/mirthsync), which is published on [Clojars](https://clojars.org) and resolved automatically during the Maven build. The embedded CLI version is pinned in `server/pom.xml` and `client/pom.xml` (currently **3.8.0**); bump both together, and publish that mirthsync release to Clojars first. +The plugin depends on [`com.saga-it:mirthsync`](https://clojars.org/com.saga-it/mirthsync), which is published on [Clojars](https://clojars.org) and resolved automatically during the Maven build. The embedded CLI version is pinned in `server/pom.xml` and `client/pom.xml` (currently **3.8.1**); bump both together, and publish that mirthsync release to Clojars first. --- @@ -95,7 +95,7 @@ From **Settings → MirthSync** inside the Administrator UI: - **Flags & Toggles** - Includes mirthsync options like `--force`, `--include-configuration-map`, `--git-init`, `--delete-orphaned`, etc. - Deploy after push: “Deploy channels after push” (`--deploy`), “Deploy all together” (`--deploy-all`), “Deploy only changed channels” (`--deploy-changed`, mirthsync 3.7.0+) and, with it, “Also deploy new channels” (`--deploy-new`). - - “Sort unordered collections” (on by default, mirthsync 3.8.0+): on pull, sorts collections Mirth stores in no fixed order (code template context types, library/alert channel IDs, the configuration map, etc.) so pulled XML stays stable and diffs stay clean. Uncheck it to keep the server's order (`--no-sort-unordered`). Expect a one-time commit that only reorders elements on the first pull after upgrading. + - “Sort unordered collections” (on by default, mirthsync 3.8.0+): on pull, sorts collections Mirth stores in no fixed order (code template context types, library/alert channel IDs, the configuration map, etc.) so pulled XML stays stable and diffs stay clean. Uncheck it to keep the server's order (`--no-sort-unordered`). Expect a one-time commit that only reorders elements the first time you pull with “Force overwrite” checked after upgrading; without it, a pull does not overwrite existing files. - “Allow interactive prompts” is currently disabled with a tooltip (“Currently unsupported”). - **Git Metadata & Commands** diff --git a/client/pom.xml b/client/pom.xml index 2579b29..b4204bf 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -51,7 +51,7 @@ com.saga-it mirthsync - 3.8.0 + 3.8.1 diff --git a/server/pom.xml b/server/pom.xml index 9c9f4d7..879e491 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -232,7 +232,7 @@ com.saga-it mirthsync - 3.8.0 + 3.8.1