Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a6c86daf62 | ||
|
|
f88b6961d1 | ||
|
|
eb65c1def7 | ||
|
|
96e3805568 | ||
|
|
2d9a10e85c | ||
|
|
12d1b2657f | ||
|
|
b0b4fb69cb | ||
|
|
f3a3fcc079 |
@@ -5,7 +5,8 @@ on:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
publish-tauri:
|
||||
publish-windows:
|
||||
name: Build and publish Windows installer
|
||||
permissions:
|
||||
contents: write
|
||||
environment: production
|
||||
@@ -30,25 +31,7 @@ jobs:
|
||||
run:
|
||||
working-directory: GitLite
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
max-parallel: 1
|
||||
matrix:
|
||||
include:
|
||||
# - platform: 'macos-latest'
|
||||
# args: '--target aarch64-apple-darwin'
|
||||
# - platform: 'macos-latest'
|
||||
# args: '--target x86_64-apple-darwin'
|
||||
- platform: "windows-latest"
|
||||
bundles: "nsis"
|
||||
updater_platform: "windows-x86_64"
|
||||
no_strip: ""
|
||||
- platform: "ubuntu-22.04"
|
||||
bundles: "appimage"
|
||||
updater_platform: "linux-x86_64"
|
||||
no_strip: "1"
|
||||
|
||||
runs-on: ${{ matrix.platform }}
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
# cicd_tool/main.py expects the repo at <workspace>/GitLite, so check out there.
|
||||
@@ -56,25 +39,11 @@ jobs:
|
||||
with:
|
||||
path: GitLite
|
||||
|
||||
- name: install dependencies (ubuntu only)
|
||||
if: matrix.platform == 'ubuntu-22.04'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y build-essential curl wget file libssl-dev libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev patchelf libxdo-dev libfuse2
|
||||
|
||||
- name: setup node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: lts/*
|
||||
|
||||
- name: Install uv
|
||||
if: matrix.platform == 'ubuntu-22.04'
|
||||
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b
|
||||
|
||||
- name: install rust toolchain
|
||||
if: matrix.platform == 'ubuntu-22.04'
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
|
||||
- name: install frontend dependencies
|
||||
run: npm ci
|
||||
|
||||
@@ -88,7 +57,6 @@ jobs:
|
||||
node -e "const fs=require('fs'); const path='src-tauri/tauri.conf.json'; const config=JSON.parse(fs.readFileSync(path,'utf8')); config.version=process.env.RELEASE_VERSION; fs.writeFileSync(path, JSON.stringify(config,null,2)+'\n');"
|
||||
|
||||
- name: Commit and Push Changes
|
||||
if: matrix.platform == 'windows-latest'
|
||||
shell: powershell
|
||||
run: |
|
||||
git config user.name '${{ vars.USERNAME_GIT }}'
|
||||
@@ -139,15 +107,15 @@ jobs:
|
||||
env:
|
||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD}}
|
||||
NO_STRIP: ${{ matrix.no_strip }}
|
||||
run: npm run tauri -- build --bundles ${{ matrix.bundles }}
|
||||
NO_STRIP: ""
|
||||
run: npm run tauri -- build --bundles nsis
|
||||
# ----------------------
|
||||
# Upload to MinIO (via mc) and create latest.json
|
||||
# ----------------------
|
||||
- name: Upload artifacts to MinIO with cicd_tool
|
||||
working-directory: GitLite/cicd_tool
|
||||
env:
|
||||
PUBLISH_PLATFORM: ${{ matrix.updater_platform }}
|
||||
PUBLISH_PLATFORM: windows-x86_64
|
||||
run: |
|
||||
uv sync
|
||||
uv run main.py
|
||||
@@ -167,11 +135,66 @@ jobs:
|
||||
- name: Prepare Arch job container
|
||||
working-directory: /
|
||||
run: |
|
||||
pacman -Syu --noconfirm
|
||||
pacman -S --needed --noconfirm \
|
||||
base-devel curl git nodejs npm openssh rust \
|
||||
webkit2gtk-4.1 gtk3 hicolor-icon-theme \
|
||||
set -euo pipefail
|
||||
|
||||
# The runner image may contain only a single geo mirror. Seed several
|
||||
# currently active HTTPS mirrors and retain the image's list as a
|
||||
# fallback so one slow CDN cannot fail the complete release.
|
||||
ARCH_MIRROR_BACKUP="$(mktemp)"
|
||||
cp /etc/pacman.d/mirrorlist "$ARCH_MIRROR_BACKUP"
|
||||
printf '%s\n' \
|
||||
'Server = https://frankfurt.mirror.pkgbuild.com/$repo/os/$arch' \
|
||||
'Server = https://mirror.osbeck.com/archlinux/$repo/os/$arch' \
|
||||
'Server = https://mirror.ubrco.de/archlinux/$repo/os/$arch' \
|
||||
'Server = https://ftp.halifax.rwth-aachen.de/archlinux/$repo/os/$arch' \
|
||||
'Server = https://geo.mirror.pkgbuild.com/$repo/os/$arch' \
|
||||
> /etc/pacman.d/mirrorlist
|
||||
sed -n '/^[[:space:]]*Server[[:space:]]*=/p' "$ARCH_MIRROR_BACKUP" \
|
||||
>> /etc/pacman.d/mirrorlist
|
||||
|
||||
ARCH_PACKAGES=(
|
||||
base-devel curl git nodejs npm openssh rust
|
||||
webkit2gtk-4.1 gtk3 hicolor-icon-theme
|
||||
libappindicator-gtk3 librsvg xdotool
|
||||
)
|
||||
|
||||
for ARCH_INSTALL_ATTEMPT in 1 2 3; do
|
||||
echo "pacman attempt $ARCH_INSTALL_ATTEMPT of 3"
|
||||
timeout --signal=TERM 30m \
|
||||
pacman -Syu --needed --noconfirm --noprogressbar \
|
||||
"${ARCH_PACKAGES[@]}" \
|
||||
</dev/null &
|
||||
ARCH_PACMAN_PID=$!
|
||||
(
|
||||
ARCH_WAIT_SECONDS=0
|
||||
while true; do
|
||||
sleep 30
|
||||
((ARCH_WAIT_SECONDS += 30))
|
||||
echo "pacman is still running (${ARCH_WAIT_SECONDS}s elapsed)"
|
||||
done
|
||||
) &
|
||||
ARCH_HEARTBEAT_PID=$!
|
||||
|
||||
ARCH_PACMAN_STATUS=0
|
||||
wait "$ARCH_PACMAN_PID" || ARCH_PACMAN_STATUS=$?
|
||||
kill "$ARCH_HEARTBEAT_PID" 2>/dev/null || true
|
||||
wait "$ARCH_HEARTBEAT_PID" 2>/dev/null || true
|
||||
|
||||
if [ "$ARCH_PACMAN_STATUS" -eq 0 ]; then
|
||||
break
|
||||
fi
|
||||
|
||||
if [ "$ARCH_PACMAN_STATUS" -eq 124 ]; then
|
||||
echo "pacman attempt timed out after 30 minutes" >&2
|
||||
fi
|
||||
|
||||
if [ "$ARCH_INSTALL_ATTEMPT" -eq 3 ]; then
|
||||
echo "pacman failed after 3 attempts" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sleep "$((ARCH_INSTALL_ATTEMPT * 5))"
|
||||
done
|
||||
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
@@ -218,6 +241,8 @@ jobs:
|
||||
AUR_GIT_NAME: ${{ vars.USERNAME_GIT }}
|
||||
AUR_GIT_EMAIL: ${{ vars.EMAIL_GIT }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
if [ -z "$AUR_SSH_PRIVATE_KEY" ]; then
|
||||
echo "AUR_SSH_PRIVATE_KEY is required" >&2
|
||||
exit 1
|
||||
@@ -226,13 +251,48 @@ jobs:
|
||||
install -d -m 0700 "$HOME/.ssh"
|
||||
printf '%s\n' "$AUR_SSH_PRIVATE_KEY" > "$HOME/.ssh/aur"
|
||||
chmod 0600 "$HOME/.ssh/aur"
|
||||
ssh-keyscan -H aur.archlinux.org >> "$HOME/.ssh/known_hosts"
|
||||
chmod 0600 "$HOME/.ssh/known_hosts"
|
||||
export GIT_SSH_COMMAND="ssh -i $HOME/.ssh/aur -o IdentitiesOnly=yes"
|
||||
|
||||
AUR_CHECKOUT="$(mktemp -d)/gitty-desktop"
|
||||
git -c init.defaultBranch=master clone \
|
||||
ssh://aur@aur.archlinux.org/gitty-desktop.git "$AUR_CHECKOUT"
|
||||
AUR_RETRY_DELAYS=(30 60 120 240)
|
||||
AUR_KNOWN_HOSTS_TEMP="$(mktemp)"
|
||||
AUR_HOST_KEY_READY=0
|
||||
for AUR_ATTEMPT in 1 2 3 4 5; do
|
||||
echo "AUR host-key attempt $AUR_ATTEMPT of 5"
|
||||
if timeout 30s ssh-keyscan -T 15 -H aur.archlinux.org > "$AUR_KNOWN_HOSTS_TEMP" \
|
||||
&& [ -s "$AUR_KNOWN_HOSTS_TEMP" ]; then
|
||||
AUR_HOST_KEY_READY=1
|
||||
break
|
||||
fi
|
||||
if [ "$AUR_ATTEMPT" -lt 5 ]; then
|
||||
sleep "${AUR_RETRY_DELAYS[$((AUR_ATTEMPT - 1))]}"
|
||||
fi
|
||||
done
|
||||
if [ "$AUR_HOST_KEY_READY" -ne 1 ]; then
|
||||
echo "Could not retrieve the AUR SSH host key after 5 attempts" >&2
|
||||
exit 1
|
||||
fi
|
||||
install -m 0600 "$AUR_KNOWN_HOSTS_TEMP" "$HOME/.ssh/known_hosts"
|
||||
export GIT_SSH_COMMAND="ssh -i $HOME/.ssh/aur -o IdentitiesOnly=yes -o BatchMode=yes -o ConnectTimeout=30 -o ServerAliveInterval=15 -o ServerAliveCountMax=2"
|
||||
|
||||
AUR_CHECKOUT_ROOT="$(mktemp -d)"
|
||||
AUR_CHECKOUT=""
|
||||
for AUR_ATTEMPT in 1 2 3 4 5; do
|
||||
AUR_CLONE_CANDIDATE="$AUR_CHECKOUT_ROOT/attempt-$AUR_ATTEMPT"
|
||||
echo "AUR clone attempt $AUR_ATTEMPT of 5"
|
||||
if timeout 3m git -c init.defaultBranch=master clone \
|
||||
ssh://aur@aur.archlinux.org/gitty-desktop.git "$AUR_CLONE_CANDIDATE"; then
|
||||
AUR_CHECKOUT="$AUR_CLONE_CANDIDATE"
|
||||
break
|
||||
fi
|
||||
if [ "$AUR_ATTEMPT" -lt 5 ]; then
|
||||
echo "AUR is unavailable; retrying after backoff"
|
||||
sleep "${AUR_RETRY_DELAYS[$((AUR_ATTEMPT - 1))]}"
|
||||
fi
|
||||
done
|
||||
if [ -z "$AUR_CHECKOUT" ]; then
|
||||
echo "Could not clone the AUR repository after 5 attempts" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cp "$AUR_SOURCE_DIR/PKGBUILD" "$AUR_SOURCE_DIR/.SRCINFO" "$AUR_CHECKOUT/"
|
||||
|
||||
cd "$AUR_CHECKOUT"
|
||||
@@ -246,4 +306,93 @@ jobs:
|
||||
fi
|
||||
|
||||
git commit -m "Update to $PACKAGE_VERSION"
|
||||
git push origin HEAD:master
|
||||
AUR_PUSHED=0
|
||||
for AUR_ATTEMPT in 1 2 3 4 5; do
|
||||
echo "AUR push attempt $AUR_ATTEMPT of 5"
|
||||
if timeout 3m git push origin HEAD:master; then
|
||||
AUR_PUSHED=1
|
||||
break
|
||||
fi
|
||||
if [ "$AUR_ATTEMPT" -lt 5 ]; then
|
||||
echo "AUR push failed; retrying after backoff"
|
||||
sleep "${AUR_RETRY_DELAYS[$((AUR_ATTEMPT - 1))]}"
|
||||
fi
|
||||
done
|
||||
if [ "$AUR_PUSHED" -ne 1 ]; then
|
||||
echo "Could not publish to AUR after 5 attempts" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
publish-ubuntu:
|
||||
name: Build and publish Ubuntu AppImage
|
||||
permissions:
|
||||
contents: write
|
||||
environment: production
|
||||
env:
|
||||
GITEA_API: https://git.cbsk-tech.de/api/v1
|
||||
OWNER: Christoph
|
||||
REPO: GitLite
|
||||
GITEA_TOKEN: ${{ secrets.ACTIONS_TOKEN }}
|
||||
GITEA_FALLBACK_TOKEN: ${{ github.token }}
|
||||
|
||||
MINIO_ENDPOINT: ${{ vars.MINIO_ENDPOINT }}
|
||||
S3_BUCKET: ${{ vars.S3_BUCKET }}
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.S3_ACCESS_KEY }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_KEY }}
|
||||
ARTIFACT_BASE_URL: ${{ vars.ARTIFACT_BASE_URL }}
|
||||
S3_ACCESS_KEY: ${{ secrets.S3_ACCESS_KEY }}
|
||||
S3_SECRET_KEY: ${{ secrets.S3_SECRET_KEY }}
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: GitLite
|
||||
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
path: GitLite
|
||||
|
||||
- name: Install Ubuntu dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y build-essential curl wget file libssl-dev libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev patchelf libxdo-dev libfuse2
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: lts/*
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b
|
||||
|
||||
- name: Install Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
|
||||
- name: Install frontend dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Update package.json version
|
||||
run: npm version ${{ github.ref_name }} --no-git-tag-version --allow-same-version
|
||||
|
||||
- name: Update tauri.conf.json version
|
||||
env:
|
||||
RELEASE_VERSION: ${{ github.ref_name }}
|
||||
run: |
|
||||
node -e "const fs=require('fs'); const path='src-tauri/tauri.conf.json'; const config=JSON.parse(fs.readFileSync(path,'utf8')); config.version=process.env.RELEASE_VERSION; fs.writeFileSync(path, JSON.stringify(config,null,2)+'\n');"
|
||||
|
||||
- name: Build Tauri App
|
||||
env:
|
||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD}}
|
||||
NO_STRIP: "1"
|
||||
run: npm run tauri -- build --bundles appimage
|
||||
|
||||
- name: Upload artifacts to MinIO with cicd_tool
|
||||
working-directory: GitLite/cicd_tool
|
||||
env:
|
||||
PUBLISH_PLATFORM: linux-x86_64
|
||||
run: |
|
||||
uv sync
|
||||
uv run main.py
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
import argparse
|
||||
import io
|
||||
import json
|
||||
import mimetypes
|
||||
import os
|
||||
import uuid
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
from typing import Any, Iterable, List, NamedTuple, Optional
|
||||
from urllib.parse import urlparse
|
||||
from urllib.parse import quote, urlencode
|
||||
from urllib.request import Request, urlopen
|
||||
|
||||
from minio import Minio
|
||||
from minio.error import S3Error
|
||||
@@ -329,6 +333,65 @@ def _publish_target(
|
||||
)
|
||||
|
||||
|
||||
def _gitea_request(url: str, token: str, data: Optional[bytes] = None, **headers: str):
|
||||
request = Request(url, data=data, headers={"Authorization": f"token {token}", **headers})
|
||||
return urlopen(request, timeout=120)
|
||||
|
||||
|
||||
def _upload_gitea_release_asset(version: str, artifact: Path) -> None:
|
||||
"""Attach the installer to the Gitea release that triggered this build."""
|
||||
api_url = os.environ.get("GITEA_API", "").rstrip("/")
|
||||
owner = os.environ.get("OWNER", "")
|
||||
repo = os.environ.get("REPO", "")
|
||||
token = os.environ.get("GITEA_TOKEN") or os.environ.get("GITEA_FALLBACK_TOKEN")
|
||||
if not all((api_url, owner, repo, token)):
|
||||
raise ConfigurationError(
|
||||
"GITEA_API, OWNER, REPO and GITEA_TOKEN are required to publish "
|
||||
"the release asset."
|
||||
)
|
||||
|
||||
release_url = (
|
||||
f"{api_url}/repos/{quote(owner, safe='')}/{quote(repo, safe='')}"
|
||||
f"/releases/tags/{quote(version, safe='')}"
|
||||
)
|
||||
with _gitea_request(release_url, token) as response:
|
||||
release = json.load(response)
|
||||
|
||||
existing_names = {
|
||||
asset.get("name") for asset in release.get("assets", []) if isinstance(asset, dict)
|
||||
}
|
||||
if artifact.name in existing_names:
|
||||
print(f"Release asset {artifact.name} already exists; skipping upload.")
|
||||
return
|
||||
|
||||
boundary = f"----gitty-{uuid.uuid4().hex}"
|
||||
content_type = mimetypes.guess_type(artifact.name)[0] or "application/octet-stream"
|
||||
body = b"".join(
|
||||
(
|
||||
f"--{boundary}\r\n".encode(),
|
||||
(
|
||||
f'Content-Disposition: form-data; name="attachment"; '
|
||||
f'filename="{artifact.name}"\r\n'
|
||||
).encode(),
|
||||
f"Content-Type: {content_type}\r\n\r\n".encode(),
|
||||
artifact.read_bytes(),
|
||||
f"\r\n--{boundary}--\r\n".encode(),
|
||||
)
|
||||
)
|
||||
upload_url = (
|
||||
f"{api_url}/repos/{quote(owner, safe='')}/{quote(repo, safe='')}"
|
||||
f"/releases/{release['id']}/assets?{urlencode({'name': artifact.name})}"
|
||||
)
|
||||
with _gitea_request(
|
||||
upload_url,
|
||||
token,
|
||||
data=body,
|
||||
**{"Content-Type": f"multipart/form-data; boundary={boundary}"},
|
||||
):
|
||||
pass
|
||||
print(f"Attached {artifact.name} to Gitea release {version}.")
|
||||
|
||||
|
||||
def main(version: Optional[str] = None, app_dir: Optional[str] = None) -> None:
|
||||
resolved_version = _resolve_version(version)
|
||||
artifact_base_url = os.environ.get("ARTIFACT_BASE_URL", "")
|
||||
@@ -385,6 +448,8 @@ def main(version: Optional[str] = None, app_dir: Optional[str] = None) -> None:
|
||||
artifact_base_url=artifact_base_url,
|
||||
)
|
||||
|
||||
_upload_gitea_release_asset(resolved_version, primary)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(
|
||||
|
||||
+2
-2
@@ -3967,10 +3967,10 @@
|
||||
helpOpen = false;
|
||||
return;
|
||||
}
|
||||
if (event.key === "Escape" && fileHistoryDialogOpen && !isBusy) closeFileHistoryDialog();
|
||||
if (event.key === "Escape" && compareDialogOpen) closeCompareDialog();
|
||||
else if (event.key === "Escape" && fileHistoryDialogOpen && !isBusy) closeFileHistoryDialog();
|
||||
else if (event.key === "Escape" && repoTabContextMenu) closeRepoTabContextMenu();
|
||||
else if (event.key === "Escape" && pendingDiscard && !isBusy) closeDiscardConfirm();
|
||||
else if (event.key === "Escape" && compareDialogOpen) closeCompareDialog();
|
||||
else if (event.key === "Escape" && newBranchCommit) newBranchCommit = null;
|
||||
else if (event.key === "Escape" && renameBranchTarget) renameBranchTarget = null;
|
||||
else if (event.key === "Escape" && deleteBranchTarget) closeDeleteBranchDialog();
|
||||
|
||||
+4
-4
@@ -2689,9 +2689,8 @@
|
||||
filter: drop-shadow(0 0 3px rgba(224,160,64,0.24));
|
||||
}
|
||||
.graph-svg path.graph-segment-behind {
|
||||
stroke: #7aacff;
|
||||
stroke-dasharray: 4 4;
|
||||
filter: drop-shadow(0 0 3px rgba(122,172,255,0.24));
|
||||
filter: drop-shadow(0 0 3px rgba(122,172,255,0.2));
|
||||
}
|
||||
.graph-dot {
|
||||
position: absolute;
|
||||
@@ -2715,8 +2714,8 @@
|
||||
box-shadow: 0 0 0 1px rgba(224,160,64,0.42), 0 0 10px rgba(224,160,64,0.16);
|
||||
}
|
||||
.graph-dot.behind {
|
||||
background: #7aacff;
|
||||
box-shadow: 0 0 0 1px rgba(122,172,255,0.46), 0 0 10px rgba(122,172,255,0.18);
|
||||
background: var(--dot-color, #5a8cf8);
|
||||
box-shadow: 0 0 0 1px var(--dot-color, #5a8cf8), 0 0 10px rgba(122,172,255,0.18);
|
||||
}
|
||||
.graph-dot.tip { width: 14px; height: 14px; box-shadow: 0 0 0 1px var(--dot-color, #5a8cf8); }
|
||||
.graph-dot.merge {
|
||||
@@ -2882,6 +2881,7 @@
|
||||
overflow: hidden;
|
||||
}
|
||||
.file-history-dialog-backdrop { z-index: 70; }
|
||||
.compare-dialog-backdrop { z-index: 80; }
|
||||
.file-history-dialog {
|
||||
display: grid;
|
||||
grid-template-rows: auto minmax(0, 1fr);
|
||||
|
||||
@@ -216,7 +216,7 @@
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="dialog-backdrop"
|
||||
class="dialog-backdrop compare-dialog-backdrop"
|
||||
role="presentation"
|
||||
>
|
||||
<div class="dialog compare-dialog" role="dialog" aria-modal="true" aria-label="Commit comparison" tabindex="-1">
|
||||
|
||||
@@ -140,15 +140,18 @@
|
||||
|
||||
const currentBranches = branchMembership.get(commit.hash) ?? localBranchRefs(commit);
|
||||
const commitBranches = uniqueStrings([...(beforeBranches[col] ?? []), ...currentBranches]);
|
||||
after[col] = commit.parents.length > 0 ? commit.parents[0] : null;
|
||||
afterBranches[col] = after[col] ? commitBranches.slice() : [];
|
||||
const firstParent = commit.parents[0] ?? null;
|
||||
after[col] = firstParent;
|
||||
afterBranches[col] = firstParent
|
||||
? (branchMembership.get(firstParent) ?? commitBranches).slice()
|
||||
: [];
|
||||
|
||||
const fromCommit = new Set<number>([col]);
|
||||
for (let p = 1; p < commit.parents.length; p++) {
|
||||
let slot = after.indexOf(null);
|
||||
if (slot === -1) { slot = after.length; after.push(null); afterBranches.push([]); }
|
||||
after[slot] = commit.parents[p];
|
||||
afterBranches[slot] = [];
|
||||
afterBranches[slot] = (branchMembership.get(commit.parents[p]) ?? commitBranches).slice();
|
||||
fromCommit.add(slot);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user