mirror of
https://github.com/tauri-apps/tauri.git
synced 2024-11-24 04:03:52 +03:00
feat(cli): add migration from 2.0.0-beta to 2.0.0-rc (#10395)
* refactor(cli): check tauri version on migration * rc migration * license headers * fix tests * add path * update schema
This commit is contained in:
parent
426d14bb41
commit
d5511c3117
6
.changes/rc-migration.md
Normal file
6
.changes/rc-migration.md
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
"tauri-cli": patch:feat
|
||||
"@tauri-apps/cli": patch:feat
|
||||
---
|
||||
|
||||
Added migration from `2.0.0-beta` to `2.0.0-rc`.
|
@ -2551,7 +2551,7 @@
|
||||
]
|
||||
},
|
||||
"changelog": {
|
||||
"description": "Path of the uncompressed Changelog file, to be stored at /usr/share/doc/package-name/changelog.gz. See\n https://www.debian.org/doc/debian-policy/ch-docs.html#changelog-files-and-release-notes",
|
||||
"description": "Path of the uncompressed Changelog file, to be stored at /usr/share/doc/package-name/changelog.gz. See\n <https://www.debian.org/doc/debian-policy/ch-docs.html#changelog-files-and-release-notes>",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
@ -2565,28 +2565,28 @@
|
||||
]
|
||||
},
|
||||
"preInstallScript": {
|
||||
"description": "Path to script that will be executed before the package is unpacked. See\n https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html",
|
||||
"description": "Path to script that will be executed before the package is unpacked. See\n <https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html>",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"postInstallScript": {
|
||||
"description": "Path to script that will be executed after the package is unpacked. See\n https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html",
|
||||
"description": "Path to script that will be executed after the package is unpacked. See\n <https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html>",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"preRemoveScript": {
|
||||
"description": "Path to script that will be executed before the package is removed. See\n https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html",
|
||||
"description": "Path to script that will be executed before the package is removed. See\n <https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html>",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"postRemoveScript": {
|
||||
"description": "Path to script that will be executed after the package is removed. See\n https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html",
|
||||
"description": "Path to script that will be executed after the package is removed. See\n <https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html>",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
@ -2667,28 +2667,28 @@
|
||||
]
|
||||
},
|
||||
"preInstallScript": {
|
||||
"description": "Path to script that will be executed before the package is unpacked. See\n http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html",
|
||||
"description": "Path to script that will be executed before the package is unpacked. See\n <http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html>",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"postInstallScript": {
|
||||
"description": "Path to script that will be executed after the package is unpacked. See\n http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html",
|
||||
"description": "Path to script that will be executed after the package is unpacked. See\n <http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html>",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"preRemoveScript": {
|
||||
"description": "Path to script that will be executed before the package is removed. See\n http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html",
|
||||
"description": "Path to script that will be executed before the package is removed. See\n <http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html>",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"postRemoveScript": {
|
||||
"description": "Path to script that will be executed after the package is removed. See\n http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html",
|
||||
"description": "Path to script that will be executed after the package is removed. See\n <http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html>",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
|
1
tooling/cli/Cargo.lock
generated
1
tooling/cli/Cargo.lock
generated
@ -5181,6 +5181,7 @@ dependencies = [
|
||||
"toml_edit 0.22.6",
|
||||
"ureq",
|
||||
"url",
|
||||
"walkdir",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
|
@ -98,6 +98,7 @@ oxc_allocator = "0.16"
|
||||
oxc_ast = "0.16"
|
||||
magic_string = "0.3"
|
||||
phf = { version = "0.11", features = ["macros"] }
|
||||
walkdir = "2"
|
||||
|
||||
[target."cfg(windows)".dependencies.windows-sys]
|
||||
version = "0.52"
|
||||
|
@ -2551,7 +2551,7 @@
|
||||
]
|
||||
},
|
||||
"changelog": {
|
||||
"description": "Path of the uncompressed Changelog file, to be stored at /usr/share/doc/package-name/changelog.gz. See\n https://www.debian.org/doc/debian-policy/ch-docs.html#changelog-files-and-release-notes",
|
||||
"description": "Path of the uncompressed Changelog file, to be stored at /usr/share/doc/package-name/changelog.gz. See\n <https://www.debian.org/doc/debian-policy/ch-docs.html#changelog-files-and-release-notes>",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
@ -2565,28 +2565,28 @@
|
||||
]
|
||||
},
|
||||
"preInstallScript": {
|
||||
"description": "Path to script that will be executed before the package is unpacked. See\n https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html",
|
||||
"description": "Path to script that will be executed before the package is unpacked. See\n <https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html>",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"postInstallScript": {
|
||||
"description": "Path to script that will be executed after the package is unpacked. See\n https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html",
|
||||
"description": "Path to script that will be executed after the package is unpacked. See\n <https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html>",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"preRemoveScript": {
|
||||
"description": "Path to script that will be executed before the package is removed. See\n https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html",
|
||||
"description": "Path to script that will be executed before the package is removed. See\n <https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html>",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"postRemoveScript": {
|
||||
"description": "Path to script that will be executed after the package is removed. See\n https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html",
|
||||
"description": "Path to script that will be executed after the package is removed. See\n <https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html>",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
@ -2667,28 +2667,28 @@
|
||||
]
|
||||
},
|
||||
"preInstallScript": {
|
||||
"description": "Path to script that will be executed before the package is unpacked. See\n http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html",
|
||||
"description": "Path to script that will be executed before the package is unpacked. See\n <http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html>",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"postInstallScript": {
|
||||
"description": "Path to script that will be executed after the package is unpacked. See\n http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html",
|
||||
"description": "Path to script that will be executed after the package is unpacked. See\n <http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html>",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"preRemoveScript": {
|
||||
"description": "Path to script that will be executed before the package is removed. See\n http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html",
|
||||
"description": "Path to script that will be executed before the package is removed. See\n <http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html>",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"postRemoveScript": {
|
||||
"description": "Path to script that will be executed after the package is removed. See\n http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html",
|
||||
"description": "Path to script that will be executed after the package is removed. See\n <http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html>",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
|
@ -146,7 +146,7 @@ pub fn command(options: Options) -> Result<()> {
|
||||
(None, None, None, None) => npm_name,
|
||||
_ => anyhow::bail!("Only one of --tag, --rev and --branch can be specified"),
|
||||
};
|
||||
manager.install(&[npm_spec])?;
|
||||
manager.install(&[npm_spec], &tauri_dir)?;
|
||||
}
|
||||
|
||||
let _ = acl::permission::add::command(acl::permission::add::Options {
|
||||
|
172
tooling/cli/src/helpers/cargo_manifest.rs
Normal file
172
tooling/cli/src/helpers/cargo_manifest.rs
Normal file
@ -0,0 +1,172 @@
|
||||
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
fmt::Write,
|
||||
fs::read_to_string,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
#[derive(Clone, Deserialize)]
|
||||
pub struct CargoLockPackage {
|
||||
pub name: String,
|
||||
pub version: String,
|
||||
pub source: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct CargoLock {
|
||||
pub package: Vec<CargoLockPackage>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize)]
|
||||
pub struct CargoManifestDependencyPackage {
|
||||
pub version: Option<String>,
|
||||
pub git: Option<String>,
|
||||
pub branch: Option<String>,
|
||||
pub rev: Option<String>,
|
||||
pub path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum CargoManifestDependency {
|
||||
Version(String),
|
||||
Package(CargoManifestDependencyPackage),
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct CargoManifestPackage {
|
||||
pub version: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct CargoManifest {
|
||||
pub package: CargoManifestPackage,
|
||||
pub dependencies: HashMap<String, CargoManifestDependency>,
|
||||
}
|
||||
|
||||
pub struct CrateVersion {
|
||||
pub version: String,
|
||||
pub found_crate_versions: Vec<String>,
|
||||
}
|
||||
|
||||
pub fn crate_version(
|
||||
tauri_dir: &Path,
|
||||
manifest: Option<&CargoManifest>,
|
||||
lock: Option<&CargoLock>,
|
||||
name: &str,
|
||||
) -> CrateVersion {
|
||||
let crate_lock_packages: Vec<CargoLockPackage> = lock
|
||||
.as_ref()
|
||||
.map(|lock| {
|
||||
lock
|
||||
.package
|
||||
.iter()
|
||||
.filter(|p| p.name == name)
|
||||
.cloned()
|
||||
.collect()
|
||||
})
|
||||
.unwrap_or_default();
|
||||
let (crate_version_string, found_crate_versions) =
|
||||
match (&manifest, &lock, crate_lock_packages.len()) {
|
||||
(Some(_manifest), Some(_lock), 1) => {
|
||||
let crate_lock_package = crate_lock_packages.first().unwrap();
|
||||
let version_string = if let Some(s) = &crate_lock_package.source {
|
||||
if s.starts_with("git") {
|
||||
format!("{} ({})", s, crate_lock_package.version)
|
||||
} else {
|
||||
crate_lock_package.version.clone()
|
||||
}
|
||||
} else {
|
||||
crate_lock_package.version.clone()
|
||||
};
|
||||
(version_string, vec![crate_lock_package.version.clone()])
|
||||
}
|
||||
(None, Some(_lock), 1) => {
|
||||
let crate_lock_package = crate_lock_packages.first().unwrap();
|
||||
let version_string = if let Some(s) = &crate_lock_package.source {
|
||||
if s.starts_with("git") {
|
||||
format!("{} ({})", s, crate_lock_package.version)
|
||||
} else {
|
||||
crate_lock_package.version.clone()
|
||||
}
|
||||
} else {
|
||||
crate_lock_package.version.clone()
|
||||
};
|
||||
(
|
||||
format!("{version_string} (no manifest)"),
|
||||
vec![crate_lock_package.version.clone()],
|
||||
)
|
||||
}
|
||||
_ => {
|
||||
let mut found_crate_versions = Vec::new();
|
||||
let mut is_git = false;
|
||||
let manifest_version = match manifest.and_then(|m| m.dependencies.get(name).cloned()) {
|
||||
Some(tauri) => match tauri {
|
||||
CargoManifestDependency::Version(v) => {
|
||||
found_crate_versions.push(v.clone());
|
||||
v
|
||||
}
|
||||
CargoManifestDependency::Package(p) => {
|
||||
if let Some(v) = p.version {
|
||||
found_crate_versions.push(v.clone());
|
||||
v
|
||||
} else if let Some(p) = p.path {
|
||||
let manifest_path = tauri_dir.join(&p).join("Cargo.toml");
|
||||
let v = match read_to_string(manifest_path)
|
||||
.map_err(|_| ())
|
||||
.and_then(|m| toml::from_str::<CargoManifest>(&m).map_err(|_| ()))
|
||||
{
|
||||
Ok(manifest) => manifest.package.version,
|
||||
Err(_) => "unknown version".to_string(),
|
||||
};
|
||||
format!("path:{p:?} [{v}]")
|
||||
} else if let Some(g) = p.git {
|
||||
is_git = true;
|
||||
let mut v = format!("git:{g}");
|
||||
if let Some(branch) = p.branch {
|
||||
let _ = write!(v, "&branch={branch}");
|
||||
} else if let Some(rev) = p.rev {
|
||||
let _ = write!(v, "#{rev}");
|
||||
}
|
||||
v
|
||||
} else {
|
||||
"unknown manifest".to_string()
|
||||
}
|
||||
}
|
||||
},
|
||||
None => "no manifest".to_string(),
|
||||
};
|
||||
|
||||
let lock_version = match (lock, crate_lock_packages.is_empty()) {
|
||||
(Some(_lock), false) => crate_lock_packages
|
||||
.iter()
|
||||
.map(|p| p.version.clone())
|
||||
.collect::<Vec<String>>()
|
||||
.join(", "),
|
||||
(Some(_lock), true) => "unknown lockfile".to_string(),
|
||||
_ => "no lockfile".to_string(),
|
||||
};
|
||||
|
||||
(
|
||||
format!(
|
||||
"{} {}({})",
|
||||
manifest_version,
|
||||
if is_git { "(git manifest)" } else { "" },
|
||||
lock_version
|
||||
),
|
||||
found_crate_versions,
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
CrateVersion {
|
||||
found_crate_versions,
|
||||
version: crate_version_string,
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@
|
||||
|
||||
pub mod app_paths;
|
||||
pub mod cargo;
|
||||
pub mod cargo_manifest;
|
||||
pub mod config;
|
||||
pub mod flock;
|
||||
pub mod framework;
|
||||
|
@ -81,7 +81,7 @@ impl PackageManager {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn install(&self, dependencies: &[String]) -> crate::Result<()> {
|
||||
pub fn install<P: AsRef<Path>>(&self, dependencies: &[String], app_dir: P) -> crate::Result<()> {
|
||||
let dependencies_str = if dependencies.len() > 1 {
|
||||
"dependencies"
|
||||
} else {
|
||||
@ -100,6 +100,7 @@ impl PackageManager {
|
||||
.cross_command()
|
||||
.arg("add")
|
||||
.args(dependencies)
|
||||
.current_dir(app_dir)
|
||||
.status()
|
||||
.with_context(|| format!("failed to run {self}"))?;
|
||||
|
||||
@ -109,4 +110,71 @@ impl PackageManager {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn current_package_version<P: AsRef<Path>>(
|
||||
&self,
|
||||
name: &str,
|
||||
app_dir: P,
|
||||
) -> crate::Result<Option<String>> {
|
||||
let (output, regex) = match self {
|
||||
PackageManager::Yarn => (
|
||||
cross_command("yarn")
|
||||
.args(["list", "--pattern"])
|
||||
.arg(name)
|
||||
.args(["--depth", "0"])
|
||||
.current_dir(app_dir)
|
||||
.output()?,
|
||||
None,
|
||||
),
|
||||
PackageManager::YarnBerry => (
|
||||
cross_command("yarn")
|
||||
.arg("info")
|
||||
.arg(name)
|
||||
.arg("--json")
|
||||
.current_dir(app_dir)
|
||||
.output()?,
|
||||
Some(regex::Regex::new("\"Version\":\"([\\da-zA-Z\\-\\.]+)\"").unwrap()),
|
||||
),
|
||||
PackageManager::Npm => (
|
||||
cross_command("npm")
|
||||
.arg("list")
|
||||
.arg(name)
|
||||
.args(["version", "--depth", "0"])
|
||||
.current_dir(app_dir)
|
||||
.output()?,
|
||||
None,
|
||||
),
|
||||
PackageManager::Pnpm => (
|
||||
cross_command("pnpm")
|
||||
.arg("list")
|
||||
.arg(name)
|
||||
.args(["--parseable", "--depth", "0"])
|
||||
.current_dir(app_dir)
|
||||
.output()?,
|
||||
None,
|
||||
),
|
||||
// Bun doesn't support `list` command
|
||||
PackageManager::Bun => (
|
||||
cross_command("npm")
|
||||
.arg("list")
|
||||
.arg(name)
|
||||
.args(["version", "--depth", "0"])
|
||||
.current_dir(app_dir)
|
||||
.output()?,
|
||||
None,
|
||||
),
|
||||
};
|
||||
if output.status.success() {
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
let regex = regex.unwrap_or_else(|| regex::Regex::new("@(\\d[\\da-zA-Z\\-\\.]+)").unwrap());
|
||||
Ok(
|
||||
regex
|
||||
.captures_iter(&stdout)
|
||||
.last()
|
||||
.and_then(|cap| cap.get(1).map(|v| v.as_str().to_string())),
|
||||
)
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ use super::SectionItem;
|
||||
use super::{env_nodejs::manager_version, VersionMetadata};
|
||||
use colored::Colorize;
|
||||
use serde::Deserialize;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::helpers::{cross_command, npm::PackageManager};
|
||||
|
||||
@ -87,73 +87,6 @@ fn npm_latest_version(pm: &PackageManager, name: &str) -> crate::Result<Option<S
|
||||
}
|
||||
}
|
||||
|
||||
fn npm_package_version<P: AsRef<Path>>(
|
||||
pm: &PackageManager,
|
||||
name: &str,
|
||||
app_dir: P,
|
||||
) -> crate::Result<Option<String>> {
|
||||
let (output, regex) = match pm {
|
||||
PackageManager::Yarn => (
|
||||
cross_command("yarn")
|
||||
.args(["list", "--pattern"])
|
||||
.arg(name)
|
||||
.args(["--depth", "0"])
|
||||
.current_dir(app_dir)
|
||||
.output()?,
|
||||
None,
|
||||
),
|
||||
PackageManager::YarnBerry => (
|
||||
cross_command("yarn")
|
||||
.arg("info")
|
||||
.arg(name)
|
||||
.arg("--json")
|
||||
.current_dir(app_dir)
|
||||
.output()?,
|
||||
Some(regex::Regex::new("\"Version\":\"([\\da-zA-Z\\-\\.]+)\"").unwrap()),
|
||||
),
|
||||
PackageManager::Npm => (
|
||||
cross_command("npm")
|
||||
.arg("list")
|
||||
.arg(name)
|
||||
.args(["version", "--depth", "0"])
|
||||
.current_dir(app_dir)
|
||||
.output()?,
|
||||
None,
|
||||
),
|
||||
PackageManager::Pnpm => (
|
||||
cross_command("pnpm")
|
||||
.arg("list")
|
||||
.arg(name)
|
||||
.args(["--parseable", "--depth", "0"])
|
||||
.current_dir(app_dir)
|
||||
.output()?,
|
||||
None,
|
||||
),
|
||||
// Bun doesn't support `list` command
|
||||
PackageManager::Bun => (
|
||||
cross_command("npm")
|
||||
.arg("list")
|
||||
.arg(name)
|
||||
.args(["version", "--depth", "0"])
|
||||
.current_dir(app_dir)
|
||||
.output()?,
|
||||
None,
|
||||
),
|
||||
};
|
||||
if output.status.success() {
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
let regex = regex.unwrap_or_else(|| regex::Regex::new("@(\\d[\\da-zA-Z\\-\\.]+)").unwrap());
|
||||
Ok(
|
||||
regex
|
||||
.captures_iter(&stdout)
|
||||
.last()
|
||||
.and_then(|cap| cap.get(1).map(|v| v.as_str().to_string())),
|
||||
)
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_package_manager<T: AsRef<str>>(app_dir_entries: &[T]) -> PackageManager {
|
||||
let mut use_npm = false;
|
||||
let mut use_pnpm = false;
|
||||
@ -244,7 +177,8 @@ pub fn items(app_dir: Option<&PathBuf>, metadata: &VersionMetadata) -> Vec<Secti
|
||||
let app_dir = app_dir.clone();
|
||||
let item = SectionItem::new().action(move || {
|
||||
let version = version.clone().unwrap_or_else(|| {
|
||||
npm_package_version(&package_manager, package, &app_dir)
|
||||
package_manager
|
||||
.current_package_version(package, &app_dir)
|
||||
.unwrap_or_default()
|
||||
.unwrap_or_default()
|
||||
});
|
||||
|
@ -3,53 +3,14 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use super::{ActionResult, SectionItem};
|
||||
use crate::interface::rust::get_workspace_dir;
|
||||
use crate::{
|
||||
helpers::cargo_manifest::{crate_version, CargoLock, CargoManifest},
|
||||
interface::rust::get_workspace_dir,
|
||||
};
|
||||
use colored::Colorize;
|
||||
use serde::Deserialize;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::Write;
|
||||
use std::fs::read_to_string;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
#[derive(Clone, Deserialize)]
|
||||
struct CargoLockPackage {
|
||||
name: String,
|
||||
version: String,
|
||||
source: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct CargoLock {
|
||||
package: Vec<CargoLockPackage>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize)]
|
||||
struct CargoManifestDependencyPackage {
|
||||
version: Option<String>,
|
||||
git: Option<String>,
|
||||
branch: Option<String>,
|
||||
rev: Option<String>,
|
||||
path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
enum CargoManifestDependency {
|
||||
Version(String),
|
||||
Package(CargoManifestDependencyPackage),
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct CargoManifestPackage {
|
||||
version: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct CargoManifest {
|
||||
package: CargoManifestPackage,
|
||||
dependencies: HashMap<String, CargoManifestDependency>,
|
||||
}
|
||||
|
||||
fn crate_latest_version(name: &str) -> Option<String> {
|
||||
let url = format!("https://docs.rs/crate/{name}/");
|
||||
match ureq::get(&url).call() {
|
||||
@ -61,138 +22,6 @@ fn crate_latest_version(name: &str) -> Option<String> {
|
||||
}
|
||||
}
|
||||
|
||||
fn crate_version(
|
||||
tauri_dir: &Path,
|
||||
manifest: Option<&CargoManifest>,
|
||||
lock: Option<&CargoLock>,
|
||||
name: &str,
|
||||
) -> (String, Option<String>) {
|
||||
let crate_lock_packages: Vec<CargoLockPackage> = lock
|
||||
.as_ref()
|
||||
.map(|lock| {
|
||||
lock
|
||||
.package
|
||||
.iter()
|
||||
.filter(|p| p.name == name)
|
||||
.cloned()
|
||||
.collect()
|
||||
})
|
||||
.unwrap_or_default();
|
||||
let (crate_version_string, found_crate_versions) =
|
||||
match (&manifest, &lock, crate_lock_packages.len()) {
|
||||
(Some(_manifest), Some(_lock), 1) => {
|
||||
let crate_lock_package = crate_lock_packages.first().unwrap();
|
||||
let version_string = if let Some(s) = &crate_lock_package.source {
|
||||
if s.starts_with("git") {
|
||||
format!("{} ({})", s, crate_lock_package.version)
|
||||
} else {
|
||||
crate_lock_package.version.clone()
|
||||
}
|
||||
} else {
|
||||
crate_lock_package.version.clone()
|
||||
};
|
||||
(version_string, vec![crate_lock_package.version.clone()])
|
||||
}
|
||||
(None, Some(_lock), 1) => {
|
||||
let crate_lock_package = crate_lock_packages.first().unwrap();
|
||||
let version_string = if let Some(s) = &crate_lock_package.source {
|
||||
if s.starts_with("git") {
|
||||
format!("{} ({})", s, crate_lock_package.version)
|
||||
} else {
|
||||
crate_lock_package.version.clone()
|
||||
}
|
||||
} else {
|
||||
crate_lock_package.version.clone()
|
||||
};
|
||||
(
|
||||
format!("{version_string} (no manifest)"),
|
||||
vec![crate_lock_package.version.clone()],
|
||||
)
|
||||
}
|
||||
_ => {
|
||||
let mut found_crate_versions = Vec::new();
|
||||
let mut is_git = false;
|
||||
let manifest_version = match manifest.and_then(|m| m.dependencies.get(name).cloned()) {
|
||||
Some(tauri) => match tauri {
|
||||
CargoManifestDependency::Version(v) => {
|
||||
found_crate_versions.push(v.clone());
|
||||
v
|
||||
}
|
||||
CargoManifestDependency::Package(p) => {
|
||||
if let Some(v) = p.version {
|
||||
found_crate_versions.push(v.clone());
|
||||
v
|
||||
} else if let Some(p) = p.path {
|
||||
let manifest_path = tauri_dir.join(&p).join("Cargo.toml");
|
||||
let v = match read_to_string(manifest_path)
|
||||
.map_err(|_| ())
|
||||
.and_then(|m| toml::from_str::<CargoManifest>(&m).map_err(|_| ()))
|
||||
{
|
||||
Ok(manifest) => manifest.package.version,
|
||||
Err(_) => "unknown version".to_string(),
|
||||
};
|
||||
format!("path:{p:?} [{v}]")
|
||||
} else if let Some(g) = p.git {
|
||||
is_git = true;
|
||||
let mut v = format!("git:{g}");
|
||||
if let Some(branch) = p.branch {
|
||||
let _ = write!(v, "&branch={branch}");
|
||||
} else if let Some(rev) = p.rev {
|
||||
let _ = write!(v, "#{rev}");
|
||||
}
|
||||
v
|
||||
} else {
|
||||
"unknown manifest".to_string()
|
||||
}
|
||||
}
|
||||
},
|
||||
None => "no manifest".to_string(),
|
||||
};
|
||||
|
||||
let lock_version = match (lock, crate_lock_packages.is_empty()) {
|
||||
(Some(_lock), false) => crate_lock_packages
|
||||
.iter()
|
||||
.map(|p| p.version.clone())
|
||||
.collect::<Vec<String>>()
|
||||
.join(", "),
|
||||
(Some(_lock), true) => "unknown lockfile".to_string(),
|
||||
_ => "no lockfile".to_string(),
|
||||
};
|
||||
|
||||
(
|
||||
format!(
|
||||
"{} {}({})",
|
||||
manifest_version,
|
||||
if is_git { "(git manifest)" } else { "" },
|
||||
lock_version
|
||||
),
|
||||
found_crate_versions,
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
let crate_version = found_crate_versions
|
||||
.into_iter()
|
||||
.map(|v| semver::Version::parse(&v).ok())
|
||||
.max();
|
||||
let suffix = match (crate_version, crate_latest_version(name)) {
|
||||
(Some(Some(version)), Some(target_version)) => {
|
||||
let target_version = semver::Version::parse(&target_version).unwrap();
|
||||
if version < target_version {
|
||||
Some(format!(
|
||||
" ({}, latest: {})",
|
||||
"outdated".yellow(),
|
||||
target_version.to_string().green()
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
(crate_version_string, suffix)
|
||||
}
|
||||
|
||||
pub fn items(app_dir: Option<&PathBuf>, tauri_dir: Option<&Path>) -> Vec<SectionItem> {
|
||||
let mut items = Vec::new();
|
||||
|
||||
@ -210,13 +39,34 @@ pub fn items(app_dir: Option<&PathBuf>, tauri_dir: Option<&Path>) -> Vec<Section
|
||||
.and_then(|s| toml::from_str(&s).ok());
|
||||
|
||||
for dep in ["tauri", "tauri-build", "wry", "tao"] {
|
||||
let (version_string, version_suffix) =
|
||||
crate_version(tauri_dir, manifest.as_ref(), lock.as_ref(), dep);
|
||||
let version = crate_version(tauri_dir, manifest.as_ref(), lock.as_ref(), dep);
|
||||
let crate_version = version
|
||||
.found_crate_versions
|
||||
.into_iter()
|
||||
.map(|v| semver::Version::parse(&v).ok())
|
||||
.max();
|
||||
|
||||
let version_suffix = match (crate_version, crate_latest_version(dep)) {
|
||||
(Some(Some(version)), Some(target_version)) => {
|
||||
let target_version = semver::Version::parse(&target_version).unwrap();
|
||||
if version < target_version {
|
||||
Some(format!(
|
||||
" ({}, latest: {})",
|
||||
"outdated".yellow(),
|
||||
target_version.to_string().green()
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let item = SectionItem::new().description(format!(
|
||||
"{} {}: {}{}",
|
||||
dep,
|
||||
"[RUST]".dimmed(),
|
||||
version_string,
|
||||
version.version,
|
||||
version_suffix
|
||||
.clone()
|
||||
.map(|s| format!(",{s}"))
|
||||
|
@ -96,6 +96,18 @@ pub fn read_manifest(manifest_path: &Path) -> crate::Result<(Document, String)>
|
||||
Ok((manifest, manifest_str))
|
||||
}
|
||||
|
||||
pub fn serialize_manifest(manifest: &Document) -> String {
|
||||
manifest
|
||||
.to_string()
|
||||
// apply some formatting fixes
|
||||
.replace(r#"" ,features =["#, r#"", features = ["#)
|
||||
.replace(r#"" , features"#, r#"", features"#)
|
||||
.replace("]}", "] }")
|
||||
.replace("={", "= {")
|
||||
.replace("=[", "= [")
|
||||
.replace(r#"",""#, r#"", ""#)
|
||||
}
|
||||
|
||||
pub fn toml_array(features: &HashSet<String>) -> Array {
|
||||
let mut f = Array::default();
|
||||
let mut features: Vec<String> = features.iter().map(|f| f.to_string()).collect();
|
||||
@ -301,15 +313,7 @@ pub fn rewrite_manifest(config: &Config) -> crate::Result<(Manifest, bool)> {
|
||||
.unwrap()
|
||||
.features;
|
||||
|
||||
let new_manifest_str = manifest
|
||||
.to_string()
|
||||
// apply some formatting fixes
|
||||
.replace(r#"" ,features =["#, r#"", features = ["#)
|
||||
.replace(r#"" , features"#, r#"", features"#)
|
||||
.replace("]}", "] }")
|
||||
.replace("={", "= {")
|
||||
.replace("=[", "= [")
|
||||
.replace(r#"",""#, r#"", ""#);
|
||||
let new_manifest_str = serialize_manifest(&manifest);
|
||||
|
||||
if persist && original_manifest_str != new_manifest_str {
|
||||
let mut manifest_file =
|
||||
|
6
tooling/cli/src/migrate/migrations/mod.rs
Normal file
6
tooling/cli/src/migrate/migrations/mod.rs
Normal file
@ -0,0 +1,6 @@
|
||||
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pub mod v1;
|
||||
pub mod v2_rc;
|
@ -58,11 +58,34 @@ pub fn migrate(app_dir: &Path, tauri_dir: &Path) -> Result<()> {
|
||||
let mut new_npm_packages = Vec::new();
|
||||
let mut new_cargo_packages = Vec::new();
|
||||
|
||||
let pre = env!("CARGO_PKG_VERSION_PRE");
|
||||
let npm_version = if pre.is_empty() {
|
||||
format!("{}.0.0", env!("CARGO_PKG_VERSION_MAJOR"))
|
||||
} else {
|
||||
format!(
|
||||
"{}.{}.{}-{}.0",
|
||||
env!("CARGO_PKG_VERSION_MAJOR"),
|
||||
env!("CARGO_PKG_VERSION_MINOR"),
|
||||
env!("CARGO_PKG_VERSION_PATCH"),
|
||||
pre.split('.').next().unwrap()
|
||||
)
|
||||
};
|
||||
|
||||
let pm = PackageManager::from_project(app_dir)
|
||||
.into_iter()
|
||||
.next()
|
||||
.unwrap_or(PackageManager::Npm);
|
||||
|
||||
for pkg in ["@tauri-apps/cli", "@tauri-apps/api"] {
|
||||
let version = pm
|
||||
.current_package_version(pkg, app_dir)
|
||||
.unwrap_or_default()
|
||||
.unwrap_or_default();
|
||||
if version.starts_with("1") {
|
||||
new_npm_packages.push(format!("{pkg}@^{npm_version}"));
|
||||
}
|
||||
}
|
||||
|
||||
for entry in walk_builder(app_dir).build().flatten() {
|
||||
if entry.file_type().map(|t| t.is_file()).unwrap_or_default() {
|
||||
let path = entry.path();
|
||||
@ -86,7 +109,7 @@ pub fn migrate(app_dir: &Path, tauri_dir: &Path) -> Result<()> {
|
||||
new_npm_packages.sort();
|
||||
new_npm_packages.dedup();
|
||||
if !new_npm_packages.is_empty() {
|
||||
pm.install(&new_npm_packages)
|
||||
pm.install(&new_npm_packages, app_dir)
|
||||
.context("Error installing new npm packages")?;
|
||||
}
|
||||
|
@ -2,14 +2,17 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use crate::{interface::rust::manifest::read_manifest, Result};
|
||||
use crate::{
|
||||
interface::rust::manifest::{read_manifest, serialize_manifest},
|
||||
Result,
|
||||
};
|
||||
|
||||
use anyhow::Context;
|
||||
use itertools::Itertools;
|
||||
use tauri_utils_v1::config::Allowlist;
|
||||
use toml_edit::{Document, Entry, Item, Table, TableLike, Value};
|
||||
|
||||
use std::{fs::File, io::Write, path::Path};
|
||||
use std::path::Path;
|
||||
|
||||
const CRATE_TYPES: [&str; 3] = ["lib", "staticlib", "cdylib"];
|
||||
|
||||
@ -18,20 +21,8 @@ pub fn migrate(tauri_dir: &Path) -> Result<()> {
|
||||
let (mut manifest, _) = read_manifest(&manifest_path)?;
|
||||
migrate_manifest(&mut manifest)?;
|
||||
|
||||
let mut manifest_file =
|
||||
File::create(&manifest_path).with_context(|| "failed to open Cargo.toml for rewrite")?;
|
||||
manifest_file.write_all(
|
||||
manifest
|
||||
.to_string()
|
||||
// apply some formatting fixes
|
||||
.replace(r#"" ,features =["#, r#"", features = ["#)
|
||||
.replace(r#"" , features"#, r#"", features"#)
|
||||
.replace("]}", "] }")
|
||||
.replace("={", "= {")
|
||||
.replace("=[", "= [")
|
||||
.as_bytes(),
|
||||
)?;
|
||||
manifest_file.flush()?;
|
||||
std::fs::write(&manifest_path, serialize_manifest(&manifest))
|
||||
.context("failed to rewrite Cargo manifest")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -44,7 +35,7 @@ fn migrate_manifest(manifest: &mut Document) -> Result<()> {
|
||||
.entry("dependencies")
|
||||
.or_insert(Item::Table(Table::new()))
|
||||
.as_table_mut()
|
||||
.expect("manifest dependencies isn't a table");
|
||||
.context("manifest dependencies isn't a table")?;
|
||||
|
||||
migrate_dependency(dependencies, "tauri", &version, &features_to_remove());
|
||||
|
||||
@ -53,7 +44,7 @@ fn migrate_manifest(manifest: &mut Document) -> Result<()> {
|
||||
.entry("build-dependencies")
|
||||
.or_insert(Item::Table(Table::new()))
|
||||
.as_table_mut()
|
||||
.expect("manifest build-dependencies isn't a table");
|
||||
.context("manifest build-dependencies isn't a table")?;
|
||||
|
||||
migrate_dependency(build_dependencies, "tauri-build", &version, &[]);
|
||||
|
36
tooling/cli/src/migrate/migrations/v1/mod.rs
Normal file
36
tooling/cli/src/migrate/migrations/v1/mod.rs
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use crate::{
|
||||
helpers::app_paths::{app_dir, tauri_dir},
|
||||
Result,
|
||||
};
|
||||
|
||||
use anyhow::Context;
|
||||
|
||||
mod config;
|
||||
mod frontend;
|
||||
mod manifest;
|
||||
|
||||
pub fn run() -> Result<()> {
|
||||
let tauri_dir = tauri_dir();
|
||||
let app_dir = app_dir();
|
||||
|
||||
let migrated = config::migrate(&tauri_dir).context("Could not migrate config")?;
|
||||
manifest::migrate(&tauri_dir).context("Could not migrate manifest")?;
|
||||
frontend::migrate(app_dir, &tauri_dir)?;
|
||||
|
||||
// Add plugins
|
||||
for plugin in migrated.plugins {
|
||||
crate::add::command(crate::add::Options {
|
||||
plugin: plugin.clone(),
|
||||
branch: None,
|
||||
tag: None,
|
||||
rev: None,
|
||||
})
|
||||
.with_context(|| format!("Could not migrate plugin '{plugin}'"))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
196
tooling/cli/src/migrate/migrations/v2_rc.rs
Normal file
196
tooling/cli/src/migrate/migrations/v2_rc.rs
Normal file
@ -0,0 +1,196 @@
|
||||
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use crate::{
|
||||
helpers::{
|
||||
app_paths::{app_dir, tauri_dir},
|
||||
npm::PackageManager,
|
||||
},
|
||||
interface::rust::manifest::{read_manifest, serialize_manifest},
|
||||
Result,
|
||||
};
|
||||
|
||||
use std::{fs::read_to_string, path::Path};
|
||||
|
||||
use anyhow::Context;
|
||||
use toml_edit::{Document, Item, Table, TableLike, Value};
|
||||
|
||||
pub fn run() -> Result<()> {
|
||||
let app_dir = app_dir();
|
||||
let tauri_dir = tauri_dir();
|
||||
|
||||
let manifest_path = tauri_dir.join("Cargo.toml");
|
||||
let (mut manifest, _) = read_manifest(&manifest_path)?;
|
||||
migrate_manifest(&mut manifest)?;
|
||||
|
||||
migrate_permissions(&tauri_dir)?;
|
||||
|
||||
migrate_npm_dependencies(app_dir)?;
|
||||
|
||||
std::fs::write(&manifest_path, serialize_manifest(&manifest))
|
||||
.context("failed to rewrite Cargo manifest")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn migrate_npm_dependencies(app_dir: &Path) -> Result<()> {
|
||||
let pm = PackageManager::from_project(app_dir)
|
||||
.into_iter()
|
||||
.next()
|
||||
.unwrap_or(PackageManager::Npm);
|
||||
|
||||
let mut install_deps = Vec::new();
|
||||
for pkg in [
|
||||
"@tauri-apps/cli",
|
||||
"@tauri-apps/api",
|
||||
"@tauri-apps/plugin-authenticator",
|
||||
"@tauri-apps/plugin-autostart",
|
||||
"@tauri-apps/plugin-barcode-scanner",
|
||||
"@tauri-apps/plugin-biometric",
|
||||
"@tauri-apps/plugin-cli",
|
||||
"@tauri-apps/plugin-clipboard-manager",
|
||||
"@tauri-apps/plugin-deep-link",
|
||||
"@tauri-apps/plugin-dialog",
|
||||
"@tauri-apps/plugin-fs",
|
||||
"@tauri-apps/plugin-global-shortcut",
|
||||
"@tauri-apps/plugin-http",
|
||||
"@tauri-apps/plugin-log",
|
||||
"@tauri-apps/plugin-nfc",
|
||||
"@tauri-apps/plugin-notification",
|
||||
"@tauri-apps/plugin-os",
|
||||
"@tauri-apps/plugin-positioner",
|
||||
"@tauri-apps/plugin-process",
|
||||
"@tauri-apps/plugin-shell",
|
||||
"@tauri-apps/plugin-sql",
|
||||
"@tauri-apps/plugin-store",
|
||||
"@tauri-apps/plugin-stronghold",
|
||||
"@tauri-apps/plugin-updater",
|
||||
"@tauri-apps/plugin-upload",
|
||||
"@tauri-apps/plugin-websocket",
|
||||
"@tauri-apps/plugin-window-state",
|
||||
] {
|
||||
let version = pm
|
||||
.current_package_version(pkg, app_dir)
|
||||
.unwrap_or_default()
|
||||
.unwrap_or_default();
|
||||
if version.starts_with("1") {
|
||||
install_deps.push(format!("{pkg}@^2.0.0-rc.0"));
|
||||
}
|
||||
}
|
||||
|
||||
if !install_deps.is_empty() {
|
||||
pm.install(&install_deps, app_dir)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn migrate_permissions(tauri_dir: &Path) -> Result<()> {
|
||||
let core_plugins = [
|
||||
"app",
|
||||
"event",
|
||||
"image",
|
||||
"menu",
|
||||
"path",
|
||||
"resources",
|
||||
"tray",
|
||||
"webview",
|
||||
"window",
|
||||
];
|
||||
|
||||
for entry in walkdir::WalkDir::new(tauri_dir.join("capabilities")) {
|
||||
let entry = entry?;
|
||||
let path = entry.path();
|
||||
if path.extension().map_or(false, |ext| ext == "json") {
|
||||
let mut capability = read_to_string(path).context("failed to read capability")?;
|
||||
for plugin in core_plugins {
|
||||
capability = capability.replace(&format!("\"{plugin}:"), &format!("\"core:{plugin}:"));
|
||||
}
|
||||
std::fs::write(path, capability).context("failed to rewrite capability")?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn migrate_manifest(manifest: &mut Document) -> Result<()> {
|
||||
let version = "2.0.0-rc.0";
|
||||
|
||||
let dependencies = manifest
|
||||
.as_table_mut()
|
||||
.entry("dependencies")
|
||||
.or_insert(Item::Table(Table::new()))
|
||||
.as_table_mut()
|
||||
.context("manifest dependencies isn't a table")?;
|
||||
|
||||
for dep in [
|
||||
"tauri",
|
||||
"tauri-plugin-authenticator",
|
||||
"tauri-plugin-autostart",
|
||||
"tauri-plugin-barcode-scanner",
|
||||
"tauri-plugin-biometric",
|
||||
"tauri-plugin-cli",
|
||||
"tauri-plugin-clipboard-manager",
|
||||
"tauri-plugin-deep-link",
|
||||
"tauri-plugin-dialog",
|
||||
"tauri-plugin-fs",
|
||||
"tauri-plugin-global-shortcut",
|
||||
"tauri-plugin-http",
|
||||
"tauri-plugin-localhost",
|
||||
"tauri-plugin-log",
|
||||
"tauri-plugin-nfc",
|
||||
"tauri-plugin-notification",
|
||||
"tauri-plugin-os",
|
||||
"tauri-plugin-persisted-scope",
|
||||
"tauri-plugin-positioner",
|
||||
"tauri-plugin-process",
|
||||
"tauri-plugin-shell",
|
||||
"tauri-plugin-single-instance",
|
||||
"tauri-plugin-sql",
|
||||
"tauri-plugin-store",
|
||||
"tauri-plugin-stronghold",
|
||||
"tauri-plugin-updater",
|
||||
"tauri-plugin-upload",
|
||||
"tauri-plugin-websocket",
|
||||
"tauri-plugin-window-state",
|
||||
] {
|
||||
migrate_dependency(dependencies, dep, version);
|
||||
}
|
||||
|
||||
let build_dependencies = manifest
|
||||
.as_table_mut()
|
||||
.entry("build-dependencies")
|
||||
.or_insert(Item::Table(Table::new()))
|
||||
.as_table_mut()
|
||||
.context("manifest build-dependencies isn't a table")?;
|
||||
|
||||
migrate_dependency(build_dependencies, "tauri-build", version);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn migrate_dependency(dependencies: &mut Table, name: &str, version: &str) {
|
||||
let item = dependencies.entry(name).or_insert(Item::None);
|
||||
|
||||
// do not rewrite if dependency uses workspace inheritance
|
||||
if item
|
||||
.get("workspace")
|
||||
.and_then(|v| v.as_bool())
|
||||
.unwrap_or_default()
|
||||
{
|
||||
log::info!("`{name}` dependency has workspace inheritance enabled. The features array won't be automatically rewritten.");
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(dep) = item.as_table_mut() {
|
||||
migrate_dependency_table(dep, version);
|
||||
} else if let Some(Value::InlineTable(table)) = item.as_value_mut() {
|
||||
migrate_dependency_table(table, version);
|
||||
} else if item.as_str().is_some() {
|
||||
*item = Item::Value(version.into());
|
||||
}
|
||||
}
|
||||
|
||||
fn migrate_dependency_table<D: TableLike>(dep: &mut D, version: &str) {
|
||||
*dep.entry("version").or_insert(Item::None) = Item::Value(version.into());
|
||||
}
|
@ -3,32 +3,50 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use crate::{
|
||||
helpers::app_paths::{app_dir, tauri_dir},
|
||||
helpers::{
|
||||
app_paths::tauri_dir,
|
||||
cargo_manifest::{crate_version, CargoLock, CargoManifest},
|
||||
},
|
||||
interface::rust::get_workspace_dir,
|
||||
Result,
|
||||
};
|
||||
|
||||
use std::{fs::read_to_string, str::FromStr};
|
||||
|
||||
use anyhow::Context;
|
||||
|
||||
mod config;
|
||||
mod frontend;
|
||||
mod manifest;
|
||||
mod migrations;
|
||||
|
||||
pub fn command() -> Result<()> {
|
||||
let tauri_dir = tauri_dir();
|
||||
let app_dir = app_dir();
|
||||
|
||||
let migrated = config::migrate(&tauri_dir).context("Could not migrate config")?;
|
||||
manifest::migrate(&tauri_dir).context("Could not migrate manifest")?;
|
||||
frontend::migrate(app_dir, &tauri_dir)?;
|
||||
let manifest_contents =
|
||||
read_to_string(tauri_dir.join("Cargo.toml")).context("failed to read Cargo manifest")?;
|
||||
let manifest = toml::from_str::<CargoManifest>(&manifest_contents)
|
||||
.context("failed to parse Cargo manifest")?;
|
||||
|
||||
// Add plugins
|
||||
for plugin in migrated.plugins {
|
||||
crate::add::command(crate::add::Options {
|
||||
plugin: plugin.clone(),
|
||||
branch: None,
|
||||
tag: None,
|
||||
rev: None,
|
||||
})
|
||||
.with_context(|| format!("Could not migrate plugin '{plugin}'"))?
|
||||
let workspace_dir = get_workspace_dir()?;
|
||||
let lock_path = workspace_dir.join("Cargo.lock");
|
||||
let lock = if lock_path.exists() {
|
||||
let lockfile_contents = read_to_string(lock_path).context("failed to read Cargo lockfile")?;
|
||||
let lock =
|
||||
toml::from_str::<CargoLock>(&lockfile_contents).context("failed to parse Cargo lockfile")?;
|
||||
Some(lock)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let tauri_version = crate_version(&tauri_dir, Some(&manifest), lock.as_ref(), "tauri").version;
|
||||
let tauri_version = semver::Version::from_str(&tauri_version)?;
|
||||
|
||||
if tauri_version.major == 1 {
|
||||
migrations::v1::run().context("failed to migrate from v1")?;
|
||||
} else if tauri_version.major == 2 {
|
||||
if let Some((pre, _number)) = tauri_version.pre.as_str().split_once('.') {
|
||||
if pre == "beta" {
|
||||
migrations::v2_rc::run().context("failed to migrate from v2 beta to rc")?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
Loading…
Reference in New Issue
Block a user