If path is absolute, return it unchanged. If make_absolute is true, make it absolute.
Otherwise, make it relative to the cwd of the child.
Whenever a path is included in the argv of a child, it should be put through this function first.
fn convertPathArg(
arena: Allocator,
run_index: Configuration.Step.Index,
maker: *Maker,
path: Path,
make_absolute: bool,
) ![]const u8
fn convertPathArg(
arena: Allocator,
run_index: Configuration.Step.Index,
maker: *Maker,
path: Path,
make_absolute: bool,
) ![]const u8 {
const conf = &maker.scanned_config.configuration;
const conf_step = run_index.ptr(conf);
const conf_run = conf_step.extended.get(conf.extra).run;
const graph = maker.graph;
const path_str = try path.toString(arena);
if (Dir.path.isAbsolute(path_str)) {
// Absolute paths don't need changing.
return path_str;
}
if (make_absolute) {
return Dir.path.join(arena, &.{ graph.cache.cwd, path_str });
}
const child_cwd_rel: []const u8 = rel: {
const child_lazy_cwd = conf_run.cwd.value orelse break :rel path_str;
const child_cwd = try maker.resolveLazyPathIndexAbs(arena, child_lazy_cwd, run_index);
// Convert it from relative to *our* cwd, to relative to the *child's* cwd.
break :rel try Dir.path.relative(arena, graph.cache.cwd, &graph.environ_map, child_cwd, path_str);
};
// Not every path can be made relative, e.g. if the path and the child cwd are on different
// disk designators on Windows. In that case, `relative` will return an absolute path which we can
// just return.
if (Dir.path.isAbsolute(child_cwd_rel)) return child_cwd_rel;
// We're not done yet. In some cases this path must be prefixed with './':
// * On POSIX, the executable name cannot be a single component like 'foo'
// * Some executables might treat a leading '-' like a flag, which we must avoid
// There's no harm in it, so just *always* apply this prefix.
return Dir.path.join(arena, &.{ ".", child_cwd_rel });
}