#!/usr/bin/env bash set -Eeuo pipefail function unapply_patches() { local -i exit_code=0 quiet quilt pop -af 2>&1 || exit_code=$? case $exit_code in # Sucessfully unapplied. 0) ;; # No more patches to unapply. 2) ;; # Some error. *) return $exit_code ;; esac } function apply_patches() { local -i exit_code=0 quiet quilt push -a 2>&1 || exit_code=$? case $exit_code in # Sucessfully applied. 0) ;; # No more patches to apply. 2) ;; # Some error. *) return $exit_code ;; esac } function update_vscode() { pushd lib/vscode if ! git checkout 2>&1 "$target_vscode_version" ; then echo "$target_vscode_version does not exist locally, fetching..." git fetch --all --prune --tags echo "Checking out $target_vscode_version again..." git checkout "$target_vscode_version" fi popd } function refresh_patches() { local -i exit_code=0 while quiet quilt push 2>&1 ; ! (( exit_code=$? )) ; do quilt refresh 2>&1 done case $exit_code in # No more patches to apply. 2) ;; # Some error. *) return $exit_code ;; esac } function update_node() { local node_version node_version=$(cat .node-version) local target_node_version target_node_version=$(grep target lib/vscode/remote/.npmrc | awk -F= '{print $2}' | tr -d '"') if [[ $node_version == "$target_node_version" ]] ; then echo "Already set to $target_node_version" else echo "Updating from $node_version to $target_node_version..." echo "$target_node_version" > .node-version fi } function get-webview-script-hash() { local html html=$(<"$1") local start_tag='" html=${html##*"$start_tag"} html=${html%%"$end_tag"*} echo -n "$html" | openssl sha256 -binary | openssl base64 } function delete_csp() { quilt delete csp-hashes.diff } function update_csp() { apply_patches local files=( ./lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html ./lib/vscode/src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html ) quilt new csp-hashes.diff local file for file in "${files[@]}" ; do quilt add "$file" local hash hash=$(get-webview-script-hash "$file") echo "Calculated hash as $hash" # Use octothorpe as a delimiter since the hash may contain a slash. sed -i.bak "s#'sha256-[^']\+'#'sha256-$hash'#" "$file" done quilt refresh } function add_changelog() { local file=CHANGELOG.md if grep --quiet "Code $target_vscode_version" "$file" ; then echo "Changelog for $target_vscode_version already exists" else # TODO: This is not exactly robust. In particular, it needs to handle if # there is already a "changed" section. sed -i.bak "s/## Unreleased/## Unreleased\n\nCode v$target_vscode_version\n\n### Changed\n\n- Update to Code $target_vscode_version/" "$file" fi } function main() { cd "$(dirname "${0}")/../.." source ./ci/lib.sh declare -a steps # Hashes are always regenerated to avoid having to resolve conflicts.. steps+=("Revert CSP hashes" "delete_csp") # If version is not set, assume we are already at the target version and the # user is just trying to resolve conflics. local target_vscode_version if [[ ${VERSION-} ]] ; then # Removing patches only needs to be done locally; in CI we start from a # fresh clone each time. if [[ ! ${CI-} ]] ; then steps+=("Unapplying patches" "unapply_patches") fi target_vscode_version="${VERSION#v}" steps+=( "Update Code to $target_vscode_version" "update_vscode" "Refresh Code patches" "refresh_patches" ) else target_vscode_version="$(git -C lib/vscode describe --tags --exact-match)" echo "Detected Code version $target_vscode_version" fi steps+=( "Update Node version" "update_node" "Regenerate CSP hashes" "update_csp" "Add changelog note" "add_changelog" ) # Even if a step failed, still output the last checkmark. run-steps "${steps[@]}" || true # This step is always manual. echo "- [ ] Verify changelog" >> .cache/checklist } main "$@"