summaryrefslogtreecommitdiff
path: root/src/metadata
diff options
context:
space:
mode:
authorKim Altintop <kim@eagain.io>2023-03-29 13:20:08 +0200
committerKim Altintop <kim@eagain.io>2023-03-29 13:20:08 +0200
commita483cc97d56a770c4ccf91dfccf790a8c2d0c9fa (patch)
treeabe1fc1860def1b5f2cceae4c4da003c2f60705d /src/metadata
parenta4d2d6ac8acb34314fba166d5b85ff06c97f0ca3 (diff)
core: version each metadata type separately
It turns out to be preferable to be able to break one type without affecting the other. So instead of the global SpecVersion, use a separate FmtVersion for each type. For compatibility, keep supporting spec_version fields (until next major bump of the respective types' version). Signed-off-by: Kim Altintop <kim@eagain.io>
Diffstat (limited to 'src/metadata')
-rw-r--r--src/metadata/drop.rs54
-rw-r--r--src/metadata/identity.rs52
-rw-r--r--src/metadata/mirrors.rs72
3 files changed, 163 insertions, 15 deletions
diff --git a/src/metadata/drop.rs b/src/metadata/drop.rs
index d231712..1341f68 100644
--- a/src/metadata/drop.rs
+++ b/src/metadata/drop.rs
@@ -10,6 +10,7 @@ use std::{
},
io,
num::NonZeroUsize,
+ ops::Deref,
};
use log::warn;
@@ -32,7 +33,6 @@ use super::{
Mirrors,
Signature,
Signed,
- SpecVersion,
};
use crate::{
git::Refname,
@@ -40,6 +40,25 @@ use crate::{
str::Varchar,
};
+pub const FMT_VERSION: FmtVersion = FmtVersion(super::FmtVersion::new(0, 2, 0));
+
+#[derive(Clone, Eq, Ord, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize)]
+pub struct FmtVersion(super::FmtVersion);
+
+impl Deref for FmtVersion {
+ type Target = super::FmtVersion;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+impl Default for FmtVersion {
+ fn default() -> Self {
+ FMT_VERSION
+ }
+}
+
#[derive(Clone, serde::Serialize, serde::Deserialize)]
pub struct Roles {
pub root: Role,
@@ -83,9 +102,10 @@ pub struct Annotated {
pub type Verified = super::Verified<Drop>;
-#[derive(Clone, serde::Serialize, serde::Deserialize)]
+#[derive(Clone, serde::Deserialize)]
pub struct Drop {
- pub spec_version: SpecVersion,
+ #[serde(alias = "spec_version")]
+ pub fmt_version: FmtVersion,
#[serde(default = "Description::new")]
pub description: Description,
pub prev: Option<ContentHash>,
@@ -121,7 +141,7 @@ impl Drop {
{
use error::Verification::*;
- if !crate::SPEC_VERSION.is_compatible(&self.spec_version) {
+ if !FMT_VERSION.is_compatible(&self.fmt_version) {
return Err(IncompatibleSpecVersion);
}
@@ -153,7 +173,7 @@ impl Drop {
return Err(Expired);
}
}
- if !crate::SPEC_VERSION.is_compatible(&mirrors.signed.spec_version) {
+ if !FMT_VERSION.is_compatible(&mirrors.signed.fmt_version) {
return Err(IncompatibleSpecVersion);
}
@@ -177,7 +197,7 @@ impl Drop {
return Err(Expired);
}
}
- if !crate::SPEC_VERSION.is_compatible(&alt.signed.spec_version) {
+ if !FMT_VERSION.is_compatible(&alt.signed.fmt_version) {
return Err(IncompatibleSpecVersion);
}
@@ -203,6 +223,28 @@ impl<'a> From<&'a Drop> for Cow<'a, Drop> {
}
}
+impl serde::Serialize for Drop {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: serde::Serializer,
+ {
+ use serde::ser::SerializeStruct;
+
+ let mut s = serializer.serialize_struct("Drop", 5)?;
+ let version_field = if self.fmt_version < FMT_VERSION {
+ "spec_version"
+ } else {
+ "fmt_version"
+ };
+ s.serialize_field(version_field, &self.fmt_version)?;
+ s.serialize_field("description", &self.description)?;
+ s.serialize_field("prev", &self.prev)?;
+ s.serialize_field("roles", &self.roles)?;
+ s.serialize_field("custom", &self.custom)?;
+ s.end()
+ }
+}
+
mod verify {
use super::*;
diff --git a/src/metadata/identity.rs b/src/metadata/identity.rs
index 8071e84..15967c4 100644
--- a/src/metadata/identity.rs
+++ b/src/metadata/identity.rs
@@ -11,6 +11,7 @@ use std::{
io,
marker::PhantomData,
num::NonZeroUsize,
+ ops::Deref,
path::PathBuf,
str::FromStr,
};
@@ -46,7 +47,6 @@ use super::{
Metadata,
Signature,
Signed,
- SpecVersion,
};
use crate::{
json::{
@@ -56,6 +56,25 @@ use crate::{
metadata::git::find_parent,
};
+pub const FMT_VERSION: FmtVersion = FmtVersion(super::FmtVersion::new(0, 2, 0));
+
+#[derive(Clone, Eq, Ord, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize)]
+pub struct FmtVersion(super::FmtVersion);
+
+impl Deref for FmtVersion {
+ type Target = super::FmtVersion;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+impl Default for FmtVersion {
+ fn default() -> Self {
+ FMT_VERSION
+ }
+}
+
#[derive(
Clone, Copy, Eq, Ord, PartialEq, PartialOrd, Hash, serde::Serialize, serde::Deserialize,
)]
@@ -135,9 +154,10 @@ impl AsRef<Identity> for Verified {
}
}
-#[derive(Clone, serde::Serialize, serde::Deserialize)]
+#[derive(Clone, serde::Deserialize)]
pub struct Identity {
- pub spec_version: SpecVersion,
+ #[serde(alias = "spec_version")]
+ pub fmt_version: FmtVersion,
pub prev: Option<ContentHash>,
pub keys: KeySet<'static>,
pub threshold: NonZeroUsize,
@@ -188,7 +208,7 @@ impl Identity {
{
use error::Verification::IncompatibleSpecVersion;
- if !crate::SPEC_VERSION.is_compatible(&self.spec_version) {
+ if !FMT_VERSION.is_compatible(&self.fmt_version) {
return Err(IncompatibleSpecVersion);
}
@@ -259,6 +279,30 @@ impl<'a> From<&'a Identity> for Cow<'a, Identity> {
}
}
+impl serde::Serialize for Identity {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: serde::Serializer,
+ {
+ use serde::ser::SerializeStruct;
+
+ let mut s = serializer.serialize_struct("Identity", 7)?;
+ let version_field = if self.fmt_version < FMT_VERSION {
+ "spec_version"
+ } else {
+ "fmt_version"
+ };
+ s.serialize_field(version_field, &self.fmt_version)?;
+ s.serialize_field("prev", &self.prev)?;
+ s.serialize_field("keys", &self.keys)?;
+ s.serialize_field("threshold", &self.threshold)?;
+ s.serialize_field("mirrors", &self.mirrors)?;
+ s.serialize_field("expires", &self.expires)?;
+ s.serialize_field("custom", &self.custom)?;
+ s.end()
+ }
+}
+
fn verify_signatures<'a, S>(
payload: &[u8],
threshold: NonZeroUsize,
diff --git a/src/metadata/mirrors.rs b/src/metadata/mirrors.rs
index 9124dd3..eb437c9 100644
--- a/src/metadata/mirrors.rs
+++ b/src/metadata/mirrors.rs
@@ -4,6 +4,7 @@
use std::{
borrow::Cow,
collections::BTreeSet,
+ ops::Deref,
};
use url::Url;
@@ -12,13 +13,31 @@ use super::{
Custom,
DateTime,
Metadata,
- SpecVersion,
};
use crate::{
json::canonical,
str::Varchar,
};
+pub const FMT_VERSION: FmtVersion = FmtVersion(super::FmtVersion::new(0, 2, 0));
+
+#[derive(Clone, Eq, Ord, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize)]
+pub struct FmtVersion(super::FmtVersion);
+
+impl Deref for FmtVersion {
+ type Target = super::FmtVersion;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+impl Default for FmtVersion {
+ fn default() -> Self {
+ FMT_VERSION
+ }
+}
+
#[derive(Clone, serde::Serialize, serde::Deserialize)]
pub struct Mirror {
pub url: Url,
@@ -42,9 +61,10 @@ pub enum Kind {
Unknown(Varchar<String, 16>),
}
-#[derive(Clone, Default, serde::Serialize, serde::Deserialize)]
+#[derive(Clone, Default, serde::Deserialize)]
pub struct Mirrors {
- pub spec_version: SpecVersion,
+ #[serde(alias = "spec_version")]
+ pub fmt_version: FmtVersion,
pub mirrors: Vec<Mirror>,
pub expires: Option<DateTime>,
}
@@ -67,9 +87,30 @@ impl<'a> From<&'a Mirrors> for Cow<'a, Mirrors> {
}
}
-#[derive(Clone, Default, serde::Serialize, serde::Deserialize)]
+impl serde::Serialize for Mirrors {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: serde::Serializer,
+ {
+ use serde::ser::SerializeStruct;
+
+ let mut s = serializer.serialize_struct("Mirrors", 3)?;
+ let version_field = if self.fmt_version < FMT_VERSION {
+ "spec_version"
+ } else {
+ "fmt_version"
+ };
+ s.serialize_field(version_field, &self.fmt_version)?;
+ s.serialize_field("mirrors", &self.mirrors)?;
+ s.serialize_field("expires", &self.expires)?;
+ s.end()
+ }
+}
+
+#[derive(Clone, Default, serde::Deserialize)]
pub struct Alternates {
- pub spec_version: SpecVersion,
+ #[serde(alias = "spec_version")]
+ pub fmt_version: FmtVersion,
pub alternates: BTreeSet<Url>,
#[serde(default)]
pub custom: Custom,
@@ -93,3 +134,24 @@ impl<'a> From<&'a Alternates> for Cow<'a, Alternates> {
Self::Borrowed(a)
}
}
+
+impl serde::Serialize for Alternates {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: serde::Serializer,
+ {
+ use serde::ser::SerializeStruct;
+
+ let mut s = serializer.serialize_struct("Alternates", 4)?;
+ let version_field = if self.fmt_version < FMT_VERSION {
+ "spec_version"
+ } else {
+ "fmt_version"
+ };
+ s.serialize_field(version_field, &self.fmt_version)?;
+ s.serialize_field("alternates", &self.alternates)?;
+ s.serialize_field("custom", &self.custom)?;
+ s.serialize_field("expires", &self.expires)?;
+ s.end()
+ }
+}