From 5cefac47222c63d257d6c4ff958038659fc07515 Mon Sep 17 00:00:00 2001 From: Techassi Date: Wed, 21 Oct 2026 13:36:22 +0200 Subject: [PATCH 1/5] fix(versioned): Handle tracked per-version changes across multiple containers This fixes https://github.com/stackabletech/operator-rs/issues/1302. --- .../codegen/container/struct/conversion.rs | 17 +++--- .../src/codegen/item/field.rs | 11 ++-- ...napshots__pass@conversion_tracking.rs.snap | 27 +++++----- ...ots__pass@conversion_tracking_enum.rs.snap | 28 +++++----- ..._pass@conversion_tracking_generics.rs.snap | 54 ++++++++++--------- ...ts__pass@conversion_tracking_hints.rs.snap | 28 +++++----- ...ioned_macros__snapshots__pass@docs.rs.snap | 35 ++++++------ crates/stackable-versioned/src/lib.rs | 30 +++++++++++ 8 files changed, 139 insertions(+), 91 deletions(-) diff --git a/crates/stackable-versioned-macros/src/codegen/container/struct/conversion.rs b/crates/stackable-versioned-macros/src/codegen/container/struct/conversion.rs index 419e239fe..8093345b3 100644 --- a/crates/stackable-versioned-macros/src/codegen/container/struct/conversion.rs +++ b/crates/stackable-versioned-macros/src/codegen/container/struct/conversion.rs @@ -189,7 +189,7 @@ impl Struct { { fn tracking_from(#from_struct_ident: #from_module_ident::#struct_ident #type_generics, status: &mut __SvStatus, parent: &str) -> Self { // TODO (@Techassi): Only emit this if any of the fields below need it - use #versioned_path::TrackingInto as _; + use #versioned_path::{RemoveIf as _, TrackingInto as _}; #json_paths // Depending on the direction, we need to either insert changed values into @@ -264,7 +264,7 @@ impl Struct { return None; } - let match_arms: TokenStream = self + let removals: TokenStream = self .fields .iter() .filter_map(|f| f.generate_for_status_removal(direction, next_version, mod_gen_ctx)) @@ -273,16 +273,13 @@ impl Struct { match direction { Direction::Upgrade => { let next_version_string = next_version.inner.to_string(); - let versioned_path = &*mod_gen_ctx.crates.versioned; Some(quote! { - // NOTE (@Techassi): This is an awkward thing to do. Can we possibly use &str for the keys here? - if let Some(upgrades) = status.changes().upgrades.remove(&#next_version_string.to_owned()) { - for #versioned_path::ChangedValue { json_path, value } in upgrades { - match json_path { - #match_arms - _ => unreachable!(), - } + if let Some(upgrades) = status.changes().upgrades.get_mut(#next_version_string) { + #removals + + if upgrades.is_empty() { + status.changes().upgrades.remove(#next_version_string); } } }) diff --git a/crates/stackable-versioned-macros/src/codegen/item/field.rs b/crates/stackable-versioned-macros/src/codegen/item/field.rs index c14fcd92d..08806512d 100644 --- a/crates/stackable-versioned-macros/src/codegen/item/field.rs +++ b/crates/stackable-versioned-macros/src/codegen/item/field.rs @@ -350,6 +350,7 @@ impl VersionedField { let changes = self.changes.as_ref()?; let yaml_serde_path = &*mod_gen_ctx.crates.yaml_serde; + let versioned_path = &*mod_gen_ctx.crates.versioned; match direction { Direction::Upgrade => { @@ -360,11 +361,15 @@ impl VersionedField { // we only need to generate code if the next change is "Addition". ItemStatus::Addition { ident, .. } => { let json_path_ident = ident.json_path_ident(); + let expect_message = format!( + "internal error: {{{json_path_ident}}} must be serializable for spec.{ident}" + ); Some(quote! { - json_path if json_path == #json_path_ident => { - spec.#ident = #yaml_serde_path::from_value(value).unwrap(); - }, + if let Some(#versioned_path::ChangedValue { value, .. }) = upgrades.remove_if(|u| u.json_path == #json_path_ident) { + // TODO (@Techassi): Switch to serde_json + spec.#ident = #yaml_serde_path::from_value(value).expect(#expect_message); + } }) } _ => None, diff --git a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@conversion_tracking.rs.snap b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@conversion_tracking.rs.snap index 54b85a93d..c859f3c5f 100644 --- a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@conversion_tracking.rs.snap +++ b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@conversion_tracking.rs.snap @@ -59,20 +59,23 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::TrackingInto as _; + use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; let __sv_bah_path = ::stackable_versioned::jthong_path(parent, "bah"); let mut spec = Self { bah: ::std::default::Default::default(), baz: __sv_foospec.baz.into(), }; - if let Some(upgrades) = status.changes().upgrades.remove(&"v1beta1".to_owned()) { - for ::stackable_versioned::ChangedValue { json_path, value } in upgrades { - match json_path { - json_path if json_path == __sv_bah_path => { - spec.bah = ::yaml_serde::from_value(value).unwrap(); - } - _ => unreachable!(), - } + if let Some(upgrades) = status.changes().upgrades.get_mut("v1beta1") { + if let Some(::stackable_versioned::ChangedValue { value, .. }) = upgrades + .remove_if(|u| u.json_path == __sv_bah_path) + { + spec.bah = ::yaml_serde::from_value(value) + .expect( + "internal error: {__sv_bah_path} must be serializable for spec.bah", + ); + } + if upgrades.is_empty() { + status.changes().upgrades.remove("v1beta1"); } } spec @@ -89,7 +92,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::TrackingInto as _; + use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; let __sv_bah_path = ::stackable_versioned::jthong_path(parent, "bah"); let upgrades = status .changes() @@ -164,7 +167,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::TrackingInto as _; + use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; let mut spec = Self { bar: __sv_foospec.bah.into(), baz: __sv_foospec.baz.into(), @@ -183,7 +186,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::TrackingInto as _; + use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; let mut spec = Self { bah: __sv_foospec.bar.into(), baz: __sv_foospec.baz.into(), diff --git a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@conversion_tracking_enum.rs.snap b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@conversion_tracking_enum.rs.snap index 42addbd12..6b7773e58 100644 --- a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@conversion_tracking_enum.rs.snap +++ b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@conversion_tracking_enum.rs.snap @@ -72,7 +72,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::TrackingInto as _; + use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; let __sv_connector_path = ::stackable_versioned::jthong_path( parent, "connector", @@ -94,7 +94,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::TrackingInto as _; + use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; let __sv_connector_path = ::stackable_versioned::jthong_path( parent, "connector", @@ -224,7 +224,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::TrackingInto as _; + use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; let __sv_rest_catalog_uri_path = ::stackable_versioned::jthong_path( parent, "rest_catalog_uri", @@ -233,15 +233,17 @@ where metastore: __sv_icebergconnector.metastore.into(), rest_catalog_uri: ::std::default::Default::default(), }; - if let Some(upgrades) = status.changes().upgrades.remove(&"v1alpha2".to_owned()) - { - for ::stackable_versioned::ChangedValue { json_path, value } in upgrades { - match json_path { - json_path if json_path == __sv_rest_catalog_uri_path => { - spec.rest_catalog_uri = ::yaml_serde::from_value(value).unwrap(); - } - _ => unreachable!(), - } + if let Some(upgrades) = status.changes().upgrades.get_mut("v1alpha2") { + if let Some(::stackable_versioned::ChangedValue { value, .. }) = upgrades + .remove_if(|u| u.json_path == __sv_rest_catalog_uri_path) + { + spec.rest_catalog_uri = ::yaml_serde::from_value(value) + .expect( + "internal error: {__sv_rest_catalog_uri_path} must be serializable for spec.rest_catalog_uri", + ); + } + if upgrades.is_empty() { + status.changes().upgrades.remove("v1alpha2"); } } spec @@ -260,7 +262,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::TrackingInto as _; + use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; let __sv_rest_catalog_uri_path = ::stackable_versioned::jthong_path( parent, "rest_catalog_uri", diff --git a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@conversion_tracking_generics.rs.snap b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@conversion_tracking_generics.rs.snap index d20e46bbc..ce6f34817 100644 --- a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@conversion_tracking_generics.rs.snap +++ b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@conversion_tracking_generics.rs.snap @@ -68,21 +68,24 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::TrackingInto as _; + use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; let __sv_bah_path = ::stackable_versioned::jthong_path(parent, "bah"); let __sv_baz_path = ::stackable_versioned::jthong_path(parent, "baz"); let mut spec = Self { bah: ::std::default::Default::default(), baz: __sv_foospec.baz.tracking_into(status, &__sv_baz_path), }; - if let Some(upgrades) = status.changes().upgrades.remove(&"v1beta1".to_owned()) { - for ::stackable_versioned::ChangedValue { json_path, value } in upgrades { - match json_path { - json_path if json_path == __sv_bah_path => { - spec.bah = ::yaml_serde::from_value(value).unwrap(); - } - _ => unreachable!(), - } + if let Some(upgrades) = status.changes().upgrades.get_mut("v1beta1") { + if let Some(::stackable_versioned::ChangedValue { value, .. }) = upgrades + .remove_if(|u| u.json_path == __sv_bah_path) + { + spec.bah = ::yaml_serde::from_value(value) + .expect( + "internal error: {__sv_bah_path} must be serializable for spec.bah", + ); + } + if upgrades.is_empty() { + status.changes().upgrades.remove("v1beta1"); } } spec @@ -99,7 +102,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::TrackingInto as _; + use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; let __sv_bah_path = ::stackable_versioned::jthong_path(parent, "bah"); let __sv_baz_path = ::stackable_versioned::jthong_path(parent, "baz"); let upgrades = status @@ -130,7 +133,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::TrackingInto as _; + use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; let mut spec = Self { inner_1: __sv_baz.inner_1.into(), inner_2: __sv_baz.inner_2.into(), @@ -150,7 +153,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::TrackingInto as _; + use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; let mut spec = Self { inner_1: __sv_baz.inner_1.into(), inner_2: __sv_baz.inner_2.into(), @@ -224,7 +227,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::TrackingInto as _; + use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; let __sv_baz_path = ::stackable_versioned::jthong_path(parent, "baz"); let mut spec = Self { bar: __sv_foospec.bah.into(), @@ -244,7 +247,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::TrackingInto as _; + use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; let __sv_baz_path = ::stackable_versioned::jthong_path(parent, "baz"); let mut spec = Self { bah: __sv_foospec.bar.into(), @@ -265,21 +268,24 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::TrackingInto as _; + use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; let __sv_inner_3_path = ::stackable_versioned::jthong_path(parent, "inner_3"); let mut spec = Self { inner_1: __sv_baz.inner_1.into(), inner_2: __sv_baz.inner_2.into(), inner_3: ::std::default::Default::default(), }; - if let Some(upgrades) = status.changes().upgrades.remove(&"v1".to_owned()) { - for ::stackable_versioned::ChangedValue { json_path, value } in upgrades { - match json_path { - json_path if json_path == __sv_inner_3_path => { - spec.inner_3 = ::yaml_serde::from_value(value).unwrap(); - } - _ => unreachable!(), - } + if let Some(upgrades) = status.changes().upgrades.get_mut("v1") { + if let Some(::stackable_versioned::ChangedValue { value, .. }) = upgrades + .remove_if(|u| u.json_path == __sv_inner_3_path) + { + spec.inner_3 = ::yaml_serde::from_value(value) + .expect( + "internal error: {__sv_inner_3_path} must be serializable for spec.inner_3", + ); + } + if upgrades.is_empty() { + status.changes().upgrades.remove("v1"); } } spec @@ -297,7 +303,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::TrackingInto as _; + use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; let __sv_inner_3_path = ::stackable_versioned::jthong_path(parent, "inner_3"); let upgrades = status.changes().upgrades.entry("v1".to_owned()).or_default(); upgrades diff --git a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@conversion_tracking_hints.rs.snap b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@conversion_tracking_hints.rs.snap index b45919ea7..90b12653a 100644 --- a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@conversion_tracking_hints.rs.snap +++ b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@conversion_tracking_hints.rs.snap @@ -26,7 +26,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::TrackingInto as _; + use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; let __sv_bar_path = ::stackable_versioned::jthong_path(parent, "bar"); let mut spec = Self { bar: __sv_foo.bar.map(|v| v.tracking_into(status, &__sv_bar_path)), @@ -47,7 +47,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::TrackingInto as _; + use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; let __sv_bar_path = ::stackable_versioned::jthong_path(parent, "bar"); let mut spec = Self { bar: __sv_foo.bar.map(|v| v.tracking_into(status, &__sv_bar_path)), @@ -68,21 +68,23 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::TrackingInto as _; + use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; let __sv_baz_baz_path = ::stackable_versioned::jthong_path(parent, "baz_baz"); let mut spec = Self { bar_bar: __sv_bar.bar_bar.into(), baz_baz: ::std::default::Default::default(), }; - if let Some(upgrades) = status.changes().upgrades.remove(&"v1alpha2".to_owned()) - { - for ::stackable_versioned::ChangedValue { json_path, value } in upgrades { - match json_path { - json_path if json_path == __sv_baz_baz_path => { - spec.baz_baz = ::yaml_serde::from_value(value).unwrap(); - } - _ => unreachable!(), - } + if let Some(upgrades) = status.changes().upgrades.get_mut("v1alpha2") { + if let Some(::stackable_versioned::ChangedValue { value, .. }) = upgrades + .remove_if(|u| u.json_path == __sv_baz_baz_path) + { + spec.baz_baz = ::yaml_serde::from_value(value) + .expect( + "internal error: {__sv_baz_baz_path} must be serializable for spec.baz_baz", + ); + } + if upgrades.is_empty() { + status.changes().upgrades.remove("v1alpha2"); } } spec @@ -99,7 +101,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::TrackingInto as _; + use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; let __sv_baz_baz_path = ::stackable_versioned::jthong_path(parent, "baz_baz"); let upgrades = status .changes() diff --git a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@docs.rs.snap b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@docs.rs.snap index fd4d643bb..c85ca94aa 100644 --- a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@docs.rs.snap +++ b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@docs.rs.snap @@ -42,7 +42,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::TrackingInto as _; + use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; let __sv_baz_path = ::stackable_versioned::jthong_path(parent, "baz"); let mut spec = Self { foo: __sv_foo.foo.into(), @@ -52,14 +52,17 @@ where corge: __sv_foo.corge.into(), fred: __sv_foo.waldo.into(), }; - if let Some(upgrades) = status.changes().upgrades.remove(&"v1beta1".to_owned()) { - for ::stackable_versioned::ChangedValue { json_path, value } in upgrades { - match json_path { - json_path if json_path == __sv_baz_path => { - spec.baz = ::yaml_serde::from_value(value).unwrap(); - } - _ => unreachable!(), - } + if let Some(upgrades) = status.changes().upgrades.get_mut("v1beta1") { + if let Some(::stackable_versioned::ChangedValue { value, .. }) = upgrades + .remove_if(|u| u.json_path == __sv_baz_path) + { + spec.baz = ::yaml_serde::from_value(value) + .expect( + "internal error: {__sv_baz_path} must be serializable for spec.baz", + ); + } + if upgrades.is_empty() { + status.changes().upgrades.remove("v1beta1"); } } spec @@ -77,7 +80,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::TrackingInto as _; + use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; let __sv_baz_path = ::stackable_versioned::jthong_path(parent, "baz"); let upgrades = status .changes() @@ -183,7 +186,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::TrackingInto as _; + use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; let mut spec = Self { foo: __sv_foo.foo.into(), deprecated_bar: __sv_foo.deprecated_bar.into(), @@ -207,7 +210,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::TrackingInto as _; + use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; let mut spec = Self { foo: __sv_foo.foo.into(), deprecated_bar: __sv_foo.deprecated_bar.into(), @@ -297,7 +300,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::TrackingInto as _; + use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; let mut spec = Self { foo: __sv_foo.foo.into(), deprecated_bar: __sv_foo.deprecated_bar.into(), @@ -317,7 +320,7 @@ where __SvStatus: ::stackable_versioned::TrackingStatus + ::core::default::Default, { fn tracking_from(__sv_foo: v1::Foo, status: &mut __SvStatus, parent: &str) -> Self { - use ::stackable_versioned::TrackingInto as _; + use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; let mut spec = Self { foo: __sv_foo.foo.into(), deprecated_bar: __sv_foo.deprecated_bar.into(), @@ -398,7 +401,7 @@ where __SvStatus: ::stackable_versioned::TrackingStatus + ::core::default::Default, { fn tracking_from(__sv_foo: v1::Foo, status: &mut __SvStatus, parent: &str) -> Self { - use ::stackable_versioned::TrackingInto as _; + use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; let mut spec = Self { foo: __sv_foo.foo.into(), deprecated_bar: __sv_foo.deprecated_bar.into(), @@ -417,7 +420,7 @@ where __SvStatus: ::stackable_versioned::TrackingStatus + ::core::default::Default, { fn tracking_from(__sv_foo: v2::Foo, status: &mut __SvStatus, parent: &str) -> Self { - use ::stackable_versioned::TrackingInto as _; + use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; let mut spec = Self { foo: __sv_foo.foo.into(), deprecated_bar: __sv_foo.deprecated_bar.into(), diff --git a/crates/stackable-versioned/src/lib.rs b/crates/stackable-versioned/src/lib.rs index ed9ee1689..e9d71bd02 100644 --- a/crates/stackable-versioned/src/lib.rs +++ b/crates/stackable-versioned/src/lib.rs @@ -194,6 +194,36 @@ pub struct UnknownDesiredApiVersionError { pub api_version: String, } +/// This extension trait for (currently only) [`Vec`]s enables the removal of the first matched +/// element based on a predicate. +pub trait RemoveIf { + /// Removes an element if the `predicate` evaluates to `true` and returns it. + fn remove_if(&mut self, predicate: impl FnMut(&T) -> bool) -> Option; +} + +impl RemoveIf for Vec { + fn remove_if(&mut self, predicate: impl FnMut(&T) -> bool) -> Option { + let index = self.iter().position(predicate)?; + Some(self.remove(index)) + } +} + pub fn jthong_path(parent: &str, child: &str) -> String { format!("{parent}.{child}") } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn remove_if() { + let mut all = vec![1, 2, 3, 4, 5, 6]; + let first_even = all + .remove_if(|i| i % 2 == 0) + .expect("source vec contains 2, 4, 6 which are even"); + + assert_eq!(first_even, 2); + assert_eq!(all.len(), 5); + } +} From d61666bb73a9b6302a9b5d24d24683e8d60de03e Mon Sep 17 00:00:00 2001 From: Techassi Date: Wed, 21 Oct 2026 13:48:32 +0200 Subject: [PATCH 2/5] fix: Bump rustls-webpki to 0.103.16 to negate RUSTSEC-2026-0382 --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a662ad0b7..0fb49ca5e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3379,9 +3379,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" [[package]] name = "rustls-webpki" -version = "0.103.15" +version = "0.103.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c3cf1d8b1e7d4927e2d154c3fcb02979afb9939629c62cd9048d4f07b60ac2" +checksum = "4443b1b6d39d7c663139942cc4558262562d2c84123bb6282ef177009ca8b281" dependencies = [ "ring", "rustls-pki-types", From 3e65cd5ee190e163eb63a695c7d3c761bd4d7cf0 Mon Sep 17 00:00:00 2001 From: Techassi Date: Wed, 21 Oct 2026 14:45:47 +0200 Subject: [PATCH 3/5] chore(versioned): s/remove/extract/g --- .../codegen/container/struct/conversion.rs | 2 +- .../src/codegen/item/field.rs | 2 +- ...napshots__pass@conversion_tracking.rs.snap | 10 +++++----- ...ots__pass@conversion_tracking_enum.rs.snap | 10 +++++----- ..._pass@conversion_tracking_generics.rs.snap | 20 +++++++++---------- ...ts__pass@conversion_tracking_hints.rs.snap | 10 +++++----- ...ioned_macros__snapshots__pass@docs.rs.snap | 18 ++++++++--------- crates/stackable-versioned/src/lib.rs | 16 +++++++-------- 8 files changed, 44 insertions(+), 44 deletions(-) diff --git a/crates/stackable-versioned-macros/src/codegen/container/struct/conversion.rs b/crates/stackable-versioned-macros/src/codegen/container/struct/conversion.rs index 8093345b3..316b01a74 100644 --- a/crates/stackable-versioned-macros/src/codegen/container/struct/conversion.rs +++ b/crates/stackable-versioned-macros/src/codegen/container/struct/conversion.rs @@ -189,7 +189,7 @@ impl Struct { { fn tracking_from(#from_struct_ident: #from_module_ident::#struct_ident #type_generics, status: &mut __SvStatus, parent: &str) -> Self { // TODO (@Techassi): Only emit this if any of the fields below need it - use #versioned_path::{RemoveIf as _, TrackingInto as _}; + use #versioned_path::{ExtractIfExt as _, TrackingInto as _}; #json_paths // Depending on the direction, we need to either insert changed values into diff --git a/crates/stackable-versioned-macros/src/codegen/item/field.rs b/crates/stackable-versioned-macros/src/codegen/item/field.rs index 08806512d..17ee2beb1 100644 --- a/crates/stackable-versioned-macros/src/codegen/item/field.rs +++ b/crates/stackable-versioned-macros/src/codegen/item/field.rs @@ -366,7 +366,7 @@ impl VersionedField { ); Some(quote! { - if let Some(#versioned_path::ChangedValue { value, .. }) = upgrades.remove_if(|u| u.json_path == #json_path_ident) { + if let Some(#versioned_path::ChangedValue { value, .. }) = upgrades.extract_first_if(|u| u.json_path == #json_path_ident) { // TODO (@Techassi): Switch to serde_json spec.#ident = #yaml_serde_path::from_value(value).expect(#expect_message); } diff --git a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@conversion_tracking.rs.snap b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@conversion_tracking.rs.snap index c859f3c5f..348dac6f8 100644 --- a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@conversion_tracking.rs.snap +++ b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@conversion_tracking.rs.snap @@ -59,7 +59,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; + use ::stackable_versioned::{ExtractIfExt as _, TrackingInto as _}; let __sv_bah_path = ::stackable_versioned::jthong_path(parent, "bah"); let mut spec = Self { bah: ::std::default::Default::default(), @@ -67,7 +67,7 @@ where }; if let Some(upgrades) = status.changes().upgrades.get_mut("v1beta1") { if let Some(::stackable_versioned::ChangedValue { value, .. }) = upgrades - .remove_if(|u| u.json_path == __sv_bah_path) + .extract_first_if(|u| u.json_path == __sv_bah_path) { spec.bah = ::yaml_serde::from_value(value) .expect( @@ -92,7 +92,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; + use ::stackable_versioned::{ExtractIfExt as _, TrackingInto as _}; let __sv_bah_path = ::stackable_versioned::jthong_path(parent, "bah"); let upgrades = status .changes() @@ -167,7 +167,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; + use ::stackable_versioned::{ExtractIfExt as _, TrackingInto as _}; let mut spec = Self { bar: __sv_foospec.bah.into(), baz: __sv_foospec.baz.into(), @@ -186,7 +186,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; + use ::stackable_versioned::{ExtractIfExt as _, TrackingInto as _}; let mut spec = Self { bah: __sv_foospec.bar.into(), baz: __sv_foospec.baz.into(), diff --git a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@conversion_tracking_enum.rs.snap b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@conversion_tracking_enum.rs.snap index 6b7773e58..ef0ba4fd1 100644 --- a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@conversion_tracking_enum.rs.snap +++ b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@conversion_tracking_enum.rs.snap @@ -72,7 +72,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; + use ::stackable_versioned::{ExtractIfExt as _, TrackingInto as _}; let __sv_connector_path = ::stackable_versioned::jthong_path( parent, "connector", @@ -94,7 +94,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; + use ::stackable_versioned::{ExtractIfExt as _, TrackingInto as _}; let __sv_connector_path = ::stackable_versioned::jthong_path( parent, "connector", @@ -224,7 +224,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; + use ::stackable_versioned::{ExtractIfExt as _, TrackingInto as _}; let __sv_rest_catalog_uri_path = ::stackable_versioned::jthong_path( parent, "rest_catalog_uri", @@ -235,7 +235,7 @@ where }; if let Some(upgrades) = status.changes().upgrades.get_mut("v1alpha2") { if let Some(::stackable_versioned::ChangedValue { value, .. }) = upgrades - .remove_if(|u| u.json_path == __sv_rest_catalog_uri_path) + .extract_first_if(|u| u.json_path == __sv_rest_catalog_uri_path) { spec.rest_catalog_uri = ::yaml_serde::from_value(value) .expect( @@ -262,7 +262,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; + use ::stackable_versioned::{ExtractIfExt as _, TrackingInto as _}; let __sv_rest_catalog_uri_path = ::stackable_versioned::jthong_path( parent, "rest_catalog_uri", diff --git a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@conversion_tracking_generics.rs.snap b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@conversion_tracking_generics.rs.snap index ce6f34817..5782cc0d4 100644 --- a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@conversion_tracking_generics.rs.snap +++ b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@conversion_tracking_generics.rs.snap @@ -68,7 +68,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; + use ::stackable_versioned::{ExtractIfExt as _, TrackingInto as _}; let __sv_bah_path = ::stackable_versioned::jthong_path(parent, "bah"); let __sv_baz_path = ::stackable_versioned::jthong_path(parent, "baz"); let mut spec = Self { @@ -77,7 +77,7 @@ where }; if let Some(upgrades) = status.changes().upgrades.get_mut("v1beta1") { if let Some(::stackable_versioned::ChangedValue { value, .. }) = upgrades - .remove_if(|u| u.json_path == __sv_bah_path) + .extract_first_if(|u| u.json_path == __sv_bah_path) { spec.bah = ::yaml_serde::from_value(value) .expect( @@ -102,7 +102,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; + use ::stackable_versioned::{ExtractIfExt as _, TrackingInto as _}; let __sv_bah_path = ::stackable_versioned::jthong_path(parent, "bah"); let __sv_baz_path = ::stackable_versioned::jthong_path(parent, "baz"); let upgrades = status @@ -133,7 +133,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; + use ::stackable_versioned::{ExtractIfExt as _, TrackingInto as _}; let mut spec = Self { inner_1: __sv_baz.inner_1.into(), inner_2: __sv_baz.inner_2.into(), @@ -153,7 +153,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; + use ::stackable_versioned::{ExtractIfExt as _, TrackingInto as _}; let mut spec = Self { inner_1: __sv_baz.inner_1.into(), inner_2: __sv_baz.inner_2.into(), @@ -227,7 +227,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; + use ::stackable_versioned::{ExtractIfExt as _, TrackingInto as _}; let __sv_baz_path = ::stackable_versioned::jthong_path(parent, "baz"); let mut spec = Self { bar: __sv_foospec.bah.into(), @@ -247,7 +247,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; + use ::stackable_versioned::{ExtractIfExt as _, TrackingInto as _}; let __sv_baz_path = ::stackable_versioned::jthong_path(parent, "baz"); let mut spec = Self { bah: __sv_foospec.bar.into(), @@ -268,7 +268,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; + use ::stackable_versioned::{ExtractIfExt as _, TrackingInto as _}; let __sv_inner_3_path = ::stackable_versioned::jthong_path(parent, "inner_3"); let mut spec = Self { inner_1: __sv_baz.inner_1.into(), @@ -277,7 +277,7 @@ where }; if let Some(upgrades) = status.changes().upgrades.get_mut("v1") { if let Some(::stackable_versioned::ChangedValue { value, .. }) = upgrades - .remove_if(|u| u.json_path == __sv_inner_3_path) + .extract_first_if(|u| u.json_path == __sv_inner_3_path) { spec.inner_3 = ::yaml_serde::from_value(value) .expect( @@ -303,7 +303,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; + use ::stackable_versioned::{ExtractIfExt as _, TrackingInto as _}; let __sv_inner_3_path = ::stackable_versioned::jthong_path(parent, "inner_3"); let upgrades = status.changes().upgrades.entry("v1".to_owned()).or_default(); upgrades diff --git a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@conversion_tracking_hints.rs.snap b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@conversion_tracking_hints.rs.snap index 90b12653a..884853255 100644 --- a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@conversion_tracking_hints.rs.snap +++ b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@conversion_tracking_hints.rs.snap @@ -26,7 +26,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; + use ::stackable_versioned::{ExtractIfExt as _, TrackingInto as _}; let __sv_bar_path = ::stackable_versioned::jthong_path(parent, "bar"); let mut spec = Self { bar: __sv_foo.bar.map(|v| v.tracking_into(status, &__sv_bar_path)), @@ -47,7 +47,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; + use ::stackable_versioned::{ExtractIfExt as _, TrackingInto as _}; let __sv_bar_path = ::stackable_versioned::jthong_path(parent, "bar"); let mut spec = Self { bar: __sv_foo.bar.map(|v| v.tracking_into(status, &__sv_bar_path)), @@ -68,7 +68,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; + use ::stackable_versioned::{ExtractIfExt as _, TrackingInto as _}; let __sv_baz_baz_path = ::stackable_versioned::jthong_path(parent, "baz_baz"); let mut spec = Self { bar_bar: __sv_bar.bar_bar.into(), @@ -76,7 +76,7 @@ where }; if let Some(upgrades) = status.changes().upgrades.get_mut("v1alpha2") { if let Some(::stackable_versioned::ChangedValue { value, .. }) = upgrades - .remove_if(|u| u.json_path == __sv_baz_baz_path) + .extract_first_if(|u| u.json_path == __sv_baz_baz_path) { spec.baz_baz = ::yaml_serde::from_value(value) .expect( @@ -101,7 +101,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; + use ::stackable_versioned::{ExtractIfExt as _, TrackingInto as _}; let __sv_baz_baz_path = ::stackable_versioned::jthong_path(parent, "baz_baz"); let upgrades = status .changes() diff --git a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@docs.rs.snap b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@docs.rs.snap index c85ca94aa..50a37ba62 100644 --- a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@docs.rs.snap +++ b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshots__pass@docs.rs.snap @@ -42,7 +42,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; + use ::stackable_versioned::{ExtractIfExt as _, TrackingInto as _}; let __sv_baz_path = ::stackable_versioned::jthong_path(parent, "baz"); let mut spec = Self { foo: __sv_foo.foo.into(), @@ -54,7 +54,7 @@ where }; if let Some(upgrades) = status.changes().upgrades.get_mut("v1beta1") { if let Some(::stackable_versioned::ChangedValue { value, .. }) = upgrades - .remove_if(|u| u.json_path == __sv_baz_path) + .extract_first_if(|u| u.json_path == __sv_baz_path) { spec.baz = ::yaml_serde::from_value(value) .expect( @@ -80,7 +80,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; + use ::stackable_versioned::{ExtractIfExt as _, TrackingInto as _}; let __sv_baz_path = ::stackable_versioned::jthong_path(parent, "baz"); let upgrades = status .changes() @@ -186,7 +186,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; + use ::stackable_versioned::{ExtractIfExt as _, TrackingInto as _}; let mut spec = Self { foo: __sv_foo.foo.into(), deprecated_bar: __sv_foo.deprecated_bar.into(), @@ -210,7 +210,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; + use ::stackable_versioned::{ExtractIfExt as _, TrackingInto as _}; let mut spec = Self { foo: __sv_foo.foo.into(), deprecated_bar: __sv_foo.deprecated_bar.into(), @@ -300,7 +300,7 @@ where status: &mut __SvStatus, parent: &str, ) -> Self { - use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; + use ::stackable_versioned::{ExtractIfExt as _, TrackingInto as _}; let mut spec = Self { foo: __sv_foo.foo.into(), deprecated_bar: __sv_foo.deprecated_bar.into(), @@ -320,7 +320,7 @@ where __SvStatus: ::stackable_versioned::TrackingStatus + ::core::default::Default, { fn tracking_from(__sv_foo: v1::Foo, status: &mut __SvStatus, parent: &str) -> Self { - use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; + use ::stackable_versioned::{ExtractIfExt as _, TrackingInto as _}; let mut spec = Self { foo: __sv_foo.foo.into(), deprecated_bar: __sv_foo.deprecated_bar.into(), @@ -401,7 +401,7 @@ where __SvStatus: ::stackable_versioned::TrackingStatus + ::core::default::Default, { fn tracking_from(__sv_foo: v1::Foo, status: &mut __SvStatus, parent: &str) -> Self { - use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; + use ::stackable_versioned::{ExtractIfExt as _, TrackingInto as _}; let mut spec = Self { foo: __sv_foo.foo.into(), deprecated_bar: __sv_foo.deprecated_bar.into(), @@ -420,7 +420,7 @@ where __SvStatus: ::stackable_versioned::TrackingStatus + ::core::default::Default, { fn tracking_from(__sv_foo: v2::Foo, status: &mut __SvStatus, parent: &str) -> Self { - use ::stackable_versioned::{RemoveIf as _, TrackingInto as _}; + use ::stackable_versioned::{ExtractIfExt as _, TrackingInto as _}; let mut spec = Self { foo: __sv_foo.foo.into(), deprecated_bar: __sv_foo.deprecated_bar.into(), diff --git a/crates/stackable-versioned/src/lib.rs b/crates/stackable-versioned/src/lib.rs index e9d71bd02..708ebb98c 100644 --- a/crates/stackable-versioned/src/lib.rs +++ b/crates/stackable-versioned/src/lib.rs @@ -194,15 +194,15 @@ pub struct UnknownDesiredApiVersionError { pub api_version: String, } -/// This extension trait for (currently only) [`Vec`]s enables the removal of the first matched +/// This extension trait for (currently only) [`Vec`]s enables the extraction of the first matched /// element based on a predicate. -pub trait RemoveIf { - /// Removes an element if the `predicate` evaluates to `true` and returns it. - fn remove_if(&mut self, predicate: impl FnMut(&T) -> bool) -> Option; +pub trait ExtractIfExt { + /// Extracts the first element for which the `predicate` evaluates to `true` and returns it. + fn extract_first_if(&mut self, predicate: impl FnMut(&T) -> bool) -> Option; } -impl RemoveIf for Vec { - fn remove_if(&mut self, predicate: impl FnMut(&T) -> bool) -> Option { +impl ExtractIfExt for Vec { + fn extract_first_if(&mut self, predicate: impl FnMut(&T) -> bool) -> Option { let index = self.iter().position(predicate)?; Some(self.remove(index)) } @@ -217,10 +217,10 @@ mod tests { use super::*; #[test] - fn remove_if() { + fn extract_first_if() { let mut all = vec![1, 2, 3, 4, 5, 6]; let first_even = all - .remove_if(|i| i % 2 == 0) + .extract_first_if(|i| i % 2 == 0) .expect("source vec contains 2, 4, 6 which are even"); assert_eq!(first_even, 2); From dccaeee774a0404e67f492b5ca780a814c2e3271 Mon Sep 17 00:00:00 2001 From: Techassi Date: Wed, 21 Oct 2026 14:49:53 +0200 Subject: [PATCH 4/5] chore(versioned): Add changelog entries --- crates/stackable-versioned/CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/stackable-versioned/CHANGELOG.md b/crates/stackable-versioned/CHANGELOG.md index f8dff1247..7ea0a63bd 100644 --- a/crates/stackable-versioned/CHANGELOG.md +++ b/crates/stackable-versioned/CHANGELOG.md @@ -6,9 +6,15 @@ All notable changes to this project will be documented in this file. ### Added +- Add public `ExtractIfExt` trait ([#13006]). - Re-add support for generics in tracking impls ([#1304]). +### Fixed + +- Correctly handle tracked per-version changes across multiple containers ([#1306]). + [#1304]: https://github.com/stackabletech/operator-rs/pull/1304 +[#1306]: https://github.com/stackabletech/operator-rs/pull/1306 ## [0.13.0] - 2026-10-14 From 8ab4e73bfc39a68c705b925c531af31c2af213a1 Mon Sep 17 00:00:00 2001 From: Techassi Date: Wed, 21 Oct 2026 15:10:01 +0200 Subject: [PATCH 5/5] test(versioned): Force previously broken code path --- .../inputs/conversions/pass/persons_to_v1alpha1.json | 3 ++- .../tests/inputs/conversions/pass/persons_to_v3.json | 3 ++- crates/stackable-versioned/tests/person.rs | 12 +----------- .../conversions__pass@persons_to_v1alpha1.json.snap | 8 +++++--- .../conversions__pass@persons_to_v3.json.snap | 2 +- 5 files changed, 11 insertions(+), 17 deletions(-) diff --git a/crates/stackable-versioned/tests/inputs/conversions/pass/persons_to_v1alpha1.json b/crates/stackable-versioned/tests/inputs/conversions/pass/persons_to_v1alpha1.json index 631768ca6..6434b00c2 100644 --- a/crates/stackable-versioned/tests/inputs/conversions/pass/persons_to_v1alpha1.json +++ b/crates/stackable-versioned/tests/inputs/conversions/pass/persons_to_v1alpha1.json @@ -73,7 +73,8 @@ "gender": "Male", "relationship": { "married": { - "with": "Jane Doe" + "with": "Jane Doe", + "since": "1970-01-01" } }, "socials": { diff --git a/crates/stackable-versioned/tests/inputs/conversions/pass/persons_to_v3.json b/crates/stackable-versioned/tests/inputs/conversions/pass/persons_to_v3.json index 4722f0f46..53f46b263 100644 --- a/crates/stackable-versioned/tests/inputs/conversions/pass/persons_to_v3.json +++ b/crates/stackable-versioned/tests/inputs/conversions/pass/persons_to_v3.json @@ -73,7 +73,8 @@ "gender": "Male", "relationship": { "married": { - "with": "Jane Doe" + "with": "Jane Doe", + "since": "1970-01-01" } }, "socials": { diff --git a/crates/stackable-versioned/tests/person.rs b/crates/stackable-versioned/tests/person.rs index a2cf037c6..74fba62a4 100644 --- a/crates/stackable-versioned/tests/person.rs +++ b/crates/stackable-versioned/tests/person.rs @@ -102,17 +102,7 @@ pub mod versioned { pub struct Married { with: String, - // FIXME (@Techassi): Any other version than v3 leads to a panic. There are two issues here: - // - // - The tracking impls for each container assume they are the only container which need to - // access to ChangedValues' `upgrades` and/or `downgrades` fields and currently removes - // the list of `ChangedValue`s for a particular version. The code must only remove the - // entire entry once the list inside is empty. Otherwise, other containers won't be able - // to access the tracked changes. - // - Each tracking impl must only look and remove the changes which matched with the - // expected JSON path. Unmatched JSON paths currently lead to a panic. They should instead - // be ignored. - #[versioned(added(since = "v3"))] + #[versioned(added(since = "v2"))] since: String, } diff --git a/crates/stackable-versioned/tests/snapshots/conversions__pass@persons_to_v1alpha1.json.snap b/crates/stackable-versioned/tests/snapshots/conversions__pass@persons_to_v1alpha1.json.snap index 4ff52d2f4..eab916aad 100644 --- a/crates/stackable-versioned/tests/snapshots/conversions__pass@persons_to_v1alpha1.json.snap +++ b/crates/stackable-versioned/tests/snapshots/conversions__pass@persons_to_v1alpha1.json.snap @@ -146,6 +146,10 @@ input_file: crates/stackable-versioned/tests/inputs/conversions/pass/persons_to_ { "jsonPath": "$.gender", "value": "Male" + }, + { + "jsonPath": "$.relationship.Married.0.since", + "value": "1970-01-01" } ] } @@ -192,9 +196,7 @@ input_file: crates/stackable-versioned/tests/inputs/conversions/pass/persons_to_ { "jsonPath": "$.gender", "value": "Male" - } - ], - "v3": [ + }, { "jsonPath": "$.relationship.Married.0.since", "value": "1970-01-01" diff --git a/crates/stackable-versioned/tests/snapshots/conversions__pass@persons_to_v3.json.snap b/crates/stackable-versioned/tests/snapshots/conversions__pass@persons_to_v3.json.snap index 65c68e008..1db1b46ff 100644 --- a/crates/stackable-versioned/tests/snapshots/conversions__pass@persons_to_v3.json.snap +++ b/crates/stackable-versioned/tests/snapshots/conversions__pass@persons_to_v3.json.snap @@ -110,7 +110,7 @@ input_file: crates/stackable-versioned/tests/inputs/conversions/pass/persons_to_ "lastName": "Doe", "relationship": { "married": { - "since": "", + "since": "1970-01-01", "with": "Jane Doe" } },