#!/bin/sh
# Copyright (C) 2011, 2016 Canonical, Ltd.
# Author: Marc Deslauriers <marc.deslauriers@canonical.com>
# Author: Steve Beattie <steve.beattie@canonical.com>
# License: GPLv3

set -e

help() {
    cat <<EOM
Usage: add-derived-kernel -r <release> -d <derived_release> [-D <derived_kernel>] kernel_name

  -r    release (ex: xenial) (REQUIRED)
  -d    derived kernel release (ex: yakkety) (REQUIRED)
  -D    kernel derived from (if different from linux) (OPTIONAL)

kernel_name: suffix of the kernel to be added and trcaked (e.g. "lts-wily")

All arguments are required.

examples:

to create linux-lts-vivid for the trusty release:

  add-derived-kernel -r trusty -d vivid lts-vivid

to create linux-aws for xenial based on the xenial kernel:

  add-derived-kernel -r xenial -d xenial aws

to create linux-oem for xenial based on the xenial linux-hwe-edge kernel:

  add-derived-kernel -r xenial -d xenial -D linux-hwe-edge oem

if you want all the cves for the kernel to stay in the needs-triage
state, pass a non-existent kernel version as release to derive from (-d)
argument; e.g.:

  add-derived-kernel -r focal -d norelease oem-5.14

EOM
}

RELEASE=
DERIVED_RELEASE=
DERIVED_KERNEL=

while getopts "hr:d:D:" opt ; do
    case "$opt" in
        r) RELEASE="$OPTARG";;
        d) DERIVED_RELEASE="$OPTARG";;
        D) DERIVED_KERNEL="${OPTARG}";;
        h) help ; exit 0;;
        ?) help;;
    esac
done

shift $((OPTIND - 1))
KERNEL="$1"

if [ -z "${RELEASE}" ] || [ -z "${DERIVED_RELEASE}" ] || [ -z "${KERNEL}" ] ; then
    help
    exit 1
fi

if [ -z "${DERIVED_KERNEL}" ] ; then
    DERIVED_KERNEL="linux"
fi

chunk=$(mktemp -t add-derived-kernel-XXXXXX)

echo "" > "$chunk"
grep "^.*_linux:" active/00boilerplate.linux | sed -e "s#_linux:.*#_linux-${KERNEL}: DNE#" >> "$chunk"
sed -i -e "s#^${RELEASE}_linux-${KERNEL}:.*#${RELEASE}_linux-${KERNEL}: needs-triage#" "$chunk"
sed -i -e "s#^Patches_linux-${KERNEL}:.*#Patches_linux-${KERNEL}:#" "$chunk"
sed -i -e "s#^upstream_linux-${KERNEL}:.*#upstream_linux-${KERNEL}: needs-triage#" "$chunk"

if ! grep -q "^${RELEASE}_linux-${KERNEL}:" active/00boilerplate.linux ; then
    echo "Updating 00boilerplate.linux..."
    cat "$chunk" >> active/00boilerplate.linux
else
    echo "00boilerplate.linux already contains linux-${KERNEL}, skipping update."
fi

echo "Adding new backport to existing CVEs..."
grep "^${RELEASE}_linux:" active/CVE* | cut -d: -f1 | sort -u | while read -r cve_file ; do
    if ! grep -q "^${RELEASE}_linux-${KERNEL}:" "$cve_file" ; then
        cat "$chunk" >> "$cve_file"
    else
        echo "$cve_file already contains linux-${KERNEL}, skipping update."
    fi
done

rm -f "$chunk"

echo "Updating status of existing CVEs..."
for i in $(cd active && grep "^${DERIVED_RELEASE}_${DERIVED_KERNEL}: " CVE* | cut -d" " -f2 | sort -u | grep -v released); do
	(cd active && grep -l "^${DERIVED_RELEASE}_${DERIVED_KERNEL}: $i" CVE* | sort -u | xargs grep  -l "${RELEASE}_linux-${KERNEL}: \(DNE\|needs-triage\)" )  | \
	xargs --no-run-if-empty ./scripts/mass-cve-edit -p "linux-${KERNEL}" -r "${RELEASE}" -s "$i"
done

echo "Updating status of released CVEs (ok if empty and prints help)..."
(cd active && grep -l "^${DERIVED_RELEASE}_${DERIVED_KERNEL}: released" CVE* | sort -u | \
  xargs grep  --files-without-match "${RELEASE}_linux-${KERNEL}: not-affected" ) | \
 xargs --no-run-if-empty  ./scripts/mass-cve-edit -p "linux-${KERNEL}" -r "${RELEASE}" -s not-affected

printf "\n\nPlease update cve_lib.py, kernel_lib.py, sis-generate-usn, cve-alert.sh, and prepare-kernel-usn.py in scripts/\n"
echo "Please add package description information if necessary to meta_lists/package_info_overrides.json"
echo "If this kernel has not been published yet, please add it to the unpublished_kernels list in check-syntax."
echo "Also, before publishing a USN against the new kernel, ensure packages_mirror has been run"
