1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-24 15:19:26 -05:00

feat: deno remove (#24952)

Co-authored-by: Satya Rohith <me@satyarohith.com>
This commit is contained in:
David Sherret 2024-08-12 16:17:25 -04:00 committed by GitHub
parent b1036e4d9c
commit 085058cfff
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 229 additions and 5 deletions

View file

@ -83,6 +83,11 @@ pub struct AddFlags {
pub packages: Vec<String>,
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct RemoveFlags {
pub packages: Vec<String>,
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct BenchFlags {
pub files: FileFlags,
@ -428,6 +433,7 @@ pub struct HelpFlags {
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum DenoSubcommand {
Add(AddFlags),
Remove(RemoveFlags),
Bench(BenchFlags),
Bundle(BundleFlags),
Cache(CacheFlags),
@ -1216,6 +1222,7 @@ pub fn flags_from_vec(args: Vec<OsString>) -> clap::error::Result<Flags> {
if let Some((subcommand, mut m)) = matches.remove_subcommand() {
match subcommand.as_str() {
"add" => add_parse(&mut flags, &mut m),
"remove" => remove_parse(&mut flags, &mut m),
"bench" => bench_parse(&mut flags, &mut m),
"bundle" => bundle_parse(&mut flags, &mut m),
"cache" => cache_parse(&mut flags, &mut m),
@ -1442,6 +1449,7 @@ pub fn clap_root() -> Command {
.defer(|cmd| {
let cmd = cmd
.subcommand(add_subcommand())
.subcommand(remove_subcommand())
.subcommand(bench_subcommand())
.subcommand(bundle_subcommand())
.subcommand(cache_subcommand())
@ -1515,6 +1523,31 @@ You can add multiple dependencies at once:
})
}
fn remove_subcommand() -> Command {
Command::new("remove")
.alias("rm")
.about("Remove dependencies")
.long_about(
"Remove dependencies from the configuration file.
deno remove @std/path
You can remove multiple dependencies at once:
deno remove @std/path @std/assert
",
)
.defer(|cmd| {
cmd.arg(
Arg::new("packages")
.help("List of packages to remove")
.required(true)
.num_args(1..)
.action(ArgAction::Append),
)
})
}
fn bench_subcommand() -> Command {
Command::new("bench")
.about(
@ -3726,6 +3759,12 @@ fn add_parse_inner(
AddFlags { packages }
}
fn remove_parse(flags: &mut Flags, matches: &mut ArgMatches) {
flags.subcommand = DenoSubcommand::Remove(RemoveFlags {
packages: matches.remove_many::<String>("packages").unwrap().collect(),
});
}
fn bench_parse(flags: &mut Flags, matches: &mut ArgMatches) {
flags.type_check_mode = TypeCheckMode::Local;
@ -10247,6 +10286,35 @@ mod tests {
);
}
#[test]
fn remove_subcommand() {
let r = flags_from_vec(svec!["deno", "remove"]);
r.unwrap_err();
let r = flags_from_vec(svec!["deno", "remove", "@david/which"]);
assert_eq!(
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Remove(RemoveFlags {
packages: svec!["@david/which"],
}),
..Flags::default()
}
);
let r =
flags_from_vec(svec!["deno", "remove", "@david/which", "@luca/hello"]);
assert_eq!(
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Remove(RemoveFlags {
packages: svec!["@david/which", "@luca/hello"],
}),
..Flags::default()
}
);
}
#[test]
fn run_with_frozen_lockfile() {
let cases = [

View file

@ -355,7 +355,7 @@ impl CliFactory {
let fs = self.fs();
let cli_options = self.cli_options()?;
// For `deno install` we want to force the managed resolver so it can set up `node_modules/` directory.
create_cli_npm_resolver(if cli_options.use_byonm() && !matches!(cli_options.sub_command(), DenoSubcommand::Install(_) | DenoSubcommand::Add(_)) {
create_cli_npm_resolver(if cli_options.use_byonm() && !matches!(cli_options.sub_command(), DenoSubcommand::Install(_) | DenoSubcommand::Add(_) | DenoSubcommand::Remove(_)) {
CliNpmResolverCreateOptions::Byonm(CliNpmResolverByonmCreateOptions {
fs: fs.clone(),
root_node_modules_dir: Some(match cli_options.node_modules_dir_path() {

View file

@ -100,6 +100,9 @@ async fn run_subcommand(flags: Arc<Flags>) -> Result<i32, AnyError> {
DenoSubcommand::Add(add_flags) => spawn_subcommand(async {
tools::registry::add(flags, add_flags, tools::registry::AddCommandName::Add).await
}),
DenoSubcommand::Remove(remove_flags) => spawn_subcommand(async {
tools::registry::remove(flags, remove_flags).await
}),
DenoSubcommand::Bench(bench_flags) => spawn_subcommand(async {
if bench_flags.watch.is_some() {
tools::bench::run_benchmarks_with_watch(flags, bench_flags).await

View file

@ -64,6 +64,7 @@ mod unfurl;
use auth::get_auth_method;
use auth::AuthMethod;
pub use pm::add;
pub use pm::remove;
pub use pm::AddCommandName;
use publish_order::PublishOrderGraph;
use unfurl::SpecifierUnfurler;

View file

@ -1,6 +1,7 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use std::borrow::Cow;
use std::path::Path;
use std::path::PathBuf;
use std::sync::Arc;
@ -23,6 +24,7 @@ use jsonc_parser::ast::Value;
use crate::args::AddFlags;
use crate::args::CacheSetting;
use crate::args::Flags;
use crate::args::RemoveFlags;
use crate::factory::CliFactory;
use crate::file_fetcher::FileFetcher;
use crate::jsr::JsrFetchResolver;
@ -337,9 +339,7 @@ pub async fn add(
// make a new CliFactory to pick up the updated config file
let cli_factory = CliFactory::from_flags(flags);
// cache deps
if cli_factory.cli_options()?.enable_future_features() {
crate::module_loader::load_top_level_deps(&cli_factory).await?;
}
crate::module_loader::load_top_level_deps(&cli_factory).await?;
Ok(())
}
@ -513,6 +513,85 @@ fn generate_imports(packages_to_version: Vec<(String, String)>) -> String {
contents.join("\n")
}
fn remove_from_config(
config_path: &Path,
keys: &[&'static str],
packages_to_remove: &[String],
removed_packages: &mut Vec<String>,
fmt_options: &FmtOptionsConfig,
) -> Result<(), AnyError> {
let mut json: serde_json::Value =
serde_json::from_slice(&std::fs::read(config_path)?)?;
for key in keys {
let Some(obj) = json.get_mut(*key).and_then(|v| v.as_object_mut()) else {
continue;
};
for package in packages_to_remove {
if obj.shift_remove(package).is_some() {
removed_packages.push(package.clone());
}
}
}
let config = serde_json::to_string_pretty(&json)?;
let config =
crate::tools::fmt::format_json(config_path, &config, fmt_options)
.ok()
.flatten()
.unwrap_or(config);
std::fs::write(config_path, config)
.context("Failed to update configuration file")?;
Ok(())
}
pub async fn remove(
flags: Arc<Flags>,
remove_flags: RemoveFlags,
) -> Result<(), AnyError> {
let (config_file, factory) = DenoOrPackageJson::from_flags(flags.clone())?;
let options = factory.cli_options()?;
let start_dir = &options.start_dir;
let fmt_config_options = config_file.fmt_options();
let mut removed_packages = Vec::new();
if let Some(deno_json) = start_dir.maybe_deno_json() {
remove_from_config(
&deno_json.specifier.to_file_path().unwrap(),
&["imports"],
&remove_flags.packages,
&mut removed_packages,
&fmt_config_options,
)?;
}
if let Some(pkg_json) = start_dir.maybe_pkg_json() {
remove_from_config(
&pkg_json.path,
&["dependencies", "devDependencies"],
&remove_flags.packages,
&mut removed_packages,
&fmt_config_options,
)?;
}
if removed_packages.is_empty() {
log::info!("No packages were removed");
} else {
for package in &removed_packages {
log::info!("Removed {}", crate::colors::green(package));
}
// Update deno.lock
node_resolver::PackageJsonThreadLocalCache::clear();
let cli_factory = CliFactory::from_flags(flags);
crate::module_loader::load_top_level_deps(&cli_factory).await?;
}
Ok(())
}
fn update_config_file_content(
obj: jsonc_parser::ast::Object,
config_file_contents: &str,

View file

@ -3,7 +3,7 @@
"steps": [
{
"args": "add npm:ajv@latest",
"output": "Add npm:ajv@8.11.0\n"
"output": "add.out"
}
]
}

View file

@ -0,0 +1,15 @@
Add npm:ajv@8.11.0
[UNORDERED_START]
Download http://localhost:4260/ajv
Download http://localhost:4260/fast-deep-equal
Download http://localhost:4260/json-schema-traverse
Download http://localhost:4260/require-from-string
Download http://localhost:4260/uri-js
Download http://localhost:4260/punycode
Download http://localhost:4260/ajv/ajv-8.11.0.tgz
Download http://localhost:4260/require-from-string/require-from-string-2.0.2.tgz
Download http://localhost:4260/uri-js/uri-js-4.4.1.tgz
Download http://localhost:4260/fast-deep-equal/fast-deep-equal-3.1.3.tgz
Download http://localhost:4260/json-schema-traverse/json-schema-traverse-1.0.0.tgz
Download http://localhost:4260/punycode/punycode-2.1.1.tgz
[UNORDERED_END]

View file

@ -0,0 +1,16 @@
{
"tempDir": true,
"steps": [{
"args": ["add", "@std/assert", "@std/http"],
"output": "add.out"
}, {
"args": ["eval", "console.log(Deno.readTextFileSync('deno.lock').trim())"],
"output": "add_lock.out"
}, {
"args": ["remove", "@std/assert", "@std/http"],
"output": "rm.out"
}, {
"args": ["eval", "console.log(Deno.readTextFileSync('deno.lock').trim())"],
"output": "remove_lock.out"
}]
}

View file

@ -0,0 +1,12 @@
Created deno.json configuration file.
Add jsr:@std/assert@1.0.0
Add jsr:@std/http@1.0.0
[UNORDERED_START]
Download http://127.0.0.1:4250/@std/http/1.0.0_meta.json
Download http://127.0.0.1:4250/@std/assert/1.0.0_meta.json
Download http://127.0.0.1:4250/@std/http/1.0.0/mod.ts
Download http://127.0.0.1:4250/@std/assert/1.0.0/mod.ts
Download http://127.0.0.1:4250/@std/assert/1.0.0/assert_equals.ts
Download http://127.0.0.1:4250/@std/assert/1.0.0/assert.ts
Download http://127.0.0.1:4250/@std/assert/1.0.0/fail.ts
[UNORDERED_END]

View file

@ -0,0 +1,24 @@
{
"version": "3",
"packages": {
"specifiers": {
"jsr:@std/assert@^1.0.0": "jsr:@std/assert@1.0.0",
"jsr:@std/http@^1.0.0": "jsr:@std/http@1.0.0"
},
"jsr": {
"@std/assert@1.0.0": {
"integrity": "7ae268c58de9693b4997fd93d9b303a47df336664e2008378ccb93c3458d092a"
},
"@std/http@1.0.0": {
"integrity": "d75bd303c21123a9b58f7249e38b4c0aa3a09f7d76b13f9d7e7842d89052091a"
}
}
},
"remote": {},
"workspace": {
"dependencies": [
"jsr:@std/assert@^1.0.0",
"jsr:@std/http@^1.0.0"
]
}
}

View file

@ -0,0 +1,4 @@
{
"version": "3",
"remote": {}
}

View file

@ -0,0 +1,2 @@
Removed @std/assert
Removed @std/http