feat: allow config's version to be a path to package.json, closes #2967 (#2971)

This commit is contained in:
Lucas Fernandes Nogueira
2022-01-07 16:55:30 -03:00
committed by GitHub
parent 0600099696
commit 46f2eae8aa
5 changed files with 68 additions and 7 deletions

View File

@@ -0,0 +1,5 @@
---
"tauri": patch
---
Allow `tauri.conf.json > package > version` to specify a path to a `package.json` file and pull the version from it.

View File

@@ -10,9 +10,12 @@
//! This is a core functionality that is not considered part of the stable API.
//! If you use it, note that it may include breaking changes in the future.
use std::{collections::HashMap, path::PathBuf};
use std::{collections::HashMap, fmt, fs::read_to_string, path::PathBuf};
use serde::Deserialize;
use serde::{
de::{Deserializer, Error as DeError, Visitor},
Deserialize,
};
use serde_json::Value as JsonValue;
use url::Url;
@@ -479,16 +482,68 @@ impl Default for BuildConfig {
}
}
#[derive(Debug, PartialEq)]
struct PackageVersion(String);
impl<'d> serde::Deserialize<'d> for PackageVersion {
fn deserialize<D: Deserializer<'d>>(deserializer: D) -> Result<PackageVersion, D::Error> {
struct PackageVersionVisitor;
impl<'d> Visitor<'d> for PackageVersionVisitor {
type Value = PackageVersion;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
formatter,
"a semver string or a path to a package.json file"
)
}
fn visit_str<E: DeError>(self, value: &str) -> Result<PackageVersion, E> {
let path = PathBuf::from(value);
if path.exists() {
let json_str = read_to_string(&path)
.map_err(|e| DeError::custom(format!("failed to read version JSON file: {}", e)))?;
let package_json: serde_json::Value = serde_json::from_str(&json_str)
.map_err(|e| DeError::custom(format!("failed to read version JSON file: {}", e)))?;
if let Some(obj) = package_json.as_object() {
let version = obj
.get("version")
.ok_or_else(|| DeError::custom("JSON must contain a `version` field"))?
.as_str()
.ok_or_else(|| DeError::custom("`version` must be a string"))?;
Ok(PackageVersion(version.into()))
} else {
Err(DeError::custom("value is not a path to a JSON object"))
}
} else {
Ok(PackageVersion(value.into()))
}
}
}
deserializer.deserialize_string(PackageVersionVisitor {})
}
}
/// The package configuration.
#[derive(Debug, Default, PartialEq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PackageConfig {
/// App name.
pub product_name: Option<String>,
/// App version.
/// App version. It is a semver version number or a path to a `package.json` file contaning the `version` field.
#[serde(deserialize_with = "version_deserializer", default)]
pub version: Option<String>,
}
fn version_deserializer<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
where
D: Deserializer<'de>,
{
Option::<PackageVersion>::deserialize(deserializer).map(|v| v.map(|v| v.0))
}
/// The config type mapped to `tauri.conf.json`.
#[derive(Debug, Default, PartialEq, Deserialize)]
#[serde(rename_all = "camelCase")]

View File

@@ -345,9 +345,9 @@ dependencies = [
[[package]]
name = "clap"
version = "3.0.0-rc.9"
version = "3.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7843ae7a539bef687e018bf9edf7e87728024b29d02b0f8409726be8880ae1a"
checksum = "d01c9347757e131122b19cd19a05c85805b68c2352a97b623efdc3c295290299"
dependencies = [
"atty",
"bitflags",

View File

@@ -7,7 +7,7 @@
},
"package": {
"productName": "Tauri API",
"version": "0.1.0"
"version": "../package.json"
},
"tauri": {
"cli": {

View File

@@ -56,11 +56,12 @@ pub fn command(options: Options) -> Result<()> {
} else {
None
};
let config = get_config(merge_config.as_deref())?;
let tauri_path = tauri_dir();
set_current_dir(&tauri_path).with_context(|| "failed to change current working directory")?;
let config = get_config(merge_config.as_deref())?;
let manifest = rewrite_manifest(config.clone())?;
let config_guard = config.lock().unwrap();