Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 27 additions & 27 deletions crates/dropshot-api-manager/src/doc_files_local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<ApiDocFile>,
/// Commit hash parsed from the `.gitstub` file, if this file was
/// loaded from one. `None` for regular JSON files.
pub git_stub_commit: Option<GitCommitHash>,
}

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
Expand All @@ -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<ApiDocFile>,
/// Commit hash parsed from the `.gitstub` file, if this file was
/// loaded from one. `None` for regular JSON files.
git_stub_commit: Option<GitCommitHash>,
},
Valid(LocalApiValid),
/// A file that exists but couldn't be parsed.
Unparseable(LocalApiUnparseable),
}
Expand All @@ -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,
}
}
Expand All @@ -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 {
Expand All @@ -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,
}
}
Expand All @@ -112,18 +114,18 @@ impl ApiLoad for Vec<LocalApiDocFile> {
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(
Expand All @@ -143,10 +145,8 @@ impl ApiLoad for Vec<LocalApiDocFile> {
}

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);
}
}
}
Expand Down
34 changes: 18 additions & 16 deletions crates/dropshot-api-manager/src/resolved.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -376,7 +378,7 @@ pub enum VersionProblem<'a> {
you."
)]
BlessedVersionShouldBeGitStub {
local_file: &'a LocalApiDocFile,
local_file: &'a LocalApiValid,
git_stub: GitStub,
},

Expand All @@ -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,
},

Expand All @@ -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 \
Expand Down Expand Up @@ -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.
Expand All @@ -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,
},
}
Expand Down Expand Up @@ -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,
}
}
Expand All @@ -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(),
}
}

Expand All @@ -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 \
Expand Down Expand Up @@ -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.",
Expand Down Expand Up @@ -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 =
Expand All @@ -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);
}
Expand Down Expand Up @@ -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<VersionProblem<'a>>| {
// 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() {
Expand Down
Loading