Skip to content

Commit

Permalink
feat: vrc-get upgrade
Browse files Browse the repository at this point in the history
  • Loading branch information
anatawa12 committed Jan 30, 2023
1 parent 17f900c commit 60d2dbf
Show file tree
Hide file tree
Showing 3 changed files with 169 additions and 11 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ For more details, please see --help
- [x] `vrc-get install [pkg] [version]` (with alias `vrc-get i [pkg] [version]`)
- [x] `vrc-get remove [pkg]` (with alias `vrc-get rm [pkg]`)
- [x] `vrc-get outdated`
- [x] `vrc-get upgrade [pkg] [version]`
- [x] `vrc-get repo list`
- [x] `vrc-get repo add <url> [NAME]`
- [x] `vrc-get repo remove <name or url>`
Expand Down
105 changes: 103 additions & 2 deletions src/commands.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::version::Version;
use crate::vpm::structs::remote_repo::PackageVersions;
use crate::vpm::{download_remote_repository, VersionSelector};
use crate::vpm::{download_remote_repository, AddPackageErr, VersionSelector};
use clap::{Parser, Subcommand};
use reqwest::Url;
use serde_json::{from_value, Map, Value};
Expand Down Expand Up @@ -31,13 +31,17 @@ pub enum Command {
#[command(alias = "rm")]
Remove(Remove),
Outdated(Outdated),
Upgrade(Upgrade),
#[command(subcommand)]
Repo(Repo),
}

multi_command!(Command is Install, Remove, Outdated, Repo);
multi_command!(Command is Install, Remove, Outdated, Upgrade, Repo);

/// Adds package to unity project
///
/// With install command, you'll add to dependencies. With upgrade command,
/// you'll upgrade dependencies or locked dependencies but not add to dependencies.
#[derive(Parser)]
#[command(author, version)]
pub struct Install {
Expand Down Expand Up @@ -172,6 +176,103 @@ impl Outdated {
}
}

/// Upgrade specified package or all packages to latest or specified version.
///
/// With install command, you'll add to dependencies. With upgrade command,
/// you'll upgrade dependencies or locked dependencies but not add to dependencies.
#[derive(Parser)]
#[command(author, version)]
pub struct Upgrade {
/// Name of Package
#[arg()]
name: Option<String>,
/// Version of package. if not specified, latest version will be used
#[arg(id = "VERSION")]
version: Option<Version>,
/// Include prerelease
#[arg(long = "prerelease")]
prerelease: bool,

/// Path to project dir. by default CWD or parents of CWD will be used
#[arg(short = 'p', long = "project")]
project: Option<PathBuf>,
}

impl Upgrade {
pub async fn run(self) {
let client = crate::create_client();
let env = crate::vpm::Environment::load_default(client)
.await
.expect("loading global config");
let mut unity = crate::vpm::UnityProject::find_unity_project(self.project)
.await
.expect("unity project not found");

if let Some(name) = self.name {
let version_selector = match self.version {
None if self.prerelease => VersionSelector::LatestIncluidingPrerelease,
None => VersionSelector::Latest,
Some(ref version) => VersionSelector::Specific(version),
};
let package = env
.find_package_by_name(&name, version_selector)
.await
.expect("finding package")
.expect("no matching package not found");

unity
.upgrade_package(&env, &package)
.await
.expect("upgrading package");

println!("upgraded {} to {}", name, package.version);
} else {
let version_selector = match self.prerelease {
true => VersionSelector::LatestIncluidingPrerelease,
false => VersionSelector::Latest,
};
let package_names = unity.locked_packages().keys().cloned().collect::<Vec<_>>();
for name in package_names {
let package = env
.find_package_by_name(&name, version_selector)
.await
.expect("finding package")
.expect("no matching package not found");

match unity.upgrade_package(&env, &package).await {
Ok(_) => {
println!("upgraded {} to {}", name, package.version);
}
Err(AddPackageErr::Io(e)) => log::error!("upgrading package: {}", e),
Err(AddPackageErr::AlreadyNewerPackageInstalled) => {}
Err(AddPackageErr::ConflictWithDependencies {
dependency_name, ..
}) => {
log::warn!(
"upgrading {} to {}: conflicts with {}",
name,
package.version,
dependency_name
);
}
Err(AddPackageErr::DependencyNotFound {
dependency_name, ..
}) => {
log::error!(
"upgrading {} to {}: dependencies of it {} not found",
name,
package.version,
dependency_name
);
}
}
}
}

unity.save().await.expect("saving manifest file");
}
}

/// Commands around repositories
#[derive(Subcommand)]
#[command(author, version)]
Expand Down
74 changes: 65 additions & 9 deletions src/vpm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -880,26 +880,36 @@ impl UnityProject {
}
}

// check for version conflict
self.check_conflict(&request.name, &request.version)?;

let adding_deps = self.collect_adding_packages(env, request).await?;

// check for version conflict for all deps
for x in &adding_deps {
self.check_conflict(&x.name, &x.version)?;
}

let mut packages = adding_deps.iter().collect::<Vec<_>>();
packages.push(request);
let packages = packages;

// check for version conflict for all deps
self.check_adding_package(&packages)?;

// there's no errors to add package. adding to dependencies

// first, add to dependencies
self.manifest
.add_dependency(&request.name, VpmDependency::new(request.version.clone()));

self.do_add_packages_to_locked(env, &packages).await
}

fn check_adding_package(&mut self, packages: &[&PackageJson]) -> Result<(), AddPackageErr> {
for x in packages {
self.check_conflict(&x.name, &x.version)?;
}

return Ok(());
}

async fn do_add_packages_to_locked(
&mut self,
env: &Environment,
packages: &[&PackageJson],
) -> Result<(), AddPackageErr> {
// then, lock all dependencies
for pkg in packages.iter() {
self.manifest.add_locked(
Expand All @@ -923,6 +933,51 @@ impl UnityProject {
Ok(())
}

/// Add specified package to self project.
///
/// If the package or newer one is already installed in dependencies, this does nothing
/// and returns AlreadyNewerPackageInstalled err.
///
/// If the package or newer one is already installed in locked list,
/// this adds specified (not locked) version to dependencies
pub async fn upgrade_package(
&mut self,
env: &Environment,
request: &PackageJson,
) -> Result<(), AddPackageErr> {
use crate::vpm::AddPackageErr::*;
// if same or newer requested package is in dependencies, do nothing
if let Some(dep) = self.manifest.dependencies().get(&request.name) {
if dep.version >= request.version {
return Err(AlreadyNewerPackageInstalled);
}
}

// if same or newer requested package is in locked dependencies,
// Do nothing
if let Some(locked) = self.manifest.locked().get(&request.name) {
if locked.version >= request.version {
return Err(AlreadyNewerPackageInstalled);
}
}

let adding_deps = self.collect_adding_packages(env, request).await?;
let mut packages = adding_deps.iter().collect::<Vec<_>>();
packages.push(request);
let packages = packages;

// check for version conflict for all deps
self.check_adding_package(&packages)?;

// there's no errors to add package. adding to dependencies

// first, add to dependencies
self.manifest
.add_dependency(&request.name, VpmDependency::new(request.version.clone()));

self.do_add_packages_to_locked(env, &packages).await
}

/// Remove specified package from self project.
///
/// This doesn't look packages not listed in vpm-maniefst.json.
Expand Down Expand Up @@ -1064,6 +1119,7 @@ impl UnityProject {
}
}

#[derive(Clone, Copy)]
pub enum VersionSelector<'a> {
Latest,
LatestIncluidingPrerelease,
Expand Down

0 comments on commit 60d2dbf

Please sign in to comment.