Is it possible to check only for git diff section?
here is the scenario, there are several developers checkin the code, I would like to check which developer that violate the rules and send email to that developer
For my projects, I use a script to cull out the violations, as swiftlint is fast enough to lint the entire code relatively quickly. Here's an example script that I use: https://gist.github.com/daniel-beard/db4059e5a351a12060a8
Yes this is possible:
git diff --cached --name-only | while read filename; do
swiftlint lint --path "$filename";
done
You could even add SwiftLint as a pre-commit hook, such that you cannot commit (without adding a skip option to your commit) without all changed files passing SwiftLint.
thanks. good input
This works for staged changes only, but not for modified files.
Dropping the --cached
part will give you list of modified files.
It also needs to filter out non Swift files. Here's the script I ended up using:
# Run SwiftLint
START_DATE=$(date +"%s")
SWIFT_LINT=/usr/local/bin/swiftlint
# Run SwiftLint for given filename
run_swiftlint() {
local filename="${1}"
if [[ "${filename##*.}" == "swift" ]]; then
${SWIFT_LINT} autocorrect --path "${filename}"
${SWIFT_LINT} lint --path "${filename}"
fi
}
if [[ -e "${SWIFT_LINT}" ]]; then
echo "SwiftLint version: $(${SWIFT_LINT} version)"
# Run for both staged and unstaged files
git diff --name-only | while read filename; do run_swiftlint "${filename}"; done
git diff --cached --name-only | while read filename; do run_swiftlint "${filename}"; done
else
echo "${SWIFT_LINT} is not installed."
exit 0
fi
END_DATE=$(date +"%s")
DIFF=$(($END_DATE - $START_DATE))
echo "SwiftLint took $(($DIFF / 60)) minutes and $(($DIFF % 60)) seconds to complete."
We put is somewhere in the project, e.g. in Scripts/swiftlint.sh
and then in Xcode itself the build phase step is quite short "${SRCROOT}/Scripts/swiftlint.sh"
. I don't like looking at Xcode project diffs much :)
you could replace this check if [[ "${filename##*.}" == "swift" ]]; then
by git diff --name-only | grep "\.swift"
when doing the while loop to only loop on swift files
@mgrebenets Hi Max, its great to find your answer :)
What is the use of local filename="${1}"
? it will work even without this line.
hi, I made a bash script to check only modified files
https://github.com/danilobecke/lint/blob/master/lintDiffOnly.sh
Assuming SwiftLint's cache is working reliably, what's the advantage of doing this?
Assuming SwiftLint's cache is working reliably, what's the advantage of doing this?
One use case I can see would be slowly integrating SwiftLint by requiring only touched files to be without warnings. This way you can avoid a huge reformatting commit for example.
That's a great use case
I suggest to use git diff
with --diff-filter=d
to filter out delete files, i.e.
git diff --cached --diff-filter=d --name-only
or
git diff --diff-filter=d --name-only
Calling SwiftLint on deleted file will result in an error
I think this doesn't take into consideration the excluded list in the configuration file.
@abdelmagied94
That's the case, in our full version we have something like this:
# Run code checks for given filename.
run_checks() {
local filename="${1}"
# Ignore Pods and Vendor paths.
[[ ${filename} =~ Pods/ ]] && return 0
[[ ${filename} =~ Vendor/ ]] && return 0
# Ignore autogenerated SwiftGen files.
[[ ${filename} =~ .*SwiftGen\.swift ]] && return 0
# Ignore templates and generated files.
[[ ${filename} =~ .*Generated.* ]] && return 0
# Only lint .swift files.
! [[ ${filename##*.} == "swift" ]] && return 0
# Run the checks.
${SWIFTLINT} autocorrect --path "${filename}"
${SWIFTFORMAT} "${filename}"
${SWIFTLINT} lint --strict --path "${filename}"
}
The downside is that we have to duplicate the logic of SwiftLint and in this case SwiftFormat exclude list, but works for us given that we have those exclude lists following some naming conventions.
It could be improve by parsing SwiftLint yaml config in some way and matching file names against it, if it's worth the additional effort.
Made a gist for accomplishing exactly this. It filters out violations that are not in the git diff hunks, and hooks via a bash run script. https://gist.github.com/george-lim/f1166bc75d9047495934a6eb974bb127
Is there a way to check SwiftLint warnings and errors only for the lines that were modified and not the files? Because our code base is pretty big with some files spanning over 3,000 lines. So people who are making changes to just a couple of lines in that file end up getting warnings and errors for the complete file.
@RohithSriram Not an answer to your problem, so sorry about that, but if your file is over 3000 lines, then that's a problem and you should be thinking about how to make those files smaller.
Separate the functionality into multiple smaller components.
Large files like that are hard to maintain, especially a new developer to the project will have no idea what is going on in that file.
Most helpful comment
This works for staged changes only, but not for modified files.
Dropping the
--cached
part will give you list of modified files.It also needs to filter out non Swift files. Here's the script I ended up using:
We put is somewhere in the project, e.g. in
Scripts/swiftlint.sh
and then in Xcode itself the build phase step is quite short"${SRCROOT}/Scripts/swiftlint.sh"
. I don't like looking at Xcode project diffs much :)