-
Notifications
You must be signed in to change notification settings - Fork 70
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
264 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,28 @@ | ||
use anyhow::Result; | ||
use anyhow::{anyhow, Result}; | ||
|
||
use scarb::core::Config; | ||
use scarb::ops; | ||
|
||
use crate::args::AddArgs; | ||
|
||
#[tracing::instrument(skip_all, level = "info")] | ||
pub fn run(_conf: &Config) -> Result<()> { | ||
todo!() | ||
pub fn run(args: AddArgs, config: &mut Config) -> Result<()> { | ||
let ws = ops::read_workspace(config.manifest_path(), config)?; | ||
|
||
// TODO(mkaput): Extract more generic pattern for this. See `Packages` in Cargo. | ||
let package = match args.package { | ||
Some(name) => ws | ||
.members() | ||
.find(|pkg| pkg.id.name == name) | ||
.ok_or_else(|| anyhow!("package `{name}` not found in workspace `{ws}`"))?, | ||
None => ws.current_package()?.clone(), | ||
}; | ||
|
||
if !args.dry_run { | ||
// Reload the workspace since we have changed dependencies | ||
let ws = ops::read_workspace(config.manifest_path(), config)?; | ||
let _ = ops::resolve_workspace(&ws)?; | ||
} | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
use anyhow::Result; | ||
use camino::{Utf8Path, Utf8PathBuf}; | ||
use semver::VersionReq; | ||
use toml_edit::Document; | ||
|
||
use crate::core::{GitReference, PackageName}; | ||
|
||
use super::tomlx::get_table_mut; | ||
use super::{Op, OpCtx}; | ||
|
||
pub struct AddDependency { | ||
pub name: Option<PackageName>, | ||
pub version: Option<VersionReq>, | ||
pub path: Option<Utf8PathBuf>, | ||
pub git: Option<String>, | ||
pub branch: Option<String>, | ||
pub tag: Option<String>, | ||
pub rev: Option<String>, | ||
} | ||
|
||
struct Dep { | ||
name: PackageName, | ||
source: Source, | ||
} | ||
|
||
enum Source { | ||
Registry(RegistrySource), | ||
Path(PathSource), | ||
Git(GitSource), | ||
} | ||
|
||
struct RegistrySource { | ||
version: VersionReq, | ||
} | ||
|
||
struct PathSource { | ||
version: Option<VersionReq>, | ||
path: Utf8PathBuf, | ||
} | ||
|
||
struct GitSource { | ||
version: Option<VersionReq>, | ||
git: String, | ||
reference: GitReference, | ||
} | ||
|
||
impl Op for AddDependency { | ||
fn apply_to(self: Box<Self>, doc: &mut Document, ctx: OpCtx<'_>) -> Result<()> { | ||
let table = get_table_mut(doc, &["dependencies"])?; | ||
|
||
let dep_key = self.toml_key(); | ||
|
||
match table | ||
.as_table_like_mut() | ||
.unwrap() | ||
.get_key_value_mut(dep_key) | ||
{ | ||
Some((mut dep_key, dep_item)) => self.update_toml(&mut dep_key, dep_item), | ||
None => { | ||
table[dep_key] = self.to_toml(); | ||
} | ||
} | ||
|
||
if let Some(t) = table.as_inline_table_mut() { | ||
t.fmt() | ||
} | ||
|
||
Ok(()) | ||
} | ||
} | ||
|
||
impl AddDependency { | ||
// TODO(mkaput): With namespaced packages, this should produce a path. | ||
fn toml_key(&self) -> &str { | ||
self.name | ||
.as_ref() | ||
.expect("package name should be known at this point") | ||
.as_str() | ||
} | ||
} | ||
|
||
fn path_value(manifest_path: &Utf8Path, abs_path: &Utf8Path) -> String { | ||
pathdiff::diff_utf8_paths(abs_path, manifest_path) | ||
.expect("Both paths should be absolute at this point.") | ||
.as_str() | ||
.replace('\\', "/") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
//! `Scarb.toml` editor. | ||
|
||
use std::str::FromStr; | ||
|
||
use anyhow::{Context, Result}; | ||
use camino::Utf8Path; | ||
use toml_edit::Document; | ||
|
||
pub use add::AddDependency; | ||
|
||
use crate::core::Config; | ||
use crate::internal::fsx; | ||
|
||
mod add; | ||
mod tomlx; | ||
|
||
pub trait Op { | ||
fn apply_to(self: Box<Self>, doc: &mut Document, ctx: OpCtx<'_>) -> Result<()>; | ||
} | ||
|
||
pub struct OpCtx<'c> { | ||
manifest_path: &'c Utf8Path, | ||
opts: &'c EditManifestOptions<'c>, | ||
} | ||
|
||
pub struct EditManifestOptions<'c> { | ||
pub config: &'c Config, | ||
pub dry_run: bool, | ||
} | ||
|
||
/// Edit manifest file (for example, add dependencies). | ||
#[tracing::instrument(level = "trace", skip(ops, opts))] | ||
pub fn edit_manifest( | ||
manifest_path: &Utf8Path, | ||
ops: Vec<Box<dyn Op>>, | ||
opts: EditManifestOptions<'_>, | ||
) -> Result<()> { | ||
let original_raw_manifest = fsx::read_to_string(manifest_path)?; | ||
let mut doc = Document::from_str(&original_raw_manifest) | ||
.with_context(|| format!("failed to read manifest at `{manifest_path}`"))?; | ||
|
||
for op in ops { | ||
op.apply_to( | ||
&mut doc, | ||
OpCtx { | ||
manifest_path, | ||
opts: &opts, | ||
}, | ||
)?; | ||
} | ||
|
||
// TODO(mkaput): Sort dependencies and scripts etc. | ||
|
||
let new_raw_manifest = doc.to_string(); | ||
if new_raw_manifest == original_raw_manifest { | ||
opts.config.ui().warn("no changes have to be made"); | ||
} else if opts.dry_run { | ||
opts.config.ui().warn("aborting due to dry run"); | ||
} else { | ||
fsx::write(manifest_path, new_raw_manifest.as_bytes())?; | ||
} | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
use anyhow::{ensure, Result}; | ||
use toml_edit::{Document, Item, Table}; | ||
|
||
pub fn get_table_mut<'a>(doc: &'a mut Document, path: &[&str]) -> Result<&'a mut Item> { | ||
return visit(doc.as_item_mut(), path); | ||
|
||
fn visit<'a>(item: &'a mut Item, path: &[&str]) -> Result<&'a mut Item> { | ||
if let Some(segment) = path.first() { | ||
let item = item[segment].or_insert({ | ||
let mut table = Table::new(); | ||
table.set_implicit(true); | ||
Item::Table(table) | ||
}); | ||
|
||
ensure!( | ||
item.is_table_like(), | ||
"the table `{segment}` could not be found." | ||
); | ||
visit(item, &path[1..]) | ||
} else { | ||
assert!(item.is_table_like()); | ||
Ok(item) | ||
} | ||
} | ||
} |