Skip to content

Commit

Permalink
make Git source respect revision, show source command
Browse files Browse the repository at this point in the history
  • Loading branch information
schell committed Dec 19, 2024
1 parent e1b9e8c commit 3f1ab56
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 33 deletions.
22 changes: 22 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ log = "0.4"
relative-path = "1.9.3"
serde = { version = "1.0.214", features = ["derive"] }
serde_json = "1.0.132"
snafu = "0.8.5"
toml = "0.8.19"
test-log = "0.2.16"

Expand Down
1 change: 1 addition & 0 deletions crates/cargo-gpu/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ log.workspace = true
relative-path.workspace = true
serde.workspace = true
serde_json.workspace = true
snafu.workspace = true
toml.workspace = true
chrono.workspace = true
http.workspace = true
Expand Down
4 changes: 2 additions & 2 deletions crates/cargo-gpu/src/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ impl Install {
if line.contains("${AUTO-REPLACE-SOURCE}") {
let replaced_line = match spirv_source {
SpirvSource::CratesIO(_) => String::new(),
SpirvSource::Git((repo, _)) => format!("git = \"{repo}\""),
SpirvSource::Git { url, .. } => format!("git = \"{url}\""),
SpirvSource::Path((path, _)) => format!("path = \"{path}\""),
};
return format!("{replaced_line}\n");
Expand All @@ -163,7 +163,7 @@ impl Install {
SpirvSource::CratesIO(version) | SpirvSource::Path((_, version)) => {
format!("version = \"{}\"", version.replace('v', ""))
}
SpirvSource::Git((_, revision)) => format!("rev = \"{revision}\""),
SpirvSource::Git { rev, .. } => format!("rev = \"{rev}\""),
};
return format!("{replaced_line}\n");
}
Expand Down
35 changes: 29 additions & 6 deletions crates/cargo-gpu/src/show.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,43 @@
use crate::cache_dir;

#[derive(Clone, Debug, clap::Parser)]
pub struct ShowSpirvSource {
/// The location of the shader-crate to inspect to determine its spirv-std dependency.
#[clap(long, default_value = "./")]
pub shader_crate: std::path::PathBuf,
}

/// Different tidbits of information that can be queried at the command line.
#[derive(Clone, Debug, clap::Subcommand)]
pub enum Info {
/// Displays the location of the cache directory
CacheDirectory,
/// The source location of spirv-std
SpirvSource(ShowSpirvSource),
}

/// `cargo gpu show`
#[derive(clap::Parser)]
pub struct Show {
#[clap(long)]
/// Displays the location of the cache directory
cache_directory: bool,
/// Display information about rust-gpu
#[clap(subcommand)]
command: Info,
}

impl Show {
/// Entrypoint
pub fn run(self) {
if self.cache_directory {
log::info!("cache_directory: ");
println!("{}", cache_dir().display());
log::info!("{:?}: ", self.command);
match self.command {
Info::CacheDirectory => {
println!("{}", cache_dir().display());
}
Info::SpirvSource(ShowSpirvSource { shader_crate }) => {
let rust_gpu_source =
crate::spirv_source::SpirvSource::get_spirv_std_dep_definition(&shader_crate);
println!("{rust_gpu_source}");
}
}
}
}
5 changes: 4 additions & 1 deletion crates/cargo-gpu/src/spirv_cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ impl SpirvCli {
if let Some(rust_gpu_version) = maybe_rust_gpu_version {
let mut source = SpirvSource::CratesIO(rust_gpu_version.clone());
if let Some(rust_gpu_source) = maybe_rust_gpu_source {
source = SpirvSource::Git((rust_gpu_source, rust_gpu_version));
source = SpirvSource::Git {
url: rust_gpu_source,
rev: rust_gpu_version,
};
}
maybe_spirv_source = Some(source);
}
Expand Down
84 changes: 60 additions & 24 deletions crates/cargo-gpu/src/spirv_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub enum SpirvSource {
/// then the source of `rust-gpu` is `Git`.
///
/// `(String, String)` is the repo source and revision hash or tag.
Git((String, String)),
Git { url: String, rev: String },
/// If the shader specifies a version like:
/// `spirv-std = { path = "/path/to/rust-gpu" ... }`
/// then the source of `rust-gpu` is `Path`.
Expand All @@ -39,7 +39,11 @@ impl core::fmt::Display for SpirvSource {
reason = "It's a core library trait implementation"
)]
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
format!("{}+{}", self.to_repo(), self.to_version()).fmt(f)
match self {
SpirvSource::CratesIO(version) => f.write_str(version),
SpirvSource::Git { url, rev } => f.write_str(&format!("{url}+{rev}")),
SpirvSource::Path((a, b)) => f.write_str(&format!("{a}+{b}")),
}
}
}

Expand All @@ -65,15 +69,15 @@ impl SpirvSource {
pub fn to_version(&self) -> String {
match self {
Self::CratesIO(version) | Self::Path((_, version)) => version.to_string(),
Self::Git((_, revision)) => revision.to_string(),
Self::Git { rev, .. } => rev.to_string(),
}
}

/// Convert the source to just its repo or path.
fn to_repo(&self) -> String {
match self {
Self::CratesIO(_) => RUST_GPU_REPO.to_owned(),
Self::Git((repo, _)) => repo.to_owned(),
Self::Git { url, .. } => url.to_owned(),
Self::Path((path, _)) => path.to_owned(),
}
}
Expand Down Expand Up @@ -162,7 +166,7 @@ impl SpirvSource {
}

/// Get the shader crate's `spirv_std = ...` definition in its `Cargo.toml`
fn get_spirv_std_dep_definition(shader_crate_path: &std::path::PathBuf) -> Self {
pub fn get_spirv_std_dep_definition(shader_crate_path: &std::path::PathBuf) -> Self {
log::debug!("Running `cargo tree` on {}", shader_crate_path.display());
let output_cargo_tree = std::process::Command::new("cargo")
.current_dir(shader_crate_path)
Expand All @@ -178,6 +182,7 @@ impl SpirvSource {
let maybe_spirv_std_def = cargo_tree_string
.lines()
.find(|line| line.contains("spirv-std"));
log::trace!(" found {maybe_spirv_std_def:?}");

let Some(spirv_std_def) = maybe_spirv_std_def else {
panic!("`spirv-std` not found in shader's `Cargo.toml` at {shader_crate_path:?}:\n{cargo_tree_string}");
Expand All @@ -191,6 +196,7 @@ impl SpirvSource {
/// Which would return:
/// `SpirvSource::Git("https://github.com/Rust-GPU/rust-gpu", "54f6978c")`
fn parse_spirv_std_source_and_version(spirv_std_def: &str) -> Self {
log::trace!("parsing spirv-std source and version from def: '{spirv_std_def}'");
let parts: Vec<String> = spirv_std_def.split_whitespace().map(String::from).collect();
let version = parts
.get(1)
Expand All @@ -202,9 +208,21 @@ impl SpirvSource {
let mut source_string = parts.get(2).unwrap().to_owned();
source_string = source_string.replace(['(', ')'], "");

// Unfortunately Uri ignores the fragment/hash portion of the Uri.
//
// There's been a ticket open for years:
// <https://github.com/hyperium/http/issues/127>
//
// So here we'll parse the fragment out of the source string by hand
let uri = source_string.parse::<http::Uri>().unwrap();
let maybe_hash = if source_string.contains('#') {
let splits = source_string.split('#');
splits.last().map(std::borrow::ToOwned::to_owned)
} else {
None
};
if uri.scheme().is_some() {
source = Self::parse_git_source(version, &uri);
source = Self::parse_git_source(version, &uri, maybe_hash);
} else {
source = Self::Path((source_string, version));
}
Expand All @@ -216,24 +234,29 @@ impl SpirvSource {
}

/// Parse a Git source like: `https://github.com/Rust-GPU/rust-gpu?rev=54f6978c#54f6978c`
fn parse_git_source(version: String, uri: &http::Uri) -> Self {
let mut revision = version;

fn parse_git_source(version: String, uri: &http::Uri, fragment: Option<String>) -> Self {
log::trace!(
"parsing git source from version: '{version}' and uri: '{uri}' and fragment: {}",
fragment.as_deref().unwrap_or("?")
);
let repo = format!(
"{}://{}{}",
uri.scheme().unwrap(),
uri.host().unwrap(),
uri.path()
);

if let Some(query) = uri.query() {
let marker = "rev=";
let sanity_check = query.contains(marker) && query.split('=').count() == 2;
assert!(sanity_check, "revision not found in Git URI: {query}");
revision = query.replace(marker, "");
}
let rev = uri.query().map_or_else(
|| fragment.unwrap_or(version),
|query| {
let marker = "rev=";
let sanity_check = query.contains(marker) && query.split('=').count() == 2;
assert!(sanity_check, "revision not found in Git URI: {query}");
query.replace(marker, "")
},
);

Self::Git((repo, revision))
Self::Git { url: repo, rev }
}

/// `git clone` the `rust-gpu` repo. We use it to get the required Rust toolchain to compile
Expand Down Expand Up @@ -283,10 +306,10 @@ mod test {
let source = SpirvSource::get_spirv_std_dep_definition(&shader_template_path);
assert_eq!(
source,
SpirvSource::Git((
"https://github.com/Rust-GPU/rust-gpu".to_owned(),
"82a0f69".to_owned()
))
SpirvSource::Git {
url: "https://github.com/Rust-GPU/rust-gpu".to_owned(),
rev: "82a0f69".to_owned()
}
);
}

Expand All @@ -297,10 +320,23 @@ mod test {
let source = SpirvSource::parse_spirv_std_source_and_version(definition);
assert_eq!(
source,
SpirvSource::Git((
"https://github.com/Rust-GPU/rust-gpu".to_owned(),
"82a0f69".to_owned()
))
SpirvSource::Git {
url: "https://github.com/Rust-GPU/rust-gpu".to_owned(),
rev: "82a0f69".to_owned()
}
);
}

#[test_log::test]
fn parsing_spirv_std_dep_for_git_source_hash() {
let definition = "spirv-std v9.9.9 (https://github.com/Rust-GPU/rust-gpu#82a0f69) (*)";
let source = SpirvSource::parse_spirv_std_source_and_version(definition);
assert_eq!(
source,
SpirvSource::Git {
url: "https://github.com/Rust-GPU/rust-gpu".to_owned(),
rev: "82a0f69".to_owned()
}
);
}
}

0 comments on commit 3f1ab56

Please sign in to comment.