#!/bin/bash #============================================================================== #title : notices_fix.sh #description : Using go.sum file generates third-party notices for the project #author : Vikas Bhansali (vibhansa@microsoft.com) #date : 02-Oct-2021 #usage : sh notices_fix.sh #============================================================================== # File to hold dependency list from go.sum file dependency_list="./dependencies.lst" output_file="./NOTICE" # Function to create header for notices file function dump_header { # Dump static header to NOTICE file echo "--------------------- START OF THIRD PARTY NOTICE ----------------------------- NOTICES AND INFORMATION Do Not Translate or Localize This software incorporates material from third parties. Microsoft makes certain open source code available at https://3rdpartysource.microsoft.com, or you may send a check or money order for US $5.00, including the product name, the open source component name, and version number, to: Source Code Compliance Team Microsoft Corporation One Microsoft Way Redmond, WA 98052 USA Notwithstanding any other terms, you may reverse engineer this software to the extent required to debug changes to any libraries licensed under the GNU Lesser General Public License. Third Party Programs: The software may include third party programs that Microsoft, not the third party, licenses to you under this agreement. Notices, if any, for the third party programs are included for your information only. --------------------------------------------------------------------------------------- " > $output_file } function dump_footer { echo -ne "--------------------- END OF THIRD PARTY NOTICE --------------------------------\n" >> $output_file } function append_lic_to_notice { echo >> $output_file echo -e "\n\n" >> $output_file echo "****************************************************************************" >> $output_file echo -e "\n============================================================================" >> $output_file echo -e ">>>" $1 >> $output_file echo -e "==============================================================================" >> $output_file echo >> $output_file cat lic.tmp >> $output_file rm -rf lic.tmp } # Function to download the file and add it to Notice file with formatting function download_and_dump { #echo "Downloading lic for $1 from $2" # Cleanup old tmp file rm -rf lic.tmp # Fetch the raw license file wget -q -O lic.tmp $2 if [[ $? -eq 0 ]] then append_lic_to_notice $1 return 0 fi return -1 } function try_differ_names() { # Try lic file without any extension download_and_dump $1 $2 if [[ $? -ne 0 ]] then # Try with .txt extension download_and_dump $line $lic_path.txt fi if [[ $? -ne 0 ]] then # Try with .md extension download_and_dump $line $lic_path.md fi return $? } function download_notice { line=$1 case $line in *go-autorest/*) # There are multiple entries with this for each of its subfolder so download only once if [[ $autorest_done -eq 0 ]] then lic_path="https://raw.githubusercontent.com/Azure/go-autorest/master/LICENSE" download_and_dump "github.com/Azure/go-autorest/autorest" $lic_path if [[ $? -ne 0 ]] then # This might need manual intervention echo "Failed to get LICENSE from : AutoRest" else autorest_done=1 fi fi echo -ne "." ;; github.com*) # Try standard lic path first to get the info with 'master' branch lic_path="https://raw.githubusercontent.com/"`echo $line | cut -d "/" --complement -f1`"/master/LICENSE" try_differ_names $line $lic_path # If basic name fails try removing subfolders and search outside if [[ $? -ne 0 ]] then lic_path="https://raw.githubusercontent.com/"`echo $line | cut -d "/" -f2-3`"/master/LICENSE" try_differ_names $line $lic_path fi # Try searching if there is main branch instead of master if [[ $? -ne 0 ]] then lic_path="https://raw.githubusercontent.com/"`echo $line | cut -d "/" --complement -f1`"/main/LICENSE" try_differ_names $line $lic_path fi # If basic name fails try removing subfolders and search outside for main branch if [[ $? -ne 0 ]] then lic_path="https://raw.githubusercontent.com/"`echo $line | cut -d "/" -f2-3`"/main/LICENSE" try_differ_names $line $lic_path fi # Some have COPYING file for license if [[ $? -ne 0 ]] then lic_path="https://raw.githubusercontent.com/"`echo $line | cut -d "/" --complement -f1`"/master/COPYING" download_and_dump $line $lic_path fi # Camel case name search in master branch if [[ $? -ne 0 ]] then lic_path="https://raw.githubusercontent.com/"`echo $line | cut -d "/" -f2-3`"/master/License" try_differ_names $line $lic_path fi # Camel case name search in main branch if [[ $? -ne 0 ]] then lic_path="https://raw.githubusercontent.com/"`echo $line | cut -d "/" -f2-3`"/main/License" try_differ_names $line $lic_path fi if [[ $? -ne 0 ]] then # This might need manual intervention echo "Failed to get LICENSE from : $line" fi echo -ne "." ;; *etcd.io/etcd*) # There are multiple entries with this for each of its subfolder so download only once if [[ $etcd_done -eq 0 ]] then lic_path="https://raw.githubusercontent.com/etcd-io/etcd/main/LICENSE" download_and_dump "go.etcd.io/etcd" $lic_path if [[ $? -ne 0 ]] then # This might need manual intervention echo "Failed to get LICENSE from : etcd.id" else etcd_done=1 fi fi echo -ne "." ;; *golang.org/x* | *rsc.io/* | *cloud.google.com/* | *google.golang.org/* | *go.uber.org/* | *go.opencensus.io* | *go.opentelemetry.io/*) #echo ">>> " $line # Get the contents of this package wget -q -O lic.tmp "https://pkg.go.dev/$line?tab=licenses" if [[ $? -ne 0 ]] then # This might need manual intervention echo "Failed to get LICENSE from : $line" else # This will be html output so filter only license content sed -n '/License-contents/,/\/pre\>/p' lic.tmp > lic1.tmp head -1 lic1.tmp | grep "Copyright" | cut -d ">" -f 2 > lic.tmp sed '1d;$d' lic1.tmp >> lic.tmp # now dump it to our notice file append_lic_to_notice $line fi echo -ne "." ;; *gopkg.in/ini.v1*) wget -q -O lic.tmp "https://raw.githubusercontent.com/go-ini/ini/v1.63.2/LICENSE" if [[ $? -ne 0 ]] then # This might need manual intervention echo "Failed to get LICENSE from : $line" else append_lic_to_notice $line fi echo -ne "." ;; *gopkg.in/*) #https://raw.githubusercontent.com/go-yaml/yaml/v3/LICENSE pkg=`echo $line | cut -d "/" -f 2 | cut -d "." -f 1` ver=`echo $line | cut -d "/" -f 2 | cut -d "." -f 2` wget -q -O lic.tmp "https://raw.githubusercontent.com/go-$pkg/$pkg/$ver/LICENSE" if [[ $? -ne 0 ]] then # This might need manual intervention echo "Failed to get LICENSE from : $line" else append_lic_to_notice $line fi echo -ne "." ;; *dmitri.shuralyov.com*) #dmitri.shuralyov.com/gpu/mtl # Get the contents of this package wget -q -O lic.tmp "https://$line\$file/LICENSE" if [[ $? -ne 0 ]] then # This might need manual intervention echo "Failed to get LICENSE from : $line" else append_lic_to_notice $line fi echo -ne "." ;; *honnef.co/go/tools*) # Get the contents of this package wget -q -O lic.tmp "https://raw.githubusercontent.com/dominikh/go-tools/master/LICENSE" if [[ $? -ne 0 ]] then # This might need manual intervention echo "Failed to get LICENSE from : $line" else append_lic_to_notice $line fi echo -ne "." ;; *) echo "Others: " $line;; esac } function generate_notices { ret=0 while IFS= read -r line; do case $line in *go-autorest/*) if grep -q ">>> github.com/Azure/go-autorest/autorest" $output_file then echo -ne "." else #echo "Missing $line in old file" download_notice $line ret=1 fi echo -ne "." ;; *etcd.io/etcd*) if grep -q ">>> go.etcd.io/etcd" $output_file then echo -ne "." else #echo "Missing $line in old file" download_notice $line ret=1 fi echo -ne "." ;; *) if grep -q ">>> $line" $output_file then echo -ne "." else #echo "Missing $line in old file" download_notice $line ret=1 fi echo -ne "." ;; esac done < $dependency_list return $ret } # Create temp directory for working on this rm -rf ./notice_tmp mkdir ./notice_tmp/ chmod 777 ./notice_tmp/ cd ./notice_tmp/ # From go.sum file create unique list of dependencies we have echo "Searching for dependencies" cat ../go.sum | cut -d " " -f 1 | sort -u > $dependency_list echo "Populating Notices" # Check if notice.txt file exists or not if [ -e ../$output_file ] then # file is already there so copy that to temp folder # Ignore the file footer while making this copy echo "File exists check for new dependencies only" head -n -1 ../$output_file > $output_file else # Main code to call the respective methods echo "File does not exists, start from scratch" dump_header fi # Generate notices in a temp file now generate_notices # Generate footer for the file if [[ $? -ne 0 ]] then # File is modified make space for fotter echo -e "\n" >> $output_file fi dump_footer echo "Comparing missing dependencies" # Compare the input list and notice file for final consolidation grep ">>>" $output_file | cut -d " " -f 2 > notice.lst diff $dependency_list notice.lst | grep -v "go-autorest" | grep -v "go.etcd.io" # Delete the temp directory cp $output_file ../NOTICE cd - rm -rf ./notice_tmp/ echo "NOTICE updated..."