use super::TomlEditableEntry;
use super::work_dependencies::{is_work_dependency_target, validate_work_dependency_edit};
use crate::cmd::edit::adapter::{TomlAdapter, WorkTomlAdapter};
use crate::cmd::edit::engine as edit_engine;
use crate::cmd::edit::refs::{is_refs_target, validate_ref_edit};
use crate::cmd::edit::runtime as edit_runtime;
use crate::cmd::edit::{
ArtifactType, deserialize_edit_doc, serialize_edit_doc, unexpected_edit_state,
};
use crate::config::Config;
use crate::diagnostic::{Diagnostic, DiagnosticCode, DiagnosticResult};
use crate::write::WriteOp;
pub(in crate::cmd::edit) fn set_toml_field<A>(
config: &Config,
id: &str,
target: &edit_engine::ResolvedTarget,
value: &str,
op: WriteOp,
artifact: ArtifactType,
allow_forced_simple_set: bool,
) -> DiagnosticResult<()>
where
A: TomlAdapter,
A::Entry: TomlEditableEntry,
{
let mut entry = A::load(config, id)?;
apply_toml_target_to_entry(
&mut entry,
target,
value,
artifact,
allow_forced_simple_set,
id,
)?;
if is_refs_target(target) {
validate_ref_edit(config, artifact, id, value)?;
}
A::write(config, &entry, op)?;
Ok(())
}
pub(in crate::cmd::edit) fn set_work_toml_field(
config: &Config,
id: &str,
target: &edit_engine::ResolvedTarget,
value: &str,
op: WriteOp,
allow_forced_simple_set: bool,
) -> DiagnosticResult<()> {
let mut entry = WorkTomlAdapter::load(config, id)?;
apply_toml_target_to_entry(
&mut entry,
target,
value,
ArtifactType::WorkItem,
allow_forced_simple_set,
id,
)?;
if is_refs_target(target) {
validate_ref_edit(config, ArtifactType::WorkItem, id, value)?;
}
if is_work_dependency_target(target) {
validate_work_dependency_edit(config, &entry)?;
}
WorkTomlAdapter::write(config, &entry, op)?;
Ok(())
}
fn apply_toml_target_to_entry<E>(
entry: &mut E,
target: &edit_engine::ResolvedTarget,
value: &str,
artifact: ArtifactType,
allow_forced_simple_set: bool,
id: &str,
) -> DiagnosticResult<()>
where
E: TomlEditableEntry,
{
let mut doc = serialize_edit_doc(entry.spec(), id)?;
match target {
edit_engine::ResolvedTarget::Node {
path,
kind: edit_engine::TargetKind::Scalar,
origin,
..
} => match origin {
edit_engine::TargetOrigin::Simple => {
let simple = path
.as_simple()
.ok_or_else(|| unexpected_edit_state(id, "simple target path expected"))?;
if allow_forced_simple_set {
edit_runtime::set_simple_field_forced(artifact, &mut doc, simple, value, id)?;
} else {
edit_runtime::set_simple_field(artifact, &mut doc, simple, value, id)?;
}
}
edit_engine::TargetOrigin::Nested => {
edit_runtime::set_nested_field(artifact, &mut doc, path, value, id)?;
}
},
edit_engine::ResolvedTarget::IndexedItem {
origin,
container_path,
index,
item_kind: edit_engine::TargetKind::Scalar,
..
} => match origin {
edit_engine::TargetOrigin::Simple => {
let simple = container_path.as_simple().ok_or_else(|| {
unexpected_edit_state(id, "simple indexed container expected")
})?;
edit_runtime::set_simple_list_item(artifact, &mut doc, simple, *index, value, id)?;
}
edit_engine::TargetOrigin::Nested => {
edit_runtime::set_nested_list_item(
artifact,
&mut doc,
container_path,
*index,
value,
id,
)?;
}
},
_ => {
return Err(Diagnostic::new(
DiagnosticCode::E0817PathTypeMismatch,
"set requires a scalar field or indexed scalar list item",
id,
));
}
}
*entry.spec_mut() = deserialize_edit_doc(doc, id)?;
Ok(())
}