Skip to content

Commit 3f1ab56

Browse files
committed
make Git source respect revision, show source command
1 parent e1b9e8c commit 3f1ab56

File tree

7 files changed

+119
-33
lines changed

7 files changed

+119
-33
lines changed

Cargo.lock

Lines changed: 22 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ log = "0.4"
2424
relative-path = "1.9.3"
2525
serde = { version = "1.0.214", features = ["derive"] }
2626
serde_json = "1.0.132"
27+
snafu = "0.8.5"
2728
toml = "0.8.19"
2829
test-log = "0.2.16"
2930

crates/cargo-gpu/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ log.workspace = true
1717
relative-path.workspace = true
1818
serde.workspace = true
1919
serde_json.workspace = true
20+
snafu.workspace = true
2021
toml.workspace = true
2122
chrono.workspace = true
2223
http.workspace = true

crates/cargo-gpu/src/install.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ impl Install {
152152
if line.contains("${AUTO-REPLACE-SOURCE}") {
153153
let replaced_line = match spirv_source {
154154
SpirvSource::CratesIO(_) => String::new(),
155-
SpirvSource::Git((repo, _)) => format!("git = \"{repo}\""),
155+
SpirvSource::Git { url, .. } => format!("git = \"{url}\""),
156156
SpirvSource::Path((path, _)) => format!("path = \"{path}\""),
157157
};
158158
return format!("{replaced_line}\n");
@@ -163,7 +163,7 @@ impl Install {
163163
SpirvSource::CratesIO(version) | SpirvSource::Path((_, version)) => {
164164
format!("version = \"{}\"", version.replace('v', ""))
165165
}
166-
SpirvSource::Git((_, revision)) => format!("rev = \"{revision}\""),
166+
SpirvSource::Git { rev, .. } => format!("rev = \"{rev}\""),
167167
};
168168
return format!("{replaced_line}\n");
169169
}

crates/cargo-gpu/src/show.rs

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,43 @@
22
33
use crate::cache_dir;
44

5+
#[derive(Clone, Debug, clap::Parser)]
6+
pub struct ShowSpirvSource {
7+
/// The location of the shader-crate to inspect to determine its spirv-std dependency.
8+
#[clap(long, default_value = "./")]
9+
pub shader_crate: std::path::PathBuf,
10+
}
11+
12+
/// Different tidbits of information that can be queried at the command line.
13+
#[derive(Clone, Debug, clap::Subcommand)]
14+
pub enum Info {
15+
/// Displays the location of the cache directory
16+
CacheDirectory,
17+
/// The source location of spirv-std
18+
SpirvSource(ShowSpirvSource),
19+
}
20+
521
/// `cargo gpu show`
622
#[derive(clap::Parser)]
723
pub struct Show {
8-
#[clap(long)]
9-
/// Displays the location of the cache directory
10-
cache_directory: bool,
24+
/// Display information about rust-gpu
25+
#[clap(subcommand)]
26+
command: Info,
1127
}
1228

1329
impl Show {
1430
/// Entrypoint
1531
pub fn run(self) {
16-
if self.cache_directory {
17-
log::info!("cache_directory: ");
18-
println!("{}", cache_dir().display());
32+
log::info!("{:?}: ", self.command);
33+
match self.command {
34+
Info::CacheDirectory => {
35+
println!("{}", cache_dir().display());
36+
}
37+
Info::SpirvSource(ShowSpirvSource { shader_crate }) => {
38+
let rust_gpu_source =
39+
crate::spirv_source::SpirvSource::get_spirv_std_dep_definition(&shader_crate);
40+
println!("{rust_gpu_source}");
41+
}
1942
}
2043
}
2144
}

crates/cargo-gpu/src/spirv_cli.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@ impl SpirvCli {
4848
if let Some(rust_gpu_version) = maybe_rust_gpu_version {
4949
let mut source = SpirvSource::CratesIO(rust_gpu_version.clone());
5050
if let Some(rust_gpu_source) = maybe_rust_gpu_source {
51-
source = SpirvSource::Git((rust_gpu_source, rust_gpu_version));
51+
source = SpirvSource::Git {
52+
url: rust_gpu_source,
53+
rev: rust_gpu_version,
54+
};
5255
}
5356
maybe_spirv_source = Some(source);
5457
}

crates/cargo-gpu/src/spirv_source.rs

Lines changed: 60 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ pub enum SpirvSource {
2424
/// then the source of `rust-gpu` is `Git`.
2525
///
2626
/// `(String, String)` is the repo source and revision hash or tag.
27-
Git((String, String)),
27+
Git { url: String, rev: String },
2828
/// If the shader specifies a version like:
2929
/// `spirv-std = { path = "/path/to/rust-gpu" ... }`
3030
/// then the source of `rust-gpu` is `Path`.
@@ -39,7 +39,11 @@ impl core::fmt::Display for SpirvSource {
3939
reason = "It's a core library trait implementation"
4040
)]
4141
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
42-
format!("{}+{}", self.to_repo(), self.to_version()).fmt(f)
42+
match self {
43+
SpirvSource::CratesIO(version) => f.write_str(version),
44+
SpirvSource::Git { url, rev } => f.write_str(&format!("{url}+{rev}")),
45+
SpirvSource::Path((a, b)) => f.write_str(&format!("{a}+{b}")),
46+
}
4347
}
4448
}
4549

@@ -65,15 +69,15 @@ impl SpirvSource {
6569
pub fn to_version(&self) -> String {
6670
match self {
6771
Self::CratesIO(version) | Self::Path((_, version)) => version.to_string(),
68-
Self::Git((_, revision)) => revision.to_string(),
72+
Self::Git { rev, .. } => rev.to_string(),
6973
}
7074
}
7175

7276
/// Convert the source to just its repo or path.
7377
fn to_repo(&self) -> String {
7478
match self {
7579
Self::CratesIO(_) => RUST_GPU_REPO.to_owned(),
76-
Self::Git((repo, _)) => repo.to_owned(),
80+
Self::Git { url, .. } => url.to_owned(),
7781
Self::Path((path, _)) => path.to_owned(),
7882
}
7983
}
@@ -162,7 +166,7 @@ impl SpirvSource {
162166
}
163167

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

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

211+
// Unfortunately Uri ignores the fragment/hash portion of the Uri.
212+
//
213+
// There's been a ticket open for years:
214+
// <https://github.com/hyperium/http/issues/127>
215+
//
216+
// So here we'll parse the fragment out of the source string by hand
205217
let uri = source_string.parse::<http::Uri>().unwrap();
218+
let maybe_hash = if source_string.contains('#') {
219+
let splits = source_string.split('#');
220+
splits.last().map(std::borrow::ToOwned::to_owned)
221+
} else {
222+
None
223+
};
206224
if uri.scheme().is_some() {
207-
source = Self::parse_git_source(version, &uri);
225+
source = Self::parse_git_source(version, &uri, maybe_hash);
208226
} else {
209227
source = Self::Path((source_string, version));
210228
}
@@ -216,24 +234,29 @@ impl SpirvSource {
216234
}
217235

218236
/// Parse a Git source like: `https://github.com/Rust-GPU/rust-gpu?rev=54f6978c#54f6978c`
219-
fn parse_git_source(version: String, uri: &http::Uri) -> Self {
220-
let mut revision = version;
221-
237+
fn parse_git_source(version: String, uri: &http::Uri, fragment: Option<String>) -> Self {
238+
log::trace!(
239+
"parsing git source from version: '{version}' and uri: '{uri}' and fragment: {}",
240+
fragment.as_deref().unwrap_or("?")
241+
);
222242
let repo = format!(
223243
"{}://{}{}",
224244
uri.scheme().unwrap(),
225245
uri.host().unwrap(),
226246
uri.path()
227247
);
228248

229-
if let Some(query) = uri.query() {
230-
let marker = "rev=";
231-
let sanity_check = query.contains(marker) && query.split('=').count() == 2;
232-
assert!(sanity_check, "revision not found in Git URI: {query}");
233-
revision = query.replace(marker, "");
234-
}
249+
let rev = uri.query().map_or_else(
250+
|| fragment.unwrap_or(version),
251+
|query| {
252+
let marker = "rev=";
253+
let sanity_check = query.contains(marker) && query.split('=').count() == 2;
254+
assert!(sanity_check, "revision not found in Git URI: {query}");
255+
query.replace(marker, "")
256+
},
257+
);
235258

236-
Self::Git((repo, revision))
259+
Self::Git { url: repo, rev }
237260
}
238261

239262
/// `git clone` the `rust-gpu` repo. We use it to get the required Rust toolchain to compile
@@ -283,10 +306,10 @@ mod test {
283306
let source = SpirvSource::get_spirv_std_dep_definition(&shader_template_path);
284307
assert_eq!(
285308
source,
286-
SpirvSource::Git((
287-
"https://github.com/Rust-GPU/rust-gpu".to_owned(),
288-
"82a0f69".to_owned()
289-
))
309+
SpirvSource::Git {
310+
url: "https://github.com/Rust-GPU/rust-gpu".to_owned(),
311+
rev: "82a0f69".to_owned()
312+
}
290313
);
291314
}
292315

@@ -297,10 +320,23 @@ mod test {
297320
let source = SpirvSource::parse_spirv_std_source_and_version(definition);
298321
assert_eq!(
299322
source,
300-
SpirvSource::Git((
301-
"https://github.com/Rust-GPU/rust-gpu".to_owned(),
302-
"82a0f69".to_owned()
303-
))
323+
SpirvSource::Git {
324+
url: "https://github.com/Rust-GPU/rust-gpu".to_owned(),
325+
rev: "82a0f69".to_owned()
326+
}
327+
);
328+
}
329+
330+
#[test_log::test]
331+
fn parsing_spirv_std_dep_for_git_source_hash() {
332+
let definition = "spirv-std v9.9.9 (https://github.com/Rust-GPU/rust-gpu#82a0f69) (*)";
333+
let source = SpirvSource::parse_spirv_std_source_and_version(definition);
334+
assert_eq!(
335+
source,
336+
SpirvSource::Git {
337+
url: "https://github.com/Rust-GPU/rust-gpu".to_owned(),
338+
rev: "82a0f69".to_owned()
339+
}
304340
);
305341
}
306342
}

0 commit comments

Comments
 (0)