copyright 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. #!/usr/bin/env bash
  2. # copyright/Open GoPro, Version 2.0 (C) Copyright 2021 GoPro, Inc. (http://gopro.com/OpenGoPro).
  3. # This copyright was auto-generated on Wed, Sep 1, 2021 5:06:27 PM
  4. COPYRIGHT="##FILE##/Open GoPro, Version ##VERSION## (C) Copyright 2021 GoPro, Inc. (http://gopro.com/OpenGoPro)."
  5. TIME="This copyright was auto-generated on ##TIME##"
  6. INPUT=
  7. CHECK_ONLY=false
  8. num_wrong=0
  9. help() {
  10. cat <<EOF
  11. Usage: copyright [OPTIONS] VERSION
  12. Check for or apply copyrights to source files.
  13. Required positional arguments:
  14. VERSION version to check for / apply in the copyright
  15. Optional arguments:
  16. -i INPUT INPUT is directory to analyze. By default if not passed, git changed / added files will be analyzed.
  17. -h Print this Help.
  18. -c Check only (and output problems). Do not apply changes. Returns 3 if any missing copyrights found
  19. EOF
  20. }
  21. # MacOS doesn't have realpath. This is taken from https://stackoverflow.com/questions/3572030/bash-script-absolute-path-with-os-x
  22. realpath_support_macos() {
  23. [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"
  24. }
  25. main() {
  26. # Build array of input files
  27. IFS=$'\n' # Change interframe separator to handle files with spaces
  28. if [ -z "$INPUT" ]; then
  29. echo "Analyzing added / modified files."
  30. files=($(git diff --cached --name-only --diff-filter=ACM)) # Added / modified files
  31. else
  32. echo "Analyzing all files recursively at $(realpath_support_macos $INPUT)."
  33. # All files except for those in .git and
  34. # Lunr files which must contain front matter at first line
  35. files=($(find $INPUT -type f ! -path "./.git/*" ! -path "./docs/assets/js/lunr/*"))
  36. fi
  37. # Ensure there are any files to analyze
  38. if [[ "${#files[@]}" == 0 ]]; then
  39. echo "No files to analyze."
  40. exit 0
  41. fi
  42. FORMAT="%-120s | %-7s | %-7s | %-7s | %-7s |"
  43. printf "\n$FORMAT\n" "FILE" "CORRECT" "WRONG" "MISSING" "N/A"
  44. printf '=%.0s' {1..162}
  45. echo
  46. # Analyze each file for a copyright
  47. for file in ${files[@]}; do
  48. copyright=
  49. line_start=
  50. line_end=
  51. found_version=
  52. incorrect="MISSING"
  53. # Is there a copyright?
  54. # Note! We're only looking at the first 7 lines as an optimization to avoid reading large files.
  55. # In actuality, there is no reason for it be after the 3rd line.
  56. copyright=$(head -n 7 $file | cat -n | grep -m1 '(C) Copyright.*GoPro' | sed -e 's/^[[:space:]]*//') # Add line numbers when cat'ing, then trim leading whitespace.
  57. generic_copyright=$(head -n 7 $file | cat -n | grep -i -m1 'copyright' | sed -e 's/^[[:space:]]*//')
  58. if [[ "$copyright" ]]; then
  59. # If this file explicitely does not get a copyright, continue
  60. if [[ $(echo "$copyright" | grep -c "No (C) Copyright") > 0 ]]; then
  61. printf "$FORMAT\n" "$file" "" "" "" "*"
  62. continue
  63. fi
  64. # Is this the correct version, continue
  65. found_version=$(echo "$copyright" | sed 's/.*Version \(.*\) (C).*/\1/')
  66. if [[ "$VERSION" == "$found_version" ]]; then
  67. printf "$FORMAT\n" "$file" "*"
  68. continue
  69. fi
  70. # The version is incorrect. If we are to make changes (i.e. we are not only checking)...
  71. incorrect="WRONG_VERSION"
  72. if [[ "$CHECK_ONLY" == false ]]; then
  73. # Get line number where copyright starts
  74. line_start=$(echo "$copyright" | cut -f1)
  75. # And where it ends (line 1 = copyright, line 2 = timestamp, line 3 = newline)
  76. line_end=$((line_start + 2))
  77. # Strip the lines since we will add the correct copyright below
  78. lines="$line_start,$line_end"
  79. sed -i.bak "$lines"'d' $file && rm "$file".bak # The .bak is to appease MacOS
  80. fi
  81. elif [[ "$generic_copyright" ]]; then
  82. #this file has a copyright that is potentially not our own
  83. printf "$FORMAT\n" "$file" "" "" "" "*"
  84. continue
  85. fi
  86. # The copyright was either missing or had an incorrect version. Now see if this file deserves a copyright.
  87. # First check known filenames that don't have extensions
  88. case $(basename "$file") in
  89. Makefile | Dockerfile)
  90. start="#"
  91. stop=""
  92. ;;
  93. *)
  94. # Now check file extensions
  95. extension="${file##*.}"
  96. case $extension in
  97. py | yml | r | R | rb)
  98. start="#"
  99. stop=""
  100. ;;
  101. c | h | cpp | cxx | hpp | js | ts | swift | css | proto | java | cs | kt | kts | ktm | m | php | rs | go | dart)
  102. start="/*"
  103. stop=" */"
  104. ;;
  105. lua)
  106. start="--"
  107. stop=""
  108. ;;
  109. *)
  110. # Special case for shell files. We use the file command since they might not have an extension
  111. if [[ $(echo $(file $file) | grep -c "shell script") > 0 ]]; then
  112. start="#"
  113. stop=""
  114. else
  115. printf "$FORMAT\n" "$file" "" "" "" "*"
  116. continue
  117. fi
  118. ;;
  119. esac
  120. ;;
  121. esac
  122. num_wrong=$((num_wrong + 1))
  123. if [[ "$incorrect" == "MISSING" ]]; then
  124. printf "$FORMAT" "$file" "" "" "X"
  125. else
  126. printf "$FORMAT" "$file" "" "X"
  127. fi
  128. # Build the copyright string if desired
  129. if [[ "$CHECK_ONLY" == false ]]; then
  130. # Replace template strings with actual values and make into comment
  131. new_copyright="${COPYRIGHT/"##FILE##"/$(basename "$file")}"
  132. new_copyright="${new_copyright/"##VERSION##"/$VERSION}"
  133. new_copyright="$start $new_copyright$stop"
  134. # Build the time string
  135. time="${TIME/"##TIME##"/$(date)}"
  136. time="$start $time$stop"
  137. # Now write it. First we need to find where to put the copyright if there was not already one.
  138. if [ -z "$line_start" ]; then
  139. # If shebang exists, write on the line after the shebang. Shebang is always on the first line.
  140. if [ "$(head -c 2 $file)" = "#!" ]; then
  141. line_start=2
  142. # Otherwise, use the first line
  143. else
  144. line_start=1
  145. fi
  146. fi
  147. # Now build the new file
  148. head -n $((line_start - 1)) $file >temp 2>/dev/null # Original file up until the line where the copyright was (or is to be)
  149. # MacOS warns about 0 so pipe sdterr to null
  150. echo "$new_copyright" >>temp # Add copyright
  151. echo "$time" >>temp # Add timestamp
  152. echo >>temp # Add new line
  153. tail -n +$line_start $file >>temp # Lines after where the copyright was (or will be)
  154. mv temp "$file" # Replace the original file
  155. echo " --> Added copyright ✔️"
  156. else
  157. echo
  158. fi
  159. done
  160. if [[ "$CHECK_ONLY" == true ]]; then
  161. echo
  162. echo "Total found $num_wrong missing or incorrect copyrights"
  163. if [[ "$num_wrong" > 0 ]]; then
  164. exit 3
  165. fi
  166. fi
  167. exit 0
  168. }
  169. # Parse optional arguments
  170. while getopts "hci:" option; do
  171. case ${option} in
  172. h) #For option h
  173. help
  174. exit 0
  175. ;;
  176. c) #For option c
  177. CHECK_ONLY=true
  178. ;;
  179. i) #For option i
  180. INPUT=$OPTARG
  181. ;;
  182. \? | :)
  183. help
  184. exit 1
  185. ;;
  186. *)
  187. echo "Unexpected error occurred." >&2
  188. help
  189. exit 1
  190. ;;
  191. esac
  192. done
  193. # Jump to positional arguments
  194. shift $((OPTIND - 1))
  195. if [[ $# < 1 ]]; then
  196. echo "Missing VERSION parameter" >&2
  197. help
  198. exit 1
  199. fi
  200. VERSION=$1
  201. main