generated from Exiles/coa-template
Initial commit
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
* -text
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
name: release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- '*-coa.*' # Asc-1.1.6-coa.2, 9.1.40-coa.3, etc.
|
||||||
|
- 'v*' # v0.3.0 for repos without an upstream version
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
runs-on: linux-amd64
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0 # build_zip uses git archive HEAD; full history is fine
|
||||||
|
|
||||||
|
- name: Build per-addon zip(s)
|
||||||
|
run: bash tools/build_zip.sh
|
||||||
|
|
||||||
|
- name: Publish release (Gitea API direct; no action dependency)
|
||||||
|
env:
|
||||||
|
GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
REPO: ${{ github.repository }}
|
||||||
|
TAG: ${{ github.ref_name }}
|
||||||
|
API: ${{ github.server_url }}/api/v1
|
||||||
|
# Gitea attachment ceiling is 200 MiB (see roles/gitea config).
|
||||||
|
# Skip anything larger so one oversized asset doesn't fail the job.
|
||||||
|
MAX_BYTES: 209715200
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
# Create the release (or reuse if it already exists for this tag).
|
||||||
|
RID=$(curl -s -H "Authorization: token $GITEA_TOKEN" \
|
||||||
|
"$API/repos/$REPO/releases/tags/$TAG" 2>/dev/null \
|
||||||
|
| jq -r '.id // empty')
|
||||||
|
if [ -z "$RID" ]; then
|
||||||
|
RID=$(curl -sf -X POST -H "Authorization: token $GITEA_TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
"$API/repos/$REPO/releases" \
|
||||||
|
-d "$(jq -nc --arg t "$TAG" '{tag_name:$t,name:$t,draft:false,prerelease:false}')" \
|
||||||
|
| jq -r '.id')
|
||||||
|
fi
|
||||||
|
echo "release id: $RID"
|
||||||
|
# Upload every dist/*.zip. Per-asset failures don't fail the job —
|
||||||
|
# we want partial releases to still publish rather than block the
|
||||||
|
# whole pipeline on one big file.
|
||||||
|
failed=0
|
||||||
|
uploaded=0
|
||||||
|
for f in dist/*.zip; do
|
||||||
|
name=$(basename "$f")
|
||||||
|
size=$(stat -c '%s' "$f")
|
||||||
|
if [ "$size" -gt "$MAX_BYTES" ]; then
|
||||||
|
echo "::warning::skip $name (${size} B > ${MAX_BYTES} B Gitea limit; host on CDN instead)"
|
||||||
|
failed=$((failed+1))
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
echo "uploading $name ($(numfmt --to=iec "$size"))"
|
||||||
|
if curl -sf -X POST -H "Authorization: token $GITEA_TOKEN" \
|
||||||
|
-F "attachment=@$f" \
|
||||||
|
"$API/repos/$REPO/releases/$RID/assets?name=$name" \
|
||||||
|
| jq -r '" -> " + .browser_download_url'; then
|
||||||
|
uploaded=$((uploaded+1))
|
||||||
|
else
|
||||||
|
echo "::warning::upload failed for $name"
|
||||||
|
failed=$((failed+1))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo "release published: $uploaded uploaded, $failed skipped/failed"
|
||||||
|
# Only fail the job if NO assets uploaded — a release with zero
|
||||||
|
# attachments isn't useful to anyone.
|
||||||
|
[ "$uploaded" -gt 0 ]
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
.env
|
||||||
|
.DS_Store
|
||||||
|
.release
|
||||||
|
.install
|
||||||
|
.lua/*
|
||||||
|
.vscode
|
||||||
|
.idea
|
||||||
|
dist/
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
Copyright (C) 2026 by Exiles
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
+116
@@ -0,0 +1,116 @@
|
|||||||
|
# Porting addons to CoA / Project Ascension 3.3.5
|
||||||
|
|
||||||
|
The CoA Beta client is WoW 3.3.5 with a heavily reworked FrameXML /
|
||||||
|
SharedXML / StaticPopup / Settings system, 21 custom playable classes,
|
||||||
|
and selectively-modern globals (`C_Timer.After`, `C_ClassInfo`). Most
|
||||||
|
upstream retail / Classic / Wrath addons need a small bundle of fixes.
|
||||||
|
This document lists every recurring failure mode we've seen across the
|
||||||
|
existing 25 Exiles forks plus the matching one-paragraph fix.
|
||||||
|
|
||||||
|
Keep this file in your fork until you're done porting; once everything
|
||||||
|
loads cleanly you can leave it as documentation or delete it.
|
||||||
|
|
||||||
|
The canonical / live version of this checklist is at
|
||||||
|
[coa.exil.es/coa/dev/addons](https://coa.exil.es/coa/dev/addons) — if
|
||||||
|
you discover a new failure mode while porting, please add it there.
|
||||||
|
|
||||||
|
## Bug-pattern checklist
|
||||||
|
|
||||||
|
### Retail-only globals are nil
|
||||||
|
`InterfaceOptionsFrame*`, `InterfaceOptions_AddCategory`,
|
||||||
|
`InterfaceOptionsFramePanelContainer`, `Settings.*`, `Enum.ClassMask`
|
||||||
|
(only knows vanilla classes), retail `C_TooltipInfo`. Guard with
|
||||||
|
`if X then … end` or fall back to a sensible default (`UIParent` for
|
||||||
|
parent-frame fallbacks).
|
||||||
|
|
||||||
|
### FileDataIDs silently no-op
|
||||||
|
`Set*Texture(<integer>)` does nothing on 3.3.5 — textures render as red
|
||||||
|
placeholders. Use string paths. The comment next to an FDID call in
|
||||||
|
upstream code usually already names the path.
|
||||||
|
|
||||||
|
### Hardcoded class lists miss CoA's 21 custom classes
|
||||||
|
`SHAMAN/HERO` masks, `CLASS_SORT_ORDER` iteration, `RAID_CLASS_COLORS`
|
||||||
|
direct keys, `CLASS_ICON_TCOORDS`. Witchdoctor / Templar / Sun Cleric /
|
||||||
|
Primalist / Tinker / etc. won't appear. Extend via `GetNumClasses()`,
|
||||||
|
`LOCALIZED_CLASS_NAMES_MALE` fallback, or a class-keyed `or { … }`
|
||||||
|
guard.
|
||||||
|
|
||||||
|
### `C_ClassInfo.GetSpecInfo(class, spec)` arg mismatch
|
||||||
|
`GetAllSpecs(class)` returns non-string items on this client. Always
|
||||||
|
`pcall` the `GetSpecInfo` / `GetSpecInfoByID` call and skip iterations
|
||||||
|
that fail.
|
||||||
|
|
||||||
|
### `StaticPopup_Show` during `PLAYER_LOGIN` silently fails
|
||||||
|
Fires too early on this client. Defer with `C_Timer.After(0, …)`.
|
||||||
|
Failure mode is silent — the popup never appears and any code that
|
||||||
|
depends on user confirmation (e.g. WeakAuras' downgrade-repair flow)
|
||||||
|
never runs.
|
||||||
|
|
||||||
|
### `.tga` textures don't load
|
||||||
|
The engine only loads `.blp`. Ship BLP2 / DXT3 (`alphaEncoding = 1`) —
|
||||||
|
DXT5 (`ae=7`) does NOT decode on 3.3.5. Conversion:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
blp-conv --blp-version blp2 --blp-format dxt3 --alpha-bits 8 in.png out.blp
|
||||||
|
```
|
||||||
|
|
||||||
|
### `Minimap:SetMaskTexture("Interface\\BUTTONS\\WHITE8X8")` silently rounds
|
||||||
|
The shared white mask used by retail SexyMap-style addons falls back to
|
||||||
|
the round minimap on CoA. Bundle an opaque BLP and point the mask at it
|
||||||
|
instead.
|
||||||
|
|
||||||
|
### `UnitClass("player")` at file-load time returns nil
|
||||||
|
Resolve class inside `OnEnable` / event handler, not as a file-level
|
||||||
|
`local`.
|
||||||
|
|
||||||
|
### CLEU argument positions changed
|
||||||
|
Verify against the 3.3.5 signature:
|
||||||
|
|
||||||
|
```
|
||||||
|
(event, timestamp, subevent, hideCaster,
|
||||||
|
srcGUID, srcName, srcFlags, srcRaidFlags,
|
||||||
|
destGUID, destName, destFlags, destRaidFlags,
|
||||||
|
spellId, spellName, spellSchool, …)
|
||||||
|
```
|
||||||
|
|
||||||
|
`destFlags` is arg 11, not arg 9. Many retail-era addons get this
|
||||||
|
wrong.
|
||||||
|
|
||||||
|
## Ace3 specifics
|
||||||
|
|
||||||
|
If the addon embeds Ace3 libs (`Libs/AceXxx-3.0/`), use the canonical
|
||||||
|
`Exiles/coa-ace3` bundle to overwrite them. The sweep script in that
|
||||||
|
repo handles every fork in one pass — see its README. Don't ship a
|
||||||
|
bespoke Ace3 vendor; mismatched MINOR versions across loaded addons
|
||||||
|
cause silent breakage at LibStub resolution time.
|
||||||
|
|
||||||
|
`coa-elvui` is the one exception — ElvUI ships its own customized
|
||||||
|
Ace3 stack and is excluded from the sweep.
|
||||||
|
|
||||||
|
## Standard layout
|
||||||
|
|
||||||
|
The Exiles fork-layout convention is `<repo>/<AddonFolder>/<AddonFolder>.toc`
|
||||||
|
at depth-1, with dev tooling (`tools/`, `.gitea/`, `README.md`, `LICENSE`,
|
||||||
|
`PORTING.md`) at the repo root. Multi-addon repos place each addon in its
|
||||||
|
own sibling folder.
|
||||||
|
|
||||||
|
`tools/build_zip.sh` discovers these `<Folder>/<Folder>.toc` pairs
|
||||||
|
automatically.
|
||||||
|
|
||||||
|
## Tagging convention
|
||||||
|
|
||||||
|
`<upstream>-coa.N` per repo. Examples:
|
||||||
|
|
||||||
|
| Repo | Tag |
|
||||||
|
|---|---|
|
||||||
|
| `coa-decursive` | `Asc-1.1.6-coa.1` |
|
||||||
|
| `coa-leatrix-plus` | `3.3.5-coa.1` |
|
||||||
|
| `coa-ace3` | `52e5f2c-coa.1` (upstream commit pin) |
|
||||||
|
| `coa-dbm` | `2026.05.25-coa.1` (no `## Version:` line; date-based) |
|
||||||
|
|
||||||
|
The trailing `-coa.N` counter bumps for each CoA-fork iteration. Pushing
|
||||||
|
the tag fires the release workflow and publishes the per-addon zips to
|
||||||
|
`https://git.sub-net.at/Exiles/<repo>/releases/tag/<tag>`.
|
||||||
|
|
||||||
|
See [coa.exil.es/coa/dev/releases](https://coa.exil.es/coa/dev/releases)
|
||||||
|
for the full release pipeline doc.
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
# coa-template
|
||||||
|
|
||||||
|
Template repo for new `Exiles/coa-*` addon forks. Click **Use This
|
||||||
|
Template** on the Gitea page to start a fresh repo with the canonical
|
||||||
|
release pipeline, layout convention, and CoA porting checklist
|
||||||
|
pre-wired.
|
||||||
|
|
||||||
|
## What you get
|
||||||
|
|
||||||
|
```
|
||||||
|
.
|
||||||
|
├── .gitea/workflows/release.yml # tag-triggered release pipeline
|
||||||
|
├── tools/
|
||||||
|
│ ├── build_zip.sh # git-archive per addon folder
|
||||||
|
│ └── init_from_upstream.sh # one-shot upstream import helper
|
||||||
|
├── .gitattributes # * -text (preserve upstream EOLs)
|
||||||
|
├── .gitignore # standard 7-line + dist/
|
||||||
|
├── LICENSE # 0BSD
|
||||||
|
├── PORTING.md # CoA-compat bug-pattern checklist
|
||||||
|
└── README.md # this file
|
||||||
|
```
|
||||||
|
|
||||||
|
## Quick start (backporting an existing addon)
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# 1. Use this template to create Exiles/coa-myaddon, then:
|
||||||
|
git clone gitea@git.sub-net.at:Exiles/coa-myaddon.git
|
||||||
|
cd coa-myaddon
|
||||||
|
|
||||||
|
# 2. Pull the upstream source into MyAddon/ at the repo root.
|
||||||
|
tools/init_from_upstream.sh \
|
||||||
|
https://github.com/Ascension-Addons/MyAddon \
|
||||||
|
MyAddon
|
||||||
|
|
||||||
|
# 3. Make it run on CoA. Read PORTING.md — every recurring failure mode
|
||||||
|
# we've seen across the existing 25 Exiles forks is documented there
|
||||||
|
# with the matching fix.
|
||||||
|
|
||||||
|
# 4. Verify the build works.
|
||||||
|
bash tools/build_zip.sh
|
||||||
|
unzip -l dist/MyAddon.zip | head -5 # first entry: MyAddon/
|
||||||
|
|
||||||
|
# 5. Push your fork.
|
||||||
|
git push origin master
|
||||||
|
|
||||||
|
# 6. Tag the first release. Read MyAddon/MyAddon.toc for the upstream
|
||||||
|
# version, then:
|
||||||
|
git tag -a 1.2.3-coa.1 -m "first Exiles release"
|
||||||
|
git push origin 1.2.3-coa.1
|
||||||
|
|
||||||
|
# The runner picks it up within seconds and publishes
|
||||||
|
# https://git.sub-net.at/Exiles/coa-myaddon/releases/tag/1.2.3-coa.1
|
||||||
|
```
|
||||||
|
|
||||||
|
## Layout convention
|
||||||
|
|
||||||
|
Every addon source folder sits at the repo root with the same name as
|
||||||
|
its `.toc`:
|
||||||
|
|
||||||
|
```
|
||||||
|
coa-myaddon/
|
||||||
|
├── MyAddon/
|
||||||
|
│ ├── MyAddon.toc
|
||||||
|
│ └── ...
|
||||||
|
└── (dev tooling at root)
|
||||||
|
```
|
||||||
|
|
||||||
|
Multi-addon repos (DBM, Altoholic, Atlasloot, …) place each addon as a
|
||||||
|
sibling folder at the repo root. `tools/build_zip.sh` discovers them all
|
||||||
|
and emits one zip per addon plus a combined `coa-myaddon-all.zip`.
|
||||||
|
|
||||||
|
## Release pipeline
|
||||||
|
|
||||||
|
The workflow in `.gitea/workflows/release.yml` triggers on tags matching
|
||||||
|
`*-coa.*` or `v*`. It checks out, runs `tools/build_zip.sh`, and uploads
|
||||||
|
each `dist/*.zip` as a Gitea release attachment via plain `curl` — no
|
||||||
|
external action dependency, no org-level secret. Per-asset upload
|
||||||
|
failures are tolerated (the job still publishes whatever uploaded);
|
||||||
|
oversized assets (>200 MiB) get a `::warning` and skip.
|
||||||
|
|
||||||
|
Runner: `gitea-runner01.corp.sub-net.at` (host executor, label
|
||||||
|
`linux-amd64`). Configured by the `gitea_runner` Ansible role.
|
||||||
|
|
||||||
|
Full docs: [coa.exil.es/coa/dev/releases](https://coa.exil.es/coa/dev/releases).
|
||||||
|
|
||||||
|
## Maintenance
|
||||||
|
|
||||||
|
This template is updated by hand when the canonical files in
|
||||||
|
`Exiles/coa-decursive` (the pilot) change. To re-sync the canonical
|
||||||
|
release pipeline from the pilot:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cp /path/to/coa-decursive/tools/build_zip.sh tools/build_zip.sh
|
||||||
|
cp /path/to/coa-decursive/.gitea/workflows/release.yml .gitea/workflows/release.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
The PORTING.md checklist is the lean snapshot of
|
||||||
|
[coa.exil.es/coa/dev/addons](https://coa.exil.es/coa/dev/addons) — when
|
||||||
|
you discover a new CoA failure mode, add it to the Tome page first, then
|
||||||
|
re-snapshot here.
|
||||||
Executable
+71
@@ -0,0 +1,71 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Build per-addon zip artefacts from HEAD via git-archive.
|
||||||
|
#
|
||||||
|
# - Discovers top-level addon folders (Foo/Foo.toc).
|
||||||
|
# - Re-creates dist/ each run.
|
||||||
|
# - Always archives HEAD, so the working tree state is irrelevant.
|
||||||
|
# - If more than one addon folder is present, also emits <repo>-all.zip
|
||||||
|
# with every addon folder side-by-side at the zip root.
|
||||||
|
# - When run inside Gitea Actions the working tree lives under a
|
||||||
|
# per-job dir like /var/lib/act_runner/work/.../hostexecutor, so the
|
||||||
|
# repo name comes from $GITHUB_REPOSITORY (set by the runner) and
|
||||||
|
# only falls back to the toplevel basename for local invocations.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
root=$(git rev-parse --show-toplevel)
|
||||||
|
cd "$root"
|
||||||
|
|
||||||
|
# Gitea Actions sets GITHUB_REPOSITORY=owner/repo. The basename of
|
||||||
|
# `git rev-parse --show-toplevel` inside the runner is the worker dir
|
||||||
|
# (e.g. `hostexecutor`), which would name the bundle wrong.
|
||||||
|
if [ -n "${GITHUB_REPOSITORY:-}" ]; then
|
||||||
|
repo_name="${GITHUB_REPOSITORY##*/}"
|
||||||
|
else
|
||||||
|
repo_name=$(basename "$root")
|
||||||
|
fi
|
||||||
|
dist="$root/dist"
|
||||||
|
|
||||||
|
# Find Foo/Foo.toc pairs at depth 1; ignore libs nested deeper.
|
||||||
|
addons=()
|
||||||
|
while IFS= read -r toc; do
|
||||||
|
dir=$(dirname "$toc")
|
||||||
|
folder=$(basename "$dir")
|
||||||
|
base=$(basename "$toc" .toc)
|
||||||
|
# Accept Foo.toc and Foo_Wrath.toc style flavour variants; folder must match
|
||||||
|
# at least one toc basename prefix (Foo).
|
||||||
|
case "$base" in
|
||||||
|
"$folder"|"$folder"_*) addons+=("$folder") ;;
|
||||||
|
esac
|
||||||
|
done < <(command find . -mindepth 2 -maxdepth 2 -type f -name '*.toc' | sed 's|^\./||' | sort)
|
||||||
|
|
||||||
|
# Dedupe (a folder with Foo.toc + Foo_Wrath.toc shows up twice).
|
||||||
|
if [ ${#addons[@]} -gt 0 ]; then
|
||||||
|
mapfile -t addons < <(printf '%s\n' "${addons[@]}" | awk '!seen[$0]++')
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ${#addons[@]} -eq 0 ]; then
|
||||||
|
echo "no addon folders found (looking for */Foo.toc with matching folder name)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rf "$dist"
|
||||||
|
mkdir -p "$dist"
|
||||||
|
|
||||||
|
for folder in "${addons[@]}"; do
|
||||||
|
out="$dist/$folder.zip"
|
||||||
|
# No --prefix: the folder already sits at the repo root, so git-archive
|
||||||
|
# emits entries as <folder>/... which is exactly what
|
||||||
|
# Interface/AddOns/ expects after extraction.
|
||||||
|
git archive HEAD --format=zip -o "$out" -- "$folder"
|
||||||
|
echo "built dist/$folder.zip"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Combined bundle only makes sense when there are multiple addons.
|
||||||
|
if [ ${#addons[@]} -gt 1 ]; then
|
||||||
|
tmp=$(mktemp -d)
|
||||||
|
trap 'rm -rf "$tmp"' EXIT
|
||||||
|
git archive HEAD --format=tar -- "${addons[@]}" | tar -x -C "$tmp"
|
||||||
|
out="$dist/$repo_name-all.zip"
|
||||||
|
( cd "$tmp" && zip -qr "$out" "${addons[@]}" )
|
||||||
|
echo "built dist/$repo_name-all.zip"
|
||||||
|
fi
|
||||||
Executable
+99
@@ -0,0 +1,99 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# init_from_upstream.sh — bootstrap a new Exiles addon fork from upstream.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# tools/init_from_upstream.sh <upstream-url> <AddonFolderName> [upstream-branch]
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
# tools/init_from_upstream.sh https://github.com/Ascension-Addons/CallToArms CallToArms
|
||||||
|
#
|
||||||
|
# What it does:
|
||||||
|
# 1. Adds `upstream` remote and fetches it.
|
||||||
|
# 2. Squash-imports the upstream tree at the named branch (default master/main)
|
||||||
|
# into <AddonFolderName>/ at the repo root.
|
||||||
|
# 3. Leaves you with a single staged commit you review and finalise.
|
||||||
|
#
|
||||||
|
# What it does NOT do:
|
||||||
|
# - Push anything.
|
||||||
|
# - Tag anything.
|
||||||
|
# - Modify the upstream history (it's a squash import, not a merge).
|
||||||
|
#
|
||||||
|
# After running, verify with:
|
||||||
|
# bash tools/build_zip.sh
|
||||||
|
# unzip -l dist/<AddonFolderName>.zip | head -5
|
||||||
|
# then `git commit --amend` if you want to edit the message, push,
|
||||||
|
# and tag <upstream-version>-coa.1 to trigger the first release.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [ "$#" -lt 2 ] || [ "$#" -gt 3 ]; then
|
||||||
|
echo "usage: $0 <upstream-url> <AddonFolderName> [upstream-branch]" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
upstream_url=$1
|
||||||
|
folder=$2
|
||||||
|
branch=${3:-}
|
||||||
|
|
||||||
|
if [ -d "$folder" ]; then
|
||||||
|
echo "refusing to overwrite existing folder $folder/" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! git remote get-url upstream >/dev/null 2>&1; then
|
||||||
|
git remote add upstream "$upstream_url"
|
||||||
|
else
|
||||||
|
git remote set-url upstream "$upstream_url"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "==> fetching upstream"
|
||||||
|
git fetch --tags upstream
|
||||||
|
|
||||||
|
if [ -z "$branch" ]; then
|
||||||
|
# Try master, then main.
|
||||||
|
if git rev-parse --verify "upstream/master" >/dev/null 2>&1; then
|
||||||
|
branch=master
|
||||||
|
elif git rev-parse --verify "upstream/main" >/dev/null 2>&1; then
|
||||||
|
branch=main
|
||||||
|
else
|
||||||
|
echo "couldn't find upstream/master or upstream/main; pass branch explicitly" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "==> importing tree from upstream/$branch into $folder/"
|
||||||
|
|
||||||
|
# Extract upstream tree into a temporary worktree-like dir, then move into folder.
|
||||||
|
tmp=$(mktemp -d)
|
||||||
|
trap 'rm -rf "$tmp"' EXIT
|
||||||
|
git archive "upstream/$branch" | tar -x -C "$tmp"
|
||||||
|
mkdir -p "$folder"
|
||||||
|
# rsync preserves dotfiles; --exclude keeps obvious noise out.
|
||||||
|
rsync -a --exclude '.git/' --exclude '.github/' --exclude '.gitea/' \
|
||||||
|
--exclude '.idea/' --exclude '.vscode/' --exclude '.DS_Store' \
|
||||||
|
"$tmp"/ "$folder"/
|
||||||
|
|
||||||
|
git add "$folder"
|
||||||
|
upstream_sha=$(git rev-parse "upstream/$branch")
|
||||||
|
upstream_short=$(git rev-parse --short "upstream/$branch")
|
||||||
|
git commit -m "Import $folder from upstream@$upstream_short
|
||||||
|
|
||||||
|
upstream: $upstream_url
|
||||||
|
branch: $branch
|
||||||
|
commit: $upstream_sha"
|
||||||
|
|
||||||
|
cat <<EOF
|
||||||
|
|
||||||
|
==> done. next steps:
|
||||||
|
1. bash tools/build_zip.sh
|
||||||
|
2. unzip -l dist/$folder.zip | head -5
|
||||||
|
(expect first entry: $folder/)
|
||||||
|
3. git push origin master
|
||||||
|
4. Read $folder/$folder.toc — look for the version string.
|
||||||
|
Tag with <upstream-version>-coa.1, e.g.:
|
||||||
|
git tag -a 1.2.3-coa.1 -m "first Exiles release"
|
||||||
|
git push origin 1.2.3-coa.1
|
||||||
|
The release workflow picks it up and publishes
|
||||||
|
https://git.sub-net.at/Exiles/<this-repo>/releases/tag/<tag>.
|
||||||
|
|
||||||
|
The upstream remote stays configured so future rebases / re-imports
|
||||||
|
are one-line: \`git fetch upstream && ...\`.
|
||||||
|
EOF
|
||||||
Reference in New Issue
Block a user