diff --git a/crates/dropshot-api-manager/src/doc_files_local.rs b/crates/dropshot-api-manager/src/doc_files_local.rs index aa5e582..1dcfee2 100644 --- a/crates/dropshot-api-manager/src/doc_files_local.rs +++ b/crates/dropshot-api-manager/src/doc_files_local.rs @@ -38,6 +38,23 @@ pub struct LocalApiUnparseable { pub reason: UnparseableReason, } +/// A local file that exists and was successfully parsed. +#[derive(Debug)] +pub struct LocalApiValid { + /// The parsed OpenAPI document. + pub doc: Box, + /// Commit hash parsed from the `.gitstub` file, if this file was + /// loaded from one. `None` for regular JSON files. + pub git_stub_commit: Option, +} + +impl LocalApiValid { + /// Returns the document file name. + pub fn doc_file_name(&self) -> &ApiDocFileName { + self.doc.doc_file_name() + } +} + /// Represents an OpenAPI document found in this working tree. /// /// This includes documents for lockstep APIs and versioned APIs, for both @@ -49,13 +66,7 @@ pub struct LocalApiUnparseable { #[derive(Debug)] pub enum LocalApiDocFile { /// A valid, successfully parsed OpenAPI document. - Valid { - /// The parsed OpenAPI document. - doc: Box, - /// Commit hash parsed from the `.gitstub` file, if this file was - /// loaded from one. `None` for regular JSON files. - git_stub_commit: Option, - }, + Valid(LocalApiValid), /// A file that exists but couldn't be parsed. Unparseable(LocalApiUnparseable), } @@ -64,7 +75,7 @@ impl LocalApiDocFile { /// Returns the document file name. pub fn doc_file_name(&self) -> &ApiDocFileName { match self { - Self::Valid { doc, .. } => doc.doc_file_name(), + Self::Valid(v) => v.doc_file_name(), Self::Unparseable(u) => &u.name, } } @@ -74,19 +85,10 @@ impl LocalApiDocFile { /// This works for both valid and unparseable files. pub fn contents(&self) -> &[u8] { match self { - Self::Valid { doc, .. } => doc.contents(), + Self::Valid(v) => v.doc.contents(), Self::Unparseable(u) => &u.contents, } } - - /// Returns the commit hash from a `.gitstub` file, if this file was - /// loaded from one. - pub fn git_stub_commit(&self) -> Option<&GitCommitHash> { - match self { - Self::Valid { git_stub_commit, .. } => git_stub_commit.as_ref(), - Self::Unparseable(_) => None, - } - } } impl DocFileInfo for LocalApiDocFile { @@ -96,7 +98,7 @@ impl DocFileInfo for LocalApiDocFile { fn version(&self) -> Option<&semver::Version> { match self { - Self::Valid { doc, .. } => Some(doc.version()), + Self::Valid(v) => Some(v.doc.version()), Self::Unparseable(_) => None, } } @@ -112,18 +114,18 @@ impl ApiLoad for Vec { type Unparseable = LocalApiUnparseable; fn try_extend(&mut self, item: ApiDocFile) -> anyhow::Result<()> { - self.push(LocalApiDocFile::Valid { + self.push(LocalApiDocFile::Valid(LocalApiValid { doc: Box::new(item), git_stub_commit: None, - }); + })); Ok(()) } fn make_item(raw: ApiDocFile) -> Self { - vec![LocalApiDocFile::Valid { + vec![LocalApiDocFile::Valid(LocalApiValid { doc: Box::new(raw), git_stub_commit: None, - }] + })] } fn make_unparseable( @@ -143,10 +145,8 @@ impl ApiLoad for Vec { } fn set_git_stub_commit(&mut self, commit: GitCommitHash) { - if let Some(LocalApiDocFile::Valid { git_stub_commit, .. }) = - self.last_mut() - { - *git_stub_commit = Some(commit); + if let Some(LocalApiDocFile::Valid(valid)) = self.last_mut() { + valid.git_stub_commit = Some(commit); } } } diff --git a/crates/dropshot-api-manager/src/resolved.rs b/crates/dropshot-api-manager/src/resolved.rs index b450f93..ed445b9 100644 --- a/crates/dropshot-api-manager/src/resolved.rs +++ b/crates/dropshot-api-manager/src/resolved.rs @@ -11,7 +11,9 @@ use crate::{ doc_files_blessed::{BlessedApiDocFile, BlessedFiles, BlessedGitStub}, doc_files_generated::{GeneratedApiDocFile, GeneratedFiles}, doc_files_generic::ApiFiles, - doc_files_local::{LocalApiDocFile, LocalApiUnparseable, LocalFiles}, + doc_files_local::{ + LocalApiDocFile, LocalApiUnparseable, LocalApiValid, LocalFiles, + }, environment::ResolvedEnv, iter_only::iter_only, output::{InlineErrorChain, plural}, @@ -376,7 +378,7 @@ pub enum VersionProblem<'a> { you." )] BlessedVersionShouldBeGitStub { - local_file: &'a LocalApiDocFile, + local_file: &'a LocalApiValid, git_stub: GitStub, }, @@ -385,7 +387,7 @@ pub enum VersionProblem<'a> { JSON. This tool can perform the conversion for you." )] GitStubShouldBeJson { - local_file: &'a LocalApiDocFile, + local_file: &'a LocalApiValid, blessed: &'a BlessedApiDocFile, }, @@ -401,14 +403,14 @@ pub enum VersionProblem<'a> { "Duplicate local file found: both JSON and Git stub versions exist for \ this API version. This tool can remove the redundant file for you." )] - DuplicateLocalFile { local_file: &'a LocalApiDocFile }, + DuplicateLocalFile { local_file: &'a LocalApiValid }, #[error( "Git stub has an outdated commit reference that is no longer \ an ancestor of the merge base. This can happen after a rebase or \ force-push. This tool can update the Git stub for you." )] - GitStubCommitStale { local_file: &'a LocalApiDocFile, git_stub: GitStub }, + GitStubCommitStale { local_file: &'a LocalApiValid, git_stub: GitStub }, #[error( "The first commit for this blessed version could not be determined. This \ @@ -675,12 +677,12 @@ pub enum Fix<'a> { }, /// Convert a full JSON file to a Git stub. ConvertToGitStub { - local_file: &'a LocalApiDocFile, + local_file: &'a LocalApiValid, git_stub: &'a GitStub, }, /// Convert a Git stub back to a full JSON file. ConvertToJson { - local_file: &'a LocalApiDocFile, + local_file: &'a LocalApiValid, blessed: &'a BlessedApiDocFile, }, /// Regenerate a corrupted local file from the blessed content. @@ -704,7 +706,7 @@ pub enum Fix<'a> { /// Update a Git stub whose commit hash has become stale (e.g., /// after a rebase). UpdateGitStub { - local_file: &'a LocalApiDocFile, + local_file: &'a LocalApiValid, git_stub: &'a GitStub, }, } @@ -1293,7 +1295,7 @@ fn resolve_removed_blessed_versions<'a>( fn file_validity(doc_file: &LocalApiDocFile) -> FileValidity { match doc_file { - LocalApiDocFile::Valid { .. } => FileValidity::Valid, + LocalApiDocFile::Valid(_) => FileValidity::Valid, LocalApiDocFile::Unparseable(_) => FileValidity::Unparseable, } } @@ -1305,7 +1307,7 @@ fn file_with_reason(doc_file: &LocalApiDocFile) -> String { unparseable.name, InlineErrorChain::new(&unparseable.reason), ), - LocalApiDocFile::Valid { .. } => doc_file.doc_file_name().to_string(), + LocalApiDocFile::Valid(_) => doc_file.doc_file_name().to_string(), } } @@ -1322,7 +1324,7 @@ fn orphaned_message(doc_file: &LocalApiDocFile) -> String { ), // Orphaned valid files get a hint about whether the list of supported // versions has changed. - LocalApiDocFile::Valid { .. } => format!( + LocalApiDocFile::Valid(_) => format!( "A local OpenAPI document was found that does not correspond to \ a supported version of this API: {}. This is unusual, but it \ could happen if you're either retiring an older version of this \ @@ -1372,7 +1374,7 @@ fn lockstep_stale_message( InlineErrorChain::new(&unparseable.reason), ), // A valid file that needs to be updated. - LocalApiDocFile::Valid { .. } => format!( + LocalApiDocFile::Valid(_) => format!( "For this lockstep API, OpenAPI document generated from the \ current code does not match the local file: {:?}. This tool \ can update the local file for you.", @@ -1904,7 +1906,7 @@ fn resolve_api_version_blessed<'a>( non_matching.push(local_file); } } - LocalApiDocFile::Valid { .. } => { + LocalApiDocFile::Valid(valid) => { // For valid files, verify that hash matching implies content // matching (and vice versa). let contents_match = @@ -1915,7 +1917,7 @@ fn resolve_api_version_blessed<'a>( ); if hashes_match { - matching.push(local_file); + matching.push(valid); } else { non_matching.push(local_file); } @@ -2043,11 +2045,11 @@ fn resolve_api_version_blessed<'a>( // compared to what the blessed source expects. This is shared // between the single-match and duplicate-files branches below. let check_git_stub_staleness = - |local_file: &'a LocalApiDocFile, + |local_file: &'a LocalApiValid, expected_git_stub: &GitStub, problems: &mut Vec>| { // Non-gitstub files (JSON) don't have a commit to check. - let Some(local_commit) = local_file.git_stub_commit() else { + let Some(local_commit) = &local_file.git_stub_commit else { return; }; if *local_commit != expected_git_stub.commit() {