Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions bazel/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
name = "bazel"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
84 changes: 84 additions & 0 deletions bazel/src/bazel_info.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
use std::fmt::Debug;
use std::path::PathBuf;
use std::process::Command;

#[derive(Debug, Clone, PartialEq)]
pub struct BazelInfo {
pub workspace_root: PathBuf,
pub output_base: PathBuf,
pub execroot: PathBuf,
}

fn parse_bazel_info(info: &str) -> Option<BazelInfo> {
let mut workspace_root: Option<PathBuf> = None;
let mut output_base: Option<PathBuf> = None;
let mut execroot: Option<PathBuf> = None;
info.split('\n').for_each(|l| {
let split: Vec<&str> = l.splitn(2, ':').collect();
if split.len() != 2 {
return;
}
let first = split.get(0);
let next = split.get(1);
match (first, next) {
(Some(key), Some(value)) => match key {
&"execution_root" => execroot = Some(value.trim().into()),
&"output_base" => output_base = Some(value.trim().into()),
&"workspace" => workspace_root = Some(value.trim().into()),
_ => {}
},
_ => {}
}
});
match (execroot, output_base, workspace_root) {
(Some(execroot), Some(output_base), Some(workspace_root)) => Some(BazelInfo {
workspace_root,
execroot,
output_base,
}),
_ => {
eprintln!(
"Couldn't find workspace_root, execroot or output_base in output:\n`{}`",
info
);
None
}
}
}

pub fn get_bazel_info(workspace_dir: Option<&str>) -> Option<BazelInfo> {
let mut raw_command = Command::new("bazel");
let mut command = raw_command.arg("info");
command = match workspace_dir {
Some(d) => command.current_dir(d),
None => command,
};

let output = command.output().ok()?;

if !output.status.success() {
return None;
}

let s = std::str::from_utf8(output.stdout.as_slice()).ok()?;

parse_bazel_info(s)
}

#[cfg(test)]
mod tests {
use super::parse_bazel_info;
use super::BazelInfo;

#[test]
fn parses_info() {
assert_eq!(
parse_bazel_info(include_str!("info.txt")),
Some(BazelInfo {
workspace_root: "/home/user/dev/bazel/bazel".into(),
execroot: "/home/user/.cache/bazel/_bazel_user/726bdc44ca84ffc53f631c27e313c4cf/execroot/io_bazel".into(),
output_base: "/home/user/.cache/bazel/_bazel_user/726bdc44ca84ffc53f631c27e313c4cf".into()
})
)
}
}
23 changes: 23 additions & 0 deletions bazel/src/info.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
bazel-bin: /home/user/.cache/bazel/_bazel_user/726bdc44ca84ffc53f631c27e313c4cf/execroot/io_bazel/bazel-out/k8-fastbuild/bin
bazel-genfiles: /home/user/.cache/bazel/_bazel_user/726bdc44ca84ffc53f631c27e313c4cf/execroot/io_bazel/bazel-out/k8-fastbuild/bin
bazel-testlogs: /home/user/.cache/bazel/_bazel_user/726bdc44ca84ffc53f631c27e313c4cf/execroot/io_bazel/bazel-out/k8-fastbuild/testlogs
character-encoding: file.encoding = ISO-8859-1, defaultCharset = ISO-8859-1
command_log: /home/user/.cache/bazel/_bazel_user/726bdc44ca84ffc53f631c27e313c4cf/command.log
committed-heap-size: 418MB
execution_root: /home/user/.cache/bazel/_bazel_user/726bdc44ca84ffc53f631c27e313c4cf/execroot/io_bazel
gc-count: 11
gc-time: 42ms
install_base: /home/user/.cache/bazel/_bazel_user/install/41b71f1bb3ce13f20cfeeb31a9357113
java-home: /home/user/.cache/bazel/_bazel_user/install/41b71f1bb3ce13f20cfeeb31a9357113/embedded_tools/jdk
java-runtime: OpenJDK Runtime Environment (build 11.0.6+10-LTS) by Azul Systems, Inc.
java-vm: OpenJDK 64-Bit Server VM (build 11.0.6+10-LTS, mixed mode) by Azul Systems, Inc.
max-heap-size: 4175MB
output_base: /home/user/.cache/bazel/_bazel_user/726bdc44ca84ffc53f631c27e313c4cf
output_path: /home/user/.cache/bazel/_bazel_user/726bdc44ca84ffc53f631c27e313c4cf/execroot/io_bazel/bazel-out
package_path: %workspace%
release: release 5.2.0
repository_cache: /home/user/.cache/bazel/_bazel_user/cache/repos/v1
server_log: /home/user/.cache/bazel/_bazel_user/726bdc44ca84ffc53f631c27e313c4cf/java.log.home.user.log.java.20220821-211440.206313
server_pid: 206313
used-heap-size: 266MB
workspace: /home/user/dev/bazel/bazel
118 changes: 118 additions & 0 deletions bazel/src/label.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@

use std::path::PathBuf;

use crate::bazel_info::BazelInfo;

pub struct ExternalLabel {
repository: String,
package: String,
target: String,
}
pub struct LocalLabel {
package: String,
target: String,
}

pub struct RelativeLabel {
sub_package: String,
target: String,
}

pub enum Label {
External(ExternalLabel),
Local(LocalLabel),
Relative(RelativeLabel),
}

impl Label {
fn split_package_target(label: &str) -> Option<(&str, &str)> {
let mut split_parts = label.split(":");
let package = split_parts.next()?;
let target = split_parts.next()?;
Some((package, target))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note, //foo can be used as a short-hand for //foo:foo,
and relative labels can skip the :, e.g. foo instead of :foo.

}

fn split_repository_package_target(label: &str) -> Option<(&str, &str, &str)> {
let mut split_parts = label.split("//");
let repository = split_parts.next()?;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And @foo as a short-hand for @foo//:foo.

let package_target = split_parts.next()?;
let (package, target) = Self::split_package_target(package_target)?;
Some((repository, package, target))
}

pub fn replace_fake_file_with_build_target(fake_file: PathBuf) -> Option<PathBuf> {
if fake_file.exists() {
return Some(fake_file);
}
fake_file.parent().and_then(|p| {
let build = p.join("BUILD");
let build_bazel = p.join("BUILD.bazel");
if build.exists() {
Some(build)
} else if build_bazel.exists() {
Some(build_bazel)
} else {
None
}
})
}

pub fn resolve(
self,
bazel_info: &BazelInfo,
current_file_dir: Option<PathBuf>,
) -> Option<PathBuf> {
// TODO: support nested workspaces either by getting info again or at the start getting the info for all the workspaces in the directory
match self {
Label::External(l) => {
let execroot_dirname = bazel_info.execroot.file_name()?;

if l.repository == execroot_dirname.to_str()? {
Some(bazel_info.workspace_root.join(l.package).join(l.target))
} else {
Some(
bazel_info
.output_base
.join("external")
.join(l.repository)
.join(l.package)
.join(l.target),
)
}
}
Label::Local(l) => Some(bazel_info.workspace_root.join(l.package).join(l.target)),
Label::Relative(l) => {
current_file_dir.and_then(|d| Some(d.join(l.sub_package).join(l.target)))
}
}
}

pub fn new(label: &str) -> Option<Self> {
if !label.contains(":") {
return None;
}

if label.starts_with("@") {
let (repository, package, target) =
Self::split_repository_package_target(label.trim_start_matches('@'))?;
return Some(Label::External(ExternalLabel {
repository: repository.to_owned(),
package: package.to_owned(),
target: target.to_owned(),
}));
}
if label.starts_with("//") {
let (package, target) = Self::split_package_target(label.trim_start_matches("//"))?;
return Some(Label::Local(LocalLabel {
package: package.to_owned(),
target: target.to_owned(),
}));
}

let (package, target) = Self::split_package_target(label)?;
Some(Label::Relative(RelativeLabel {
sub_package: package.to_owned(),
target: target.to_owned(),
}))
}
}
2 changes: 2 additions & 0 deletions bazel/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod bazel_info;
pub mod label;
1 change: 1 addition & 0 deletions starlark/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ either = "1.6.1"
static_assertions = "1.1.0"
memoffset = "0.6.4"
thiserror = "1.0.30"
bazel = { version = "0.1.0", path = "../bazel" }
starlark_derive = { version = "0.9.0-pre", path = "../starlark_derive" }
starlark_map = { version = "0.9.0-pre", path = "../starlark_map" }
gazebo.version = "0.8.0"
Expand Down
Loading