Skip to content

Commit

Permalink
[xtask] Add support for cargo metadata new workspace member format (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
syl20bnr committed Mar 21, 2024
1 parent 3e4af41 commit 0a8a3cc
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 27 deletions.
2 changes: 1 addition & 1 deletion crates/burn-fusion/src/stream/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ impl StreamId {
#[cfg(feature = "std")]
fn id() -> std::thread::ThreadId {
std::thread_local! {
static ID: std::cell::OnceCell::<std::thread::ThreadId> = std::cell::OnceCell::new();
static ID: std::cell::OnceCell::<std::thread::ThreadId> = const { std::cell::OnceCell::new() };
};

// Getting the current thread is expensive, so we cache the value into a thread local
Expand Down
69 changes: 43 additions & 26 deletions xtask/src/utils/workspace.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
use std::process::Command;
use std::{path::Path, process::Command};

use serde_json::Value;

const MEMBER_PATH_PREFIX: &str = if cfg!(target_os = "windows") {
"path+file:///"
} else {
"path+file://"
};

pub(crate) enum WorkspaceMemberType {
Crate,
Example,
Expand All @@ -26,43 +32,27 @@ pub(crate) fn get_workspaces(w_type: WorkspaceMemberType) -> Vec<WorkspaceMember
.arg("metadata")
.output()
.expect("Failed to execute command");

// Parse the JSON output
let metadata: Value = serde_json::from_slice(&output.stdout).expect("Failed to parse JSON");

// Extract workspaces from the metadata, excluding examples/ and xtask
let workspaces = metadata["workspace_members"]
.as_array()
.expect("Expected an array of workspace members")
.iter()
.filter_map(|member| {
let parts: Vec<_> = member.as_str()?.split_whitespace().collect();
let (workspace_name, workspace_path) =
(parts.first()?.to_owned(), parts.last()?.to_owned());

let prefix = if cfg!(target_os = "windows") {
"(path+file:///"
let member_str = member.as_str()?;
let has_whitespace = member_str.chars().any(|c| c.is_whitespace());
let (name, path) = if has_whitespace {
parse_workspace_member0(member_str)?
} else {
"(path+file://"
parse_workspace_member1(member_str)?
};
let workspace_path = workspace_path.replace(prefix, "").replace(')', "");

match w_type {
WorkspaceMemberType::Crate
if workspace_name != "xtask" && !workspace_path.contains("examples/") =>
{
Some(WorkspaceMember::new(
workspace_name.to_string(),
workspace_path.to_string(),
))
WorkspaceMemberType::Crate if name != "xtask" && !path.contains("examples/") => {
Some(WorkspaceMember::new(name.to_string(), path.to_string()))
}
WorkspaceMemberType::Example
if workspace_name != "xtask" && workspace_path.contains("examples/") =>
{
Some(WorkspaceMember::new(
workspace_name.to_string(),
workspace_path.to_string(),
))
WorkspaceMemberType::Example if name != "xtask" && path.contains("examples/") => {
Some(WorkspaceMember::new(name.to_string(), path.to_string()))
}
_ => None,
}
Expand All @@ -71,3 +61,30 @@ pub(crate) fn get_workspaces(w_type: WorkspaceMemberType) -> Vec<WorkspaceMember

workspaces
}

/// Legacy cargo metadata format for member specs (rust < 1.77)
/// Example:
/// "backend-comparison 0.13.0 (path+file:///Users/username/burn/backend-comparison)"
fn parse_workspace_member0(specs: &str) -> Option<(String, String)> {
let parts: Vec<_> = specs.split_whitespace().collect();
let (name, path) = (parts.first()?.to_owned(), parts.last()?.to_owned());
// skip the first character because it is a '('
let path = path
.chars()
.skip(1)
.collect::<String>()
.replace(MEMBER_PATH_PREFIX, "")
.replace(')', "");
Some((name.to_string(), path.to_string()))
}

/// Cargo metadata format for member specs (rust >= 1.77)
/// Example:
/// "path+file:///Users/username/burn/backend-comparison#0.13.0"
fn parse_workspace_member1(specs: &str) -> Option<(String, String)> {
let no_prefix = specs.replace(MEMBER_PATH_PREFIX, "").replace(')', "");
let path = Path::new(no_prefix.split_once('#')?.0);
let name = path.file_name()?.to_str()?;
let path = path.to_str()?;
Some((name.to_string(), path.to_string()))
}

0 comments on commit 0a8a3cc

Please sign in to comment.