Skip to content

Commit

Permalink
Add new options to inputs tool.
Browse files Browse the repository at this point in the history
Add new options to the `inputs` tool in order to change
the format of its output:

- `--no-shell-escape` to avoid shell-escaping the results.

- `--dependency-order` to return results in dependency order,
  instead of sorting them alphabetically.

- `--print0` to use \0 as the list separator in the list,
  useful to process the target paths with `xargs -0` and
  similar tools.
  • Loading branch information
digit-google committed Sep 2, 2024
1 parent 5b94d34 commit 2843493
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 11 deletions.
48 changes: 46 additions & 2 deletions misc/output_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,17 @@ def test_tool_inputs(self) -> None:
out2
''')

# Verify that results are shell-escaped by default.
# Also verify that phony outputs are never part of the results.
self.assertEqual(run(plan, flags='-t inputs --dependency-order out3'),
'''in2
in1
out1
out2
implicit
order_only
''')

# Verify that results are shell-escaped by default, unless --no-shell-escape
# is used. Also verify that phony outputs are never part of the results.
quote = '"' if platform.system() == "Windows" else "'"

plan = '''
Expand All @@ -226,12 +235,47 @@ def test_tool_inputs(self) -> None:
build all: phony out$ 3
'''

# Quoting changes the order of results when sorting alphabetically.
self.assertEqual(run(plan, flags='-t inputs all'),
f'''{quote}out 2{quote}
in1
out1
''')

self.assertEqual(run(plan, flags='-t inputs --no-shell-escape all'),
'''in1
out 2
out1
''')

# But not when doing dependency order.
self.assertEqual(
run(
plan,
flags='-t inputs --dependency-order all'
),
f'''in1
out1
{quote}out 2{quote}
''')

self.assertEqual(
run(
plan,
flags='-t inputs --dependency-order --no-shell-escape all'
),
f'''in1
out1
out 2
''')

self.assertEqual(
run(
plan,
flags='-t inputs --dependency-order --no-shell-escape --print0 all'
),
f'''in1\0out1\0out 2\0'''
)


def test_explain_output(self):
Expand Down
47 changes: 38 additions & 9 deletions src/ninja.cc
Original file line number Diff line number Diff line change
Expand Up @@ -767,23 +767,44 @@ int NinjaMain::ToolInputs(const Options* options, int argc, char* argv[]) {
argc++;
argv--;

bool print0 = false;
bool shell_escape = true;
bool dependency_order = false;

optind = 1;
int opt;
const option kLongOptions[] = { { "help", no_argument, NULL, 'h' },
{ "no-shell-escape", no_argument, NULL, 'E' },
{ "print0", no_argument, NULL, '0' },
{ "dependency-order", no_argument, NULL,
'd' },
{ NULL, 0, NULL, 0 } };
while ((opt = getopt_long(argc, argv, "h", kLongOptions, NULL)) != -1) {
while ((opt = getopt_long(argc, argv, "h0Ed", kLongOptions, NULL)) != -1) {
switch (opt) {
case 'd':
dependency_order = true;
break;
case 'E':
shell_escape = false;
break;
case '0':
print0 = true;
break;
case 'h':
default:
// clang-format off
printf(
"Usage '-t inputs [options] [targets]\n"
"\n"
"List all inputs used for a set of targets.\n"
"Note that results are shell escaped, and sorted alphabetically,\n"
"List all inputs used for a set of targets, sorted in dependency order.\n"
"Note that by default, results are shell escaped, and sorted alphabetically,\n"
"and never include validation target paths.\n\n"
"Options:\n"
" -h, --help Print this message.\n");
" -h, --help Print this message.\n"
" -0, --print0 Use \\0, instead of \\n as a line terminator.\n"
" -E, --no-shell-escape Do not shell escape the result.\n"
" -d, --dependency-order Sort results by dependency order.\n"
);
// clang-format on
return 1;
}
Expand All @@ -802,12 +823,20 @@ int NinjaMain::ToolInputs(const Options* options, int argc, char* argv[]) {
for (const Node* node : nodes)
collector.VisitNode(node);

std::vector<std::string> inputs = collector.GetInputsAsStrings(true);
std::sort(inputs.begin(), inputs.end());

for (const std::string& input : inputs)
puts(input.c_str());
std::vector<std::string> inputs = collector.GetInputsAsStrings(shell_escape);
if (!dependency_order)
std::sort(inputs.begin(), inputs.end());

if (print0) {
for (const std::string& input : inputs) {
fwrite(input.c_str(), input.size(), 1, stdout);
fputc('\0', stdout);
}
fflush(stdout);
} else {
for (const std::string& input : inputs)
puts(input.c_str());
}
return 0;
}

Expand Down

0 comments on commit 2843493

Please sign in to comment.