From e5eca30d2119003c025d4e05a9ea792d5ec778a6 Mon Sep 17 00:00:00 2001 From: Ward Vandewege Date: Sun, 14 Jun 2020 21:55:50 -0400 Subject: [PATCH] Replace check-copyright-headers.sh with check-copyright-headers.sh. Rename coding-standards.sh to coding-standards.rb, it was already a Ruby script. All git hooks are now Ruby. Fix bugs in check-copyright-headers: no longer print a 'fatal' error when a branch is first pushed. No longer skip checking of new files in some circumstances (git `commit` object instead of `blob` object). No issue # Arvados-DCO-1.1-Signed-off-by: Ward Vandewege --- git/hooks/check-copyright-headers.rb | 113 ++++++++++++++++++ git/hooks/check-copyright-headers.sh | 69 ----------- ...oding-standards.sh => coding-standards.rb} | 5 +- git/hooks/enforce-dco-signoff.rb | 9 +- 4 files changed, 125 insertions(+), 71 deletions(-) create mode 100755 git/hooks/check-copyright-headers.rb delete mode 100755 git/hooks/check-copyright-headers.sh rename git/hooks/{coding-standards.sh => coding-standards.rb} (97%) diff --git a/git/hooks/check-copyright-headers.rb b/git/hooks/check-copyright-headers.rb new file mode 100755 index 0000000..b235270 --- /dev/null +++ b/git/hooks/check-copyright-headers.rb @@ -0,0 +1,113 @@ +#!/usr/bin/env ruby + +# Copyright (C) The Arvados Authors. All rights reserved. +# +# SPDX-License-Identifier: AGPL-3.0 + +# This script can be installed as a git update hook. + +# It can also be installed as a gitolite 'hooklet' in the +# hooks/common/update.secondary.d/ directory. + +# NOTE: this script runs under the same assumptions as the 'update' hook, so +# the starting directory must be maintained and arguments must be passed on. + +$refname = ARGV[0] +$oldrev = ARGV[1] +$newrev = ARGV[2] +$user = ENV['USER'] + +puts "Enforcing copyright headers..." +puts "(#{$refname}) (#{$oldrev[0,6]}) (#{$newrev[0,6]})" + +def load_licenseignore + $licenseignore = `git show #{$newrev}:.licenseignore`.split("\n") +end + +def check_file(filename, header, broken) + ignore = false + $licenseignore.each do |li| + if filename =~ /#{li}/ + ignore = true + end + end + return broken if ignore + + if header !~ /SPDX-License-Identifier:/ + if not broken + puts "\nERROR\n" + end + puts "missing or invalid copyright header in file #{filename}" + broken = true + end + return broken +end + +# enforce copyright headers +def check_copyright_headers + if ($newrev[0,6] == '000000') + # A branch is being deleted. Do not check old commits for DCO signoff! + all_revs = [] + elsif ($oldrev[0,6] == '000000') + if $refname != 'refs/heads/master' + # A new branch was pushed. Check all new commits in this branch. + puts "git rev-list --objects master..#{$newrev} | git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)'| sed -n 's/^blob //p'" + blob_revs = `git rev-list --objects master..#{$newrev} | git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)'| sed -n 's/^blob //p'`.split("\n") + commit_revs = `git rev-list --objects master..#{$newrev} | git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)'| sed -n 's/^commit //p'`.split("\n") + all_revs = blob_revs + commit_revs + else + # When does this happen? + puts "UNEXPECTED ERROR" + exit 1 + end + else + blob_revs = `git rev-list --objects #{$oldrev}..#{$newrev} --not --branches='*' | git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)'| sed -n 's/^blob //p'`.split("\n") + commit_revs = `git rev-list --objects #{$oldrev}..#{$newrev} | git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)'| sed -n 's/^commit //p'`.split("\n") + all_revs = blob_revs + commit_revs + end + + broken = false + + all_revs.each do |rev| + ignore = false + tmp = rev.split(' ') + if tmp[2].nil? + # git object of type 'commit' + # This could be a new file that was added in this commit + # If this wasn't a bare repo, we could run the following to get the list of new files in this commit: + # new_files = `git show #{tmp[0]} --name-only --diff-filter=A --pretty=""`.split("\n") + # Instead, we just look at all the files touched in the commit and check the diff to see + # see if it is a new file. This could prove brittle... + files = `git show #{tmp[0]} --name-only --pretty=""`.split("\n") + files.each do |f| + filename = f + commit = `git show #{tmp[0]} -- #{f}` + if commit =~ /^new file mode \d{6}\nindex 000000/ + /^.*?@@\n(.*)$/m.match(commit) + header = `echo "#{$1}" | head -n20 | egrep -A3 -B1 'Copyright.*All rights reserved.'` + broken = check_file(filename, header, broken) + end + end + else + # git object of type 'blob' + filename = tmp[2] + header = `git show #{tmp[0]} | head -n20 | egrep -A3 -B1 'Copyright.*All rights reserved.'` + broken = check_file(filename, header, broken) + end + end + + if broken + puts + puts "[POLICY] all files must contain copyright headers, for more information see" + puts + puts "  https://arvados.org/projects/arvados/wiki/Coding_Standards#Copyright-headers" + puts + puts "Enforcing copyright headers: FAIL" + exit 1 + + end + puts "Enforcing copyright headers: PASS" +end + +load_licenseignore +check_copyright_headers diff --git a/git/hooks/check-copyright-headers.sh b/git/hooks/check-copyright-headers.sh deleted file mode 100755 index 53dde73..0000000 --- a/git/hooks/check-copyright-headers.sh +++ /dev/null @@ -1,69 +0,0 @@ -#!/bin/bash -# Copyright (C) The Arvados Authors. All rights reserved. -# -# SPDX-License-Identifier: AGPL-3.0 - -# This script is intended to be run as a git update hook. It ensures that all -# commits adhere to the copyright header convention for the Arvados project, -# which is documented at -# -# https://dev.arvados.org/projects/arvados/wiki/Coding_Standards#Copyright-headers - -REFNAME=$1 -OLDREV=$2 -NEWREV=$3 - -EXITCODE=0 - -echo "Enforcing copyright headers..." - -# Load the .licenseignore file -LICENSEIGNORE=`mktemp` -git show ${NEWREV}:.licenseignore > "${LICENSEIGNORE}" 2>/dev/null -if [[ "$?" != "0" ]]; then - # e.g., .licenseignore does not exist - ignores=() -else - IFS=$'\n' read -a ignores -r -d $'\000' < "$LICENSEIGNORE" || true -fi -rm -f $LICENSEIGNORE - -oldIFS="$IFS" -IFS=$'\n' -for rev in $(git rev-list --objects $OLDREV..$NEWREV --not --branches='*' | git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)'| sed -n 's/^blob //p'); do - - IFS="$oldIFS" read -r -a array <<<"$rev" - sha=${array[0]} - fnm=${array[2]} - - # Make sure to skip files that match patterns in .licenseignore - ignore= - for pattern in "${ignores[@]}"; do - if [[ ${fnm} == ${pattern} ]]; then - ignore=1 - fi - done - if [[ ${ignore} = 1 ]]; then continue; fi - - HEADER=`git show ${sha} | head -n20 | egrep -A3 -B1 'Copyright.*All rights reserved.'` - - if [[ ! "$HEADER" =~ "SPDX-License-Identifier:" ]]; then - if [[ "$EXITCODE" == "0" ]]; then - echo - echo "ERROR" - echo - fi - echo "missing or invalid copyright header in file ${fnm}" - EXITCODE=1 - fi -done -IFS="$oldIFS" - -if [[ "$EXITCODE" != "0" ]]; then - echo - echo "[POLICY] all files must contain copyright headers, for more information see" - echo - echo "  https://dev.arvados.org/projects/arvados/wiki/Coding_Standards#Copyright-headers" - echo - exit $EXITCODE -fi diff --git a/git/hooks/coding-standards.sh b/git/hooks/coding-standards.rb similarity index 97% rename from git/hooks/coding-standards.sh rename to git/hooks/coding-standards.rb index d74c705..4097d1a 100755 --- a/git/hooks/coding-standards.sh +++ b/git/hooks/coding-standards.rb @@ -48,7 +48,8 @@ blacklist ['26d74dc0524c87c5dcc0c76040ce413a4848b57a'] # Only enforce policy on the master branch exit 0 if $refname != 'refs/heads/master' -puts "Enforcing Policies... \n(#{$refname}) (#{$oldrev[0,6]}) (#{$newrev[0,6]})" +puts "Enforcing Policies..." +puts "(#{$refname}) (#{$oldrev[0,6]}) (#{$newrev[0,6]})" $regex = /\[ref: (\d+)\]/ @@ -139,8 +140,10 @@ def check_message_format end if broken + puts "Enforcing Policies: FAIL" exit 1 end + puts "Enforcing Policies: PASS" end check_message_format diff --git a/git/hooks/enforce-dco-signoff.rb b/git/hooks/enforce-dco-signoff.rb index ab93401..191a34b 100755 --- a/git/hooks/enforce-dco-signoff.rb +++ b/git/hooks/enforce-dco-signoff.rb @@ -1,5 +1,9 @@ #!/usr/bin/env ruby +# Copyright (C) The Arvados Authors. All rights reserved. +# +# SPDX-License-Identifier: AGPL-3.0 + # This script can be installed as a git update hook. # It can also be installed as a gitolite 'hooklet' in the @@ -13,7 +17,8 @@ $oldrev = ARGV[1] $newrev = ARGV[2] $user = ENV['USER'] -puts "Enforcing DCO signoff: (#{$refname}) (#{$oldrev[0,6]}) (#{$newrev[0,6]})" +puts "Enforcing DCO signoff..." +puts "(#{$refname}) (#{$oldrev[0,6]}) (#{$newrev[0,6]})" $regex = /\[ref: (\d+)\]/ @@ -57,8 +62,10 @@ def check_message_format end if broken + puts "Enforcing DCO signoff: FAIL" exit 1 end + puts "Enforcing DCO signoff: PASS" end check_message_format -- 2.30.2