Skip to content

Commit

Permalink
fix manifest writing issue, test manifest, add some static checks
Browse files Browse the repository at this point in the history
  • Loading branch information
jesseditson committed Mar 27, 2024
1 parent c811c60 commit 905500b
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 44 deletions.
2 changes: 1 addition & 1 deletion src/binary/command/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ impl BinaryCommand for Command {
let field = args.get_one::<ManifestField>("field").unwrap();
let fs = file_system_stdlib::NativeFileSystem::new(build_dir);
let site = Site::load(&fs)?;
print!("{}", site.manifest.field(field).unwrap_or("".to_string()));
print!("{}", site.manifest.field_as_string(field));
Ok(ExitStatus::Ok)
}
}
26 changes: 24 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,15 @@ pub use object_definition::ObjectDefinition;

pub static ARCHIVAL_VERSION: &str = env!("CARGO_PKG_VERSION");

const MIN_COMPAT_VERSION: &str = ">=0.4.1";
const MIN_COMPAT_VERSION: &str = ">=0.5.0";
pub(crate) fn check_compatibility(version_string: &str) -> (bool, String) {
let req = VersionReq::parse(MIN_COMPAT_VERSION).unwrap();
match Version::parse(version_string) {
Ok(version) => {
if req.matches(&version) {
(true, "passed compatibility check.".to_owned())
} else {
(false, format!("version {} is incompatible with this version of archival (minimum required version {}).", version, MIN_COMPAT_VERSION))
(false, format!("site archival version {} is incompatible with this version of archival (minimum required version {}).", version, MIN_COMPAT_VERSION))
}
}
Err(e) => (false, format!("invalid version {}: {}", version_string, e)),
Expand Down Expand Up @@ -555,6 +555,28 @@ mod lib {
assert_eq!(rendered_links.len(), 0);
Ok(())
}

#[test]
fn modify_manifest() -> Result<(), Box<dyn Error>> {
let mut fs = MemoryFileSystem::default();
let zip = include_bytes!("../tests/fixtures/archival-website.zip");
unpack_zip(zip.to_vec(), &mut fs)?;
let mut archival = Archival::new(fs)?;
archival.modify_manifest(|m| {
m.site_url = Some("test.com".to_string());
m.archival_site = Some("test".to_string());
m.prebuild = vec!["test".to_string()];
})?;
let output = archival.site.manifest.to_toml()?;
println!("{}", output);
assert!(output.contains("archival_site = \"test\""));
assert!(output.contains("site_url = \"test.com\""));
// Doesn't fill defaults
assert!(!output.contains("objects"));
// Does show non-defaults
assert!(output.contains("prebuild = [\"test\"]"));
Ok(())
}
}

#[cfg(test)]
Expand Down
143 changes: 103 additions & 40 deletions src/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ impl fmt::Display for InvalidManifestError {

#[derive(Debug, Default, Deserialize, Serialize)]
pub struct Manifest {
root: PathBuf,
pub archival_version: Option<String>,
pub prebuild: Vec<String>,
pub site_url: Option<String>,
Expand All @@ -42,12 +43,29 @@ pub enum ManifestField {
SiteUrl,
ArchivalSite,
ObjectsDir,
Prebuild,
PagesDir,
BuildDir,
StaticDir,
LayoutDir,
}

impl ManifestField {
fn field_name(&self) -> &str {
match self {
ManifestField::ArchivalVersion => "archival_version",
ManifestField::ArchivalSite => "archival_site",
ManifestField::SiteUrl => "site_url",
ManifestField::ObjectsDir => "objects",
ManifestField::Prebuild => "prebuild",
ManifestField::PagesDir => "pages",
ManifestField::BuildDir => "build_dir",
ManifestField::StaticDir => "static_dir",
ManifestField::LayoutDir => "layout_dir",
}
}
}

impl fmt::Display for Manifest {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
Expand Down Expand Up @@ -81,6 +99,7 @@ impl fmt::Display for Manifest {
impl Manifest {
pub fn default(root: &Path) -> Manifest {
Manifest {
root: root.to_owned(),
archival_version: None,
prebuild: vec![],
site_url: None,
Expand All @@ -93,6 +112,28 @@ impl Manifest {
layout_dir: root.join(LAYOUT_DIR_NAME),
}
}
fn is_default(&self, field: &ManifestField) -> bool {
let str_value = self.field_as_string(field);
match field {
ManifestField::Prebuild => str_value == "[]",
ManifestField::ObjectsDir => {
str_value == self.root.join(OBJECTS_DIR_NAME).to_string_lossy()
}
ManifestField::PagesDir => {
str_value == self.root.join(PAGES_DIR_NAME).to_string_lossy()
}
ManifestField::BuildDir => {
str_value == self.root.join(BUILD_DIR_NAME).to_string_lossy()
}
ManifestField::StaticDir => {
str_value == self.root.join(STATIC_DIR_NAME).to_string_lossy()
}
ManifestField::LayoutDir => {
str_value == self.root.join(LAYOUT_DIR_NAME).to_string_lossy()
}
_ => str_value.is_empty(),
}
}
pub fn from_file(
manifest_path: &Path,
fs: &impl FileSystemAPI,
Expand Down Expand Up @@ -132,54 +173,76 @@ impl Manifest {
Ok(manifest)
}

pub fn field(&self, field: &ManifestField) -> Option<String> {
fn toml_field(&self, field: &ManifestField) -> Option<Value> {
match field {
ManifestField::ArchivalVersion => self.archival_version.to_owned(),
ManifestField::ArchivalSite => self.archival_site.to_owned(),
ManifestField::SiteUrl => self.site_url.to_owned(),
ManifestField::ObjectsDir => Some(self.pages_dir.to_string_lossy().to_string()),
ManifestField::PagesDir => Some(self.pages_dir.to_string_lossy().to_string()),
ManifestField::BuildDir => Some(self.build_dir.to_string_lossy().to_string()),
ManifestField::StaticDir => Some(self.static_dir.to_string_lossy().to_string()),
ManifestField::LayoutDir => Some(self.layout_dir.to_string_lossy().to_string()),
ManifestField::ArchivalVersion => self.archival_version.to_owned().map(Value::String),
ManifestField::ArchivalSite => self.archival_site.to_owned().map(Value::String),
ManifestField::SiteUrl => self.site_url.to_owned().map(Value::String),
ManifestField::Prebuild => {
if self.prebuild.is_empty() {
None
} else {
Some(Value::Array(
self.prebuild
.iter()
.map(|v| Value::String(v.to_string()))
.collect(),
))
}
}
ManifestField::ObjectsDir => Some(Value::String(
self.objects_dir.to_string_lossy().to_string(),
)),
ManifestField::PagesDir => {
Some(Value::String(self.pages_dir.to_string_lossy().to_string()))
}
ManifestField::BuildDir => {
Some(Value::String(self.build_dir.to_string_lossy().to_string()))
}
ManifestField::StaticDir => {
Some(Value::String(self.static_dir.to_string_lossy().to_string()))
}
ManifestField::LayoutDir => {
Some(Value::String(self.layout_dir.to_string_lossy().to_string()))
}
}
}

pub fn field_as_string(&self, field: &ManifestField) -> String {
match self.toml_field(field) {
Some(fv) => match fv {
Value::Array(a) => toml::to_string(&a).unwrap_or_default(),
Value::String(s) => s,
_ => panic!("unsupported manifest field type"),
},
None => String::default(),
}
}

fn durable_fields() -> Vec<ManifestField> {
vec![
ManifestField::ArchivalSite,
ManifestField::SiteUrl,
ManifestField::Prebuild,
ManifestField::ArchivalSite,
ManifestField::PagesDir,
ManifestField::ObjectsDir,
ManifestField::BuildDir,
ManifestField::StaticDir,
ManifestField::ObjectsDir,
]
}

pub fn to_toml(&self) -> Result<String, toml::ser::Error> {
let mut write_obj = Table::new();
for key in [
"archival_version",
"site_url",
"object file",
"objects",
"pages",
"static_dir",
"layout_dir",
"build_dir",
] {
let value = match key {
"archival_version" => self.field(&ManifestField::ArchivalVersion),
"site_url" => self.field(&ManifestField::SiteUrl),
"pages" => self.field(&ManifestField::PagesDir),
"objects" => self.field(&ManifestField::ObjectsDir),
"build_dir" => self.field(&ManifestField::BuildDir),
"static_dir" => self.field(&ManifestField::StaticDir),
"layout_dir" => self.field(&ManifestField::ObjectsDir),
_ => None,
};
if let Some(value) = value {
write_obj.insert(key.to_string(), Value::String(value));
for field in Self::durable_fields() {
let key = field.field_name();
if !self.is_default(&field) {
if let Some(value) = self.toml_field(&field) {
write_obj.insert(key.to_string(), value);
}
}
}
write_obj.insert(
"prebuild".to_string(),
Value::Array(
self.prebuild
.iter()
.map(|v| Value::String(v.to_string()))
.collect(),
),
);
toml::to_string_pretty(&write_obj)
}

Expand Down
2 changes: 1 addition & 1 deletion tests/binary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ mod binary_tests {
#[traced_test]
fn compatiblity_ok() -> Result<(), Box<dyn Error>> {
assert!(matches!(
archival::binary::binary(get_args(vec!["compat", "0.4.1"]))?,
archival::binary::binary(get_args(vec!["compat", "0.5.0"]))?,
ExitStatus::Ok
));
Ok(())
Expand Down

0 comments on commit 905500b

Please sign in to comment.