Skip to content

Instantly share code, notes, and snippets.

@erodozer
Last active October 11, 2023 02:14
Show Gist options
  • Save erodozer/ca172bb3b8dbbea1abf5cb047062abca to your computer and use it in GitHub Desktop.
Save erodozer/ca172bb3b8dbbea1abf5cb047062abca to your computer and use it in GitHub Desktop.
Godot github package dependency helper script
#!/usr/bin/env bash
# godot-package helper
# @author Erodozer <[email protected]>
#
# Simple Bach Script that fetches and merges standard godot addon repositories from github
# to your project. You can use this instead of Godot's Asset Library if you wish to
# include dependencies in your projects while developing, but not include them in your git.
#
# Run this from the root directory of your project
#
# It parses a json file called godot_packages.json with the following schema
#
# [
# {
# # one of
# "github": "<user>/<repo>",
# "git": "<giturl>",
#
# # one of (branch with name main is used by default if none are set)
# "commit" ?: string, # pull by a specific commit hash, regardless of branch
# "branch" ?: string, # select the latest commit by branch name
# "tag" ?: string, # pull a specific tagged commit
#
# # specify specific folders to copy instead of dumping the whole repository
# "include" ?: [
# "<path>(?:<rename>)"
# ]
# },
# ...
# ]
#
# You may declare the same repository multiple times, as each pull is versioned by its point.
#
#
# Downloaded addons are merged into your project's addon's folder.
# If the addon as a LICENSE file in the root of the repo, it is copied to the addon's nested folder
# .gitignore files are also added to the nested folder.
#
#
# Requires:
# unzip
# jq
# wget (optional, only if using github references)
# git (optional, only if using git urls)
TMP_DIR=".godot-addon-tmp"
# create the dir tree for our work
mkdir -p $TMP_DIR
mkdir -p "$TMP_DIR/archives"
mkdir -p "$TMP_DIR/content"
echo "*" > "$TMP_DIR/.gitignore"
fetch_archive () {
row="$1"
# parse record
_jq() {
echo "${row}" | jq -r "${1}"
}
branch=$(_jq ".branch // \"main\"" )
tag=$(_jq '.tag // empty')
commit=$(_jq '.commit // empty')
if [ ! -z "$commit" ]; then
treeish=$commit
elif [ ! -z "$tag" ]; then
treeish=$tag
else
treeish=$branch
fi
# pull archive using git
if [ ! -z $(_jq '.git // empty') ]; then
git_remote=$(_jq '.git')
echo "fetching from git $git_remote"
repo=${git_remote##*/}
repo=${repo%.git}
echo $repo
outfile="$TMP_DIR/archives/$repo-$treeish.zip"
# pull archive if it does not exist in the cache
if [ ! -f "$outfile" ]; then
git archive --remote=$git_remote -o $outfile $treeish
fi
# fetch archive from github (wget)
elif [ ! -z $(_jq '.github // empty') ]; then
github=$(_jq '.github')
user=$(echo "$github" | cut -d "/" -f 1)
repo=$(echo "$github" | cut -d "/" -f 2)
outfile="$(echo "$github" | tr "/" _)-$treeish"
if [ ! -z "$tag" ]; then
remote_url="https://github.com/$user/$repo/archive/refs/tags/$tag.zip"
elif [ ! -z "$commit" ]; then
remote_url="https://github.com/$user/$repo/archive/$commit.zip"
else
remote_url="https://github.com/$user/$repo/archive/refs/heads/$branch.zip"
fi
outfile="$TMP_DIR/archives/$outfile.zip"
if [ ! -f "$outfile" ]; then
wget -O $outfile $remote_url
fi
else
exit 1 "git or github must be declared"
fi
# extract the archive to a random folder to avoid collisions
dst_folder="$TMP_DIR/content/$RANDOM"
unzip $outfile -d $dst_folder
# overlap archive contents on addons folder
include=$(_jq '.include // empty')
mv_archive "$dst_folder/$repo-$treeish" "$include"
}
mv_archive() {
package_folder="$1"
include="$2"
echo "Including: $include"
# extract only the included directories
# useful for monorepos of multiple addons
if [ ! -z "$include" ]; then
echo "$include" | jq -cr ".[]" | while read d; do
src_folder=$(echo "$d" | cut -d ">" -f 1)
dst_folder=$(echo "$d" | cut -d ">" -f 2)
echo "copying $package_folder/addons/$src_folder to ./addons/$dst_folder"
rm -r "./addons/$dst_folder"
mv "$package_folder/addons/$src_folder" "./addons/$dst_folder"
echo "*" > "./addons/$dst_folder/.gitignore"
done;
else
addons_folder="$package_folder/addons"
for dir in $(ls -d $addons_folder/*); do
echo "*" > "$dir/.gitignore"
if [ ! -f "$dir/LICENSE" ]; then
cp "$package_folder/LICENSE" "$dir/LICENSE"
fi
if [ ! -f "$dir/README.md" ]; then
cp "$package_folder/README.md" "$dir/README.md"
fi
done
cp -r "$addons_folder" "."
fi
}
# fetch archives in parallel
for row in $(jq -c '.[]' godot_packages.json); do
fetch_archive $row &
done
wait
# remove expanded archive folders, keeping the cache
rm -r $TMP_DIR/content
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment