Goal
I'm trying to introduce SwiftLint to an existing project, in a gradual way, enforcing a "you touched it, you fix it" rule. All changes to the project are done via branches and PRs and the intention is that all files created or modified by a PR must pass the linting rules before being merged.
Progress
Currently I have:
git diff --name-status "main" \
| grep '^[^D]' \
| grep '.swift$' \
| awk -F '\t' '{ printf("%s\0", $NF) }' \
| xargs -0 swiftlint lint --strict --quiet --reporter xcode
Which is:
- All changes relative to "main"
- .. that aren't deletions
- .. that are to
.swift
files - .. extract the last tab-separated field (to handle renames), listed with
null
separators - .. and pass to
swiftlint
viaxargs
, expectingnull
separators
That works as intended in an interactive shell, but when invoked by Xcode as a build step it lints every file instead. If I change the last line to include echo
and then inspect Xcode's build log:
| xargs -0 echo swiftlint lint --strict --quiet --reporter Xcode
... I can see that the file names are concatenated together, rather than listed individually.
Expected:
swiftlint lint --strict --quiet --reporter Xcode path/to/first.swift path/to/second.swift
Actual:
swiftlint lint --strict --quiet --reporter Xcode path/to/first.swiftpath/to/second.swift
swiftLint
sees that as one file that doesn't exist and then falls back to linting everything instead.
The outcome is the same whether Xcode is using /bin/sh
or /bin/bash
.
I suspect my problem is around the quoting or escaping of the \0
for awk
, but can't find the solution.