summaryrefslogtreecommitdiff
path: root/hack/update-vendor-licenses.sh
blob: 42d16fcaee2a63f2e725ee60945b12ca06106a54 (about) (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
#!/usr/bin/env bash
# Copyright 2015 The Kubernetes Authors.
#
# 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.

# Update the LICENSES directory.
# Generates a table of Go dependencies and their licenses.
#
# Usage:
#    $0 [--create-missing] [/path/to/licenses]
#
#    --create-missing will write the files that only exist upstream, locally.
#    This option is mostly used for testing as we cannot check-in any of the
#    additionally created files into the vendor auto-generated tree.
#
#    Run every time a license file is added/modified within /vendor to
#    update /LICENSES
#
# -----------------------------------------------------------------------------
# CHANGELOG
# KubeEdge Authors:
# - File derived from kubernetes v1.19.0-beta.2
# - Changed KUBE_ROOT value to use absolute path


set -o errexit
set -o nounset
set -o pipefail

KUBE_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
source "${KUBE_ROOT}/hack/lib/init.sh"

export LANG=C
export LC_ALL=C

###############################################################################
# Process package content
#
# @param package  The incoming package name
# @param type     The type of content (LICENSE, COPYRIGHT or COPYING)
#
process_content () {
  local package=$1
  local type=$2

  local package_root
  local ensure_pattern
  local dir_root
  local find_maxdepth
  local find_names
  local -a local_files=()

  # Necessary to expand {}
  case ${type} in
      LICENSE) find_names=(-iname 'licen[sc]e*')
               find_maxdepth=1
               # Sadly inconsistent in the wild, but mostly license files
               # containing copyrights, but no readme/notice files containing
               # licenses (except to "see license file")
               ensure_pattern="license|copyright"
               ;;
    # We search READMEs for copyrights and this includes notice files as well
    # Look in as many places as we find files matching
    COPYRIGHT) find_names=(-iname 'notice*' -o -iname 'readme*')
               find_maxdepth=3
               ensure_pattern="copyright"
               ;;
      COPYING) find_names=(-iname 'copying*')
               find_maxdepth=1
               ensure_pattern="license|copyright"
               ;;
  esac

  # Start search at package root
  case ${package} in
    github.com/*|golang.org/*|bitbucket.org/*|gonum.org/*)
     package_root=$(echo "${package}" |awk -F/ '{ print $1"/"$2"/"$3 }')
     ;;
    go4.org/*)
     package_root=$(echo "${package}" |awk -F/ '{ print $1 }')
     ;;
    gopkg.in/*)
     # Root of gopkg.in package always ends with '.v(number)' and my contain
     # more than two path elements. For example:
     # - gopkg.in/yaml.v2
     # - gopkg.in/inf.v0
     # - gopkg.in/square/go-jose.v2
     package_root=$(echo "${package}" |grep -oh '.*\.v[0-9]')
     ;;
    */*)
     package_root=$(echo "${package}" |awk -F/ '{ print $1"/"$2 }')
     ;;
    *)
     package_root="${package}"
     ;;
  esac

  # Find files - only root and package level
  local_files=()
  IFS=" " read -r -a local_files <<< "$(
    for dir_root in ${package} ${package_root}; do
      [[ -d ${DEPS_DIR}/${dir_root} ]] || continue

      # One (set) of these is fine
      find "${DEPS_DIR}/${dir_root}" \
          -xdev -follow -maxdepth ${find_maxdepth} \
          -type f "${find_names[@]}"
    done | sort -u)"

  local index
  local f
  index="${package}-${type}"
  if [[ -z "${CONTENT[${index}]-}" ]]; then
    for f in "${local_files[@]-}"; do
      if [[ -z "$f" ]]; then
        # Set the default value and then check it to prevent
        # accessing potentially empty array
        continue
      fi
      # Find some copyright info in any file and break
      if grep -E -i -wq "${ensure_pattern}" "${f}"; then
        CONTENT[${index}]="${f}"
        break
      fi
    done
  fi
}


#############################################################################
# MAIN
#############################################################################

export GO111MODULE=on
export GOFLAGS=-mod=readonly

# Check bash version
if (( BASH_VERSINFO[0] < 4 )); then
  echo
  echo "ERROR: Bash v4+ required."
  # Extra help for OSX
  if [[ "$(uname -s)" == "Darwin" ]]; then
    echo
    echo "Ensure you are up to date on the following packages:"
    echo "$ brew install md5sha1sum bash jq"
  fi
  echo
  exit 9
fi

# This variable can be injected, as in the verify script.
LICENSE_ROOT="${LICENSE_ROOT:-${KUBE_ROOT}}"
cd "${LICENSE_ROOT}"

kube::util::ensure-temp-dir

# Save the generated LICENSE file for each package temporarily
TMP_LICENSE_FILE="${KUBE_TEMP}/LICENSES.$$"

# The directory to save all the LICENSE files
LICENSES_DIR="${LICENSES_DIR:-${LICENSE_ROOT}/LICENSES}"
mkdir -p "${LICENSES_DIR}"

# The tmp directory to save all the LICENSE files, will move to LICENSES_DIR
TMP_LICENSES_DIR="${KUBE_TEMP}/LICENSES.DIR.$$"
mkdir -p "${TMP_LICENSES_DIR}"

DEPS_DIR="vendor"
declare -Ag CONTENT

# Put the K8S LICENSE on top
if [ -f "${LICENSE_ROOT}/LICENSE" ]; then
  (
    echo "================================================================================"
    echo "= KubeEdge licensed under: ="
    echo
    cat "${LICENSE_ROOT}/LICENSE"
    echo
    echo "= LICENSE $(kube::util::md5 "${LICENSE_ROOT}/LICENSE")"
    echo "================================================================================"
  ) > "${TMP_LICENSE_FILE}"
  mv "${TMP_LICENSE_FILE}" "${TMP_LICENSES_DIR}/LICENSE"
fi

# Capture all module dependencies
modules=$(go list -m -json all | jq -r .Path | sort -f)
# Loop through every vendored package
for PACKAGE in ${modules}; do
  if [[ -e "staging/src/${PACKAGE}" ]]; then
    echo "${PACKAGE} is a staging package, skipping" >&2
    continue
  fi
  if [[ ! -e "${DEPS_DIR}/${PACKAGE}" ]]; then
    echo "${PACKAGE} doesn't exist in ${DEPS_DIR}, skipping" >&2
    continue
  fi
  # if there are no files vendored under this package...
  if [[ -z "$(find "${DEPS_DIR}/${PACKAGE}" -mindepth 1 -maxdepth 1 -type f)" ]]; then
    # and we have at least the same number of submodules as subdirectories...
    if [[ "$(find "${DEPS_DIR}/${PACKAGE}/" -mindepth 1 -maxdepth 1 -type d | wc -l)" -le "$(echo "${modules}" | grep -cE "^${PACKAGE}/")" ]]; then
      echo "Only submodules of ${PACKAGE} are vendored, skipping" >&2
      continue
    fi
  fi
  
  echo "${PACKAGE}"

  process_content "${PACKAGE}" LICENSE
  process_content "${PACKAGE}" COPYRIGHT
  process_content "${PACKAGE}" COPYING

  # copy content and throw error message
  {
    echo "= ${DEPS_DIR}/${PACKAGE} licensed under: ="
    echo

    file=""
    if [[ -n "${CONTENT[${PACKAGE}-LICENSE]-}" ]]; then
      file="${CONTENT[${PACKAGE}-LICENSE]-}"
    elif [[ -n "${CONTENT[${PACKAGE}-COPYRIGHT]-}" ]]; then
      file="${CONTENT[${PACKAGE}-COPYRIGHT]-}"
    elif [[ -n "${CONTENT[${PACKAGE}-COPYING]-}" ]]; then
      file="${CONTENT[${PACKAGE}-COPYING]-}"
    fi
    if [[ -z "${file}" ]]; then
      cat >&2 << __EOF__
No license could be found for ${PACKAGE} - aborting.

Options:
1. Check if the upstream repository has a newer version with LICENSE, COPYRIGHT and/or
   COPYING files.
2. Contact the author of the package to ensure there is a LICENSE, COPYRIGHT and/or
   COPYING file present.
3. Do not use this package in KubeEdge.
__EOF__
      exit 9
    fi

    cat "${file}"
    echo
    echo "= ${file} $(kube::util::md5 "${file}")"
  } >> "${TMP_LICENSE_FILE}"

  dest_dir="${TMP_LICENSES_DIR}/vendor/${PACKAGE}"
  mkdir -p "${dest_dir}"
  mv "${TMP_LICENSE_FILE}" "${dest_dir}/LICENSE"
done

# Leave things like OWNERS alone.
rm -f "${LICENSES_DIR}/LICENSE"
rm -rf "${LICENSES_DIR}/vendor"
mv "${TMP_LICENSES_DIR}"/* "${LICENSES_DIR}"