Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions pkgbuilds/flea/.omarchy/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"source": "local",
"release_ring": "fast",
"min_release_age": "24h"
}
100 changes: 100 additions & 0 deletions pkgbuilds/flea/.omarchy/upstream.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#!/bin/bash
# Flea publishes signed source tags but no release artifacts or checksum manifest.
# Check the small GitHub source tarball only when a newer stable release exists,
# validate its expected root, then report its hash alongside the fixed hashes of
# the four upstream security patches carried until a release includes them.
set -euo pipefail

REPO='thisisgm/flea'
RELEASES_URL="https://api.github.com/repos/$REPO/releases?per_page=100"
PATCH_2BD7CC2='c610a9f44294b67341940203943c9c567003b65cc436d6013cd36754379183d8'
PATCH_27D19CA='e457ef17e26f70057b1184eeb938fccc5906f48a7c77f1df573d55d13a845425'
PATCH_23290CE='f8381456a3b5f39d341cc6610bf27beb8354892b17a1c8c6d7882db4e40824c3'
PATCH_B4B7EE4='46bdbe43f135a052c893b1987f8b0928736445616a84b0c65d2181ee74b21b25'

current=$(awk -F= '/^pkgver=/ { print $2; exit }' PKGBUILD)
releases=$(curl -fsSL "$RELEASES_URL")
now=$(date +%s)
min_age=${MIN_RELEASE_AGE_SECONDS:-0}

candidates=0
best_version=''
best_tag=''
best_published_at=''

while IFS=$'\t' read -r tag published_at; do
if [[ ! $tag =~ ^v([0-9]+\.[0-9]+\.[0-9]+)$ ]]; then
printf '%s has an unusable stable release tag: %s\n' "$REPO" "${tag:-<empty>}" >&2
exit 1
fi
version=${BASH_REMATCH[1]}

if [[ -z $published_at ]] || ! published_epoch=$(date --date="$published_at" +%s 2>/dev/null); then
printf '%s release %s has an invalid publication time\n' "$REPO" "$tag" >&2
exit 1
fi
candidates=$((candidates + 1))

if (( now - published_epoch < min_age )) && [[ ${BYPASS_MIN_RELEASE_AGE:-} != 1 ]]; then
continue
fi

if [[ -z $best_version ]] || (( $(vercmp "$version" "$best_version") > 0 )); then
best_version=$version
best_tag=$tag
best_published_at=$published_at
fi
done < <(jq -r '.[] | select((.draft or .prerelease) | not) | [.tag_name // "", .published_at // ""] | @tsv' <<<"$releases")

if (( candidates == 0 )); then
printf 'No stable releases found for %s\n' "$REPO" >&2
exit 1
fi

if [[ -z $best_version ]] || (( $(vercmp "$best_version" "$current") <= 0 )); then
echo '{}'
exit 0
fi

tarball=$(mktemp)
trap 'rm -f "$tarball"' EXIT
curl -fsSL -o "$tarball" "https://github.com/$REPO/archive/refs/tags/$best_tag.tar.gz"

expected_root="flea-$best_version"
served_roots=$(tar -tzf "$tarball" | cut -d/ -f1 | sort -u)
if [[ $served_roots != "$expected_root" ]]; then
printf 'Release %s contains root %s, expected %s\n' "$best_tag" "$served_roots" "$expected_root" >&2
exit 1
fi

archive_rs=$(tar -xOzf "$tarball" "$expected_root/src/backend/archive.rs")
archiveops_rs=$(tar -xOzf "$tarball" "$expected_root/src/backend/archiveops.rs")
run_rs=$(tar -xOzf "$tarball" "$expected_root/src/backend/run.rs")
archivereq_rs=$(tar -xOzf "$tarball" "$expected_root/src/backend/archivereq.rs")
archivework_rs=$(tar -xOzf "$tarball" "$expected_root/src/backend/archivework.rs")
mediaprobe_rs=$(tar -xOzf "$tarball" "$expected_root/src/backend/mediaprobe.rs")
metareq_rs=$(tar -xOzf "$tarball" "$expected_root/src/backend/metareq.rs")
sharelink_qml=$(tar -xOzf "$tarball" "$expected_root/ui/ShareLink.qml")
copyfile_rs=$(tar -xOzf "$tarball" "$expected_root/src/backend/copyfile.rs")

if ! grep -Fq 'a.push("--".to_string());' <<<"$archive_rs" ||
! grep -Fq 'let input = std::fs::canonicalize(input)' <<<"$archiveops_rs" ||
! grep -Fq 'if op != "compress" && op != "extract"' <<<"$run_rs$archivereq_rs" ||
! grep -Fq 'the sandbox is unavailable: bwrap or prlimit is not on PATH' <<<"$archivework_rs" ||
! grep -Fq 'if !sandbox::available()' <<<"$mediaprobe_rs" ||
! grep -Fq 'if !sandbox::available()' <<<"$metareq_rs" ||
! grep -Fq 'copyToClipboard.command = ["wl-copy", url]' <<<"$sharelink_qml" ||
! grep -Fq '.custom_flags(O_NOFOLLOW)' <<<"$copyfile_rs"; then
printf 'Release %s does not contain every required upstream security fix\n' "$best_tag" >&2
exit 1
fi

jq -n \
--arg pkgver "$best_version" \
--arg published_at "$best_published_at" \
--arg source "$(sha256sum "$tarball" | cut -d' ' -f1)" \
--arg patch_2bd7cc2 "$PATCH_2BD7CC2" \
--arg patch_27d19ca "$PATCH_27D19CA" \
--arg patch_23290ce "$PATCH_23290CE" \
--arg patch_b4b7ee4 "$PATCH_B4B7EE4" \
'{pkgver: $pkgver, published_at: $published_at, sha256sums: {any: [$source, $patch_2bd7cc2, $patch_27d19ca, $patch_23290ce, $patch_b4b7ee4]}}'
132 changes: 132 additions & 0 deletions pkgbuilds/flea/PKGBUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# Maintainer: GM <gianmarcomorales@icloud.com>

pkgname=flea
pkgver=0.1.2
pkgrel=1
pkgdesc='Fast, keyboard-first file manager for Omarchy'
arch=('x86_64')
url='https://github.com/thisisgm/flea'
license=('MIT')

depends=(
'bubblewrap'
'gcc-libs'
'glib2'
'glibc'
'hicolor-icon-theme'
'omarchy'
'quickshell'
'qt6-multimedia'
'qt6-webengine'
'shared-mime-info'
'util-linux'
'xdg-utils'
)
makedepends=('cargo')
optdepends=(
'7zip: 7z archive support'
'dropbox-cli: Dropbox browsing and share links'
'ffmpeg: media metadata previews'
'imagemagick: image conversion'
'libarchive: archive listing and extraction'
'tailscale: Taildrop sharing'
'wl-clipboard: copy Dropbox share links to the clipboard'
)
conflicts=('flea-git')
options=('!debug')

_security_patches=(
'2bd7cc207c110ae3b3ea61a4d4e42336f1815111'
'27d19ca4a38ef4a0a920fb78441ce662a0101327'
'23290ce1917b0d7f0392dd09d04bf2a7504ec93a'
'b4b7ee47244b52457eec2874e21a8656d8ace647'
)
source=(
"$pkgname-$pkgver.tar.gz::$url/archive/refs/tags/v$pkgver.tar.gz"
"security-2bd7cc2.patch::$url/commit/${_security_patches[0]}.patch"
"security-27d19ca.patch::$url/commit/${_security_patches[1]}.patch"
"security-23290ce.patch::$url/commit/${_security_patches[2]}.patch"
"security-b4b7ee4.patch::$url/commit/${_security_patches[3]}.patch"
)
sha256sums=(
'3788a735be2cb6eef0c1770833c82bc6591e20b7681fe02172aaea21c2a2d8fb'
'c610a9f44294b67341940203943c9c567003b65cc436d6013cd36754379183d8'
'e457ef17e26f70057b1184eeb938fccc5906f48a7c77f1df573d55d13a845425'
'f8381456a3b5f39d341cc6610bf27beb8354892b17a1c8c6d7882db4e40824c3'
'46bdbe43f135a052c893b1987f8b0928736445616a84b0c65d2181ee74b21b25'
)

prepare() {
cd "$pkgname-$pkgver"

security_patch_present() {
case "$1" in
2bd7cc207c110ae3b3ea61a4d4e42336f1815111)
grep -Fq 'a.push("--".to_string());' src/backend/archive.rs &&
grep -Fq 'let input = std::fs::canonicalize(input)' src/backend/archiveops.rs &&
grep -Fq 'if op != "compress" && op != "extract"' \
src/backend/run.rs src/backend/archivereq.rs
;;
27d19ca4a38ef4a0a920fb78441ce662a0101327)
grep -Fq 'the sandbox is unavailable: bwrap or prlimit is not on PATH' src/backend/archivework.rs &&
grep -Fq 'if !sandbox::available()' src/backend/mediaprobe.rs &&
grep -Fq 'if !sandbox::available()' src/backend/metareq.rs
;;
23290ce1917b0d7f0392dd09d04bf2a7504ec93a)
grep -Fq 'copyToClipboard.command = ["wl-copy", url]' ui/ShareLink.qml
;;
b4b7ee47244b52457eec2874e21a8656d8ace647)
grep -Fq '.custom_flags(O_NOFOLLOW)' src/backend/copyfile.rs
;;
*)
return 1
;;
esac
}

local commit patch_file
for commit in "${_security_patches[@]}"; do
patch_file="$srcdir/security-${commit:0:7}.patch"

if patch --batch --forward --dry-run -Np1 -i "$patch_file" >/dev/null 2>&1; then
patch --batch --forward -Np1 -i "$patch_file"
elif security_patch_present "$commit"; then
printf 'Security patch %s is already present upstream\n' "$commit"
else
printf 'Security patch %s no longer applies and is not present upstream\n' "$commit" >&2
return 1
fi
done
}

build() {
cd "$pkgname-$pkgver"

export CARGO_TARGET_DIR=target
cargo build --frozen --release
}

check() {
cd "$pkgname-$pkgver"

export CARGO_TARGET_DIR=target
cargo test --frozen --release
./tests/js.sh
./tests/keymap-gen.sh
}

package() {
cd "$pkgname-$pkgver"

install -Dm755 target/release/flea "$pkgdir/usr/bin/flea"
install -Dm644 packaging/com.thisisgm.flea.desktop \
"$pkgdir/usr/share/applications/com.thisisgm.flea.desktop"
install -Dm644 packaging/com.thisisgm.flea.svg \
"$pkgdir/usr/share/icons/hicolor/scalable/apps/com.thisisgm.flea.svg"
install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE"

install -Dm644 ui/qmldir ui/*.qml -t "$pkgdir/usr/share/flea/ui"
install -Dm644 ui/js/*.js -t "$pkgdir/usr/share/flea/ui/js"
ln -s /usr/share/omarchy/shell/Commons "$pkgdir/usr/share/flea/ui/Commons"
ln -s /usr/share/omarchy/shell/Ui "$pkgdir/usr/share/flea/ui/Ui"
}
Loading