diff --git a/.mailmap b/.mailmap new file mode 100644 index 0000000..32e52a1 --- /dev/null +++ b/.mailmap @@ -0,0 +1,7 @@ +# SPDX-FileCopyrightText: 2023, Rylie Pavlik +# +# SPDX-License-Identifier: MIT + +Rylie Pavlik +Rylie Pavlik + diff --git a/src/models/document_creation_information.rs b/src/models/document_creation_information.rs index 6a3c01e..6d9bb63 100644 --- a/src/models/document_creation_information.rs +++ b/src/models/document_creation_information.rs @@ -250,9 +250,9 @@ mod test { .creation_info .creator_comment, Some( - r#"This package has been shipped in source and binary form. + r"This package has been shipped in source and binary form. The binaries were created with gcc 4.5.1 and expect to link to -compatible system run time libraries."# +compatible system run time libraries." .to_string() ) ); diff --git a/src/models/spdx_document.rs b/src/models/spdx_document.rs index 69834e3..413ed93 100644 --- a/src/models/spdx_document.rs +++ b/src/models/spdx_document.rs @@ -72,7 +72,7 @@ pub struct SPDX { #[serde(default)] pub annotations: Vec, - /// Counter for creating SPDXRefs. Is not part of the spec, so don't serialize. + /// Counter for creating `SPDXRefs`. Is not part of the spec, so don't serialize. #[serde(skip)] pub spdx_ref_counter: i32, } diff --git a/src/parsers/mod.rs b/src/parsers/mod.rs index 358492c..c96d41d 100644 --- a/src/parsers/mod.rs +++ b/src/parsers/mod.rs @@ -171,6 +171,25 @@ fn spdx_from_atoms(atoms: &[Atom]) -> Result { }) } +fn parse_date_time(value: &str) -> chrono::ParseResult> { + // Trailing Z output by recent versions of reuse break chrono. + let trimmed = if value.ends_with("+00:00Z") { + value + .strip_suffix('Z') + .expect("always works, we checked first") + } else { + value + }; + let parsed = if let Some(trimmed) = trimmed.strip_suffix('Z') { + // we got Z instead of offset + let revised = format!("{trimmed}+00:00"); + DateTime::parse_from_rfc3339(&revised)? + } else { + DateTime::parse_from_rfc3339(trimmed)? + }; + Ok(parsed.with_timezone(&Utc)) +} + fn process_atom_for_document_creation_information( atom: &Atom, mut document_creation_information_in_progress: &mut Option, @@ -245,8 +264,7 @@ fn process_atom_for_document_creation_information( if let Some(document_creation_information) = &mut document_creation_information_in_progress { - document_creation_information.creation_info.created = - DateTime::parse_from_rfc3339(value)?.with_timezone(&Utc); + document_creation_information.creation_info.created = parse_date_time(value)?; } } Atom::CreatorComment(value) => { @@ -596,11 +614,11 @@ fn process_atom_for_relationships( #[derive(Debug, Default)] struct AnnotationInProgress { - annotator_in_progress: Option, - date_in_progress: Option>, - comment_in_progress: Option, - type_in_progress: Option, - spdxref_in_progress: Option, + annotator: Option, + date: Option>, + comment: Option, + annotation_type: Option, + spdxref: Option, } fn process_annotation( @@ -609,11 +627,11 @@ fn process_annotation( annotations: &mut Vec, ) { if let AnnotationInProgress { - annotator_in_progress: Some(annotator), - date_in_progress: Some(date), - comment_in_progress: Some(comment), - type_in_progress: Some(annotation_type), - spdxref_in_progress: Some(spdxref), + annotator: Some(annotator), + date: Some(date), + comment: Some(comment), + annotation_type: Some(annotation_type), + spdxref: Some(spdxref), } = &mut annotation_in_progress { let annotation = Annotation::new( @@ -624,11 +642,11 @@ fn process_annotation( comment.clone(), ); *annotation_in_progress = AnnotationInProgress { - annotator_in_progress: None, - comment_in_progress: None, - date_in_progress: None, - spdxref_in_progress: None, - type_in_progress: None, + annotator: None, + comment: None, + date: None, + spdxref: None, + annotation_type: None, }; annotations.push(annotation); } @@ -643,20 +661,19 @@ fn process_atom_for_annotations( match atom { Atom::Annotator(value) => { - annotation_in_progress.annotator_in_progress = Some(value.clone()); + annotation_in_progress.annotator = Some(value.clone()); } Atom::AnnotationDate(value) => { - annotation_in_progress.date_in_progress = - Some(DateTime::parse_from_rfc3339(value)?.with_timezone(&Utc)); + annotation_in_progress.date = Some(parse_date_time(value)?); } Atom::AnnotationComment(value) => { - annotation_in_progress.comment_in_progress = Some(value.clone()); + annotation_in_progress.comment = Some(value.clone()); } Atom::AnnotationType(value) => { - annotation_in_progress.type_in_progress = Some(*value); + annotation_in_progress.annotation_type = Some(*value); } Atom::SPDXREF(value) => { - annotation_in_progress.spdxref_in_progress = Some(value.clone()); + annotation_in_progress.spdxref = Some(value.clone()); } _ => {} } @@ -720,6 +737,17 @@ mod test_super { use super::*; + #[test] + fn datetime_variants_ok() { + let with_z = "2024-05-20T14:46:54+00:00Z"; + let without_z = "2024-05-20T14:46:54+00:00"; + assert_eq!(parse_date_time(with_z), parse_date_time(without_z)); + assert!(parse_date_time(with_z).is_ok()); + + let only_z = "2024-05-20T14:46:54Z"; + assert_eq!(parse_date_time(only_z), parse_date_time(without_z)); + } + #[test] fn whole_spdx_is_parsed() { let file = read_to_string("tests/data/SPDXTagExample-v2.2.spdx").unwrap(); diff --git a/tests/integration.rs b/tests/integration.rs index fef8003..414384d 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -15,22 +15,22 @@ use std::result::Result as StdResult; #[test] fn deserialize_json_v2_2() -> Result<()> { - Ok(load_spdx("tests/data/SPDXJSONExample-v2.2.spdx.json", spdx_from_json).map(ignore)?) + load_spdx("tests/data/SPDXJSONExample-v2.2.spdx.json", spdx_from_json).map(ignore) } #[test] fn deserialize_json_v2_3() -> Result<()> { - Ok(load_spdx("tests/data/SPDXJSONExample-v2.3.spdx.json", spdx_from_json).map(ignore)?) + load_spdx("tests/data/SPDXJSONExample-v2.3.spdx.json", spdx_from_json).map(ignore) } #[test] fn deserialize_tag_value_v2_2() -> Result<()> { - Ok(load_spdx("tests/data/SPDXTagExample-v2.2.spdx", spdx_from_tag_value).map(ignore)?) + load_spdx("tests/data/SPDXTagExample-v2.2.spdx", spdx_from_tag_value).map(ignore) } #[test] fn deserialize_tag_value_v2_3() -> Result<()> { - Ok(load_spdx("tests/data/SPDXTagExample-v2.3.spdx", spdx_from_tag_value).map(ignore)?) + load_spdx("tests/data/SPDXTagExample-v2.3.spdx", spdx_from_tag_value).map(ignore) } /// Helper function for ignoring a value.