Moved add_copyright.py from xos to automation-tools
Change-Id: I2c26293bbf1404207e4b7965bba2216e2749e756
diff --git a/developer/add_copyright.py b/developer/add_copyright.py
new file mode 100755
index 0000000..e87a7c8
--- /dev/null
+++ b/developer/add_copyright.py
@@ -0,0 +1,287 @@
+#!/usr/bin/env python
+
+# Copyright 2017-present Open Networking Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from __future__ import absolute_import, print_function
+import sys
+import os
+from io import open
+
+
+COPYRIGHTS = {
+ "slash": """/*
+ * Copyright 2017-present Open Networking Foundation
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */""",
+ "hash": """# Copyright 2017-present Open Networking Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.""",
+ "html": """<!--
+Copyright 2017-present Open Networking Foundation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->""",
+ "jinja": """{#
+Copyright 2017-present Open Networking Foundation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+#}""",
+ "ini": """;Copyright 2017-present Open Networking Foundation
+;
+;Licensed under the Apache License, Version 2.0 (the "License");
+;you may not use this file except in compliance with the License.
+;You may obtain a copy of the License at
+;
+;http://www.apache.org/licenses/LICENSE-2.0
+;
+;Unless required by applicable law or agreed to in writing, software
+;distributed under the License is distributed on an "AS IS" BASIS,
+;WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+;See the License for the specific language governing permissions and
+;limitations under the License.""",
+}
+
+EXT_MAPPING = {
+ ".js": COPYRIGHTS["slash"],
+ ".ts": COPYRIGHTS["slash"],
+ ".scss": COPYRIGHTS["slash"],
+ ".css": COPYRIGHTS["slash"],
+ ".gradle": COPYRIGHTS["slash"],
+ ".go": COPYRIGHTS["slash"],
+ ".c": COPYRIGHTS["slash"],
+ ".h": COPYRIGHTS["slash"],
+
+ "docker": COPYRIGHTS["hash"],
+ ".py": COPYRIGHTS["hash"],
+ ".model": COPYRIGHTS["hash"], # attic files
+ ".sh": COPYRIGHTS["hash"],
+ ".yaml": COPYRIGHTS["hash"],
+ ".yml": COPYRIGHTS["hash"],
+ ".m4": COPYRIGHTS["hash"],
+ ".sql": COPYRIGHTS["hash"],
+
+ ".html": COPYRIGHTS["html"],
+ ".xml": COPYRIGHTS["html"],
+ ".j2": COPYRIGHTS["jinja"],
+ ".ini": COPYRIGHTS["ini"],
+}
+
+
+def get_copyright(file):
+ name, ext = os.path.splitext(file)
+
+ if "Dockerfile" in name:
+ return EXT_MAPPING["docker"]
+ try:
+ return EXT_MAPPING[ext]
+ except KeyError:
+ print("Missing copyright for file of type: %s" % ext)
+ return None
+
+
+def add_copyright(file):
+ with open(file, 'r') as original:
+ data = original.read()
+ if "Licensed under the Apache License, Version 2.0" not in data:
+ print("Adding copyright to: %s" % file)
+
+ # don't push special first lines below copyright
+ specialline = ""
+ if data and "#!" in data.splitlines()[0]:
+ print("Has Shebang: %s" % data.splitlines()[0])
+ (specialline, data) = data.split("\n", 1)
+ specialline += "\n"
+
+ elif data and "---" in data.splitlines()[0]:
+ print("Has YAML start of document: %s" % data.splitlines()[0])
+ (specialline, data) = data.split("\n", 1)
+ specialline += "\n"
+
+ copy = get_copyright(file)
+ if copy:
+ with open(file, 'w') as modified:
+ modified.write(specialline + copy + "\n" + data)
+ return
+
+
+def get_files_ignore_by_git(root):
+ # NOTE this is not perfect, some file will still be copyrighted, but we
+ # save some time
+ if root == ".gitignore":
+ gitignore = root
+ else:
+ gitignore = os.path.join(root, ".gitignore")
+
+ exclusion_list = []
+ if os.path.exists(gitignore):
+ for line in open(gitignore).readlines():
+ if "#" not in line:
+ line = line.strip()
+ if line.endswith("/"):
+ line = line.replace("/", "")
+ exclusion_list.append(line)
+ return exclusion_list
+
+
+def should_skip(entry):
+
+ # do not skip directories
+ if os.path.isdir(entry):
+ return False
+
+ if "LICENSE.txt" in entry \
+ or ".git" in entry \
+ or ".idea" in entry:
+ return True
+
+ name, ext = os.path.splitext(entry)
+ if not ext or ext == "" \
+ or ext == ".pyc" \
+ or ext == ".txt" \
+ or ext == ".in" \
+ or ext == ".crt" \
+ or ext == ".unused" \
+ or ext == ".list" \
+ or ext == ".README" \
+ or ext == ".json" \
+ or ext == ".log" \
+ or ext == ".asc" \
+ or ext == ".dot" \
+ or ext == ".do" \
+ or ext == ".template" \
+ or ext == ".svg" \
+ or ext == ".ttf" \
+ or ext == ".woff" \
+ or ext == ".woof2" \
+ or ext == ".eot" \
+ or ext == ".md" \
+ or ext == ".png" \
+ or ext == ".pdf" \
+ or ext == ".PNG" \
+ or ext == ".jpg" \
+ or ext == ".gif" \
+ or ext == ".ico" \
+ or ext == ".conf"\
+ or ext == ".key" \
+ or ext == ".proto" \
+ or ext == ".xproto" \
+ or ext == ".xtarget" \
+ or ext == ".otf" \
+ or ext == ".desc":
+ return True
+ return False
+
+
+def recursive_iterate_dirs(source, apply_copyright=True):
+ # print "Iterating on: %s" % source
+ # skipping files in the gitignore
+ gitignored = get_files_ignore_by_git(source)
+ entries = []
+ for entry in os.listdir(source):
+
+ if entry in gitignored:
+ # print "Skipping because gitignored: %s" % entry
+ continue
+
+ entry = os.path.join(source, entry)
+ if should_skip(entry):
+ # print "Skipping: %s" % entry
+ continue
+
+ if os.path.isdir(entry):
+ entries.append(recursive_iterate_dirs(entry, apply_copyright))
+ elif os.path.isfile(entry):
+ entries.append(entry)
+ if apply_copyright is True:
+ add_copyright(entry)
+ return entries
+
+
+def flatten(aList):
+ t = []
+ for i in aList:
+ if not isinstance(i, list):
+ t.append(i)
+ else:
+ t.extend(flatten(i))
+ return t
+
+
+def list_file_types(source):
+ file_types = []
+ files = flatten(recursive_iterate_dirs(source, apply_copyright=False))
+ for entry in files:
+ name, ext = os.path.splitext(entry)
+ if ext not in file_types:
+ file_types.append(ext)
+ print(file_types)
+
+
+def main():
+ if len(sys.argv) < 2:
+ raise Exception("You must provide a path to the source folder"
+ "as arguments to the script")
+ source_root = os.path.abspath(os.path.join(os.getcwd(), sys.argv[1]))
+ if not os.path.exists(source_root):
+ raise Exception("You must provide an existing the source folder")
+ if len(sys.argv) == 3:
+ list_file_types(source_root)
+ else:
+ recursive_iterate_dirs(source_root)
+
+
+if __name__ == "__main__":
+ main()