Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
47 changes: 29 additions & 18 deletions bear/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,8 @@ mod types {
pub directory: PathResolver,
#[serde(default)]
pub file: PathResolver,
#[serde(default)]
pub executable: PathResolver,
}

/// Path resolver options matching the YAML format.
Expand Down Expand Up @@ -367,7 +369,7 @@ pub mod validation {
#[error("Duplicate {field} entry at: {idx}")]
DuplicateEntry { field: &'static str, idx: usize },
#[error("Path format error: {message}")]
PathFormatError { message: &'static str },
PathFormatError { message: String },
#[error("Multiple validation errors: {errors:?}")]
Multiple { errors: Vec<ValidationError> },
}
Expand Down Expand Up @@ -519,6 +521,29 @@ pub mod validation {
}
}

fn validate_path_dependency(
base: &PathResolver,
dependent: &PathResolver,
dependent_name: &str,
) -> Result<(), ValidationError> {
use PathResolver::*;

let conflict = match (base, dependent) {
(Relative, Absolute | Canonical) => Some("must be relative too"),
(Canonical, Absolute) => Some("can't be absolute"),
(Absolute, Canonical) => Some("can't be canonical"),
(AsIs, Absolute | Relative | Canonical) => Some("must also be AsIs"),
_ => None,
};

match conflict {
Some(reason) => Err(ValidationError::PathFormatError {
message: format!("When directory is {base:?}, {dependent_name} {reason}"),
}),
None => Ok(()),
}
}

impl Validator<PathFormat> for PathFormat {
type Error = ValidationError;

Expand All @@ -527,23 +552,9 @@ pub mod validation {
/// - When directory is canonical, file can't be absolute
/// - When directory is absolute, file can't be canonical
fn validate(config: &PathFormat) -> Result<(), Self::Error> {
use PathResolver::*;

match (&config.directory, &config.file) {
(Relative, Absolute | Canonical) => Err(ValidationError::PathFormatError {
message: "When directory is relative, file must be relative too",
}),
(Canonical, Absolute) => Err(ValidationError::PathFormatError {
message: "When directory is canonical, file can't be absolute",
}),
(Absolute, Canonical) => Err(ValidationError::PathFormatError {
message: "When directory is absolute, file can't be canonical",
}),
(AsIs, Absolute | Relative | Canonical) => Err(ValidationError::PathFormatError {
message: "When directory as-is, file should be the same",
}),
_ => Ok(()),
}
validate_path_dependency(&config.directory, &config.file, "file")?;
validate_path_dependency(&config.directory, &config.executable, "executable")?;
Ok(())
}
}

Expand Down
22 changes: 16 additions & 6 deletions bear/src/output/clang/converter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,19 @@ impl CommandConverter {
}
}

/// Formats an executable file path
///
/// Returns the formatted path, falling back to the original path on error.
fn format_executable(&self, formatted_directory: &Path, executable: &Path) -> PathBuf {
match self.path_formatter.format_executable(formatted_directory, executable) {
Ok(formatted_path) => formatted_path,
Err(e) => {
warn!("Failed to format executable path {}: {}", executable.display(), e);
executable.to_path_buf()
}
}
}

/// Builds command arguments for a specific source file.
///
/// This method constructs the command arguments list that includes the executable,
Expand Down Expand Up @@ -242,12 +255,9 @@ impl CommandConverter {
command_args.extend(formatted_args);
}
ArgumentKind::Compiler => {
if let Some(executable_name) = cmd.executable.file_name() {
if let Some(name_str) = executable_name.to_str() {
command_args.push(name_str.to_string());
} else {
command_args.extend(original_args);
}
let executable = self.format_executable(&formatted_directory, &cmd.executable);
if let Some(executable_str) = executable.to_str() {
command_args.push(executable_str.to_string());
} else {
command_args.extend(original_args);
}
Expand Down
7 changes: 7 additions & 0 deletions bear/src/output/clang/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ pub trait PathFormatter: Send + Sync {

/// Format a file path according to the configured strategy.
fn format_file(&self, directory: &Path, file: &Path) -> Result<PathBuf, FormatError>;

/// Format an executable path according to the configured strategy.
fn format_executable(&self, directory: &Path, file: &Path) -> Result<PathBuf, FormatError>;
}

/// Implementation of PathFormatter that uses the configuration to determine
Expand All @@ -62,6 +65,10 @@ impl PathFormatter for ConfigurablePathFormatter {
fn format_file(&self, directory: &Path, file: &Path) -> Result<PathBuf, FormatError> {
self.config.file.resolve(directory, file)
}

fn format_executable(&self, directory: &Path, executable: &Path) -> Result<PathBuf, FormatError> {
self.config.executable.resolve(directory, executable)
}
}

impl PathResolver {
Expand Down