diff --git a/.github/lint_matchers.json b/.github/lint_matchers.json
new file mode 100644
index 00000000..7805b99d
--- /dev/null
+++ b/.github/lint_matchers.json
@@ -0,0 +1,14 @@
+{
+ "problemMatcher": [
+ {
+ "owner": "lint",
+ "pattern": [
+ {
+ "regexp": "^'([^']+)'\\s+(eol mismatch\\s-\\s.+)$",
+ "file": 1,
+ "message": 2
+ }
+ ]
+ }
+ ]
+}
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
new file mode 100644
index 00000000..6d9e06b0
--- /dev/null
+++ b/.github/workflows/lint.yml
@@ -0,0 +1,20 @@
+name: Lint
+on: [push, pull_request]
+
+jobs:
+ check-eol:
+ name: Check Line Endings
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+
+ - name: Setup Python
+ uses: actions/setup-python@v4
+ with:
+ python-version: '3.8'
+
+ - name: Check EOL
+ run: |
+ echo "::add-matcher::.github/lint_matchers.json"
+ python eol.py
diff --git a/eol.py b/eol.py
new file mode 100644
index 00000000..931c72b6
--- /dev/null
+++ b/eol.py
@@ -0,0 +1,61 @@
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import argparse
+import re
+import subprocess
+import sys
+
+parser = argparse.ArgumentParser()
+parser.add_argument("-f", "--fail-fast", action="store_true")
+parser.add_argument("-v", "--verbose", action="store_true")
+
+exitcode = 0
+
+if __name__ == "__main__":
+ args = parser.parse_args()
+
+ regex = re.compile(r"i\/(?P\S+)\s+w\/(?P\S+)\s+attr\/(?P\S+)?(?:\s+eol=(?P\S+))?\s+(?P\S+)")
+ result = subprocess.Popen(
+ ["git", "ls-files", "--eol"],
+ stdout=subprocess.PIPE,
+ text=True
+ )
+
+ # Iterate over lines returned from git... Trying to buffer the entire
+ # result of git lfs-files in a Python stream is SLOW.
+ for line in result.stdout:
+ result = regex.match(line)
+ if result is None:
+ raise RuntimeError(line)
+
+ path = result.group("path")
+ if result.group("attribute") == "-text":
+ if args.verbose:
+ print(f"'{path}'\tnot a text file")
+ continue
+
+ if eol := result.group("eol"):
+ indexEol = result.group("index")
+ workingEol = result.group("working")
+ if (eol, eol) != (indexEol, workingEol):
+ print(f"'{path}'\teol mismatch - expected: '{eol}', git index: '{indexEol}', working copy: '{workingEol}'")
+ exitcode = 1
+ if args.fail_fast:
+ sys.exit(exitcode)
+ elif args.verbose:
+ print(f"'{path}'\tgood eols")
+ elif args.verbose:
+ print(f"'{path}'\tno defined eols")
+
+ sys.exit(exitcode)