2022-05-23 23:31:49 +02:00
#!/usr/bin/env bash
set -e
2022-05-24 00:23:58 +02:00
function display_alert( ) {
echo " --> $* "
}
2022-06-14 14:03:42 +02:00
echo "::group::Read kernel.org versions"
# Read the current versions of kernel from kernel.org JSON releases. Again, thanks, kernel.org.
curl --silent "https://www.kernel.org/releases.json" > /tmp/kernel-releases.json
echo "Kernel releases versions from JSON:"
cat /tmp/kernel-releases.json | jq -r ".releases[].version"
2022-05-24 00:23:58 +02:00
2023-05-17 17:02:56 +02:00
declare -ag WANTED_KERNEL_VERSIONS_KERNEL_ORG
mapfile -t WANTED_KERNEL_VERSIONS_KERNEL_ORG < <( cat /tmp/kernel-releases.json | jq -r ".releases[].version" | grep -v -e "^next\-" | sed -e 's|-rc|.-rc|' | cut -d "." -f 1,2)
2022-05-23 23:31:49 +02:00
2023-05-17 17:02:56 +02:00
# Include some extra ones that Armbian uses in legacies etc
declare -ag WANTED_KERNEL_VERSIONS = ( " ${ WANTED_KERNEL_VERSIONS_KERNEL_ORG [@] } " "4.9" "4.4" )
2022-06-14 14:03:42 +02:00
# Show the array
display_alert "Wanted kernel versions:" " ${ WANTED_KERNEL_VERSIONS [@] } "
echo "::endgroup::"
2022-05-23 23:31:49 +02:00
2022-06-14 14:03:42 +02:00
echo "::group::Prepare basics"
2023-01-19 15:15:29 +01:00
ONLINE = " ${ ONLINE :- "yes" } "
EXPORT_SHALLOW_PER_VERSION = "yes"
EXPORT_COMPLETE = "yes" # note: The complete .tar is bigger than 2gb, and that does not fit into GH Releases 2gb limit for any single file. Use ORAS and ghcr.io.
2022-05-23 23:31:49 +02:00
BASE_WORK_DIR = " ${ BASE_WORK_DIR :- "/Volumes/LinuxDev/shallow_git_tree_work" } "
WORKDIR = " ${ BASE_WORK_DIR } /kernel "
SHALLOWED_TREES_DIR = " ${ WORKDIR } /shallow_trees "
2022-11-25 10:58:18 +01:00
COMPLETE_TREES_DIR = " ${ WORKDIR } /complete_trees "
2022-12-19 15:09:26 +01:00
OUTPUT_DIR_ORAS = " ${ WORKDIR } /output_oras "
2022-05-23 23:31:49 +02:00
KERNEL_GIT_TREE = " ${ WORKDIR } /worktree "
KERNEL_TORVALDS_BUNDLE_DIR = " ${ WORKDIR } /bundle-torvalds "
2023-01-19 15:15:29 +01:00
ALL_VERSIONS_FILE = " ${ OUTPUT_DIR_ORAS } /shallow_versions.txt "
mkdir -p " ${ BASE_WORK_DIR } " " ${ WORKDIR } " " ${ SHALLOWED_TREES_DIR } " " ${ COMPLETE_TREES_DIR } " " ${ KERNEL_GIT_TREE } " " ${ KERNEL_TORVALDS_BUNDLE_DIR } " " ${ OUTPUT_DIR_ORAS } "
2022-05-23 23:31:49 +02:00
2022-05-24 12:21:50 +02:00
GIT_TORVALDS_BUNDLE_URL = "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/clone.bundle" # Thanks, kernel.org!
GIT_TORVALDS_BUNDLE_ID = " $( echo -n " ${ GIT_TORVALDS_BUNDLE_URL } " | md5sum | awk '{print $1}' ) " # md5 of the URL.
GIT_TORVALDS_BUNDLE_FILE = " ${ KERNEL_TORVALDS_BUNDLE_DIR } / ${ GIT_TORVALDS_BUNDLE_ID } .gitbundle " # final filename of bundle
GIT_TORVALDS_BUNDLE_REMOTE_NAME = "torvalds-gitbundle" # name of the remote that will point to bundle
GIT_TORVALDS_LIVE_GIT_URL = "git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git" # Torvalds live tree git:// URL
GIT_TORVALDS_LIVE_REMOTE_NAME = "torvalds-live" # name of the remote that will point to live Torvalds tree
GIT_STABLE_LIVE_GIT_URL = "git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git" # Stable live tree git:// URL
GIT_STABLE_LIVE_REMOTE_NAME = "stable-live" # name of the remote that will point to live stable tree
2022-05-23 23:31:49 +02:00
# 1st stage Global:
# Init an empty git repo
if [ [ ! -d " ${ KERNEL_GIT_TREE } /.git " ] ] ; then
display_alert "Initting git tree"
git init --initial-branch= "armbian_unused_initial_branch" " ${ KERNEL_GIT_TREE } "
else
display_alert "Git tree already initted"
fi
2022-05-24 00:23:58 +02:00
echo "::endgroup::"
echo "::group::Fetching Torvalds bundle"
2022-05-23 23:31:49 +02:00
## From now on, everything is done inside the git worktree...
cd " ${ KERNEL_GIT_TREE } " || exit 2
if ! git config " remote. ${ GIT_TORVALDS_BUNDLE_REMOTE_NAME } .url " ; then
# Grab torvald's gitbundle via http from kernel.org
2022-05-24 00:23:58 +02:00
if [ [ ! -f " ${ GIT_TORVALDS_BUNDLE_FILE } " ] ] ; then # Download the bundle file if it does not exist.
display_alert "Downloading Git cold bundle via HTTP" " ${ GIT_TORVALDS_BUNDLE_URL } "
2022-05-24 12:21:50 +02:00
wget --continue --progress= dot:giga --output-document= " ${ GIT_TORVALDS_BUNDLE_FILE } " " ${ GIT_TORVALDS_BUNDLE_URL } "
2022-05-24 00:23:58 +02:00
else
display_alert "Cold bundle file exists, using it" " ${ GIT_TORVALDS_BUNDLE_FILE } " "git"
fi
2022-05-24 12:21:50 +02:00
# Fetch from Torvalds bundle (very slow) into 'torvalds-gitbundle' branch
2022-05-23 23:31:49 +02:00
display_alert "Fetching from cold git bundle, wait" " ${ GIT_TORVALDS_BUNDLE_ID } "
2022-05-24 00:23:58 +02:00
git bundle verify " ${ GIT_TORVALDS_BUNDLE_FILE } " # Make sure bundle is valid.
git remote add " ${ GIT_TORVALDS_BUNDLE_REMOTE_NAME } " " ${ GIT_TORVALDS_BUNDLE_FILE } " # Add the remote pointing to the cold bundle file
2024-08-21 17:21:24 +02:00
git fetch --progress --verbose " ${ GIT_TORVALDS_BUNDLE_REMOTE_NAME } " # Fetch it!
2022-05-23 23:31:49 +02:00
else
display_alert "Torvalds bundle already fetched..."
fi
# At this stage, we've all blobs, but no tags!
2022-05-24 00:23:58 +02:00
echo "::endgroup::"
2023-01-19 15:15:29 +01:00
echo "::group::Fetching Torvalds live"
2022-05-23 23:31:49 +02:00
# 2nd stage Global:
# Add torvalds live git as remote 'torvalds-live'
if ! git config " remote. ${ GIT_TORVALDS_LIVE_REMOTE_NAME } .url " ; then
display_alert "Adding torvalds live remote" " ${ GIT_TORVALDS_LIVE_REMOTE_NAME } "
git remote add " ${ GIT_TORVALDS_LIVE_REMOTE_NAME } " " ${ GIT_TORVALDS_LIVE_GIT_URL } "
else
display_alert "Torvalds live remote already exists..."
fi
# Fetch from it (to update), also bring in the tags. Around a 60mb download, quite fast.
2022-06-14 14:03:42 +02:00
if [ [ " ${ ONLINE } " = = "yes" ] ] ; then
display_alert "Fetching from torvalds live" " ${ GIT_TORVALDS_LIVE_REMOTE_NAME } "
2024-08-21 17:21:24 +02:00
git fetch --progress --verbose --tags " ${ GIT_TORVALDS_LIVE_REMOTE_NAME } " master # Fetch it! (including tags!)
2022-06-14 14:03:42 +02:00
# create a local branch from the fetched
display_alert "Creating local branch 'torvalds-master' from torvalds live" " ${ GIT_TORVALDS_LIVE_REMOTE_NAME } "
git branch --force "torvalds-master" FETCH_HEAD
fi
2022-05-24 00:23:58 +02:00
echo "::endgroup::"
2023-01-19 15:15:29 +01:00
echo "::group::Adding stable remote"
2022-05-23 23:31:49 +02:00
# Now, add the stable remote. Do NOT fetch from it, it's huge and has a lot more than we need.
if ! git config " remote. ${ GIT_STABLE_LIVE_REMOTE_NAME } .url " ; then
display_alert "Adding stable live remote" " ${ GIT_STABLE_LIVE_REMOTE_NAME } "
git remote add " ${ GIT_STABLE_LIVE_REMOTE_NAME } " " ${ GIT_STABLE_LIVE_GIT_URL } "
else
display_alert "Stable live remote already exists..."
fi
2023-01-19 15:15:29 +01:00
echo "::endgroup::"
2022-05-23 23:31:49 +02:00
# 3rd stage: For each version, eg: 5.17
# - Fetch from stable git source (not bundle) into `stable-5.17` branch
2022-05-24 12:21:50 +02:00
# - include tags
2022-05-23 23:31:49 +02:00
# - if this fails (eg: an unreleased kernel at that moment, tolerate and go ahead, torvalds should have -rc1)
WANTED_KERNEL_VERSIONS_COUNT = ${# WANTED_KERNEL_VERSIONS [@] }
display_alert " Wanted kernel versions: ${ WANTED_KERNEL_VERSIONS_COUNT } "
for KERNEL_VERSION in " ${ WANTED_KERNEL_VERSIONS [@] } " ; do
2022-05-24 00:23:58 +02:00
echo " ::group::Fetching stable remote for ${ KERNEL_VERSION } "
2022-05-23 23:31:49 +02:00
display_alert " Fetching stable kernel version: ${ KERNEL_VERSION } "
KERNEL_VERSION_LOCAL_BRANCH_NAME = " linux- ${ KERNEL_VERSION } .y "
KERNEL_VERSION_REMOTE_BRANCH_NAME = " linux- ${ KERNEL_VERSION } .y "
# Fetch the branch from the stable live into the local branch. Since I don't specify "--tags", it will only fetch the tags for the branch. Those DON'T include the -rc tags which came from torvalds live
2022-06-14 14:03:42 +02:00
if [ [ " ${ ONLINE } " = = "yes" ] ] ; then
declare -i STABLE_EXISTS = 0
git fetch --progress --verbose " ${ GIT_STABLE_LIVE_REMOTE_NAME } " " ${ KERNEL_VERSION_REMOTE_BRANCH_NAME } : ${ KERNEL_VERSION_LOCAL_BRANCH_NAME } " && STABLE_EXISTS = 1
if [ [ ${ STABLE_EXISTS } -eq 0 ] ] ; then
display_alert "Stable branch does not exist, copying torvalds-master to" " ${ KERNEL_VERSION_REMOTE_BRANCH_NAME } "
git branch --force " ${ KERNEL_VERSION_LOCAL_BRANCH_NAME } " "torvalds-master"
fi
fi
2022-05-24 00:23:58 +02:00
echo "::endgroup::"
2022-05-23 23:31:49 +02:00
done
# 4th stage: For each version, eg 5.17
2022-05-24 12:21:50 +02:00
# - Find the earliest tag with 5.17 in it
2022-05-23 23:31:49 +02:00
# - find the _date_ for such a tag
# - Export a shallow bundle via the date for that version;
2022-05-24 00:23:58 +02:00
# - include the shallow marker file (.git/shallow)
2022-11-25 10:58:18 +01:00
if [ [ " ${ EXPORT_SHALLOW_PER_VERSION } " = = "yes" ] ] ; then
2023-01-19 15:15:29 +01:00
echo " Writing file with all versions: ${ ALL_VERSIONS_FILE } "
echo " ${ WANTED_KERNEL_VERSIONS [@] } " > " ${ ALL_VERSIONS_FILE } "
2023-01-19 16:02:32 +01:00
2022-11-25 10:58:18 +01:00
for KERNEL_VERSION in " ${ WANTED_KERNEL_VERSIONS [@] } " ; do
echo " ::group::Exporting shallow for ${ KERNEL_VERSION } "
cd " ${ KERNEL_GIT_TREE } " || exit 2
KERNEL_VERSION_LOCAL_BRANCH_NAME = " linux- ${ KERNEL_VERSION } .y "
display_alert " Finding shallow point for version: ${ KERNEL_VERSION } " "on local branch" " ${ KERNEL_VERSION_LOCAL_BRANCH_NAME } "
# shit happens upstream too, so filter out "-dontuse" tags.
KERNEL_VERSION_FIRST_RC_TAG_NAME = " $( git tag -l | grep " ^v $( echo -n " ${ KERNEL_VERSION } " | sed -e 's/\./\\\./' ) -rc " | grep -v "\-dontuse" | sort -n | head -1) "
display_alert "Found first RC for version:" " ${ KERNEL_VERSION } " " ${ KERNEL_VERSION_FIRST_RC_TAG_NAME } "
# Now translate that tag into a date, which what we're gonna use to shallow the bundle.
# Attention: date has timezone part.
KERNEL_VERSION_SHALLOW_AT_DATE = " $( git tag --list --format= "%(creatordate)" " ${ KERNEL_VERSION_FIRST_RC_TAG_NAME } " ) "
display_alert "Date for first RC tag:" " ${ KERNEL_VERSION } " " ${ KERNEL_VERSION_FIRST_RC_TAG_NAME } " " ' ${ KERNEL_VERSION_SHALLOW_AT_DATE } ' "
# Clone from the worktree into a new directory, shallowing in the process. This is the only way to make it consistently shallow without jumping through hoops.
KERNEL_VERSION_SHALLOWED_WORKDIR = " ${ SHALLOWED_TREES_DIR } /shallow- ${ KERNEL_VERSION } - ${ KERNEL_VERSION_FIRST_RC_TAG_NAME } "
if [ [ ! -d " ${ KERNEL_VERSION_SHALLOWED_WORKDIR } " ] ] ; then
display_alert "Making shallow tree" " ${ KERNEL_VERSION_SHALLOWED_WORKDIR } "
2023-01-19 16:02:32 +01:00
# --progress --verbose -- too much output for github actions
git clone --no-checkout \
2022-11-25 10:58:18 +01:00
--single-branch --branch= " ${ KERNEL_VERSION_LOCAL_BRANCH_NAME } " \
--tags --shallow-since= " ${ KERNEL_VERSION_SHALLOW_AT_DATE } " \
" file:// ${ KERNEL_GIT_TREE } " " ${ KERNEL_VERSION_SHALLOWED_WORKDIR } "
else
display_alert "Shallow tree already exists" " ${ KERNEL_VERSION_SHALLOWED_WORKDIR } "
fi
2022-05-24 00:23:58 +02:00
2023-01-19 15:15:29 +01:00
OUTPUT_BUNDLE_FILE_NAME_TARBALL = " ${ OUTPUT_DIR_ORAS } /linux-shallow- ${ KERNEL_VERSION } .git.tar "
2022-05-23 23:31:49 +02:00
2022-11-25 10:58:18 +01:00
cd " ${ KERNEL_VERSION_SHALLOWED_WORKDIR } "
2023-01-19 15:15:29 +01:00
# Create a 'master' branch, which is the default branch name for git. Copy the shallowed branch.
git branch --force master " ${ KERNEL_VERSION_LOCAL_BRANCH_NAME } "
2022-11-25 10:58:18 +01:00
# Remove the origin remote, otherwise it would be exported due to "--all" below.
if git config "remote.origin.url" ; then
git remote rm origin
fi
2022-05-23 23:31:49 +02:00
2023-01-19 15:15:29 +01:00
# remove hooks, if dir exists
if [ [ -d " ${ KERNEL_VERSION_SHALLOWED_WORKDIR } /.git/hooks " ] ] ; then
rm -rf " ${ KERNEL_VERSION_SHALLOWED_WORKDIR } /.git/hooks "
fi
2022-05-23 23:31:49 +02:00
2023-01-19 15:15:29 +01:00
# list all tags in the shallow tree
echo -n " all tags ${ KERNEL_VERSION } : "
git -C " ${ KERNEL_VERSION_SHALLOWED_WORKDIR } " tag -l | cat | xargs echo -n || true
echo ""
2022-05-23 23:31:49 +02:00
2023-01-19 15:15:29 +01:00
# list all branches in the shallow tree
echo -n " all branches ${ KERNEL_VERSION } : "
git -C " ${ KERNEL_VERSION_SHALLOWED_WORKDIR } " branch -a | cat | xargs echo -n || true
echo ""
2022-05-23 23:31:49 +02:00
2023-01-19 15:15:29 +01:00
# export a .tar of .git. This is gonna be uploaded into ghcr.io via ORAS.
2022-11-25 10:58:18 +01:00
tar cf " ${ OUTPUT_BUNDLE_FILE_NAME_TARBALL } " .git
2022-05-23 23:31:49 +02:00
2022-11-25 10:58:18 +01:00
# List the outputs with sizes
2023-01-19 15:15:29 +01:00
ls -laht " ${ OUTPUT_DIR_ORAS } /linux-shallow- ${ KERNEL_VERSION } " .* || true
2022-05-23 23:31:49 +02:00
2022-11-25 10:58:18 +01:00
echo "::endgroup::"
done
fi
2022-05-24 00:23:58 +02:00
2022-11-25 10:58:18 +01:00
# 5th stage: export complete tree for the active versions, not shallow.
# Will be used for the separate-git+worktree version.
if [ [ " ${ EXPORT_COMPLETE } " = = "yes" ] ] ; then
echo "::group::Exporting complete tree for multiple worktree seeding"
2022-05-24 12:21:50 +02:00
2022-11-25 10:58:18 +01:00
KERNEL_VERSION_COMPLETE_WORKDIR = " ${ COMPLETE_TREES_DIR } /complete1 "
display_alert "Making complete tree" " ${ KERNEL_VERSION_COMPLETE_WORKDIR } "
2022-05-24 12:21:50 +02:00
2022-11-25 10:58:18 +01:00
if [ [ ! -d " ${ KERNEL_VERSION_COMPLETE_WORKDIR } " ] ] ; then
2022-12-19 15:09:26 +01:00
echo "Empty init..."
2022-11-25 10:58:18 +01:00
git init --initial-branch= "armbian_unused_first_branch" " ${ KERNEL_VERSION_COMPLETE_WORKDIR } "
fi
2022-11-25 11:44:07 +01:00
2022-11-25 10:58:18 +01:00
declare -a WANTED_BRANCHES = ( )
for KERNEL_VERSION in " ${ WANTED_KERNEL_VERSIONS [@] } " ; do
KERNEL_VERSION_LOCAL_BRANCH_NAME = " linux- ${ KERNEL_VERSION } .y "
WANTED_BRANCHES += ( " ${ KERNEL_VERSION_LOCAL_BRANCH_NAME } : ${ KERNEL_VERSION_LOCAL_BRANCH_NAME } " )
done
2022-12-19 17:24:03 +01:00
# Include a 'master' reference from torvalds-master; this way the produced export has the expected 'master' branch
WANTED_BRANCHES += ( "torvalds-master:master" )
2022-11-25 11:44:07 +01:00
2022-11-25 10:58:18 +01:00
# Do a single fetch against all the branches...
cd " ${ KERNEL_VERSION_COMPLETE_WORKDIR } " || exit 3
echo " adding branches ${ WANTED_BRANCHES [*] } ... "
2023-01-19 16:02:32 +01:00
# --progress --verbose -- too much output for github actions
git fetch " file:// ${ KERNEL_GIT_TREE } " " ${ WANTED_BRANCHES [@] } "
2022-11-25 11:44:07 +01:00
2022-11-25 10:58:18 +01:00
# list all tags in the complete tree
2023-01-19 15:15:29 +01:00
echo -n "all tags (complete): "
git -C " ${ KERNEL_VERSION_COMPLETE_WORKDIR } " tag -l | cat | xargs echo -n || true
echo ""
2022-11-25 11:44:07 +01:00
2022-11-25 10:58:18 +01:00
# list all branches in the complete tree
2023-01-19 15:15:29 +01:00
echo -n "all branches (complete):"
git -C " ${ KERNEL_VERSION_COMPLETE_WORKDIR } " branch -a | cat | xargs echo -n || true
echo ""
2022-11-25 11:44:07 +01:00
2022-12-19 15:09:26 +01:00
# remove hooks, if dir exists
if [ [ -d " ${ KERNEL_VERSION_COMPLETE_WORKDIR } /.git/hooks " ] ] ; then
rm -rf " ${ KERNEL_VERSION_COMPLETE_WORKDIR } /.git/hooks "
fi
2022-11-25 10:58:18 +01:00
# show du human total size of the complete tree
echo -n "total size:"
du -hsc " ${ KERNEL_VERSION_COMPLETE_WORKDIR } "
# export the complete tree
2022-12-19 15:09:26 +01:00
OUTPUT_BUNDLE_FILE_NAME_COMPLETE = " ${ OUTPUT_DIR_ORAS } /linux-complete.git.tar "
echo " Exporting .tar ${ OUTPUT_BUNDLE_FILE_NAME_COMPLETE } "
2022-11-25 10:58:18 +01:00
tar cf " ${ OUTPUT_BUNDLE_FILE_NAME_COMPLETE } " .git
2022-12-19 15:09:26 +01:00
ls -lah " ${ OUTPUT_BUNDLE_FILE_NAME_COMPLETE } "
2022-11-25 11:44:07 +01:00
2022-05-24 00:23:58 +02:00
echo "::endgroup::"
2022-11-25 10:58:18 +01:00
fi
2022-05-23 23:31:49 +02:00
# In GHA, cache the full git work tree, if it fits in GHA cache;
# If cache hit, skip 1st stage, but _always_ execute stages 2-4 (to update the cache)