Search code examples
awkxargsswiftlint

Passing a list of filenames to SwiftLint using awk and xargs


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 via xargs, expecting null 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.


Solution

  • Indeed it looks like that \0 in awk's printf() may not be doing what you want it to (while also likely depending on the platform i.e. Linux or macos)

    I'd suggest using %c instead as:

    
        | awk -F '\t' '{ printf("%s%c", $NF, 0) }' \
    
    

    Appreciate if you can confirm it worked for you, thanks!