mirror of
https://github.com/vrc-get/vrc-get.git
synced 2026-06-21 09:58:08 +00:00
chore: add vpm remove
This commit is contained in:
parent
e21f213c5b
commit
94aa133052
4 changed files with 130 additions and 2 deletions
|
|
@ -13,7 +13,7 @@ Open Source command line client of VRChat Package Manager.
|
|||
For more details, please see --help
|
||||
|
||||
- [x] `vrc-get install [pkg] [version]`
|
||||
- [ ] `vrc-get remove [pkg]`
|
||||
- [x] `vrc-get remove [pkg]` (with alias `vrc-get rm [pkg]`)
|
||||
- [x] `vrc-get repo list`
|
||||
- [x] `vrc-get repo add <url> [NAME]`
|
||||
- [x] `vrc-get repo remove <name or url>`
|
||||
|
|
|
|||
|
|
@ -25,12 +25,15 @@ macro_rules! multi_command {
|
|||
#[derive(Parser)]
|
||||
pub enum Command {
|
||||
Install(Install),
|
||||
#[command(alias = "rm")]
|
||||
Remove(Remove),
|
||||
#[command(subcommand)]
|
||||
Repo(Repo),
|
||||
}
|
||||
|
||||
multi_command!(Command is Install, Repo);
|
||||
multi_command!(Command is Install, Remove, Repo);
|
||||
|
||||
/// Adds package to unity project
|
||||
#[derive(Parser)]
|
||||
pub struct Install {
|
||||
/// Name of Package
|
||||
|
|
@ -81,6 +84,33 @@ impl Install {
|
|||
}
|
||||
}
|
||||
|
||||
/// Remove package from Unity project.
|
||||
#[derive(Parser)]
|
||||
pub struct Remove {
|
||||
/// Name of Packages to remove
|
||||
#[arg()]
|
||||
names: Vec<String>,
|
||||
|
||||
/// Path to project dir. by default CWD or parents of CWD will be used
|
||||
#[arg(short = 'p', long = "project")]
|
||||
project: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl Remove {
|
||||
pub async fn run(self) {
|
||||
let mut unity = crate::vpm::UnityProject::find_unity_project(self.project)
|
||||
.await
|
||||
.expect("unity project not found");
|
||||
|
||||
unity
|
||||
.remove(&self.names.iter().map(String::as_ref).collect::<Vec<_>>())
|
||||
.await
|
||||
.expect("removing package");
|
||||
|
||||
unity.save().await.expect("saving manifest file");
|
||||
}
|
||||
}
|
||||
|
||||
/// Commands around repositories
|
||||
#[derive(Subcommand)]
|
||||
pub enum Repo {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
extern crate core;
|
||||
|
||||
use clap::Parser;
|
||||
use reqwest::Client;
|
||||
|
||||
|
|
|
|||
|
|
@ -621,6 +621,14 @@ mod vpm_manifest {
|
|||
self.locked.insert(name.to_string(), dependency);
|
||||
}
|
||||
|
||||
pub(crate) fn remove_packages(&mut self, names: &[&str]) {
|
||||
for name in names {
|
||||
self.locked.remove(*name);
|
||||
self.dependencies.remove(*name);
|
||||
}
|
||||
self.changed = true;
|
||||
}
|
||||
|
||||
fn add_value(&mut self, key0: &str, key1: &str, value: &impl Serialize) {
|
||||
let serialized = to_value(value).expect("serialize err");
|
||||
match self.json.get_mut(key0) {
|
||||
|
|
@ -781,6 +789,50 @@ impl UnityProject {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Remove specified package from self project.
|
||||
///
|
||||
/// This doesn't look packages not listed in vpm-maniefst.json.
|
||||
pub async fn remove(&mut self, names: &[&str]) -> Result<(), RemovePackageErr> {
|
||||
use crate::vpm::RemovePackageErr::*;
|
||||
|
||||
// check for existence
|
||||
|
||||
let mut repos = Vec::with_capacity(names.len());
|
||||
let mut not_founds = Vec::new();
|
||||
for name in names.into_iter().copied() {
|
||||
if let Some(x) = self.manifest.locked().get(name) {
|
||||
repos.push(x);
|
||||
} else {
|
||||
not_founds.push(name.to_owned());
|
||||
}
|
||||
}
|
||||
|
||||
if !not_founds.is_empty() {
|
||||
return Err(NotInstalled(not_founds));
|
||||
}
|
||||
|
||||
// check for conflicts: if some package requires some packages to be removed, it's conflict.
|
||||
|
||||
let conflicts = self
|
||||
.manifest
|
||||
.locked()
|
||||
.into_iter()
|
||||
.filter(|(name, _)| !names.contains(&name.as_str()))
|
||||
.filter(|(_, dep)| names.into_iter().any(|x| dep.dependencies.contains_key(*x)))
|
||||
.map(|(name, _)| String::from(name))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if !conflicts.is_empty() {
|
||||
return Err(ConflictsWith(conflicts));
|
||||
}
|
||||
|
||||
// there's no conflicts. So do remove
|
||||
|
||||
self.manifest.remove_packages(names);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn collect_adding_packages(
|
||||
&mut self,
|
||||
env: &Environment,
|
||||
|
|
@ -919,6 +971,50 @@ impl From<io::Error> for AddPackageErr {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum RemovePackageErr {
|
||||
Io(io::Error),
|
||||
NotInstalled(Vec<String>),
|
||||
ConflictsWith(Vec<String>),
|
||||
}
|
||||
|
||||
impl fmt::Display for RemovePackageErr {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use RemovePackageErr::*;
|
||||
match self {
|
||||
Io(ioerr) => fmt::Display::fmt(ioerr, f),
|
||||
NotInstalled(names) => {
|
||||
f.write_str("the following packages are not installed: ")?;
|
||||
let mut iter = names.iter();
|
||||
f.write_str(iter.next().unwrap())?;
|
||||
while let Some(name) = iter.next() {
|
||||
f.write_str(", ")?;
|
||||
f.write_str(name)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
ConflictsWith(names) => {
|
||||
f.write_str("removing packages conflicts with the following packages: ")?;
|
||||
let mut iter = names.iter();
|
||||
f.write_str(iter.next().unwrap())?;
|
||||
while let Some(name) = iter.next() {
|
||||
f.write_str(", ")?;
|
||||
f.write_str(name)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for RemovePackageErr {}
|
||||
|
||||
impl From<io::Error> for RemovePackageErr {
|
||||
fn from(value: io::Error) -> Self {
|
||||
Self::Io(value)
|
||||
}
|
||||
}
|
||||
|
||||
/// open file or returns none if not exists
|
||||
async fn try_open_file(path: &Path) -> io::Result<Option<File>> {
|
||||
match File::open(path).await {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue