Repository: tauri-apps/tauri
File: crates/tauri-cli/src/interface/rust.rs (Rust)

Code before:
}

// Copied from https://github.com/rust-lang/cargo/blob/69255bb10de7f74511b5cef900a9d102247b6029/src/cargo/core/workspace.rs#L665
fn expand_member_path(path: &Path) -> crate::Result<Vec<PathBuf>> {
  let path = path.to_str().context("path is not UTF-8 compatible")?;
  let res = glob(path).with_context(|| format!("could not parse pattern `{path}`"))?;
  let res = res
    .map(|p| p.with_context(|| format!("unable to match path to pattern `{path}`")))
    .collect::<Result<Vec<_>, _>>()?;
  Ok(res)
}

fn get_watch_folders(additional_watch_folders: &[PathBuf]) -> crate::Result<Vec<PathBuf>> {
  let tauri_path = tauri_dir();
  let workspace_path = get_workspace_dir()?;

  // We always want to watch the main tauri folder.
  let mut watch_folders = vec![tauri_path.to_path_buf()];

  // Add the additional watch folders, resolving the path from the tauri path if it is relative
  watch_folders.extend(additional_watch_folders.iter().cloned().map(|dir| {
    if dir.is_absolute() {
      dir
    } else {
      tauri_path.join(dir)
    }
  }));

  // We also try to watch workspace members, no matter if the tauri cargo project is the workspace root or a workspace member
  let cargo_settings = CargoSettings::load(&workspace_path)?;
  if let Some(members) = cargo_settings.workspace.and_then(|w| w.members) {
    for p in members {
      let p = workspace_path.join(p);
      match expand_member_path(&p) {
        // Sometimes expand_member_path returns an empty vec, for example if the path contains `[]` as in `C:/[abc]/project/`.
        // Cargo won't complain unless theres a workspace.members config with glob patterns so we should support it too.
        Ok(expanded_paths) => {
          if expanded_paths.is_empty() {
            watch_folders.push(p);
          } else {
            watch_folders.extend(expanded_paths);
          }
        }
        Err(err) => {
          // If this fails cargo itself should fail too. But we still try to keep going with the unexpanded path.
          log::error!("Error watching {}: {}", p.display(), err.to_string());
          watch_folders.push(p);
        }
      };
    }
  }

Review comment (bug):
We need to have the path converted to absolute paths here with `std::path::absolute` or the `common_path::common_path_all` above would probably fail on things like `/somefolder/to/tauri/../watch-folder`

Code after:
  }
}

// Copied from https://github.com/rust-lang/cargo/blob/69255bb10de7f74511b5cef900a9d102247b6029/src/cargo/core/workspace.rs#L665
fn expand_member_path(path: &Path) -> crate::Result<Vec<PathBuf>> {
  let path = path.to_str().context("path is not UTF-8 compatible")?;
  let res = glob(path).with_context(|| format!("could not parse pattern `{path}`"))?;
  let res = res
    .map(|p| p.with_context(|| format!("unable to match path to pattern `{path}`")))
    .collect::<Result<Vec<_>, _>>()?;
  Ok(res)
}

fn get_watch_folders(additional_watch_folders: &[PathBuf]) -> crate::Result<Vec<PathBuf>> {
  let tauri_path = tauri_dir();
  let workspace_path = get_workspace_dir()?;

  // We always want to watch the main tauri folder.
  let mut watch_folders = vec![tauri_path.to_path_buf()];

  // Add the additional watch folders, resolving the path from the tauri path if it is relative
  watch_folders.extend(additional_watch_folders.iter().filter_map(|dir| {
    let path = if dir.is_absolute() {
      dir.to_owned()
    } else {
      tauri_path.join(dir)
    };

    let canonicalized = canonicalize(&path).ok();
    if canonicalized.is_none() {
      log::warn!(
        "Additional watch folder '{}' not found, ignoring",
        path.display()
      );
    }
    canonicalized
  }));

  // We also try to watch workspace members, no matter if the tauri cargo project is the workspace root or a workspace member
  let cargo_settings = CargoSettings::load(&workspace_path)?;
  if let Some(members) = cargo_settings.workspace.and_then(|w| w.members) {
    for p in members {
      let p = workspace_path.join(p);
      match expand_member_path(&p) {
        // Sometimes expand_member_path returns an empty vec, for example if the path contains `[]` as in `C:/[abc]/project/`.
        // Cargo won't complain unless theres a workspace.members config with glob patterns so we should support it too.
        Ok(expanded_paths) => {
          if expanded_paths.is_empty() {
            watch_folders.push(p);
          } else {
            watch_folders.extend(expanded_paths);