summaryrefslogtreecommitdiff
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
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>
-rw-r--r--src/cmd/drop.rs2
-rw-r--r--src/cmd/drop/init.rs2
-rw-r--r--src/cmd/id.rs2
-rw-r--r--src/cmd/id/init.rs2
-rw-r--r--src/lib.rs2
-rw-r--r--src/metadata.rs26
-rw-r--r--src/metadata/drop.rs54
-rw-r--r--src/metadata/identity.rs52
-rw-r--r--src/metadata/mirrors.rs72
9 files changed, 175 insertions, 39 deletions
diff --git a/src/cmd/drop.rs b/src/cmd/drop.rs
index 208dbd6..8051253 100644
--- a/src/cmd/drop.rs
+++ b/src/cmd/drop.rs
@@ -195,7 +195,7 @@ impl TryFrom<Editable> for metadata::Drop {
}
Ok(Self {
- spec_version: crate::SPEC_VERSION,
+ fmt_version: Default::default(),
description,
prev: None,
roles,
diff --git a/src/cmd/drop/init.rs b/src/cmd/drop/init.rs
index b843255..a1c5025 100644
--- a/src/cmd/drop/init.rs
+++ b/src/cmd/drop/init.rs
@@ -121,7 +121,7 @@ pub fn init(args: Init) -> cmd::Result<Output> {
let default_branch = cfg::git::default_branch(&cfg)?;
metadata::Drop {
- spec_version: crate::SPEC_VERSION,
+ fmt_version: Default::default(),
description: args.description,
prev: None,
custom: Default::default(),
diff --git a/src/cmd/id.rs b/src/cmd/id.rs
index 7504489..57e79b0 100644
--- a/src/cmd/id.rs
+++ b/src/cmd/id.rs
@@ -176,7 +176,7 @@ impl TryFrom<Editable> for metadata::Identity {
ensure!(!keys.is_empty(), "keys cannot be empty");
Ok(Self {
- spec_version: crate::SPEC_VERSION,
+ fmt_version: Default::default(),
prev: None,
keys,
threshold,
diff --git a/src/cmd/id/init.rs b/src/cmd/id/init.rs
index a0ed119..35d3bb8 100644
--- a/src/cmd/id/init.rs
+++ b/src/cmd/id/init.rs
@@ -148,7 +148,7 @@ pub fn init(args: Init) -> cmd::Result<Output> {
let meta = {
let id = metadata::Identity {
- spec_version: crate::SPEC_VERSION,
+ fmt_version: Default::default(),
prev: None,
keys,
threshold,
diff --git a/src/lib.rs b/src/lib.rs
index 789f99f..c8c8887 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -16,8 +16,6 @@ mod serde;
mod ssh;
mod str;
-pub const SPEC_VERSION: metadata::SpecVersion = metadata::SpecVersion::current();
-
pub mod cmd;
pub use cmd::{
ui::Output,
diff --git a/src/metadata.rs b/src/metadata.rs
index 9caee96..2da268f 100644
--- a/src/metadata.rs
+++ b/src/metadata.rs
@@ -56,13 +56,9 @@ pub use identity::{
};
#[derive(Clone, Eq, Ord, PartialEq, PartialOrd)]
-pub struct SpecVersion(SemVer);
-
-impl SpecVersion {
- pub const fn current() -> Self {
- Self::new(0, 1, 0)
- }
+pub struct FmtVersion(SemVer);
+impl FmtVersion {
const fn new(major: u32, minor: u32, patch: u32) -> Self {
Self(SemVer {
major,
@@ -92,19 +88,13 @@ impl SpecVersion {
}
}
-impl Default for SpecVersion {
- fn default() -> Self {
- Self::current()
- }
-}
-
-impl fmt::Display for SpecVersion {
+impl fmt::Display for FmtVersion {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.fmt(f)
}
}
-impl FromStr for SpecVersion {
+impl FromStr for FmtVersion {
type Err = <SemVer as FromStr>::Err;
fn from_str(s: &str) -> Result<Self, Self::Err> {
@@ -112,7 +102,7 @@ impl FromStr for SpecVersion {
}
}
-impl<'a> TryFrom<&'a str> for SpecVersion {
+impl<'a> TryFrom<&'a str> for FmtVersion {
type Error = <SemVer as TryFrom<&'a str>>::Error;
fn try_from(value: &str) -> Result<Self, Self::Error> {
@@ -120,13 +110,13 @@ impl<'a> TryFrom<&'a str> for SpecVersion {
}
}
-impl AsRef<SemVer> for SpecVersion {
+impl AsRef<SemVer> for FmtVersion {
fn as_ref(&self) -> &SemVer {
&self.0
}
}
-impl serde::Serialize for SpecVersion {
+impl serde::Serialize for FmtVersion {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
@@ -135,7 +125,7 @@ impl serde::Serialize for SpecVersion {
}
}
-impl<'de> serde::Deserialize<'de> for SpecVersion {
+impl<'de> serde::Deserialize<'de> for FmtVersion {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
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()
+ }
+}