From cc82241505188f8fa82398099cc7c3d623e75a61 Mon Sep 17 00:00:00 2001
From: Paul Gessinger <hello@paulgessinger.com>
Date: Tue, 17 Oct 2017 13:00:39 +0200
Subject: [PATCH] add scripts for format and license check

---
 .clang-format         |  7 ++--
 CI/check_format       | 31 +++++++++++++++
 CI/check_format_local | 11 ++++++
 CI/check_license.py   | 87 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 133 insertions(+), 3 deletions(-)
 create mode 100755 CI/check_format
 create mode 100755 CI/check_format_local
 create mode 100755 CI/check_license.py

diff --git a/.clang-format b/.clang-format
index 3db10bb5..d0a782f0 100644
--- a/.clang-format
+++ b/.clang-format
@@ -19,7 +19,7 @@ AlwaysBreakBeforeMultilineStrings: false
 AlwaysBreakTemplateDeclarations: true
 BinPackArguments: false
 BinPackParameters: false
-BraceWrapping:
+BraceWrapping:   
   AfterClass:      true
   AfterControlStatement: false
   AfterEnum:       false
@@ -45,7 +45,7 @@ DerivePointerAlignment: false
 DisableFormat:   false
 ExperimentalAutoDetectBinPacking: false
 ForEachMacros:   [ foreach, Q_FOREACH, BOOST_FOREACH ]
-IncludeCategories:
+IncludeCategories: 
   - Regex:           '^<.*>'
     Priority:        1
   - Regex:           '^(<|")boost/'
@@ -57,7 +57,7 @@ IncludeCategories:
 IndentCaseLabels: false
 IndentWidth:     2
 IndentWrappedFunctionNames: false
-KeepEmptyLinesAtTheStartOfBlocks: false
+KeepEmptyLinesAtTheStartOfBlocks: true
 MacroBlockBegin: ''
 MacroBlockEnd:   ''
 MaxEmptyLinesToKeep: 1
@@ -88,3 +88,4 @@ Standard:        Cpp11
 TabWidth:        2
 UseTab:          Never
 ...
+
diff --git a/CI/check_format b/CI/check_format
new file mode 100755
index 00000000..e9d794d9
--- /dev/null
+++ b/CI/check_format
@@ -0,0 +1,31 @@
+#!/bin/sh
+#
+# check that all code complies w/ the clang-format specification
+#
+# if all is well, returns w/o errors and does not print anything.
+# otherwise, return an error and print offending changes
+
+set -e # abort on error
+
+if [ $# -ne 1 ]; then
+    echo "wrong number of arguments"
+    echo ""
+    echo "usage: check_format <DIR>"
+    exit 1
+fi
+
+clang-format --version
+
+cd $1
+find . -iname '*.cpp' -or -iname '*.hpp' -or -iname '*.ipp' \
+  | xargs clang-format -i -style=file
+
+
+if ! [ -z $CI ]; then
+  mkdir changed
+  for f in $(git diff --name-only); do
+    cp --parents $f changed
+  done
+fi
+
+exec git diff --exit-code --stat
diff --git a/CI/check_format_local b/CI/check_format_local
new file mode 100755
index 00000000..f8fe8cba
--- /dev/null
+++ b/CI/check_format_local
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+if [ $# -ne 1 ]; then
+    echo "wrong number of arguments"
+    echo ""
+    echo "usage: check_format <DIR>"
+    exit 1
+fi
+
+WD="$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"
+docker run --rm -ti -v $WD:$WD:rw -w $WD gitlab-registry.cern.ch/pagessin/machines/check CI/check_format .
diff --git a/CI/check_license.py b/CI/check_license.py
new file mode 100755
index 00000000..61bf68b0
--- /dev/null
+++ b/CI/check_license.py
@@ -0,0 +1,87 @@
+#!/usr/bin/env python3
+import argparse
+import os
+import sys
+from subprocess import check_output
+import re
+import difflib
+from datetime import datetime
+
+
+def main():
+    p = argparse.ArgumentParser()
+    p.add_argument("input")
+    p.add_argument("--fix", action="store_true")
+
+    args = p.parse_args()
+
+    if os.path.isdir(args.input):
+        srcs = str(check_output(["find", args.input, "-iname", "*.cpp", "-or", "-iname", "*.hpp", "-or", "-iname", "*.ipp"]), "utf-8").strip().split("\n")
+    else:
+        srcs = [args.input]
+
+    year = datetime.now().strftime("%Y")
+
+    raw = """// This file is part of the ACTS project.
+//
+// Copyright (C) {year} ACTS project team
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/."""
+
+    rawstr = raw.format(year=year)
+    raw = rawstr
+
+
+    reg = (
+        r"\A// This file is part of the ACTS project.\n"
+        +r"//\n"
+        +r"// Copyright \(C\) 20[0-9]{2} ACTS project team\n"
+        +r"//\n"
+        +r"// This Source Code Form is subject to the terms of the Mozilla Public\n"
+        +r"// License, v\. 2\.0\. If a copy of the MPL was not distributed with this\n"
+        +r"// file, You can obtain one at http://mozilla.org/MPL/2.0/.\Z"
+        )
+
+    ref = re.compile(reg, re.M)
+    clean_re = re.compile(r"20[0-9]{2}")
+    def clean(s):
+        return clean_re.sub("XXXX", s)
+    def get_clean_lines(s):
+        return [clean(l)+"\n" for l in s.split("\n")]
+    raw = get_clean_lines(raw)
+
+    exit = 0
+    for src in srcs:
+        with open(src, "r+") as f:
+            license = ""
+            for x in range(len(raw)):
+                line = f.readline()
+                if not line.startswith("//"):
+                    break
+                license += line
+            license = ("".join(license)).strip()
+            m = ref.search(license)
+            if m == None:
+                sys.stderr.write("invalid / mising license in "+src+"\n")
+                diff = difflib.unified_diff(raw, get_clean_lines(license))
+                sys.stderr.writelines(diff)
+                sys.stderr.write("\n")
+
+                if args.fix:
+                    print("-> fixing file")
+                    f.seek(0)
+                    file_content = f.read()
+                    f.seek(0)
+                    f.write(rawstr+"\n\n")
+                    f.write(file_content)
+
+                exit = 1
+
+    sys.exit(exit)
+
+
+
+if "__main__" == __name__:
+    main()
-- 
GitLab