diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml deleted file mode 100644 index 2f93975..0000000 --- a/.gitea/workflows/release.yml +++ /dev/null @@ -1,75 +0,0 @@ -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,hide_archive_links:true}')" \ - | jq -r '.id') - fi - echo "release id: $RID" - # Gitea honors hide_archive_links only on edit, not create — PATCH it - # so the auto-generated Source Code (zip/tar.gz) links stay hidden. - curl -sf -X PATCH -H "Authorization: token $GITEA_TOKEN" -H "Content-Type: application/json" \ - "$API/repos/$REPO/releases/$RID" -d '{"hide_archive_links":true}' >/dev/null || true - # 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 ] diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..2ac83fa --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,14 @@ +# These are supported funding model platforms + +github: [NoM0Re] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry +custom: https://streamelements.com/nom0ree/tip + diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..0665220 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,123 @@ +name: "Bug Report" +description: Create a report to help us improve +labels: ['🐛 Bug'] +body: +- type: checkboxes + attributes: + label: Is there an existing issue for this? + description: Please [search for existing issues](https://github.com/Ascension-Addons/WeakAuras-Ascension/issues) to see if an open or closed one already exists for the bug you encountered. If a bug exists and it is closed as complete it may not yet be in a stable release. + options: + - label: I have searched the existing open and closed issues. + required: true + +- type: textarea + attributes: + label: Description + description: What did you expect to happen and what happened instead? + validations: + required: true + +- type: input + attributes: + label: WeakAuras Version + description: | + You can see the current version in the title bar of the options window, if the options do not open, check the `## Version:` field in the WeakAuras.toc file. + placeholder: "WeakAuras 5.0.0" + validations: + required: true + +- type: dropdown + id: flavor + attributes: + label: World of Warcraft Flavor + description: What version of World of Warcraft are are you running? + options: + - WotLK 3.3.5a + validations: + required: true + +- type: dropdown + id: language + attributes: + label: World of Warcraft Language + description: In which language do you play World of Warcraft? + options: + - enGB/enUS + - deDE + - frFR + - itIT + - esES + - esMX + - koKR + - ptBR + - ruRU + - zhCN + - zhTW + validations: + required: true + +- type: input + id: server + attributes: + label: Server + description: On which server/realm are you playing? + placeholder: Warmane-Icecrown + validations: + required: true + +- type: checkboxes + id: testing + attributes: + label: Tested with only WeakAuras + description: Sometimes, other addons can interfere with WeakAuras. We recommend testing with only WeakAuras enabled to see if the issue persists. + options: + - label: I got this issue with only WeakAuras enabled + required: true + +- type: textarea + attributes: + label: Lua Error + description: | + Do you have an error log of what happened? If you don't see any errors, make sure that error reporting is enabled (`/console scriptErrors 1`) or install [BugSack](https://www.curseforge.com/wow/addons/bugsack) & [BugGrabber](https://www.curseforge.com/wow/addons/bug-grabber), yes both are needed. + Note that if the error looks like `[string "--[[ Error in ' my awesome aura' ]` then the bug is in the aura that got mentioned, not in WeakAuras itself. + render: Text + validations: + required: false + +- type: textarea + attributes: + label: Reproduction Steps + description: Please list out the steps to reproduce your bug. Please verify that your reproduction steps are enough to reproduce the problem. + placeholder: | + 1. Go to '...' + 2. Click on '....' + 3. Scroll down to '....' + 4. See error + validations: + required: true + +- type: input + attributes: + label: Last Good Version + description: | + Was it working in a previous version? If yes, which was the last good one? + placeholder: "WeakAuras 5.0.0" + validations: + required: false + +- type: textarea + attributes: + label: Screenshots + description: If applicable, add screenshots to help explain your problem. + placeholder: Click here to attach your screenshots via the editor button in the top right. + validations: + required: false + +- type: textarea + attributes: + label: Export String + description: If you do not know which aura is causing issues for you, please attach a ZIP archive of your WeakAuras SavedVariables file, it's the `WeakAuras.lua` file in `World of Warcraft\_retail_\WTF\Account\YOUR_ACCOUNT\SavedVariables\`. In case you do, please export the string and paste it below. + placeholder: Paste your exported WeakAuras string here. + render: Text + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..6498af8 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: Question + url: https://discord.gg/classlesswow + about: Please ask and answer questions here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..5e0fb3a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: "\U0001F3A8 Feature Request" +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/workflows/autoclose.yaml b/.github/workflows/autoclose.yaml new file mode 100644 index 0000000..5dc7272 --- /dev/null +++ b/.github/workflows/autoclose.yaml @@ -0,0 +1,115 @@ +name: Autoclose after 2 days + +on: + schedule: + - cron: '0 0 * * *' + issues: + types: [labeled] + pull_request: + types: [labeled] + +permissions: + issues: write + pull-requests: write + +jobs: + autoclose: + runs-on: ubuntu-latest + steps: + - name: Close Issues/PRs labeled 'Auto Close' after 2 days, if label set by collaborator and no recent comments + uses: actions/github-script@v7 + with: + script: | + const { owner, repo } = context.repo; + const labelName = '⏳Auto Close'; + const maxAgeDays = 2; + const now = new Date(); + + const issues = await github.paginate(github.rest.issues.listForRepo, { + owner, + repo, + labels: labelName, + state: 'open', + per_page: 100, + }); + + for (const issue of issues) { + const issue_number = issue.number; + + const events = await github.paginate(github.rest.issues.listEventsForTimeline, { + owner, + repo, + issue_number, + per_page: 100, + }); + + const labelEvent = events.find(event => + event.event === 'labeled' && + event.label?.name === labelName + ); + + if (!labelEvent) continue; + + let labelDate = new Date(labelEvent.created_at); + + const comments = await github.paginate( + issue.pull_request + ? github.rest.pulls.listReviewComments + : github.rest.issues.listComments, + { + owner, + repo, + issue_number, + per_page: 100, + } + ); + + const recentCommentsAfterLabel = comments + .filter(c => new Date(c.created_at) > labelDate); + + let latestDate = labelDate; + if (recentCommentsAfterLabel.length > 0) { + latestDate = new Date(Math.max(...recentCommentsAfterLabel.map(c => new Date(c.created_at).getTime()))); + } + + const diffDays = (now - latestDate) / (1000 * 60 * 60 * 24); + + if (diffDays < maxAgeDays) continue; + + const actor = labelEvent.actor?.login; + if (!actor) continue; + + try { + await github.rest.repos.checkCollaborator({ + owner, + repo, + username: actor, + }); + } catch (error) { + if (error.status === 404) { + await github.rest.issues.removeLabel({ + owner, + repo, + issue_number, + name: labelName, + }); + continue; + } else { + throw error; + } + } + + await github.rest.issues.update({ + owner, + repo, + issue_number, + state: 'closed', + }); + + await github.rest.issues.removeLabel({ + owner, + repo, + issue_number, + name: labelName, + }); + } diff --git a/.github/workflows/lint-pr.yml b/.github/workflows/lint-pr.yml new file mode 100644 index 0000000..af43ec7 --- /dev/null +++ b/.github/workflows/lint-pr.yml @@ -0,0 +1,62 @@ +name: lint + +on: + pull_request: + paths: + - '**.lua' + +jobs: + lint: + runs-on: ubuntu-latest + + env: + LUA_VERSION: 5.1.5 + LUAROCKS_VERSION: 3.11.1 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Cache Lua + uses: actions/cache@v3 + id: luacache + with: + path: .lua + key: ${{ runner.os }}-lua-${{ env.LUA_VERSION }} + restore-keys: | + ${{ runner.os }}-lua-${{ env.LUA_VERSION }} + + - name: Cache LuaRocks + uses: actions/cache@v3 + id: luarockscache + with: + path: .luarocks + key: ${{ runner.os }}-luarocks-${{ env.LUAROCKS_VERSION }} + restore-keys: | + ${{ runner.os }}-luarocks-${{ env.LUAROCKS_VERSION }} + + - name: Install Lua + if: steps.luacache.outputs.cache-hit != 'true' + run: | + sudo apt-get install libreadline-dev libncurses-dev + wget https://www.lua.org/ftp/lua-${{ env.LUA_VERSION }}.tar.gz -O - | tar -xzf - + cd lua-${{ env.LUA_VERSION }} + make linux + make -j INSTALL_TOP=$GITHUB_WORKSPACE/.lua install + rm -rf $GITHUB_WORKSPACE/lua-${{ env.LUA_VERSION }} + + - name: Install LuaRocks and Luacheck + if: steps.luarockscache.outputs.cache-hit != 'true' + run: | + wget https://luarocks.org/releases/luarocks-${{ env.LUAROCKS_VERSION }}.tar.gz -O - | tar -xzf - + cd luarocks-${{ env.LUAROCKS_VERSION }} + ./configure --with-lua-bin=$GITHUB_WORKSPACE/.lua/bin --prefix=$GITHUB_WORKSPACE/.luarocks + make build + make install + PATH=$PATH:$GITHUB_WORKSPACE/.luarocks/bin + luarocks install luacheck + luarocks install lanes + rm -rf $GITHUB_WORKSPACE/luarocks-${{ env.LUAROCKS_VERSION }} + + - name: Luacheck + run: .luarocks/bin/luacheck . -q diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..cb8c310 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,66 @@ +name: lint + +on: + push: + paths: + - '.github/workflows/**.yml' + - '**.lua' + pull_request: + paths: + - '**.lua' + +jobs: + lint: + runs-on: ubuntu-latest + + env: + LUA_VERSION: 5.1.5 + LUAROCKS_VERSION: 3.11.1 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Cache Lua + uses: actions/cache@v3 + id: luacache + with: + path: .lua + key: ${{ runner.os }}-lua-${{ env.LUA_VERSION }} + restore-keys: | + ${{ runner.os }}-lua-${{ env.LUA_VERSION }} + + - name: Cache LuaRocks + uses: actions/cache@v3 + id: luarockscache + with: + path: .luarocks + key: ${{ runner.os }}-luarocks-${{ env.LUAROCKS_VERSION }} + restore-keys: | + ${{ runner.os }}-luarocks-${{ env.LUAROCKS_VERSION }} + + - name: Install Lua + if: steps.luacache.outputs.cache-hit != 'true' + run: | + sudo apt-get install libreadline-dev libncurses-dev + wget https://www.lua.org/ftp/lua-${{ env.LUA_VERSION }}.tar.gz -O - | tar -xzf - + cd lua-${{ env.LUA_VERSION }} + make linux + make -j INSTALL_TOP=$GITHUB_WORKSPACE/.lua install + rm -rf $GITHUB_WORKSPACE/lua-${{ env.LUA_VERSION }} + + - name: Install LuaRocks and Luacheck + if: steps.luarockscache.outputs.cache-hit != 'true' + run: | + wget https://luarocks.org/releases/luarocks-${{ env.LUAROCKS_VERSION }}.tar.gz -O - | tar -xzf - + cd luarocks-${{ env.LUAROCKS_VERSION }} + ./configure --with-lua-bin=$GITHUB_WORKSPACE/.lua/bin --prefix=$GITHUB_WORKSPACE/.luarocks + make build + make install + PATH=$PATH:$GITHUB_WORKSPACE/.luarocks/bin + luarocks install luacheck + luarocks install lanes + rm -rf $GITHUB_WORKSPACE/luarocks-${{ env.LUAROCKS_VERSION }} + + - name: Luacheck + run: .luarocks/bin/luacheck . diff --git a/.gitignore b/.gitignore index b11d5da..3552451 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1 @@ .idea -.idea - -dist/ diff --git a/WeakAuras/Init.lua b/WeakAuras/Init.lua index 791daaf..e5948b5 100644 --- a/WeakAuras/Init.lua +++ b/WeakAuras/Init.lua @@ -9,7 +9,7 @@ WeakAuras.halfWidth = WeakAuras.normalWidth / 2 WeakAuras.doubleWidth = WeakAuras.normalWidth * 2 local versionStringFromToc = GetAddOnMetadata("WeakAuras", "Version") -local versionString = "5.22.0 Beta" +local versionString = "5.21.2 Beta" -- Year, Month, Day, Hour, Minute, Seconds local buildTime = "2025".."11".."29".."04".."45".."00" local isTTSEnabled = C_VoiceChat and C_VoiceChat.SpeakText and true or false diff --git a/WeakAuras/Types.lua b/WeakAuras/Types.lua index db21db5..68573c7 100644 --- a/WeakAuras/Types.lua +++ b/WeakAuras/Types.lua @@ -1187,16 +1187,6 @@ WeakAuras.class_types = {} for i, class in ipairs(CLASS_SORT_ORDER) do WeakAuras.class_types[class] = WrapTextInColorCode(LOCALIZED_CLASS_NAMES_MALE[class], WA_GetClassColor(class)) end --- CoA: CLASS_SORT_ORDER only contains the 11 vanilla classes, missing the 21 --- custom CoA classes. Fall back to LOCALIZED_CLASS_NAMES_MALE for anything not --- yet registered. Same pattern used by the spec builder further down this file. -if LOCALIZED_CLASS_NAMES_MALE then - for class in pairs(LOCALIZED_CLASS_NAMES_MALE) do - if not WeakAuras.class_types[class] then - WeakAuras.class_types[class] = WrapTextInColorCode(LOCALIZED_CLASS_NAMES_MALE[class], WA_GetClassColor(class)) - end - end -end if WeakAuras.IsClassicPlus() then WeakAuras.class_types["DEATHKNIGHT"] = nil end @@ -3842,28 +3832,6 @@ do end table.sort(classOrder) end - else - -- CoA: CLASS_SORT_ORDER only contains the 11 vanilla classes. Append any - -- keys present in LOCALIZED_CLASS_NAMES_MALE that are not already in the - -- list (custom classes such as Witchdoctor, Templar, etc.). Build a fresh - -- local copy — do NOT mutate the global CLASS_SORT_ORDER. - if LOCALIZED_CLASS_NAMES_MALE then - local inOrder = {} - for _, class in ipairs(classOrder) do - inOrder[class] = true - end - classOrder = {unpack(classOrder)} - local extra = {} - for class in pairs(LOCALIZED_CLASS_NAMES_MALE) do - if not inOrder[class] then - extra[#extra + 1] = class - end - end - table.sort(extra) - for _, class in ipairs(extra) do - classOrder[#classOrder + 1] = class - end - end end if C_ClassInfo and C_ClassInfo.GetAllSpecs and C_ClassInfo.GetSpecInfo then @@ -3871,10 +3839,7 @@ do local specs = C_ClassInfo.GetAllSpecs(class) if specs then for _, spec in ipairs(specs) do - local ok, info = pcall(C_ClassInfo.GetSpecInfo, class, spec) - if ok and info then - addSpec(class, info) - end + addSpec(class, C_ClassInfo.GetSpecInfo(class, spec)) end end end diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index 0358bb2..df00e53 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -1304,16 +1304,8 @@ loadedFrame:SetScript("OnEvent", function(self, event, ...) if dbIsValid then Private.Login(takeNewSnapshots) else - -- db isn't valid. Request permission to run repair tool before logging in. - -- CoA: defer the StaticPopup_Show by one frame so it fires after the - -- PLAYER_LOGIN event-frame stack has unwound. On the CoA reworked - -- StaticPopup system, firing this synchronously during PLAYER_LOGIN - -- silently fails to show the popup, which means Private.Login() is - -- never invoked, no auras load, and the next logout writes an empty - -- WeakAurasSaved over the user's profile. - C_Timer.After(0, function() - StaticPopup_Show("WEAKAURAS_CONFIRM_REPAIR", nil, nil, {reason = "downgrade"}) - end) + -- db isn't valid. Request permission to run repair tool before logging in + StaticPopup_Show("WEAKAURAS_CONFIRM_REPAIR", nil, nil, {reason = "downgrade"}) end elseif event == "PLAYER_LOGOUT" then for id in pairs(db.displays) do @@ -2272,25 +2264,14 @@ StaticPopupDialogs["WEAKAURAS_CONFIRM_REPAIR"] = { local AutomaticRepairText = L["WeakAuras has detected that it has been downgraded.\nYour saved auras may no longer work properly.\nWould you like to run the |cffff0000EXPERIMENTAL|r repair tool? This will overwrite any changes you have made since the last database upgrade.\nLast upgrade: %s\n\n|cffff0000You should BACKUP your WTF folder BEFORE pressing this button.|r"] local ManualRepairText = L["Are you sure you want to run the |cffff0000EXPERIMENTAL|r repair tool?\nThis will overwrite any changes you have made since the last database upgrade.\nLast upgrade: %s"] - -- CoA: guard against malformed data; default reason to "unknown" so the - -- popup can't error out and block Private.Login() from ever running. - local reason = "unknown" - if self.data then - reason = self.data.reason or "unknown" - end - - if reason == "user" then + if self.data.reason == "user" then self.text:SetText(ManualRepairText:format(LastUpgrade())) else self.text:SetText(AutomaticRepairText:format(LastUpgrade())) end end, OnCancel = function(self) - local reason = "unknown" - if self.data then - reason = self.data.reason or "unknown" - end - if reason ~= "user" then + if self.data.reason ~= "user" then Private.Login() end end, diff --git a/tools/build_zip.sh b/tools/build_zip.sh deleted file mode 100755 index 45d1400..0000000 --- a/tools/build_zip.sh +++ /dev/null @@ -1,71 +0,0 @@ -#!/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 -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 /... 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