Bläddra i källkod

Related to #1547: use `dioxus-cli` within a workspace (wildcard-members, real package names) (#1642)

* Related to #1547: use `dioxus-cli` within a workspace

Although the `dx` CLI allows to specify a package name to chose from workspace members,
it does not support workspace members specified as glob-wildcards.
Neither it respects the effective package name, specified in the crate's `Cargo.toml`.

This PR addresses that issue:
- upon `dx build ...`, if the `--bin` CLI-argument is provided, treat the current dir as a workspace;
- search through the workspace's `members`: resolve each of them with `glob`;
- assume that any workspace member has a `Cargo.toml` in it (cargo does it, so it's okay);
- read said manifest, and check the package name in it;
- if found — there we have our sought package.

* Use cargo-metadata to find out the workspace structure

* glob is unused
Raman Hafiyatulin 1 år sedan
förälder
incheckning
098689083d
2 ändrade filer med 33 tillägg och 41 borttagningar
  1. 3 0
      packages/cli/src/error.rs
  2. 30 41
      packages/cli/src/main.rs

+ 3 - 0
packages/cli/src/error.rs

@@ -29,6 +29,9 @@ pub enum Error {
     #[error("Cargo Error: {0}")]
     CargoError(String),
 
+    #[error("Couldn't retrieve cargo metadata")]
+    CargoMetadata(#[source] cargo_metadata::Error),
+
     #[error("{0}")]
     CustomError(String),
 

+ 30 - 41
packages/cli/src/main.rs

@@ -9,42 +9,31 @@ use dioxus_cli::plugin::PluginManager;
 
 use Commands::*;
 
-fn get_bin(bin: Option<String>) -> Result<Option<PathBuf>> {
-    const ERR_MESSAGE: &str = "The `--bin` flag has to be ran in a Cargo workspace.";
-
-    if let Some(ref bin) = bin {
-        let manifest = cargo_toml::Manifest::from_path("./Cargo.toml")
-            .map_err(|_| Error::CargoError(ERR_MESSAGE.to_string()))?;
-
-        if let Some(workspace) = manifest.workspace {
-            for item in workspace.members.iter() {
-                let path = PathBuf::from(item);
-
-                if !path.exists() {
-                    continue;
-                }
-
-                if !path.is_dir() {
-                    continue;
-                }
-
-                if path.ends_with(bin.clone()) {
-                    return Ok(Some(path));
-                }
-            }
-        } else {
-            return Err(Error::CargoError(ERR_MESSAGE.to_string()));
-        }
-    }
-
-    // If the bin exists but we couldn't find it
-    if bin.is_some() {
-        return Err(Error::CargoError(
-            "The specified bin does not exist.".to_string(),
-        ));
-    }
-
-    Ok(None)
+fn get_bin(bin: Option<String>) -> Result<PathBuf> {
+    let metadata = cargo_metadata::MetadataCommand::new()
+        .exec()
+        .map_err(Error::CargoMetadata)?;
+    let package = if let Some(bin) = bin {
+        metadata
+            .workspace_packages()
+            .into_iter()
+            .find(|p| p.name == bin)
+            .ok_or(format!("no such package: {}", bin))
+            .map_err(Error::CargoError)?
+    } else {
+        metadata
+            .root_package()
+            .ok_or("no root package?".into())
+            .map_err(Error::CargoError)?
+    };
+
+    let crate_dir = package
+        .manifest_path
+        .parent()
+        .ok_or("couldn't take parent dir".into())
+        .map_err(Error::CargoError)?;
+
+    Ok(crate_dir.into())
 }
 
 #[tokio::main]
@@ -55,7 +44,7 @@ async fn main() -> anyhow::Result<()> {
 
     let bin = get_bin(args.bin)?;
 
-    let _dioxus_config = DioxusConfig::load(bin.clone())
+    let _dioxus_config = DioxusConfig::load(Some(bin.clone()))
         .map_err(|e| anyhow!("Failed to load Dioxus config because: {e}"))?
         .unwrap_or_else(|| {
             log::warn!("You appear to be creating a Dioxus project from scratch; we will use the default config");
@@ -72,15 +61,15 @@ async fn main() -> anyhow::Result<()> {
             .map_err(|e| anyhow!("🚫 Translation of HTML into RSX failed: {}", e)),
 
         Build(opts) => opts
-            .build(bin.clone())
+            .build(Some(bin.clone()))
             .map_err(|e| anyhow!("🚫 Building project failed: {}", e)),
 
         Clean(opts) => opts
-            .clean(bin.clone())
+            .clean(Some(bin.clone()))
             .map_err(|e| anyhow!("🚫 Cleaning project failed: {}", e)),
 
         Serve(opts) => opts
-            .serve(bin.clone())
+            .serve(Some(bin.clone()))
             .await
             .map_err(|e| anyhow!("🚫 Serving project failed: {}", e)),
 
@@ -93,7 +82,7 @@ async fn main() -> anyhow::Result<()> {
             .map_err(|e| anyhow!("🚫 Configuring new project failed: {}", e)),
 
         Bundle(opts) => opts
-            .bundle(bin.clone())
+            .bundle(Some(bin.clone()))
             .map_err(|e| anyhow!("🚫 Bundling project failed: {}", e)),
 
         #[cfg(feature = "plugin")]