Compare commits

...

52 Commits

Author SHA1 Message Date
xenia e0a4c6d2dd update nixpkgs 2026-03-06 15:59:01 -05:00
xenia 908bb3cf9d update racket to 9.1 + racket packages 2026-02-24 18:13:29 -05:00
xenia 428be2c5d8 fix non-flake default.nix 2026-02-24 18:10:27 -05:00
xenia 640a982a0a update nixpkgs 2026-02-24 18:10:20 -05:00
xenia fcd5cda980 add openocd_headless 2026-02-08 20:19:00 -05:00
xenia 26e98da6bf update todo 2026-02-08 19:02:24 -05:00
xenia da8840cb2b export typical derivation mods for CI 2026-02-08 18:00:37 -05:00
xenia 1d87c46056 add nix-serve-ng patches to lix; bump lix-plugins 2026-02-08 17:32:24 -05:00
xenia 34099e07db update nixpkgs 2026-02-08 16:22:32 -05:00
xenia 4ed8f576dd fix jq 2026-02-08 14:34:32 -05:00
xenia 715dfa77e6 add more ci exceptions 2026-02-08 14:30:59 -05:00
xenia a7e46105db modularlize ci scripts 2026-02-08 12:47:19 -05:00
xenia c5fee7a80c update todo 2026-02-08 12:27:48 -05:00
xenia 65870eec90 dont spam the journal so much 2026-02-08 00:10:59 -05:00
xenia 62303b70d0 add ci script 2026-02-08 00:07:18 -05:00
xenia df384b5543 whoops 2026-02-07 20:54:15 -05:00
xenia 20f6a5b4d7 create headless qemu_kvm 2026-02-07 20:41:09 -05:00
xenia c872488134 allow single nix-eval-jobs call 2026-02-07 20:17:20 -05:00
xenia 6eb31ca8e2 update todo 2026-02-07 14:32:20 -05:00
xenia 9d5853b25d add infrastructure for diffing against nixpkgs 2026-02-07 14:25:09 -05:00
xenia 5a79d34281 pyghidra: restore original wmclass 2026-02-01 03:07:59 -05:00
xenia 00c00afb81 rework binsync package 2026-02-01 02:13:47 -05:00
xenia 7e2c134794 oops 2026-02-01 02:03:19 -05:00
xenia 46c5bc1dbc update binsync 2026-02-01 01:58:32 -05:00
xenia b83825c2a8 initial pyghidra support 2026-02-01 01:19:41 -05:00
xenia 61cf83698d add recurseIntoAttrs 2026-02-01 00:40:23 -05:00
xenia bb3f98d144 update ghidra to 12.0 + extensions 2026-01-31 23:36:08 -05:00
xenia 3fb7d05305 update racket version and packages 2026-01-31 21:48:39 -05:00
xenia 1686eb5817 update strawberry 2026-01-31 21:11:57 -05:00
xenia 322efdfefe update ocaml-manual 2026-01-31 21:01:57 -05:00
xenia a654beae67 update lix/lix-plugins to 2.94 2026-01-31 20:54:57 -05:00
xenia ddcf0d4712 patch zfs-user 2.4 2026-01-20 20:53:25 -05:00
xenia 255bd480f6 update nixpkgs 2026-01-20 19:40:54 -05:00
xenia 6ff53a02b8 experimental new repl-overlay 2026-01-05 13:46:35 -05:00
xenia b81369662c update nixpkgs 2026-01-05 13:40:16 -05:00
xenia 13e67681de update nixpkgs 2025-12-28 21:11:59 -05:00
xenia 8511ccaa4f patch strawberry 2025-12-24 16:35:42 -05:00
xenia 2028d946a5 fix tex package meta 2025-12-23 05:02:14 -05:00
xenia 7e52eb4d52 what 2025-12-23 04:53:52 -05:00
xenia 1319b12cb7 texlive: provide default dragnpkgs scheme 2025-12-23 04:33:27 -05:00
xenia 74ba7dba3e update beamer template 2025-12-23 04:25:26 -05:00
xenia 0f55b27419 pkgs.satisfactory-dedicated-server: update 2025-12-22 22:22:07 -05:00
xenia ae47a36f7f rename system -> stdenv.hostPlatform.system 2025-12-22 22:22:01 -05:00
xenia 82ac27dea3 treewide: clean up 'meta = with' pattern 2025-12-22 22:03:30 -05:00
xenia 875a804500 update 2025-12-22 21:49:19 -05:00
xenia 90f79781c7 update readme 2025-12-14 21:03:03 -05:00
xenia 6310c4ca22 update nixpkgs 2025-12-14 17:44:49 -05:00
xenia 96a1cf5c55 fix pyside6/binsync build 2025-12-07 18:40:34 -05:00
xenia b38957ff39 update binsync and libbs 2025-12-07 18:16:55 -05:00
xenia 722df1c375 uncomment binsync override 2025-12-07 18:10:22 -05:00
xenia 94247ca614 fork off dragnpkgs-25.11 2025-12-07 17:55:20 -05:00
xenia 6ba1a991dd update packages and fix builds
- remove lix-module dependency and vendor a version of the overlay
- move python packages to python313
- comment binsync because the build is fucked
- add note about building zbasefind
- update feedvalidator to latest version
- update megacom to pyproject=true
2025-12-07 17:53:39 -05:00
61 changed files with 1923 additions and 479 deletions

View File

@ -43,8 +43,8 @@ for flake usage, add this repo as an input and don't input nixpkgs at all, since
```nix
{
inputs = {
# for nixos-25.05
dragnpkgs.url = "git+https://git.lain.faith/haskal/dragnpkgs.git?ref=nixos-25.05";
# for nixos-25.11
dragnpkgs.url = "git+https://git.lain.faith/haskal/dragnpkgs.git?ref=nixos-25.11";
# for nixos-unstable
dragnpkgs.url = "git+https://git.lain.faith/haskal/dragnpkgs.git?ref=main";

10
TODO.md
View File

@ -3,10 +3,14 @@
## `ghidra`
- wrap/expose pyghidraRun so it works correctly
- mostly finished. needs some polish but it works
- export passthru python packages
- pyghidra packages
- pyghidra packages: done
- type stubs
- lower priority: gdb, lldb
- advanced ghidra build system overhaul: build all dependencies from source and don't allow it to
download random binaries from maven
- (the fidb binaries are fine)
## `ghidra-server`
@ -15,3 +19,7 @@ create NixOS VM test
- test that ghidra-svrAdmin works as an unprivileged user in the `ghidra` group
- possibly test remotely importing a binary. however, ghidra-svrAdmin working is a good indicator of
the server being functional
## racket-minimal/racket
make racket build on racket-minimal instead of being completely independent, like the guix packaging

19
ci/ci.sh Executable file
View File

@ -0,0 +1,19 @@
#!/usr/bin/env -S /run/current-system/sw/bin/nix shell nixpkgs#bash nixpkgs#nix-eval-jobs nixpkgs#jq nixpkgs#git nixpkgs#coreutils nixpkgs#nix --command bash
set -euo pipefail
mkdir gcroots || true
# idk why this is needed but it always fails the first time
nix-eval-jobs --gc-roots-dir gcroots --workers $(($(nproc) - 4)) \
--flake .#_release_eval.nixpkgs.AAAAAASomeThingsFailToEvaluate &>/dev/null || true
# nix-eval-jobs currently produces slightly under 207000 lines of line-separated json
nix-eval-jobs --gc-roots-dir gcroots --workers $(($(nproc) - 4)) \
--flake .#_release_eval 2>eval-error.log | \
tee eval.jsonl | \
jq --raw-output --slurp -L ci -f ci/make-build-plan.jq > build-plan.nixl
while read line; do
nix build --max-jobs 1 --keep-going --out-link "gcroots/$line" ".#${line}^*" || true
done < build-plan.nixl

24
ci/disabled-packages.jq Normal file
View File

@ -0,0 +1,24 @@
def remove_disabled:
.
# broken packages
| select(.[0] != "nix-serve")
| select(.[0] != "niv")
| select(.[0] != "haskellPackages" or .[1] != "niv")
| select(.[0] != "haskellPackages" or .[1] != "cabal2nix-unstable")
| select(.[0] != "hydra")
# disabled by dragnpgks
| select(.[0] != "nix-plugins")
# don't rebuild any nixos tests
| select(.[0] != "tests")
# not a derivation
| select(.[0] != "makeSquashFs")
# needs newer CPU to build
| select(.[0] != "cado-nfs")
# randomly hangs fetching cargo deps on the ci machine
| select(.[0] != "zbasefind")
;

11
ci/make-build-plan.jq Normal file
View File

@ -0,0 +1,11 @@
include "./disabled-packages";
{"nixpkgs":0, "dragnpkgs": 1} as $sel
| reduce .[] as $eval ({};
. | setpath($eval.attrPath[1:] + [$sel[$eval.attrPath[0]]]; $eval.drvPath))
| path(.. | arrays | select(.[0] != .[1]))
| remove_disabled
| join(".")

13
ci/post-receive.sh Executable file
View File

@ -0,0 +1,13 @@
#!/usr/bin/env bash
BRANCH="nixos-25.11"
while read oldrev newrev ref; do
if [[ "$ref" = "refs/heads/$BRANCH" ]]; then
echo "Starting CI for $BRANCH..."
target="/var/tmp/dragnpkgs-ci-$newrev"
git clone "$GIT_DIR" "$target" --branch "$BRANCH"
systemd-run --user --unit="dragnpkgs-ci-$newrev" --description="Running dragnpkgs CI for rev $newrev" --collect --working-directory="$target" "$target/ci/ci.sh"
fi
done

View File

@ -4,19 +4,11 @@ let
url = "";
sha256 = lockFile.nodes.nixpkgs.locked.narHash;
};
lix = builtins.fetchTarball {
url = "";
sha256 = lockFile.nodes.lix.locked.narHash;
};
lix-module = builtins.fetchTarball {
url = "";
sha256 = lockFile.nodes.lix-module.locked.narHash;
};
in
{ overlays ? [], ... } @ args:
import "${nixpkgs}" ({
overlays = [
(import ./overlay.nix)
(import "${lix-module}/overlay.nix" { inherit lix; })
(import ./lix-overlay.nix)
] ++ overlays;
} // (builtins.removeAttrs args [ "overlays" ]))

View File

@ -1,37 +1,23 @@
{
"nodes": {
"lix-module": {
"flake": false,
"locked": {
"lastModified": 1756125859,
"narHash": "sha256-6a+PWILmqHCs9B5eIBLg6HSZ8jYweZpgOWO8FlyVwYI=",
"type": "tarball",
"url": "https://git.lix.systems/lix-project/nixos-module/archive/2.93.3-2.tar.gz"
},
"original": {
"type": "tarball",
"url": "https://git.lix.systems/lix-project/nixos-module/archive/2.93.3-2.tar.gz"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1763283776,
"narHash": "sha256-Y7TDFPK4GlqrKrivOcsHG8xSGqQx3A6c+i7novT85Uk=",
"lastModified": 1772598333,
"narHash": "sha256-YaHht/C35INEX3DeJQNWjNaTcPjYmBwwjFJ2jdtr+5U=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "50a96edd8d0db6cc8db57dab6bb6d6ee1f3dc49a",
"rev": "fabb8c9deee281e50b1065002c9828f2cf7b2239",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"ref": "nixos-25.11",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"lix-module": "lix-module",
"nixpkgs": "nixpkgs"
}
}

View File

@ -2,19 +2,14 @@
description = "dragnpkgs together with nixpkgs and lix";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
lix-module = {
url = "https://git.lix.systems/lix-project/nixos-module/archive/2.93.3-2.tar.gz";
flake = false;
};
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";
};
outputs = { self, nixpkgs, lix-module }:
outputs = { self, nixpkgs }:
let
overlays = [
(import ./overlay.nix)
(import "${lix-module}/overlay.nix" { lix = null; })
(import ./lix-overlay.nix)
];
forAllSystems = nixpkgs.lib.genAttrs nixpkgs.lib.systems.flakeExposed;
libVersionInfoOverlay = import "${nixpkgs}/lib/flake-version-info.nix" nixpkgs;
@ -28,18 +23,18 @@
# self reference in the registry to be downloadable by URL in case it makes it into a
# flake.lock
meta.registry-entry = {
from = { id = "dragnpkgs-unstable"; type = "indirect"; };
from = { id = "dragnpkgs"; type = "indirect"; };
to = {
type = "git";
url = "https://git.lain.faith/haskal/dragnpkgs.git";
ref = "main";
ref = "nixos-25.11";
} // self.lib.filterAttrs
(n: _: n == "lastModified" || n == "rev" || n == "revCount" || n == "narHash")
self;
};
# the nix path entry for self
meta.path-entry = "dragnpkgs-unstable=flake:dragnpkgs-unstable";
meta.path-entry = "dragnpkgs=flake:dragnpkgs";
lib = (lib-base.extend (import ./lib/overlay.nix)).extend (final: prev: {
# initializes regular upstream nixpkgs with the given arguments
@ -154,17 +149,17 @@
};
};
config.nix.registry.dragnpkgs-unstable =
config.nix.registry.dragnpkgs =
lib.mkIf config.dragnpkgs.setFlakeRegistry self.meta.registry-entry;
config.nix.registry.nixpkgs = lib.mkIf config.dragnpkgs.setNixpkgsFlakeAlias {
from = { id = "nixpkgs"; type = "indirect"; };
to = { id = "dragnpkgs-unstable"; type = "indirect"; };
to = { id = "dragnpkgs"; type = "indirect"; };
};
config.nix.registry.templates = lib.mkIf config.dragnpkgs.setTemplatesFlakeAlias {
from = { id = "templates"; type = "indirect"; };
to = { id = "dragnpkgs-unstable"; type = "indirect"; };
to = { id = "dragnpkgs"; type = "indirect"; };
};
config.nix.nixPath = lib.mkIf config.dragnpkgs.setNixPath [
@ -242,5 +237,19 @@
};
defaultTemplate = self.templates.default;
_release_eval = let
conf = {
system = "x86_64-linux";
config = {
allowAliases = false;
allowUnfree = false;
inHydra = true;
};
};
in {
dragnpkgs = self.lib.recurseIntoAttrs (self.lib.dragnpkgs-custom conf);
nixpkgs = self.lib.recurseIntoAttrs (self.lib.nixpkgs-custom conf);
};
};
}

View File

@ -1,4 +1,4 @@
{ lib, stdenvNoCC, system, cacert, depotdownloader }:
{ lib, stdenv, cacert, depotdownloader }:
let
checkDepot = depot: with builtins;
hasAttr "depotId" depot && hasAttr "manifestId" depot;
@ -18,7 +18,7 @@ else if ! builtins.all checkDepot additionalDepots then
else
let
depotOs =
if system == "x86_64-linux" then
if stdenv.hostPlatform.system == "x86_64-linux" then
"linux"
else
throw "fetchFromSteam does not currently support systems other than x86_64-linux";
@ -26,7 +26,7 @@ let
"-app ${appId} -depot ${depot.depotId} -manifest ${depot.manifestId} -os ${depotOs}"
+ (lib.optionalString (builtins.hasAttr "beta" depot) " -beta ${depot.beta}");
depotArgs = builtins.map makeDepotArg [ depot ] ++ additionalDepots;
in stdenvNoCC.mkDerivation {
in stdenv.mkDerivation {
name = "steam-depot-${appId}" + (lib.optionalString (name != null) "-${name}");
builder = ./builder.sh;

101
lix-overlay.nix Normal file
View File

@ -0,0 +1,101 @@
# This file is adapted from <https://git.lix.systems/lix-project/nixos-module>
# and distributed under the terms of the MIT license found at
# <https://git.lix.systems/lix-project/nixos-module/src/branch/main/LICENSE>
final: prev:
let
# These packages should receive CppNix since they may link to it or otherwise
# cause problems (or even just silly mass-rebuilds) if we give them Lix
overridelist_upstream = [
"attic-client"
"devenv"
"nix-du"
"nix-init"
"nix-prefetch-git"
"nixd"
"nixos-option"
"nixt"
"nurl"
"prefetch-yarn-deps" # force these onto upstream so we are not regularly rebuilding electron
];
inherit (prev) lib;
csi = builtins.fromJSON ''"\u001b"'';
orange = "${csi}[35;1m";
normal = "${csi}[0m";
warning = ''
${orange}warning${normal}: You have the lix overlay included into a nixpkgs import twice,
perhaps due to the NixOS module being included twice, or because of using
pkgs.nixos and also including it in imports, or perhaps some unknown
machinations of a complicated flake library.
This is completely harmless since we have no-op'd the second one if you are
seeing this message, but it would be a small style improvement to fix
it :)
P.S. If you had some hack to fix nixos-option build failures in your
configuration, that was caused by including an older version of the lix
overlay twice, which is now mitigated if you see this message, so you can
delete that.
P.P.S. This Lix has super catgirl powers.
'';
maybeWarnDuplicate = x: if final.lix-overlay-present > 1 then builtins.trace warning x else x;
lixPackageSet = prev.lixPackageSets.lix_2_94;
lixPackageToUse = lixPackageSet.lix.overrideAttrs (final: prev: {
patches = (prev.patches or []) ++ [
./pkgs/lix/lix/pkg-config.patch
./pkgs/lix/lix/version-macros.patch
];
});
# It is not enough to *just* throw whatever the default nix version is at
# anything in the "don't give lix" list, we have to *also* ensure that we
# give whatever upstream version as specified in the callPackage invocation.
#
# Unfortunately I don't think there is any actual way to directly query that,
# so we instead do something extremely evil and guess which version it
# probably was. This code is not generalizable to arbitrary derivations, so
# it will hopefully not make us cry, at least.
useCppNixOverlay =
lib.genAttrs overridelist_upstream (
name:
if (lib.functionArgs prev.${name}.override ? "nix") then
let
# Get the two common inputs of a derivation/package.
inputs = prev.${name}.buildInputs ++ prev.${name}.nativeBuildInputs;
nixDependency = lib.findFirst
(drv: (drv.pname or "") == "nix")
final.nixVersions.stable_upstream # default to stable nix if nix is not an input
inputs;
nixMajor = lib.versions.major (nixDependency.version or "");
nixMinor = lib.versions.minor (nixDependency.version or "");
nixAttr = "nix_${nixMajor}_${nixMinor}";
finalNix = final.nixVersions.${nixAttr};
in
prev.${name}.override {
nix = finalNix;
}
else prev.${name}
);
overlay = useCppNixOverlay // {
lix-overlay-present = 1;
lix = maybeWarnDuplicate lixPackageToUse;
nixForLinking = final.nixVersions.stable_upstream; # make sure that nixVersions.stable isn't messed with.
nixVersions = prev.nixVersions // {
stable = final.lix;
stable_upstream = prev.nixVersions.stable;
};
nix-eval-jobs = lixPackageSet.nix-eval-jobs;
nix-doc = prev.nix-doc.override { withPlugin = false; };
};
in
# Make the overlay idempotent, since flakes passing nixos modules around by
# value and many other things make it way too easy to include the overlay
# twice
if (prev ? lix-overlay-present) then { lix-overlay-present = 2; } else overlay

View File

@ -38,15 +38,16 @@ in
example = lib.literalExpression "[ (ps: with ps; [ my_extension ]) ]";
};
binsync = {
enable = lib.mkEnableOption "Ghidra binsync integration";
_finalGhidra = lib.mkOption {
type = lib.types.package;
internal = true;
visible = false;
readOnly = true;
};
};
config = lib.mkIf cfg.enable {
programs.ghidra.extensions = lib.mkIf (cfg.binsync.enable) [
(ps: [ ps.binsync ])
];
programs.ghidra._finalGhidra = packageWithExts;
environment = {
systemPackages = [

View File

@ -36,19 +36,35 @@ final: prev: {
patdiff-bin = ofinal.callPackage ./pkgs/ocaml/patdiff-bin {};
});
python312 = prev.python312.override {
python313 = prev.python313.override {
packageOverrides = pfinal: pprev: {
feedvalidator = pfinal.callPackage ./pkgs/python/feedvalidator {};
megacom = pfinal.callPackage ./pkgs/python/megacom {};
pyghidra = pfinal.callPackage ./pkgs/reverse-engineering/ghidra/pyghidra.nix {};
libbs = pfinal.callPackage ./pkgs/reverse-engineering/binsync/libbs.nix {};
binsync = pfinal.callPackage ./pkgs/reverse-engineering/binsync/binsync.nix {};
};
};
# add to top level because it has a binary
feedvalidator = final.python312Packages.feedvalidator;
megacom = final.python312Packages.megacom;
feedvalidator = final.python313Packages.feedvalidator;
megacom = final.python313Packages.megacom;
python312 = prev.python312.override {
packageOverrides = pfinal: pprev: {
pyghidra = pfinal.callPackage ./pkgs/reverse-engineering/ghidra/pyghidra.nix {};
libbs = pfinal.callPackage ./pkgs/reverse-engineering/binsync/libbs.nix {};
binsync = pfinal.callPackage ./pkgs/reverse-engineering/binsync/binsync.nix {};
};
};
python311 = prev.python311.override {
packageOverrides = pfinal: pprev: {
pyghidra = pfinal.callPackage ./pkgs/reverse-engineering/ghidra/pyghidra.nix {};
libbs = pfinal.callPackage ./pkgs/reverse-engineering/binsync/libbs.nix {};
binsync = pfinal.callPackage ./pkgs/reverse-engineering/binsync/binsync.nix {};
};
@ -72,13 +88,23 @@ final: prev: {
patches = [ ./pkgs/zfs/0001-ZED-add-support-for-desktop-notifications-D-Bus.patch ];
};
zfs_2_4 = prev.zfs_2_4.overrideAttrs {
patches = [ ./pkgs/zfs/0001-ZED-add-support-for-desktop-notifications-D-Bus.patch ];
};
pympress = prev.pympress.overrideDerivation (oldAttrs: {
patches = [ ./pkgs/python/pympress/0001-Fix-KDE-window-icon.patch ];
});
texliveDragonPackages = {
moloch = prev.callPackage ./pkgs/tex/moloch {};
};
scheme = final.texliveMedium.withPackages (ps: [
ps.fontawesome5
ps.standalone
final.texliveDragonPackages.moloch
]);
} |> final.lib.recurseIntoAttrs;
racket-minimal = final.callPackage ./pkgs/racket/racket/minimal.nix {};
racket = final.callPackage ./pkgs/racket/racket/package.nix {};
@ -95,5 +121,51 @@ final: prev: {
buildRacketPackage = self.callPackage ./pkgs/racket/build-racket-package.nix {};
makeRacketEnv = self.callPackage ./pkgs/racket/make-racket-env.nix {};
} // (byName self));
} // (byName self)) |> final.lib.recurseIntoAttrs;
strawberry = prev.strawberry.overrideAttrs (afinal: aprev: {
version = "1.2.17";
src = final.fetchFromGitHub {
owner = "jonaski";
repo = "strawberry";
rev = afinal.version;
hash = "sha256-ZyWVOpa1laBUNW5lwbNeAmVBXEOLlXy+Xz8vbtuLi/8=";
};
patches = [
./pkgs/strawberry/0001-make-the-minimum-scrobble-length-shorter.patch
];
});
nix-serve-ng = final.haskell.lib.overrideCabal prev.nix-serve-ng (
final.callPackage ./pkgs/lix/nix-serve-ng {}
);
# export derivations modified in "typical" configurations for nixos, so they will be available in
# the CI cache
nixosDragonPackages = {
qemu_kvm_headless = prev.qemu_kvm.override {
gtkSupport = false;
sdlSupport = false;
openGLSupport = false;
rutabagaSupport = false;
};
nginxMainline_rtmp = final.nginxMainline.override (oldAttrs: {
modules = oldAttrs.modules ++ [ final.nginxModules.rtmp ];
});
podman_zfs = final.podman.override {
extraPackages = [
"/run/wrappers"
final.systemd
final.zfs
];
};
openocd_headless = final.openocd.override {
jimtcl = final.jimtcl.override {
SDLSupport = false;
};
};
} |> final.lib.recurseIntoAttrs;
}

View File

@ -52,10 +52,10 @@ in stdenvNoCC.mkDerivation rec {
chmod +x $out/bin/outer-wilds-text-adventure
'';
meta = with lib; {
meta = {
description = "Outer Wilds: A Thrilling Graphical Text Adventure";
homepage = "https://www.mobiusdigitalgames.com/outer-wilds-text-adventure.html";
license = licenses.unfree;
license = lib.licenses.unfree;
platforms = [ "x86_64-linux" ];
};
}

View File

@ -7,24 +7,24 @@
}:
let
appId = "1690800";
buildId = "19876517";
buildId = "21237536";
steamworks_sdk = fetchFromSteam {
name = "steamworks-sdk";
inherit appId;
depot = {
depotId = "1006";
manifestId = "5587033981095108078";
manifestId = "6403079453713498174";
};
hash = "sha256-CjrVpq5ztL6wTWIa63a/4xHM35DzgDR/O6qVf1YV5xw=";
hash = "sha256-q1A2ooLzKojf3kj5VCFSLngFv6522rXd5nApBQFDrHA=";
};
server_dist = fetchFromSteam {
name = "satisfactory-dedicated-server";
inherit appId;
depot = {
depotId = "1690802";
manifestId = "7620210706575413121";
manifestId = "6002578218905311874";
};
hash = "sha256-jQbtHSBFCDcdycrDjIJBY4DGV7EgITvwv3k3+htZ7io=";
hash = "sha256-OSS0tviycIOO9kvJzVHvnseYw0+gVLZOkLHyuXZSHvM=";
};
in stdenv.mkDerivation {
pname = "satisfactory-dedicated-server";
@ -69,11 +69,11 @@ in stdenv.mkDerivation {
$out/opt/Engine/Binaries/Linux/FactoryServer-Linux-Shipping
'';
meta = with lib; {
meta = {
description = "Satisfactory Dedicated Server";
homepage = "https://www.satisfactorygame.com/";
license = licenses.unfree;
license = lib.licenses.unfree;
platforms = [ "x86_64-linux" ];
sourceProvenance = [ sourceTypes.binaryNativeCode ];
sourceProvenance = with lib.sourceTypes; [ binaryNativeCode ];
};
}

View File

@ -1,199 +0,0 @@
From d9e022548aff94e90914baa921ddb4cd939c0e5c Mon Sep 17 00:00:00 2001
From: xenia <xenia@awoo.systems>
Date: Sat, 21 Dec 2024 15:33:10 -0500
Subject: [PATCH] implement lix support
---
CMakeLists.txt | 27 ------------
extra-builtins.cc | 91 ++++++++++++++++-------------------------
meson.build | 18 ++++++++
nix-plugins-config.h.in | 3 --
4 files changed, 53 insertions(+), 86 deletions(-)
delete mode 100644 CMakeLists.txt
create mode 100644 meson.build
delete mode 100644 nix-plugins-config.h.in
diff --git a/CMakeLists.txt b/CMakeLists.txt
deleted file mode 100644
index 9674fe8..0000000
--- a/CMakeLists.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-cmake_minimum_required (VERSION 3.9)
-project (nix-plugins)
-set (nix-plugins_VERSION_MAJOR 15)
-set (nix-plugins_VERSION_MINOR 0)
-set (nix-plugins_VERSION_PATCH 0)
-
-find_package(PkgConfig)
-
-pkg_check_modules(NIX REQUIRED nix-expr>=2.24 nix-main>=2.24 nix-store>=2.24)
-
-find_path(BOOST_INCLUDE_DIR boost/format.hpp)
-if(BOOST_INCLUDE_DIR STREQUAL "BOOST_INCLUDE_DIR-NOTFOUND")
- message(FATAL_ERROR "Could not find Boost formatting library.")
-endif()
-include_directories(${BOOST_INCLUDE_DIR})
-
-if(APPLE)
- set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -flat_namespace -undefined suppress")
-endif()
-
-add_library(nix-extra-builtins MODULE extra-builtins.cc)
-configure_file(nix-plugins-config.h.in nix-plugins-config.h)
-target_include_directories(nix-extra-builtins PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
-target_include_directories(nix-extra-builtins PUBLIC ${NIX_INCLUDE_DIRS})
-target_compile_options(nix-extra-builtins PUBLIC ${NIX_CFLAGS_OTHER})
-
-install(TARGETS nix-extra-builtins DESTINATION lib/nix/plugins)
diff --git a/extra-builtins.cc b/extra-builtins.cc
index 3a0f90e..95aef5e 100644
--- a/extra-builtins.cc
+++ b/extra-builtins.cc
@@ -1,12 +1,8 @@
-#include <config.h>
-#include <primops.hh>
-#include <globals.hh>
-#include <config-global.hh>
-#include <eval-settings.hh>
-#include <common-eval-args.hh>
-#include <filtering-source-accessor.hh>
-
-#include "nix-plugins-config.h"
+#include <lix/config.h>
+#include <lix/libexpr/primops.hh>
+#include <lix/libstore/globals.hh>
+#include <lix/libexpr/eval-settings.hh>
+#include <lix/libcmd/common-eval-args.hh>
using namespace nix;
@@ -21,42 +17,41 @@ static ExtraBuiltinsSettings extraBuiltinsSettings;
static GlobalConfig::Register rp(&extraBuiltinsSettings);
-static void extraBuiltins(EvalState & state, const PosIdx pos,
+static void extraBuiltins(EvalState & state,
Value ** _args, Value & v)
{
- static auto extraBuiltinsFile = state.rootPath(CanonPath(extraBuiltinsSettings.extraBuiltinsFile.to_string()));
- if (auto rootFS2 = state.rootFS.dynamic_pointer_cast<AllowListSourceAccessor>())
- rootFS2->allowPrefix(CanonPath(extraBuiltinsFile.path.abs()));
+ static auto extraBuiltinsFile =
+ SourcePath(CanonPath(extraBuiltinsSettings.extraBuiltinsFile.to_string()));
try {
- auto fun = state.allocValue();
- state.evalFile(extraBuiltinsFile, *fun);
- Value * arg;
- if (evalSettings.enableNativeCode) {
- arg = state.baseEnv.values[0];
- } else {
- auto attrs = state.buildBindings(2);
-
- auto sExec = state.symbols.create("exec");
- attrs.alloc(sExec).mkPrimOp(new PrimOp {
- .name = "exec",
- .arity = 1,
- .fun = prim_exec,
- });
-
- auto sImportNative = state.symbols.create("importNative");
- attrs.alloc(sImportNative).mkPrimOp(new PrimOp {
- .name = "importNative",
- .arity = 2,
- .fun = prim_importNative,
- });
-
- arg = state.allocValue();
- arg->mkAttrs(attrs);
- }
+ auto fun = state.ctx.mem.allocValue();
+
+ // bypass the source path checking by directly reading and evaluating the file
+ // this also bypasses the eval cache but oh well
+ Expr& e = state.ctx.parseExprFromFile(extraBuiltinsFile.unsafeIntoChecked());
+ state.eval(e, *fun);
+
+ auto attrs = state.ctx.buildBindings(2);
+
+ auto sExec = state.ctx.symbols.create("exec");
+ attrs.alloc(sExec).mkPrimOp(new PrimOp {
+ .name = "exec",
+ .arity = 1,
+ .fun = prim_exec,
+ });
+
+ auto sImportNative = state.ctx.symbols.create("importNative");
+ attrs.alloc(sImportNative).mkPrimOp(new PrimOp {
+ .name = "importNative",
+ .arity = 2,
+ .fun = prim_importNative,
+ });
+
+ Value* arg = state.ctx.mem.allocValue();
+ arg->mkAttrs(attrs);
v.mkApp(fun, arg);
- state.forceValue(v, pos);
- } catch (FileNotFound &) {
+ state.forceValue(v, noPos);
+ } catch (SysError &) {
v.mkNull();
}
}
@@ -66,19 +61,3 @@ static RegisterPrimOp rp1({
.arity = 0,
.fun = extraBuiltins,
});
-
-static void cflags(EvalState & state, const PosIdx _pos,
- Value ** _args, Value & v)
-{
- auto attrs = state.buildBindings(3);
- attrs.alloc("NIX_INCLUDE_DIRS").mkString(NIX_INCLUDE_DIRS);
- attrs.alloc("NIX_CFLAGS_OTHER").mkString(NIX_CFLAGS_OTHER);
- attrs.alloc("BOOST_INCLUDE_DIR").mkString(BOOST_INCLUDE_DIR);
- v.mkAttrs(attrs);
-}
-
-static RegisterPrimOp rp2({
- .name = "__nix-cflags",
- .arity = 0,
- .fun = cflags,
-});
diff --git a/meson.build b/meson.build
new file mode 100644
index 0000000..0be6ce6
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,18 @@
+project('lix-plugins',
+ ['c', 'cpp'],
+ default_options: ['cpp_std=gnu++20'],
+ version: '15.0.0')
+
+cpp = meson.get_compiler('cpp')
+pkgconfig = import('pkgconfig')
+
+lix_expr = dependency('lix-expr', version: '>=2.91')
+lix_store = dependency('lix-store', version: '>=2.91')
+lix_cmd = dependency('lix-cmd', version: '>=2.91')
+lix_main = dependency('lix-main', version: '>=2.91')
+boost = dependency('boost')
+
+library('lix-plugins',
+ 'extra-builtins.cc',
+ dependencies: [lix_expr, lix_store, lix_cmd, lix_main, boost],
+ install: true)
diff --git a/nix-plugins-config.h.in b/nix-plugins-config.h.in
deleted file mode 100644
index 459fea8..0000000
--- a/nix-plugins-config.h.in
+++ /dev/null
@@ -1,3 +0,0 @@
-#define NIX_INCLUDE_DIRS "@NIX_INCLUDE_DIRS@"
-#define NIX_CFLAGS_OTHER "@NIX_CFLAGS_OTHER@"
-#define BOOST_INCLUDE_DIR "@BOOST_INCLUDE_DIR@"
--
2.49.0

View File

@ -0,0 +1,8 @@
# lix-plugins
Based on code from <https://github.com/shlevy/nix-plugins>, which is released
under the MIT license located at
<https://github.com/shlevy/nix-plugins/blob/master/LICENSE>.
All modifications to the above codebase are copyright (c) 2025 xenia
<xenia@awoo.systems>; all rights reserved.

View File

@ -1,24 +1,18 @@
{
lib,
fetchFromGitHub,
stdenv,
clangStdenv,
meson,
ninja,
pkg-config,
lix,
capnproto,
boost182,
}: stdenv.mkDerivation {
boost,
}: clangStdenv.mkDerivation {
name = "lix-plugins";
src = fetchFromGitHub {
owner = "shlevy";
repo = "nix-plugins";
rev = "15.0.0";
hash = "sha256-C4VqKHi6nVAHuXVhqvTRRyn0Bb619ez4LzgUWPH1cbM=";
};
patches = [ ./0001-implement-lix-support.patch ];
src = ./.;
mesonBuildType = "release";
@ -30,14 +24,13 @@
buildInputs = [
lix
boost182
boost.dev
capnproto
];
meta = {
description = "Collection of miscellaneous plugins for the nix expression language.";
homepage = "https://github.com/shlevy/nix-plugins";
license = lib.licenses.mit;
license = with lib.licenses; [ mit fyptl ];
maintainers = [];
platforms = lib.platforms.all;
};

View File

@ -0,0 +1,62 @@
#include <lix/config.h>
#include <lix/libexpr/primops.hh>
#include <lix/libstore/globals.hh>
#include <lix/libexpr/eval-settings.hh>
#include <lix/libcmd/common-eval-args.hh>
using namespace nix;
struct ExtraBuiltinsSettings : Config {
Setting<Path> extraBuiltinsFile{this,
settings.nixConfDir + "/extra-builtins.nix",
"extra-builtins-file",
"The path to a nix expression defining extra expression-language level builtins."};
};
static ExtraBuiltinsSettings extraBuiltinsSettings;
static GlobalConfig::Register rp(&extraBuiltinsSettings);
static void prim_extraBuiltins(EvalState & state,
Value ** _args, Value & v)
{
static auto extraBuiltinsFile =
SourcePath(CanonPath(extraBuiltinsSettings.extraBuiltinsFile.to_string()));
try {
Value fun;
// bypass the source path checking by directly reading and evaluating the file
// this also bypasses the eval cache but oh well
Expr& e = state.ctx.parseExprFromFile(extraBuiltinsFile.unsafeIntoChecked());
state.eval(e, fun);
auto bindings = state.ctx.buildBindings(2);
// auto sExec = state.ctx.symbols.create("exec");
// attrs.alloc(sExec).mkPrimOp(new PrimOp {
// .name = "exec",
// .arity = 1,
// .fun = prim_exec,
// });
//
// auto sImportNative = state.ctx.symbols.create("importNative");
// attrs.alloc(sImportNative).mkPrimOp(new PrimOp {
// .name = "importNative",
// .arity = 2,
// .fun = prim_importNative,
// });
Value arg = Value(NewValueAs::attrs, bindings.finish());
v = Value(NewValueAs::app, state.ctx.mem, fun, arg);
state.forceValue(v, noPos);
} catch (SysError &) {
v.mkNull();
}
}
static RegisterPrimOp rp1({
.name = "__extraBuiltins",
.arity = 0,
.fun = prim_extraBuiltins,
});

View File

@ -0,0 +1,18 @@
project('lix-plugins',
['c', 'cpp'],
default_options: ['cpp_std=gnu++20'],
version: '15.0.0')
cpp = meson.get_compiler('cpp')
pkgconfig = import('pkgconfig')
lix_expr = dependency('lix-expr', version: '>=2.94')
lix_store = dependency('lix-store', version: '>=2.94')
lix_cmd = dependency('lix-cmd', version: '>=2.94')
lix_main = dependency('lix-main', version: '>=2.94')
boost = dependency('boost')
library('lix-plugins',
'extra-builtins.cc',
dependencies: [lix_expr, lix_store, lix_cmd, lix_main, boost],
install: true)

View File

@ -0,0 +1,12 @@
diff --git a/lix/libstore/meson.build b/lix/libstore/meson.build
index 64c4be468..19f4b1242 100644
--- a/lix/libstore/meson.build
+++ b/lix/libstore/meson.build
@@ -471,6 +471,6 @@ configure_file(
'libdir' : libdir,
'includedir' : includedir,
'PACKAGE_VERSION' : meson.project_version(),
- 'AWS_SDK_IF_FOUND' : aws_sdk.found() ? 'aws-cpp-sdk-core aws-cpp-sdk-s3 aws-cpp-std-transfer' : '',
+ 'AWS_SDK_IF_FOUND' : aws_sdk.found() ? 'aws-cpp-sdk-core aws-cpp-sdk-s3 aws-cpp-sdk-transfer' : '',
},
)

View File

@ -0,0 +1,32 @@
commit 1fa8df82df53a9255ecebf077b1698e7d86d5b08
Author: Qyriad <qyriad@qyriad.me>
Date: Tue, 18 Nov 2025 17:36:40 +0100
libutil: include LIX_MAJOR, LIX_MINOR, and LIX_PATCH macros
Fixes #1038
Change-Id: I7d8a4648890fce7ff15695876c9b9d3a6a6a6964
diff --git a/lix/meson.build b/lix/meson.build
index 40960c486..ac411679c 100644
--- a/lix/meson.build
+++ b/lix/meson.build
@@ -1,7 +1,17 @@
+# Cursed, but I don't think there's another way to get this environment variable.
+lix_suffix = run_command('bash', '-c', 'echo -n "$VERSION_SUFFIX"', check : true).stdout().strip()
+lix_version_parts = meson.project_version().split('.')
+lix_major = lix_version_parts[0]
+lix_minor = lix_version_parts[1]
+lix_patch = lix_version_parts[2].replace(lix_suffix, '')
+
config_h = configure_file(
configuration : {
'PACKAGE_NAME': '"' + meson.project_name() + '"',
'PACKAGE_VERSION': '"' + meson.project_version() + '"',
+ 'LIX_MAJOR': lix_major,
+ 'LIX_MINOR': lix_minor,
+ 'LIX_PATCH': lix_patch,
'PACKAGE_TARNAME': '"' + meson.project_name() + '"',
'PACKAGE_STRING': '"' + meson.project_name() + ' ' + meson.project_version() + '"',
'HAVE_STRUCT_DIRENT_D_TYPE': 1, # FIXME: actually check this for solaris

View File

@ -0,0 +1,29 @@
{
fetchFromGitHub,
lix,
boost,
capnproto,
}: prev: {
version = "1.1.0-unstable-2025-12-16";
src = fetchFromGitHub {
owner = "aristanetworks";
repo = "nix-serve-ng";
rev = "8ce0104efdf7f72e5a371bc48613084673b23cc0";
hash = "sha256-Pck7/jhaoYAUM9M0nWR/dwYEVwXXNP2bzB4+XtZBmno=";
};
configureFlags = (prev.configureFlags or []) ++ ["-flix"];
executablePkgconfigDepends = [
lix
];
executableSystemDepends = (prev.executableSystemDepends or []) ++ [
lix
boost.dev
capnproto
];
}

View File

@ -12,7 +12,7 @@
src = fetchurl {
url = "http://caml.inria.fr/distrib/ocaml-${version}/ocaml-${version}-refman-html.tar.gz";
hash = "sha256-NhtwltAJKxG5bwvu4hevK4xv45gRRaLEtNQ9ZW5NyvU=";
hash = "sha256-k1kARqMqsB2kODs5qdcFCi0Y3C44nOXebX3mKGlXDEY=";
};
buildPhase = "";

View File

@ -18,8 +18,8 @@ let feedvalidator_src = stdenvNoCC.mkDerivation {
src = fetchFromGitHub {
owner = "w3c";
repo = "feedvalidator";
rev = "1bbf6d9c68ef074b824c452fbc5d1f7817e6adae";
sha256 = "sha256-sHc6cgjSNcd0BcYYeybGPayQNV8SK9GjUglWg9iOQko=";
rev = "96fbf7e918293da0e3dfd06b2dece14da65ba2aa";
sha256 = "sha256-aNRtW+YnLKPdVURKxDd/QR+/Vfp93TmGnm8hf8Q5Gz0=";
};
installPhase = ''

View File

@ -2,11 +2,15 @@
fetchPypi,
buildPythonPackage,
setuptools,
pyserial,
pyserial-asyncio,
}: buildPythonPackage rec {
pname = "megacom";
version = "0.1.2";
pyproject = true;
build-system = [ setuptools ];
src = fetchPypi {
inherit pname version;
sha256 = "sha256-q2sU37uTX98RJDF0WFt7vzqtfLk3u25COCdKt34/Z70=";

View File

@ -0,0 +1,16 @@
#hash(
("ansi-color" . #hash((license . "LGPL-3.0-or-later")))
("cldr-bcp47" . #hash((license . "(MIT AND Unicode-TOU)")))
("cldr-core" . #hash((license . "(MIT AND Unicode-TOU)")))
("cldr-localenames-modern" . #hash((license . "(MIT AND Unicode-TOU)")))
("cldr-dates-modern" . #hash((license . "(MIT AND Unicode-TOU)")))
("cldr-numbers-modern" . #hash((license . "(MIT AND Unicode-TOU)")))
("memoize-lib" . #hash((license . "MIT")))
("gregor-lib" . #hash((license . "MIT")))
("tzinfo" . #hash((license . "MIT")))
("resyntax" . #hash((license . "Apache-2.0")))
("br-parser-tools-lib" . #hash((license . "LGPL-3.0-or-later")))
("brag-lib" . #hash((license . "MIT")))
("fancy-app" . #hash((license . "MIT")))
("rebellion" . #hash((license . "Apache-2.0")))
)

View File

@ -4,17 +4,17 @@
fetchFromGitHub,
}: (buildRacketPackage {
pname = "guard";
version = "0.0+de93f4b";
version = "0.0+c86ee57";
dependencies = [];
src = fetchFromGitHub {
owner = "jackfirth";
repo = "guard";
rev = "de93f4b5f38f1086177a09a40583af2932759b75";
hash = "sha256-z5sUidOIadtOZqVRBPxjIAz/D71U9XiE06EE+DGZzBg=";
rev = "c86ee57d3fc13eed689102b733702ed1162da681";
hash = "sha256-Vtcgb9LbaiBkF2ixIwXnQ78rIoou5mYDoy1R6tyz5d8=";
};
gitSubpath = ".";
passthru = {
racketModules = ["guard/private/scribble-evaluator-factory.rkt" "guard/scribblings/guard.scrbl" "guard/main.rkt"];
racketModules = ["guard/scribblings/guard.scrbl" "guard/main.rkt" "guard/private/scribble-evaluator-factory.rkt"];
racketLaunchers = [];
racoCommands = [];
};

View File

@ -5,13 +5,13 @@
fetchFromGitHub,
}: (buildRacketPackage {
pname = "north";
version = "0.8+00e5221";
version = "0.8+0eae6bf";
dependencies = [gregor-lib];
src = fetchFromGitHub {
owner = "Bogdanp";
repo = "racket-north";
rev = "00e52217081d421bcdd1c2248e309e0d92dd5314";
hash = "sha256-oSjrLNsQ53vUIFRF2spie7o/NSrlF29Dqw2et9Isf3o=";
rev = "0eae6bf000b35f23ed0ddc03cfb96f1518bbacc5";
hash = "sha256-13YWJOYvR4FXoQpxxMFDefroQweyRaMQxpd++vTYx0k=";
};
gitSubpath = "north";
passthru = {

File diff suppressed because one or more lines are too long

View File

@ -1,11 +1,11 @@
{
"version": "8.18",
"version": "9.1",
"full": {
"filename": "racket-8.18-src.tgz",
"sha256": "65477c71ec1a978a6ee4db582b9b47b1a488029d7a42e358906de154a6e5905c"
"filename": "racket-9.1-src.tgz",
"sha256": "1062dce1826884a2a758b565318570440dfd06699f1b1c47cd27d805e4f6833e"
},
"minimal": {
"filename": "racket-minimal-8.18-src.tgz",
"sha256": "24b9cf8365254b43bac308192c782edfbd86363df1322c4e063b797ed0f7db66"
"filename": "racket-minimal-9.1-src.tgz",
"sha256": "d68e7f392cc842cf29daee2a8a9297a52881ba280c6a4c6108c02ae8c77357d5"
}
}

View File

@ -118,7 +118,7 @@ stdenv.mkDerivation (finalAttrs: {
}@config:
assert lib.assertMsg (libraries == [ ]) "library integration for Racket has not been implemented";
writers.makeScriptWriter (
builtins.removeAttrs config [ "libraries" ]
removeAttrs config [ "libraries" ]
// {
interpreter = "${lib.getExe finalAttrs.finalPackage}";
}

View File

@ -10,7 +10,7 @@ runCommandLocal "racket-test-get-version-and-variant"
}
(
lib.concatLines (
builtins.map
map
(
{ expectation, output }:
''

539
pkgs/racket/racket2nix.rkt Normal file
View File

@ -0,0 +1,539 @@
#lang racket/base
(require
racket/file
racket/function
racket/hash
racket/list
racket/match
racket/port
racket/runtime-path
racket/sandbox
racket/sequence
racket/set
racket/string
net/url
pkg/lib
setup/getinfo)
(define main-dist-pkgs
(list->set (installed-pkg-names #:scope 'installation)))
(define (process-dep dep)
(match dep
[(? string? _) dep]
[(cons "base" _)
"base"]
[(cons name args*)
(let/ec exit
(define args
(for/list ([v (in-slice 2 args*)]) (cons (first v) (second v))))
(match (assq '#:platform args)
[(cons _ 'windows) (exit #f)]
[(cons _ 'unix) (void)]
[(cons _ plat) (error "unhandled platform" plat)]
[#f (void)])
(match (assq '#:version args)
[#f (void)]
[(cons _ _) (displayln "WARNING: unhandled version spec")])
name)]))
(define (process-deps deps)
(for/list ([dep (in-list deps)]
#:do [(define dep* (process-dep dep))]
#:when dep*
#:unless (set-member? main-dist-pkgs dep*))
dep*))
(define-runtime-path overrides-path "racket-catalog-overrides.rktd")
(define catalog-overrides (file->value overrides-path))
(define (racket-license->nix-license license)
(if license
(let ([lic-expr (with-input-from-string license read)])
`(list ,@(cvtl lic-expr)))
(begin
(displayln "WARNING: no license for package -- using unfree")
'(dot (dot lib licenses) unfree))))
(define (cvtl lic-expr)
(match lic-expr
[(? symbol? _)
(list `(dot (dot lib licensesSpdx) ,(symbol->string lic-expr)))]
[`(,a OR ,b)
(append (cvtl a) (cvtl b))]
[`(,a AND ,b)
(append (cvtl a) (cvtl b))]
[`(,a WITH ,b)
(error "unhandled with" lic-expr)]))
(define (module-name mod-spec)
(match mod-spec
[`(lib ,mod-name) mod-name]
[_ (error "unrecognized module spec" mod-spec)]))
(define (extract-path query)
(match (assq 'path query)
[#f #f]
[(cons _ value) value]))
;; (list 'github owner repo rev path)
;; (list 'git url rev path)
;; (list 'archive url)
;; - note if the archive contains a single directory inside, that dir is the top level
;; .plt is not supported
(define (normalize-source source checksum)
(define u (string->url source))
(match (string->url source)
[(or (url "github" _ _ _ _
(or
(list
(path/param owner '())
(path/param repo '()))
(list
(path/param owner '())
(path/param repo '())
; there might be a branch/tag -- ignore it and use "checksum" as rev
_))
(app extract-path path-maybe)
_)
(url (pregexp #px"^git|(git\\+)?https?$") _ "github.com" _ _
(list
(path/param owner '())
(path/param (pregexp #px"^(.*?)(\\.git)?$" (list _ repo _)) '()))
(app extract-path path-maybe)
_))
(list
'github
owner
repo
checksum
path-maybe)]
[(or (url "github" _ _ _ _ _ _ _)
(url (pregexp #px"^git|(git\\+)?https?$") _ "github.com" _ _ _ _ _))
(error "invalid github url" source)]
[(or (url (or "git" "git+http" "git+https") _ _ _ _ _
(app extract-path path-maybe)
_)
(url (or "http" "https") _ _ _ _
(or
(list _ ... (path/param (pregexp #px"\\.git$") '()))
(list _ ... (path/param (pregexp #px"\\.git$") '()) (path/param "" '())))
(app extract-path path-maybe)
_))
(define u*
(url
(url-scheme u)
(url-user u)
(url-host u)
(url-port u)
(url-path-absolute? u)
(url-path u)
'()
#f))
(list 'git (url->string u*) checksum path-maybe)]
[(url (or "http" "https") _ _ _ _
(list _ ... (path/param (pregexp #px"\\.(zip|tar|tgz|tar\\.gz)$") '()))
_ _)
(list 'archive source)]
[_ (error "unrecognized source url" source)]))
(define (extract-free-vars expr [scope (set)])
(match expr
[`(dot ,a ,(or (? symbol? b) (? string? b)))
(extract-free-vars a)]
[`(app ,fun ,arg)
(append (extract-free-vars fun scope)
(extract-free-vars arg scope))]
[`(attrs (,names ,values) ...)
(for/fold ([acc '()]) ([name (in-list names)] [value (in-list values)])
(append acc (extract-free-vars value scope)))]
[`(templatestring ,exprs ...)
(for/fold ([acc '()]) ([expr (in-list exprs)])
(append acc (extract-free-vars expr scope)))]
[`(list ,exprs ...)
(for/fold ([acc '()]) ([expr (in-list exprs)])
(append acc (extract-free-vars expr scope)))]
[(? symbol? _)
(if (set-member? scope expr)
'()
(list expr))]
[(? string? _) '()]
[(? boolean? _) '()]
[(? number? _) '()]))
(define (callpackageify expr)
(define free-vars (set->list (list->set (extract-free-vars expr))))
`(function
,free-vars
,expr))
(define (render-nix expr)
(match expr
[(or (? number? _)
(? symbol? _)
(? string? _))
(write expr)]
[(? boolean? _)
(write-string (if expr "true" "false"))]
[`(function ,vars ,expr)
(write-string "{\n")
(for ([var (in-list vars)])
(write var)
(write-string ",\n"))
(write-string "}:\n")
(render-nix expr)]
[`(app ,fun ,arg)
(write-string "(")
(render-nix fun)
(write-string " ")
(render-nix arg)
(write-string ")")]
[`(list ,exprs ...)
(write-string "[")
(for ([expr (in-list exprs)])
(write-string "(")
(render-nix expr)
(write-string ") "))
(write-string "]")]
[`(dot ,a ,b)
(write-string "(")
(render-nix a)
(write-string ").")
(render-nix b)]
[`(templatestring ,exprs ...)
(write-string "\"")
(for ([expr (in-list exprs)])
(if (string? expr)
(write-string expr)
(begin
(write-string "${")
(render-nix expr)
(write-string "}"))))
(write-string "\"")]
[`(attrs (,names ,values) ...)
(write-string "{\n")
(for ([name (in-list names)] [value (in-list values)])
(write name)
(write-string " = ")
(render-nix value)
(write-string ";\n"))
(write-string "}")])
(void))
(define (call-with-subprocess-env thk)
(parameterize ([current-subprocess-custodian-mode 'kill]
[current-environment-variables
(environment-variables-copy (current-environment-variables))])
(putenv "TERM" "dumb")
(putenv "NO_COLOR" "1")
(call-with-custodian-shutdown
thk)))
(define (subprocess/path/piped . args)
(define-values [proc stdout stdin stderr]
(apply subprocess #f #f 'stdout "/usr/bin/env" args))
(values proc stdout stdin))
(struct nix-repl [proc stdout stdin])
(define current-nix-repl (make-parameter #f))
(define (call-with-nix-repl thk)
(call-with-subprocess-env
(lambda ()
(define-values [proc stdout stdin]
(subprocess/path/piped
"nix"
"--extra-experimental-features"
"nix-command flakes pipe-operator repl-automation"
"repl" "--impure" "."))
(sync (regexp-match-evt #px"^[^\x05]+\x05" stdout))
(parameterize ([current-nix-repl (nix-repl proc stdout stdin)])
(thk)))))
(define (nix-eval line)
(match-define (nix-repl _ stdout stdin) (current-nix-repl))
(write-string line stdin)
(newline stdin)
(flush-output stdin)
(string-trim
(bytes->string/utf-8
(second
(sync (regexp-match-evt #px"^([^\x05]+)\x05" stdout))))))
(define (nix-format file*)
(displayln "formatting generated nix")
(define file (path->string file*))
(call-with-subprocess-env
(lambda ()
(define-values [proc stdout stdin]
(subprocess/path/piped
"alejandra" "--quiet" file))
(port->string stdout)
(subprocess-wait proc)))
(void))
(define (add-to-git-maybe file*)
(define file (path->string file*))
(call-with-subprocess-env
(lambda ()
(define-values (proc stdout stdin)
(subprocess/path/piped
"git" "rev-parse" "--show-toplevel"))
(port->string stdout)
(subprocess-wait proc)
(when (= 0 (subprocess-status proc))
(define-values [proc stdout stdin]
(subprocess/path/piped
"git" "add" file))
(port->string stdout)
(subprocess-wait proc)))))
(define (racket2nix
pkg-name
[force? #f]
[base-dir (build-path "racket-catalog")]
[acc (make-hash)])
(define pkg-dir (build-path base-dir pkg-name))
(when
(match (hash-ref acc pkg-name #f)
['pending (error "circular dependency!" pkg-name)]
['installed #f]
[#f (or (not (directory-exists? pkg-dir))
force?)])
(hash-set! acc pkg-name 'pending)
(printf "fetching info for ~a\n" pkg-name)
(define details* (get-pkg-details-from-catalogs pkg-name))
(define details
(if (hash-has-key? catalog-overrides pkg-name)
(let ([overrides (hash-ref catalog-overrides pkg-name)])
(printf "overriding ~a\n" pkg-name)
(for ([(k v) (in-hash details*)])
(when (hash-has-key? overrides k)
(printf " ~a: ~a -> ~a\n" k v (hash-ref overrides k))))
(hash-union
details*
overrides
#:combine/key (lambda (k v0 v) v)))
details*))
(define description (hash-ref details 'description))
(define license (hash-ref details 'license))
(define nix-license (racket-license->nix-license license))
(define dependencies (process-deps (hash-ref details 'dependencies)))
(define nix-deps
`(list ,@(map string->symbol dependencies)))
(for ([dependency (in-list dependencies)])
(racket2nix dependency force? base-dir acc))
(define broken? (not (hash-ref (hash-ref details 'search-terms) ':build-success:)))
(define source (hash-ref details 'source))
(define checksum (hash-ref details 'checksum))
(define git-shorthash (substring checksum 0 7))
(define source-desc (normalize-source source checksum))
(define readme (hash-ref details 'readme-url))
(define modules* (hash-ref details 'modules))
(define modules (map module-name modules*))
(make-directory* pkg-dir)
(define (generate-spec
[nix-hash '(dot lib fakeHash)]
[version "0.0"]
[racket-launchers '()]
[raco-commands '()]
[format? #f])
(define-values (nix-src* subpath)
(match source-desc
[(list 'github owner repo rev path)
(values
`((src
(app
fetchFromGitHub
(attrs
(owner ,owner)
(repo ,repo)
(rev ,rev)
(hash ,nix-hash))))
(gitSubpath ,(or path ".")))
(or path 'same))]
[(list 'git url rev path)
(values
`((src
(app
fetchgit
(attrs
(url ,url)
(rev ,rev)
(hash ,nix-hash))))
(gitSubpath ,(or path ".")))
(or path 'same))]
[(list 'archive url)
(values
`(app
fetchzip
(attrs
(url ,url)
(hash ,nix-hash)))
'same)]))
(define nix-version (format "~a+~a" version git-shorthash))
(define nix-meta
`(attrs
(description ,description)
(sourceProvenance (list (dot (dot lib sourceTypes) fromSource)))
(broken ,broken?)
(license ,nix-license)
,@(if readme `((homepage ,readme)) '())
,@(if (and racket-launchers (not (empty? racket-launchers)))
`((mainProgram ,(first racket-launchers)))
'())))
(define nix-passthru
`(attrs
(racketModules (list ,@modules))
(racketLaunchers (list ,@racket-launchers))
(racoCommands (list ,@raco-commands))))
(define nix-spec*
`(app
buildRacketPackage
(attrs
(pname ,pkg-name)
(version ,nix-version)
(dependencies ,nix-deps)
,@nix-src*
(passthru ,nix-passthru)
(meta ,nix-meta))))
(define nix-spec (callpackageify nix-spec*))
(define default-nix (build-path pkg-dir "default.nix"))
(with-output-to-file default-nix
(lambda ()
(render-nix nix-spec))
#:exists 'replace)
(when format?
(nix-format default-nix))
(add-to-git-maybe default-nix)
subpath)
(generate-spec)
(displayln "fetching source")
(call-with-nix-repl
(lambda ()
(define drv-def-out
(nix-eval
(format "drv = with legacyPackages.${builtins.currentSystem}; instrumentedFetch (racketPackages.~a.src)" pkg-name)))
(unless (equal? drv-def-out "Added drv.")
(error "failed to eval package def" drv-def-out))
(define build-output (nix-eval ":b drv"))
(define build-log (nix-eval ":log drv"))
(define real-hash
(match build-log
[(pregexp #px"FETCH_HASH:([^:]+):FETCH_HASH" (list _ real-hash))
real-hash]
[_ (error "failed to retrieve src hash" build-output build-log)]))
(define subpath (generate-spec real-hash))
(nix-eval ":r")
(define drv-def-out-r
(nix-eval
(format "drv = with legacyPackages.${builtins.currentSystem}; instrumentedFetch (racketPackages.~a.src)" pkg-name)))
(unless (equal? drv-def-out-r "Added drv.")
(error "failed to eval package def" drv-def-out-r))
(define out-path (nix-eval ":p drv.outPath"))
(define build-log-2 (nix-eval ":b drv"))
(unless (directory-exists? out-path)
(error "failed to fetch source" out-path build-log-2))
(define info-proc (get-info/full (build-path out-path subpath)))
(define version (info-proc 'version (lambda () "0.0")))
(define racket-launchers (info-proc 'racket-launcher-names (lambda () '())))
(define raco-commands* (info-proc 'raco-commands (lambda () '())))
(define raco-commands
(and raco-commands*
(map first raco-commands*)))
(generate-spec real-hash version racket-launchers raco-commands #t)
(displayln "doing final module build")
(nix-eval ":r")
(define drv-def-out-final
(nix-eval
(format "drv = with legacyPackages.${builtins.currentSystem}; racketPackages.~a" pkg-name)))
(unless (equal? drv-def-out-final "Added drv.")
(error "failed to eval package def" drv-def-out-final))
(define out-path-final (nix-eval ":p drv.outPath"))
(define build-output-final
(nix-eval ":b drv"))
(unless (directory-exists? out-path-final)
(error "failed to do final build" out-path-final build-output-final))
(void)))
(hash-set! acc pkg-name 'installed)
(void)))
(module+ main
(require racket/cmdline)
(define force? (make-parameter #f))
(define base-dir (make-parameter (build-path "racket-catalog")))
(command-line
#:program "racket2nix"
#:once-each
[("-f" "--force") "Overwrite existing nix files" (force? #t)]
[("-d" "--base-dir") bd "Base directory for nix files" (base-dir (bd))]
#:args (pkg . more-pkgs)
(define acc (make-hash))
(for ([pkg (in-list (cons pkg more-pkgs))])
(racket2nix pkg (force?) (base-dir) acc))))

View File

@ -1,66 +1,65 @@
{
lib,
fetchFromGitHub,
buildPythonPackage,
fetchFromGitHub,
setuptools,
libbs,
filelock,
gitpython,
prompt-toolkit,
pycparser,
sortedcontainers,
toml,
tqdm,
gitpython,
filelock,
pycparser,
ply,
prompt-toolkit,
tqdm,
wordfreq,
pyside6,
flask,
requests,
pytestCheckHook,
pytest-qt,
}: buildPythonPackage rec {
pytestCheckHook,
withGhidra ? false,
}:
buildPythonPackage rec {
pname = "binsync";
version = "5.7.10+dev";
version = "5.11.2+dev";
pyproject = true;
src = fetchFromGitHub {
owner = "binsync";
repo = "binsync";
rev = "e67da5ab9cddc2743f7462c9543ba7100e25eeb5";
hash = "sha256-QDOfbo2yjfjLsLILMhl/ckKwXDusXfE8+YmFpW5djN0=";
rev = "5e79ddceeef1a7ae138d93187060a5bb2b26ca9d";
hash = "sha256-Aeu1J9DMjfzOcGNAlPE/MZXlEh/qy9K4z7c1Vw/9Ozk=";
};
build-system = [ setuptools ];
dependencies = [
libbs
filelock
gitpython
prompt-toolkit
pycparser
(libbs.override { inherit withGhidra; })
sortedcontainers
toml
tqdm
gitpython
filelock
pycparser
ply
prompt-toolkit
tqdm
wordfreq
];
optional-dependencies = {
ghidra = [ pyside6 ];
};
flask
requests
] ++ lib.optionals withGhidra [ pyside6 ];
nativeCheckInputs = [
pytestCheckHook
pytest-qt
pyside6
];
] ++ lib.optionals withGhidra [ pytest-qt pyside6 ];
disabledTestPaths = [
# Test tries to import angrmanagement
# Test tries to import angr-management
"tests/test_angr_gui.py"
];
@ -71,5 +70,6 @@
homepage = "https://github.com/binsync/binsync";
changelog = "https://github.com/binsync/binsync/releases/tag/${src.tag}";
license = lib.licenses.bsd2;
maintainers = with lib.maintainers; [ scoder12 ];
};
}

View File

@ -1,77 +1,96 @@
{
lib,
fetchFromGitHub,
buildPythonPackage,
fetchFromGitHub,
setuptools,
filelock,
ghidra-bridge,
jfx-bridge,
networkx,
platformdirs,
prompt-toolkit,
psutil,
pycparser,
pyhidra,
toml,
tqdm,
ply,
pycparser,
prompt-toolkit,
tqdm,
psutil,
pyghidra,
platformdirs,
filelock,
networkx,
pytestCheckHook,
writableTmpDirAsHomeHook,
}: buildPythonPackage rec {
ghidra_headless,
withGhidra ? false,
}:
let
# Binary files from https://github.com/binsync/bs-artifacts (only used for testing and only here)
binaries = fetchFromGitHub {
owner = "binsync";
repo = "bs-artifacts";
rev = "514c2d6ef1875435c9d137bb5d99b6fc74063817";
hash = "sha256-P7+BTJgdC9W8cC/7xQduFYllF+0ds1dSlm59/BFvZ2g=";
};
in
buildPythonPackage rec {
pname = "libbs";
version = "2.16.4+dev";
version = "3.3.3+dev";
pyproject = true;
src = fetchFromGitHub {
owner = "binsync";
repo = "libbs";
rev = "0ce5c351cc81c1a0120f763aeba584fdb9dc2820";
hash = "sha256-if27Tg5S0Esrw9xHi6nr+kDIw4OTz7yZ2256/4Kbkeo=";
rev = "6959abaa1d9d784860349d2c023366088455cefe";
hash = "sha256-GMSwK6fZLTGIvEM151bBtHurxoI856FxNTHVpj+zQ30=";
};
build-system = [ setuptools ];
dependencies = [
filelock
ghidra-bridge
jfx-bridge
networkx
platformdirs
prompt-toolkit
psutil
pycparser
pyhidra
toml
tqdm
ply
];
pycparser
setuptools
prompt-toolkit
tqdm
psutil
platformdirs
filelock
networkx
] ++ lib.optionals withGhidra [ pyghidra ];
pythonRemoveDeps = lib.optionals (!withGhidra) [ "pyghidra" ];
nativeCheckInputs = [
pytestCheckHook
writableTmpDirAsHomeHook
];
] ++ (lib.optionals withGhidra [ ghidra_headless ]);
# Place test binaries in place
preCheck = ''
export HOME=$TMPDIR
mkdir -p $HOME/bs-artifacts/binaries
cp -r ${binaries}/binaries/. $HOME/bs-artifacts/binaries/.
export TEST_BINARIES_DIR=$HOME/bs-artifacts/binaries
'' + lib.optionalString withGhidra ''
export PATH="${lib.makeBinPath [ ghidra_headless.jdkPackage ]}:$PATH"
export NIX_GHIDRAHOME="${ghidra_headless}/lib/ghidra/Ghidra"
export GHIDRA_INSTALL_DIR="${ghidra_headless}/lib/ghidra"
'';
pythonImportsCheck = [ "libbs" ];
disabledTests = [
"test_change_watcher_plugin_cli"
"test_ghidra_artifact_watchers"
"TestHeadlessInterfaces"
];
disabledTestPaths = [
"tests/test_decompilers.py"
"tests/test_remote_ghidra.py"
];
] ++ lib.optionals (!withGhidra) [ "TestClientServer" ];
meta = {
description = "Library for writing plugins in any decompiler: includes API lifting, common data formatting, and GUI abstraction";
homepage = "https://github.com/binsync/libbs";
changelog = "https://github.com/binsync/libbs/releases/tag/${src.tag}";
license = lib.licenses.bsd2;
maintainers = with lib.maintainers; [ scoder12 ];
};
}

View File

@ -25,10 +25,10 @@ diff --git a/Ghidra/Debug/Debugger-rmi-trace/build.gradle b/Ghidra/Debug/Debugge
index 4fa3b9a539..2663aeaeb0 100644
--- a/Ghidra/Debug/Debugger-rmi-trace/build.gradle
+++ b/Ghidra/Debug/Debugger-rmi-trace/build.gradle
@@ -19,12 +19,17 @@ apply from: "${rootProject.projectDir}/gradle/helpProject.gradle"
apply from: "${rootProject.projectDir}/gradle/jacocoProject.gradle"
@@ -20,12 +20,17 @@ apply from: "${rootProject.projectDir}/gradle/jacocoProject.gradle"
apply from: "${rootProject.projectDir}/gradle/javaTestProject.gradle"
apply from: "${rootProject.projectDir}/gradle/distributableGhidraModule.gradle"
apply from: "${rootProject.projectDir}/gradle/javadoc.gradle"
-apply from: "${rootProject.projectDir}/gradle/hasProtobuf.gradle"
apply from: "${rootProject.projectDir}/gradle/hasPythonPackage.gradle"
-
@ -45,7 +45,7 @@ index 4fa3b9a539..2663aeaeb0 100644
dependencies {
api project(':ProposedUtils')
api project(':Pty')
@@ -37,13 +42,10 @@ dependencies {
@@ -38,13 +43,10 @@ dependencies {
}
task configureGenerateProtoPy {
@ -66,7 +66,7 @@ diff --git a/build.gradle b/build.gradle
index 159eb7dd7b..ef4add1ad8 100644
--- a/build.gradle
+++ b/build.gradle
@@ -80,6 +80,12 @@ if (flatRepo.isDirectory()) {
@@ -79,6 +79,12 @@ if (flatRepo.isDirectory()) {
mavenCentral()
flatDir name: "flat", dirs:["$flatRepo"]
}
@ -84,7 +84,7 @@ deleted file mode 100644
index a8c176bcbe..0000000000
--- a/gradle/hasProtobuf.gradle
+++ /dev/null
@@ -1,98 +0,0 @@
@@ -1,100 +0,0 @@
-/* ###
- * IP: GHIDRA
- *
@ -111,38 +111,40 @@ index a8c176bcbe..0000000000
-
-def platform = getCurrentPlatformName()
-
-def version = getProperty('ghidra.protobuf.java.version')
-
-
-dependencies {
- allProtocArtifacts 'com.google.protobuf:protoc:3.21.8:windows-x86_64@exe'
- allProtocArtifacts 'com.google.protobuf:protoc:3.21.8:linux-x86_64@exe'
- allProtocArtifacts 'com.google.protobuf:protoc:3.21.8:linux-aarch_64@exe'
- allProtocArtifacts 'com.google.protobuf:protoc:3.21.8:osx-x86_64@exe'
- allProtocArtifacts 'com.google.protobuf:protoc:3.21.8:osx-aarch_64@exe'
- allProtocArtifacts "com.google.protobuf:protoc:${version}:windows-x86_64@exe"
- allProtocArtifacts "com.google.protobuf:protoc:${version}:linux-x86_64@exe"
- allProtocArtifacts "com.google.protobuf:protoc:${version}:linux-aarch_64@exe"
- allProtocArtifacts "com.google.protobuf:protoc:${version}:osx-x86_64@exe"
- allProtocArtifacts "com.google.protobuf:protoc:${version}:osx-aarch_64@exe"
-
- if (isCurrentWindows()) {
- protocArtifact 'com.google.protobuf:protoc:3.21.8:windows-x86_64@exe'
- protocArtifact "com.google.protobuf:protoc:${version}:windows-x86_64@exe"
- }
- if (isCurrentLinux()) {
- if (platform.endsWith("x86_64")) {
- protocArtifact 'com.google.protobuf:protoc:3.21.8:linux-x86_64@exe'
- protocArtifact "com.google.protobuf:protoc:${version}:linux-x86_64@exe"
- }
- else {
- protocArtifact 'com.google.protobuf:protoc:3.21.8:linux-aarch_64@exe'
- protocArtifact "com.google.protobuf:protoc:${version}:linux-aarch_64@exe"
- }
- }
- if (isCurrentMac()) {
- if (platform.endsWith("x86_64")) {
- protocArtifact 'com.google.protobuf:protoc:3.21.8:osx-x86_64@exe'
- protocArtifact "com.google.protobuf:protoc:${version}:osx-x86_64@exe"
- }
- else {
- protocArtifact 'com.google.protobuf:protoc:3.21.8:osx-aarch_64@exe'
- protocArtifact "com.google.protobuf:protoc:${version}:osx-aarch_64@exe"
- }
- }
-}
-
-/*protobuf {
- protoc {
- artifact = 'com.google.protobuf:protoc:3.21.8'
- artifact = 'com.google.protobuf:protoc:${version}'
- }
-}*/
-

View File

@ -4,8 +4,8 @@ index ea12a661f0..da7779b07f 100644
+++ b/Ghidra/Framework/Utility/src/main/java/utility/application/ApplicationUtilities.java
@@ -36,6 +36,10 @@ public class ApplicationUtilities {
*/
public static Collection<ResourceFile> findDefaultApplicationRootDirs() {
Collection<ResourceFile> applicationRootDirs = new ArrayList<>();
public static SequencedCollection<ResourceFile> findDefaultApplicationRootDirs() {
List<ResourceFile> applicationRootDirs = new ArrayList<>();
+ String nixGhidraHome = System.getenv("NIX_GHIDRAHOME");
+ if (nixGhidraHome != null) {
+ applicationRootDirs.add(new ResourceFile(nixGhidraHome));

View File

@ -0,0 +1,33 @@
diff -crb a/src/pyghidra/launcher.py b/src/pyghidra/launcher.py
*** a/src/pyghidra/launcher.py Sun Feb 1 03:03:21 2026
--- b/src/pyghidra/launcher.py Sun Feb 1 03:03:15 2026
***************
*** 693,698 ****
--- 693,703 ----
GUI pyghidra launcher
"""
+ def __init__(self, *args, **kwargs) -> None:
+ super().__init__(*args, **kwargs)
+ if sys.platform == "linux":
+ self.vm_args.append("--add-opens=java.desktop/sun.awt.X11=ALL-UNNAMED")
+
@classmethod
def popup_error(cls, header: str, msg: str) -> NoReturn:
import tkinter.messagebox
***************
*** 713,718 ****
--- 718,730 ----
return None
def _launch(self):
+ if sys.platform == "linux":
+ from java.awt import Toolkit
+ xToolkit = Toolkit.getDefaultToolkit()
+ awtAppClassNameField = xToolkit.getClass().getDeclaredField("awtAppClassName")
+ awtAppClassNameField.setAccessible(True)
+ awtAppClassNameField.set(xToolkit, "ghidra-Ghidra")
+
from ghidra import Ghidra
from java.lang import Runtime, Thread # type:ignore @UnresolvedImport

View File

@ -19,7 +19,7 @@
let
pname = "ghidra";
version = "11.4.2";
version = "12.0";
isMacArm64 = stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isAarch64;
@ -29,7 +29,7 @@ let
owner = "NationalSecurityAgency";
repo = "Ghidra";
rev = "Ghidra_${version}_build";
hash = "sha256-/veSp2WuGOF0cYwUC4QFJD6kaMae5NuKrQ5Au4LjDe8=";
hash = "sha256-eDYbvD3Ln7twGCOBQsP8UfWAjyJUO/ofr/oitaEtCu4=";
# populate values that require us to use git. By doing this in postFetch we
# can delete .git afterwards and maintain better reproducibility of the src.
leaveDotGit = true;
@ -213,6 +213,10 @@ stdenv.mkDerivation (finalAttrs: {
"-Dcpu.core.limit="
"-Dcpu.core.override="
"-Djavax.xml.accessExternalDTD="
"-Djavax.xml.accessExternalSchema="
"-Djavax.xml.accessExternalStylesheet="
] ++ (lib.optionals stdenv.hostPlatform.isDarwin [
"-Xdock:name=$APPNAME"
"-Declipse.filelock.disable=true"
@ -251,9 +255,12 @@ stdenv.mkDerivation (finalAttrs: {
;
withExtensions = callPackage ./with-extensions.nix { ghidra = finalAttrs.finalPackage; };
jdkPackage = openjdk21;
ghidraLib = finalAttrs.finalPackage.lib;
};
meta = with lib; {
meta = {
changelog = "https://htmlpreview.github.io/?https://github.com/NationalSecurityAgency/ghidra/blob/Ghidra_${finalAttrs.version}_build/Ghidra/Configurations/Public_Release/src/global/docs/ChangeHistory.html";
description = "Software reverse engineering (SRE) suite of tools";
mainProgram = "ghidra";
@ -264,12 +271,12 @@ stdenv.mkDerivation (finalAttrs: {
"x86_64-darwin"
"aarch64-darwin"
];
sourceProvenance = with sourceTypes; [
sourceProvenance = with lib.sourceTypes; [
fromSource
binaryBytecode # deps
];
license = licenses.asl20;
maintainers = with maintainers; [
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [
roblabla
vringar
];

View File

@ -55,9 +55,6 @@
"83/1c/25b79fc3ec99b19b0a0730cc47356f7e2959863bf9f3cd314332bddb4f68/pywin32-306-cp312-cp312-win_amd64": {
"whl": "sha256-NyV3lMGtOe6b5lLaBGLcLjlMgVnf2ROopOjrb9NG2g4="
},
"8d/14/619e24a4c70df2901e1f4dbc50a6291eb63a759172558df326347dce1f0d/protobuf-3.20.3-py2.py3-none-any": {
"whl": "sha256-p8ptSIqo/38ynUxUWy262KwxRk8dixyHrRNGcXcx5Ns="
},
"8d/e4/0c27352e8222dcc0e3ce44b298015072d2057d08dd353541c980a31d26c9/jpype1-1.5.2-cp312-cp312-macosx_10_9_universal2": {
"whl": "sha256-Hh25rJCa0q4OQLBMKqiMsUJQ1SRdaXFVYVB2gfKwiy8="
},
@ -94,6 +91,9 @@
"ec/1a/610693ac4ee14fcdf2d9bf3c493370e4f2ef7ae2e19217d7a237ff42367d/packaging-23.2-py3-none-any": {
"whl": "sha256-jEkRkAM6mvfh2THQtdrMLvR1CbNN0N5n7SCbUgP8iMc="
},
"ee/01/1ed1d482960a5718fd99c82f6d79120181947cfd4667ec3944d448ed44a3/protobuf-6.31.0-py3-none-any": {
"whl": "sha256-asLoJVboIsF6jSOqEZC7wdBu+5wmGYHalcccnaCeniM="
},
"fa/4c/e0200a6e3fed5cda79e926c2a8a610676f04948f89d7e38d93c7d4b21be9/jpype1-1.5.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64": {
"whl": "sha256-mU+3sxm0U/d61Lav8B4N1BgOp0pv5aAx5OnbktvpU3Y="
}
@ -103,42 +103,54 @@
"tar.gz": "sha256-r9wisKblvse2VyN1a5DUTqkR5hsvewHE3FUkq4E7TYk="
}
},
"https://github.com/NationalSecurityAgency/ghidra-data/raw/Ghidra_11.4.2": {
"Debugger/dbgmodel": {
"https://github.com": {
"NationalSecurityAgency/ghidra-data/raw/Ghidra_12.0/Debugger/dbgmodel": {
"tlb": "sha256-jPXzouuBFgqjSQVqXKTCxyaxtumL8wl81BNRRxYzQ8c="
},
"FunctionID/vs2012_x64": {
"NationalSecurityAgency/ghidra-data/raw/Ghidra_12.0/FunctionID/vs2012_x64": {
"fidb": "sha256-1OmKs/eQuDF5MhhDC7oNiySl+/TaZbDB/6jLDPvrDNw="
},
"FunctionID/vs2012_x86": {
"NationalSecurityAgency/ghidra-data/raw/Ghidra_12.0/FunctionID/vs2012_x86": {
"fidb": "sha256-pJDtfi7SHlh0Wf6urOcDa37eTOhOcuEN/YxXQ0ppGLY="
},
"FunctionID/vs2015_x64": {
"NationalSecurityAgency/ghidra-data/raw/Ghidra_12.0/FunctionID/vs2015_x64": {
"fidb": "sha256-4E6eQPnstgHIX02E7Zv2a0U2O+HR6CwWLkyZArjLUI8="
},
"FunctionID/vs2015_x86": {
"NationalSecurityAgency/ghidra-data/raw/Ghidra_12.0/FunctionID/vs2015_x86": {
"fidb": "sha256-tm7mlmU+LtNlkZ3qrviFEDEgx5LiLnmvcNEgnX4dhkQ="
},
"FunctionID/vs2017_x64": {
"NationalSecurityAgency/ghidra-data/raw/Ghidra_12.0/FunctionID/vs2017_x64": {
"fidb": "sha256-1fpfaXKYF0+lPSR9NZnmoSiEYFrRgce5VOI4DsHwvYk="
},
"FunctionID/vs2017_x86": {
"NationalSecurityAgency/ghidra-data/raw/Ghidra_12.0/FunctionID/vs2017_x86": {
"fidb": "sha256-04nLjXb/SlnKNfiRuFIccq1fDfluJTlzotIahhSkzIE="
},
"FunctionID/vs2019_x64": {
"NationalSecurityAgency/ghidra-data/raw/Ghidra_12.0/FunctionID/vs2019_x64": {
"fidb": "sha256-FQAHeW/DakBpZgrWJEmq2q890Rs4ZKXvIeeYMcnOkRg="
},
"FunctionID/vs2019_x86": {
"NationalSecurityAgency/ghidra-data/raw/Ghidra_12.0/FunctionID/vs2019_x86": {
"fidb": "sha256-62MKNvqlhqNx63NNwLvY0TzK72l/PbWHJZY1jz3SQyo="
},
"FunctionID/vsOlder_x64": {
"NationalSecurityAgency/ghidra-data/raw/Ghidra_12.0/FunctionID/vsOlder_x64": {
"fidb": "sha256-jDtR9GYM0n4aDWEKnz8tX7yDOmasnuQ5PuLySB6FWGY="
},
"FunctionID/vsOlder_x86": {
"NationalSecurityAgency/ghidra-data/raw/Ghidra_12.0/FunctionID/vsOlder_x86": {
"fidb": "sha256-mGBca2uSFKlF2ETkHIWGDVRkmkW8p4c+9pkcDpNyB4c="
},
"lib/java-sarif-2.1-modified": {
"NationalSecurityAgency/ghidra-data/raw/Ghidra_12.0/lib/java-sarif-2.1-modified": {
"jar": "sha256-f3NlZklHVtJxql5LGvbIncUNB0qxxjdKR9+CImQiawE="
},
"Z3Prover/z3/releases/download/z3-4.13.0/z3-4.13.0-arm64-osx-11.0": {
"zip": "sha256-580yXLIhDTskHQ1VF6KTZ3Aw9YwXceGWxFdO+Z3EUWg="
},
"Z3Prover/z3/releases/download/z3-4.13.0/z3-4.13.0-x64-glibc-2.31": {
"zip": "sha256-vDGtEkRtfbG9nQrILeyde1EpuLjdbkS1cag6xgENL5s="
},
"Z3Prover/z3/releases/download/z3-4.13.0/z3-4.13.0-x64-osx-11.7.10": {
"zip": "sha256-DDPYV099zQQfH05/4wGEDbalJ/hmy3SwtHUYv4BTUC0="
},
"Z3Prover/z3/releases/download/z3-4.13.0/z3-4.13.0-x64-win": {
"zip": "sha256-K80UtoSf3erT0LPLZxzJ0TSo7wsdPv8+/X11pbvwDdM="
}
},
"https://repo.maven.apache.org/maven2": {
@ -249,19 +261,29 @@
"jar": "sha256-8CqV+hpele2z7YWf0Pt99wnRIaNSkO/4t03OKrf01u0=",
"pom": "sha256-N/h3mLGDhRE8kYv6nhJ2/lBzXvj6hJtYAMUZ1U2/Efg="
},
"com/google/protobuf#protobuf-bom/3.21.8": {
"pom": "sha256-+7Ds/DyjGFddtifjOuRUwT1qTcp68UXRTT9m4IY8PPo="
"com/google/protobuf#protobuf-bom/3.17.3": {
"pom": "sha256-bf431vImF9VqQUzNrf+NmFhaH3kXEr6HbCYWZxDR2N0="
},
"com/google/protobuf#protobuf-bom/4.31.0": {
"pom": "sha256-Y9iGmhie8C2+3XxnN+FsGYa0aYOufQyNG+8s92sz2Ac="
},
"com/google/protobuf#protobuf-gradle-plugin/0.8.18": {
"jar": "sha256-RP2JrzepsvHdQcCUqbtzPAe/f8eg4jhooQuvbjUfpeA=",
"pom": "sha256-Gwqekab09LYqWmB4wibudwqo3FdnueRzwvwY8KOImAQ="
},
"com/google/protobuf#protobuf-java/3.21.8": {
"jar": "sha256-C4WBrYENLfrv0Nz78VabFFBEhlAjjX4v1rF2yTLQjJU=",
"pom": "sha256-OJBUBuApx6MYaW8O4RnFXM7HizN+oR5MMZWfDgardAg="
"com/google/protobuf#protobuf-java/3.17.3": {
"jar": "sha256-SsVJsZJpQUGVgEnwYKHIJqMzQvYZ4QjO2MF9mHf14+0=",
"pom": "sha256-Km8izVJli4uxTBANs+F5NT+MNR0ENzo79voKOzlGStw="
},
"com/google/protobuf#protobuf-parent/3.21.8": {
"pom": "sha256-bHKyrDl1sAnR5FdQlVnp+onyV4vShD3LTWo+XPgRFws="
"com/google/protobuf#protobuf-java/4.31.0": {
"jar": "sha256-aHc9zNbMWDWvenSHWc7PXqIP8IMTbjhH++lFcrjg7Wo=",
"pom": "sha256-aElbKMVNzVwyTQxRb7igjQoaJWvNrIFIN+ciYfEqCdM="
},
"com/google/protobuf#protobuf-parent/3.17.3": {
"pom": "sha256-T09Q5moqvM/o7SCbU/q3C4k+NfQ77FqB98GESbY+hrE="
},
"com/google/protobuf#protobuf-parent/4.31.0": {
"pom": "sha256-H1mhQuar05Jar9Fo25tU0QhP7MhPW4DU3jVPrJ4I/Lg="
},
"com/h2database#h2/2.2.220": {
"jar": "sha256-l4q4YwGNP5ZeOIgFccNik+qLEKgIYZQVnE1dILUPClc=",

View File

@ -3,39 +3,21 @@
fetchFromGitHub,
buildGhidraScripts,
runCommand,
rsync,
python311,
python3,
}: let
python = python311;
libbs_path = "${python.pkgs.libbs}/${python.sitePackages}";
binsync_path = "${python.pkgs.binsync}/${python.sitePackages}";
binsync_env = python.withPackages (ps: with ps; ([
binsync
] ++ binsync.optional-dependencies.ghidra));
python = python3;
in buildGhidraScripts {
pname = "BinSync";
inherit (python.pkgs.binsync) version;
src = runCommand "binsync-ghidra-scripts" {
nativeBuildInputs = [ rsync ];
nativeBuildInputs = [];
strictDeps = true;
} ''
mkdir -p $out
rsync -r \
--exclude='__pycache__' \
--exclude='/__init__.py' \
${libbs_path}/libbs/decompiler_stubs/ghidra_libbs/. $out/.
cp ${binsync_path}/binsync/binsync_plugin.py $out
'';
postPatch = ''
substituteInPlace binsync_plugin.py \
--replace-fail 'plugin_command = "binsync -s ghidra"' \
'plugin_command = "${lib.getExe' binsync_env "binsync"} -s ghidra"'
cp ${python.pkgs.binsync.src}/binsync/binsync_plugin.py $out
'';
meta = {

View File

@ -5,13 +5,13 @@
}:
buildGhidraExtension (finalAttrs: {
pname = "findcrypt";
version = "3.1.2";
version = "3.1.4";
src = fetchFromGitHub {
owner = "antoniovazquezblanco";
repo = "GhidraFindcrypt";
rev = "v${finalAttrs.version}";
hash = "sha256-KP6Wx2U8O/37yEAcV3abKg/uWraHJJOIfb7kvcfejHA=";
hash = "sha256-ZrPLAjdfqHVjnOSBMTrXWK9DDHyIwaUt0ZYCwGiGLBg=";
};
meta = {

View File

@ -0,0 +1,35 @@
{
lib,
fetchFromGitHub,
maven,
}:
maven.buildMavenPackage rec {
pname = "binary-file-toolkit";
version = "0.4.0";
src = fetchFromGitHub {
owner = "boricj";
repo = "binary-file-toolkit";
tag = "v${version}";
hash = "sha256-ABDJDdx0OxXVOgYAw4kZAP3Psr+w7YevP1xk1RszXw8=";
};
mvnHash = "sha256-Ek2qulMSHd1ZJfEloo6fIe+QMqub/Ftna/TzTt01ky8=";
installPhase = ''
runHook preInstall
mkdir -p $out/
cp dist/* $out/
runHook postInstall
'';
meta = {
description = "Set of Java libraries for manipulating toolchain file formats";
homepage = "https://github.com/boricj/binary-file-toolkit";
changelog = "https://github.com/boricj/binary-file-toolkit/releases";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ timschumi ];
};
}

View File

@ -1,23 +1,35 @@
{
callPackage,
lib,
buildGhidraExtension,
gradle,
fetchFromGitHub,
binary-file-toolkit ? callPackage ./binary-file-toolkit.nix { },
}:
buildGhidraExtension (finalAttrs: {
pname = "ghidra-delinker-extension";
version = "0.5.1";
version = "0.7.0";
src = fetchFromGitHub {
owner = "boricj";
repo = "ghidra-delinker-extension";
rev = "v${finalAttrs.version}";
hash = "sha256-h6F50Z7S6tPOl9mIhChLKoFxHuAkq/n36ysUEFwWGxI=";
hash = "sha256-Hgpf1eqP/DRYczRDvAhXTWoycHe8N/xhMorlYDjytZg=";
};
patches = [
# The GitHub Maven repository is not available unauthenticated,
# so patch in the dependency this way and replace the fake path
# with the locally built derivation later.
# This is tracked at boricj/binary-file-toolkit#1.
./local-binary-file-toolkit.patch
];
postPatch = ''
substituteInPlace build.gradle \
--replace-fail '"''${getGitHash()}"' '"v${finalAttrs.version}"'
--replace-fail '"''${getGitHash()}"' '"v${finalAttrs.version}"' \
--replace-fail '"@binary-file-toolkit@"' '"${binary-file-toolkit}"'
'';
gradleBuildTask = "buildExtension";

View File

@ -0,0 +1,23 @@
diff --git a/build.gradle b/build.gradle
index 6f3bc6f..16fc51b 100644
--- a/build.gradle
+++ b/build.gradle
@@ -55,16 +55,8 @@ else {
repositories {
mavenLocal()
mavenCentral()
- maven {
- name = "boricj's binary-file-toolkit"
- url = uri("https://maven.pkg.github.com/boricj/binary-file-toolkit")
- credentials(HttpHeaderCredentials) {
- name = "Authorization"
- value = "Bearer " + project.findProperty("githubToken") as String ?: System.getenv("GITHUB_TOKEN")
- }
- authentication {
- header(HttpHeaderAuthentication)
- }
+ flatDir {
+ dirs "@binary-file-toolkit@"
}
}

View File

@ -5,13 +5,13 @@
}:
buildGhidraExtension (finalAttrs: {
pname = "ghidra-firmware-utils";
version = "2024.04.20";
version = "2026.01.14";
src = fetchFromGitHub {
owner = "al3xtjames";
repo = "ghidra-firmware-utils";
rev = finalAttrs.version;
hash = "sha256-BbPRSD1EzgMA3TCKHyNqLjzEgiOm67mLJuOeFOTvd0I=";
hash = "sha256-FEjcqsisMvmNCQikon/3EEkLEtgKmGRBl/WwZebP+/A=";
};
meta = {

View File

@ -5,6 +5,7 @@
binwalk,
swift,
yara,
useSwift ? false,
}:
buildGhidraScripts {
@ -20,16 +21,25 @@ buildGhidraScripts {
postPatch = ''
# Replace subprocesses with store versions
substituteInPlace binwalk.py --replace-fail 'subprocess.call(["binwalk"' 'subprocess.call(["${binwalk}/bin/binwalk"'
substituteInPlace swift_demangler.py --replace-fail '"swift"' '"${swift}/bin/swift"'
substituteInPlace yara.py --replace-fail 'subprocess.check_output(["yara"' 'subprocess.check_output(["${yara}/bin/yara"'
substituteInPlace YaraSearch.py --replace-fail '"yara "' '"${yara}/bin/yara "'
'';
substituteInPlace binwalk.py --replace-fail 'subprocess.call(["binwalk"' 'subprocess.call(["${lib.getExe binwalk}"'
substituteInPlace yara.py --replace-fail 'subprocess.check_output(["yara"' 'subprocess.check_output(["${lib.getExe yara}"'
substituteInPlace YaraSearch.py --replace-fail '"yara "' '"${lib.getExe yara} "'
''
+ (
if useSwift then
''
substituteInPlace swift_demangler.py --replace-fail '"swift"' '"${lib.getExe' swift "swift"}"'
''
else
''
rm swift_demangler.py
''
);
meta = with lib; {
meta = {
description = "Scripts for the Ghidra software reverse engineering suite";
homepage = "https://github.com/ghidraninja/ghidra_scripts";
license = with licenses; [
license = with lib.licenses; [
gpl3Only
gpl2Only
];

View File

@ -61,10 +61,10 @@ buildGhidraExtension {
runHook postInstall
'';
meta = with lib; {
meta = {
description = "Leverage the binutils disassembler capabilities for various processors";
homepage = "https://ghidra-sre.org/";
downloadPage = "https://github.com/NationalSecurityAgency/ghidra/tree/master/GPL/GnuDisassembler";
license = licenses.gpl2Only;
license = lib.licenses.gpl2Only;
};
}

View File

@ -26,13 +26,13 @@ let
self = buildGhidraExtension (finalAttrs: {
pname = "kaiju";
version = "250828";
version = "260116";
src = fetchFromGitHub {
owner = "CERTCC";
repo = "kaiju";
rev = finalAttrs.version;
hash = "sha256-edsQIBoOTY+WxVBtH1bbM7TZZHhA0jgVb2iJKC66iVM=";
hash = "sha256-cEGBBVuXUcacPzfc1cWGjDPWt8IfGNakDvfzoDCaBAI=";
};
buildInputs = [

View File

@ -23,11 +23,11 @@ buildGhidraExtension {
runHook postInstall
'';
meta = with lib; {
meta = {
inherit (ghidra.meta) homepage license;
description = "Finds functions using ML";
downloadPage = "https://github.com/NationalSecurityAgency/ghidra/tree/master/Ghidra/Extensions/MachineLearning";
sourceProvenance = with sourceTypes; [
sourceProvenance = with lib.sourceTypes; [
fromSource
binaryBytecode # deps
];

View File

@ -34,9 +34,9 @@ buildGhidraExtension {
rm dist/ghidra*
mv dist/safe.zip dist/$correct_version
'';
meta = with lib; {
meta = {
description = "Reverse-Engineering Tools SYNChronization. Allows syncing between a debugging session and Ghidra";
homepage = "https://github.com/bootleg/ret-sync";
license = licenses.gpl3Only;
license = lib.licenses.gpl3Only;
};
}

View File

@ -25,7 +25,7 @@ buildGhidraExtension {
runHook postInstall
'';
meta = with lib; {
meta = {
inherit (ghidra.meta) homepage license;
description = "Sleigh language development tools including external disassembler capabilities";
longDescription = ''
@ -33,7 +33,7 @@ buildGhidraExtension {
The GnuDisassembler extension may be also be required as a disassembly provider.
'';
downloadPage = "https://github.com/NationalSecurityAgency/ghidra/tree/master/Ghidra/Extensions/SleighDevTools";
sourceProvenance = with sourceTypes; [
sourceProvenance = with lib.sourceTypes; [
fromSource
binaryBytecode # deps
];

View File

@ -7,13 +7,13 @@
}:
buildGhidraExtension (finalAttrs: {
pname = "wasm";
version = "2.3.2";
version = "2.4.0";
src = fetchFromGitHub {
owner = "nneonneo";
repo = "ghidra-wasm-plugin";
rev = "v${finalAttrs.version}";
hash = "sha256-JFUPhh4WUcfxYow3kLMyva1Ni/cQBIit983o/KbbKps=";
hash = "sha256-2JNenzUac/OpjQ+fN1MkP8E2KIT1Ifn+C/18buSpqrE=";
};
nativeBuildInputs = [ ant ];

View File

@ -0,0 +1,35 @@
{
lib,
buildPythonPackage,
setuptools,
jpype1,
ghidra,
withBin ? false,
}: buildPythonPackage {
pname = "pyghidra";
version = "3.0.0";
src = "${ghidra.ghidraLib.src}/Ghidra/Features/PyGhidra/src/main/py";
patches = [
./0004-PyGhidra-restore-wmclass.patch
];
pyproject = true;
build-system = [ setuptools ];
dependencies = [
jpype1
];
pythonRelaxDeps = [ "jpype1" ];
makeWrapperArgs = lib.optionals withBin [
"--prefix" "PATH" ":" (lib.makeBinPath [ ghidra.jdkPackage ])
"--set-default" "NIX_GHIDRAHOME" "${ghidra}/lib/ghidra/Ghidra"
"--set-default" "GHIDRA_INSTALL_DIR" "${ghidra.ghidraLib}/lib/ghidra"
];
}

View File

@ -30,6 +30,7 @@ let
makeBinaryWrapper
] ++ lib.optional stdenv.hostPlatform.isDarwin desktopToDarwinBundle;
postBuild = ''
mkdir -p $out/lib/ghidra/Ghidra
# Prevent attempted creation of plugin lock files in the Nix store.
touch $out/lib/ghidra/Ghidra/.dbDirLock
@ -45,6 +46,10 @@ let
+ lib.optionalString stdenv.hostPlatform.isDarwin ''
convertDesktopFiles $prefix
'';
passthru = {
jdkPackage = ghidra.jdkPackage;
ghidraLib = ghidra.lib;
};
inherit (ghidra) meta;
});
in

View File

@ -173,12 +173,12 @@ in stdenv.mkDerivation (self: {
inherit pythonEnv;
};
meta = with lib; {
meta = {
description = "A powerful disassembler, decompiler and a versatile debugger.";
homepage = "https://hex-rays.com/ida-pro";
mainProgram = "ida";
platforms = [ "x86_64-linux" ];
sourceProvenance = with sourceTypes; [ binaryNativeCode ];
sourceProvenance = with lib.sourceTypes; [ binaryNativeCode ];
license = lib.licenses.unfree;
};
})

View File

@ -0,0 +1,493 @@
From 208a9c9b5d771c92df79cf32aabb5a1315dec56b Mon Sep 17 00:00:00 2001
From: xenia <xenia@awoo.systems>
Date: Wed, 24 Dec 2025 16:25:47 -0500
Subject: [PATCH] make the minimum scrobble length shorter
---
src/playlist/playlist.cpp | 2 +-
src/settings/scrobblersettingspage.ui | 2 +-
src/translations/strawberry_ca_ES.ts | 4 ++--
src/translations/strawberry_cs_CZ.ts | 4 ++--
src/translations/strawberry_de_DE.ts | 2 +-
src/translations/strawberry_el_CY.ts | 4 ++--
src/translations/strawberry_el_GR.ts | 4 ++--
src/translations/strawberry_en_US.ts | 2 +-
src/translations/strawberry_es_AR.ts | 2 +-
src/translations/strawberry_es_ES.ts | 2 +-
src/translations/strawberry_es_MX.ts | 2 +-
src/translations/strawberry_et_EE.ts | 2 +-
src/translations/strawberry_fi_FI.ts | 4 ++--
src/translations/strawberry_fr_BE.ts | 2 +-
src/translations/strawberry_fr_FR.ts | 2 +-
src/translations/strawberry_hu_HU.ts | 2 +-
src/translations/strawberry_id_ID.ts | 2 +-
src/translations/strawberry_is_IS.ts | 2 +-
src/translations/strawberry_it_IT.ts | 2 +-
src/translations/strawberry_ja_JP.ts | 2 +-
src/translations/strawberry_ko_KR.ts | 2 +-
src/translations/strawberry_nb_NO.ts | 2 +-
src/translations/strawberry_nl_NL.ts | 4 ++--
src/translations/strawberry_pl_PL.ts | 2 +-
src/translations/strawberry_pt_BR.ts | 4 ++--
src/translations/strawberry_ru_RU.ts | 2 +-
src/translations/strawberry_sv_SE.ts | 2 +-
src/translations/strawberry_tr_CY.ts | 4 ++--
src/translations/strawberry_tr_TR.ts | 4 ++--
src/translations/strawberry_uk_UA.ts | 2 +-
src/translations/strawberry_vi_VN.ts | 2 +-
src/translations/strawberry_zh_CN.ts | 2 +-
src/translations/strawberry_zh_TW.ts | 4 ++--
33 files changed, 43 insertions(+), 43 deletions(-)
diff --git a/src/playlist/playlist.cpp b/src/playlist/playlist.cpp
index 5b95d2bd..c823f7df 100644
--- a/src/playlist/playlist.cpp
+++ b/src/playlist/playlist.cpp
@@ -117,7 +117,7 @@ constexpr QRgb kInvalidSongColor = qRgb(0xC0, 0xC0, 0xC0);
constexpr int kDynamicHistoryPriority = 100;
constexpr QRgb kDynamicHistoryColor = qRgb(0x80, 0x80, 0x80);
-constexpr qint64 kMinScrobblePointNsecs = 31LL * kNsecPerSec;
+constexpr qint64 kMinScrobblePointNsecs = 16LL * kNsecPerSec;
constexpr qint64 kMaxScrobblePointNsecs = 240LL * kNsecPerSec;
constexpr int kMaxPlayedIndexes = 100;
diff --git a/src/settings/scrobblersettingspage.ui b/src/settings/scrobblersettingspage.ui
index 0b0606c4..3848c743 100644
--- a/src/settings/scrobblersettingspage.ui
+++ b/src/settings/scrobblersettingspage.ui
@@ -30,7 +30,7 @@
<item>
<widget class="QLabel" name="label_scrobble_info">
<property name="text">
- <string>Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</string>
+ <string>Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</string>
</property>
<property name="wordWrap">
<bool>true</bool>
diff --git a/src/translations/strawberry_ca_ES.ts b/src/translations/strawberry_ca_ES.ts
index 08fa29d0..672687e1 100644
--- a/src/translations/strawberry_ca_ES.ts
+++ b/src/translations/strawberry_ca_ES.ts
@@ -5702,8 +5702,8 @@ Esteu segur que voleu continuar?</translation>
<translation type="unfinished">Enable</translation>
</message>
<message>
- <source>Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
- <translation type="unfinished">Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</translation>
+ <source>Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
+ <translation type="unfinished">Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</translation>
</message>
<message>
<source>Show scrobble button</source>
diff --git a/src/translations/strawberry_cs_CZ.ts b/src/translations/strawberry_cs_CZ.ts
index 3a31995c..fb88f8ca 100644
--- a/src/translations/strawberry_cs_CZ.ts
+++ b/src/translations/strawberry_cs_CZ.ts
@@ -5712,8 +5712,8 @@ Opravdu chcete pokračovat?</translation>
<translation>Povolit</translation>
</message>
<message>
- <source>Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
- <translation type="unfinished">Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</translation>
+ <source>Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
+ <translation type="unfinished">Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</translation>
</message>
<message>
<source>Show scrobble button</source>
diff --git a/src/translations/strawberry_de_DE.ts b/src/translations/strawberry_de_DE.ts
index 3254eafa..221cd984 100644
--- a/src/translations/strawberry_de_DE.ts
+++ b/src/translations/strawberry_de_DE.ts
@@ -5702,7 +5702,7 @@ Möchten Sie wirklich fortfahren?</translation>
<translation>Aktivieren</translation>
</message>
<message>
- <source>Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
+ <source>Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
<translation>Lieder werden gescrobbelt, wenn sie gültige Metadaten haben und länger als 30 Sekunden sind, mindestens die Hälfte ihrer Dauer oder 4 Minuten (je nachdem, was früher eintritt) abgespielt wurden.</translation>
</message>
<message>
diff --git a/src/translations/strawberry_el_CY.ts b/src/translations/strawberry_el_CY.ts
index 436137b1..7f6130bb 100644
--- a/src/translations/strawberry_el_CY.ts
+++ b/src/translations/strawberry_el_CY.ts
@@ -5702,8 +5702,8 @@ Are you sure you want to continue?</translation>
<translation type="unfinished">Enable</translation>
</message>
<message>
- <source>Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
- <translation type="unfinished">Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</translation>
+ <source>Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
+ <translation type="unfinished">Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</translation>
</message>
<message>
<source>Show scrobble button</source>
diff --git a/src/translations/strawberry_el_GR.ts b/src/translations/strawberry_el_GR.ts
index c825f932..a966220c 100644
--- a/src/translations/strawberry_el_GR.ts
+++ b/src/translations/strawberry_el_GR.ts
@@ -5702,8 +5702,8 @@ Are you sure you want to continue?</source>
<translation>Ενεργοποίηση</translation>
</message>
<message>
- <source>Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
- <translation type="unfinished">Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</translation>
+ <source>Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
+ <translation type="unfinished">Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</translation>
</message>
<message>
<source>Show scrobble button</source>
diff --git a/src/translations/strawberry_en_US.ts b/src/translations/strawberry_en_US.ts
index 8e08cc97..a1c387e8 100644
--- a/src/translations/strawberry_en_US.ts
+++ b/src/translations/strawberry_en_US.ts
@@ -5698,7 +5698,7 @@ Are you sure you want to continue?</source>
<translation type="unfinished"></translation>
</message>
<message>
- <source>Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
+ <source>Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
<translation type="unfinished"></translation>
</message>
<message>
diff --git a/src/translations/strawberry_es_AR.ts b/src/translations/strawberry_es_AR.ts
index 3ee6ea55..5f4dc1f5 100644
--- a/src/translations/strawberry_es_AR.ts
+++ b/src/translations/strawberry_es_AR.ts
@@ -5701,7 +5701,7 @@ Are you sure you want to continue?</source>
<translation>Activar</translation>
</message>
<message>
- <source>Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
+ <source>Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
<translation>La reproducción de una canción es registrada solo si dispone de metadatos válidos, dura más de 30 segundos y se ha reproducido al menos durante la mitad de su duración o 4 minutos (lo que ocurra primero).</translation>
</message>
<message>
diff --git a/src/translations/strawberry_es_ES.ts b/src/translations/strawberry_es_ES.ts
index 66e7881a..e766f973 100644
--- a/src/translations/strawberry_es_ES.ts
+++ b/src/translations/strawberry_es_ES.ts
@@ -5701,7 +5701,7 @@ Are you sure you want to continue?</source>
<translation>Activar</translation>
</message>
<message>
- <source>Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
+ <source>Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
<translation>La reproducción de un tema se registra solo si dispone de metadatos válidos, dura más de 30 segundos y se ha reproducido al menos durante la mitad de su duración o 4 minutos (lo que ocurra primero).</translation>
</message>
<message>
diff --git a/src/translations/strawberry_es_MX.ts b/src/translations/strawberry_es_MX.ts
index 15128cb0..0a670041 100644
--- a/src/translations/strawberry_es_MX.ts
+++ b/src/translations/strawberry_es_MX.ts
@@ -5701,7 +5701,7 @@ Are you sure you want to continue?</source>
<translation>Activar</translation>
</message>
<message>
- <source>Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
+ <source>Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
<translation>La reproducción de una canción es registrada solo si dispone de metadatos válidos, dura más de 30 segundos y se ha reproducido al menos durante la mitad de su duración o 4 minutos (lo que ocurra primero).</translation>
</message>
<message>
diff --git a/src/translations/strawberry_et_EE.ts b/src/translations/strawberry_et_EE.ts
index db45d2b5..29709722 100644
--- a/src/translations/strawberry_et_EE.ts
+++ b/src/translations/strawberry_et_EE.ts
@@ -5702,7 +5702,7 @@ Kas soovid jätkata?</translation>
<translation>Luba</translation>
</message>
<message>
- <source>Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
+ <source>Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
<translation>Lood kraasitakse, kui neil on kehtivad metaandmed ja need on pikemad kui 30 sekundit, neid on esitatud vähemalt pool kestusest või 4 minutit (olenevalt sellest, kumb saabub varem).</translation>
</message>
<message>
diff --git a/src/translations/strawberry_fi_FI.ts b/src/translations/strawberry_fi_FI.ts
index d9480396..74127dc2 100644
--- a/src/translations/strawberry_fi_FI.ts
+++ b/src/translations/strawberry_fi_FI.ts
@@ -5702,8 +5702,8 @@ Haluatko varmasti jatkaa?</translation>
<translation>Ota käyttöön</translation>
</message>
<message>
- <source>Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
- <translation type="unfinished">Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</translation>
+ <source>Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
+ <translation type="unfinished">Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</translation>
</message>
<message>
<source>Show scrobble button</source>
diff --git a/src/translations/strawberry_fr_BE.ts b/src/translations/strawberry_fr_BE.ts
index 2e4db5af..9ddfb22b 100644
--- a/src/translations/strawberry_fr_BE.ts
+++ b/src/translations/strawberry_fr_BE.ts
@@ -5702,7 +5702,7 @@ Are you sure you want to continue?</source>
<translation>Activer</translation>
</message>
<message>
- <source>Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
+ <source>Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
<translation>Les musiques sont scrobblées si leurs métadonnées sont valides et n&apos;ont pas plus de 30 secondes, ont été jouées pour un minimum de leur moitiés de leur longueur ou plus de 4 minutes (la première des conditions qui est vérifiée).</translation>
</message>
<message>
diff --git a/src/translations/strawberry_fr_FR.ts b/src/translations/strawberry_fr_FR.ts
index efc76390..d8342595 100644
--- a/src/translations/strawberry_fr_FR.ts
+++ b/src/translations/strawberry_fr_FR.ts
@@ -5702,7 +5702,7 @@ Are you sure you want to continue?</source>
<translation>Activer</translation>
</message>
<message>
- <source>Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
+ <source>Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
<translation>Les musiques sont scrobblées si leurs métadonnées sont valides et n&apos;ont pas plus de 30 secondes, ont été jouées pour un minimum de leur moitiés de leur longueur ou plus de 4 minutes (la première des conditions qui est vérifiée).</translation>
</message>
<message>
diff --git a/src/translations/strawberry_hu_HU.ts b/src/translations/strawberry_hu_HU.ts
index 25225a06..f2050f6d 100644
--- a/src/translations/strawberry_hu_HU.ts
+++ b/src/translations/strawberry_hu_HU.ts
@@ -5702,7 +5702,7 @@ Biztos, hogy folytatja?</translation>
<translation>Engedélyezés</translation>
</message>
<message>
- <source>Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
+ <source>Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
<translation>A számok akkor lesznek scrobble-ozva, ha érvényes metaadataik vannak, 30
másodpercnél hosszabbak, illetve legalább a felükig vagy 4 percig vannak lejátszva (amelyik korábban teljesül).</translation>
</message>
diff --git a/src/translations/strawberry_id_ID.ts b/src/translations/strawberry_id_ID.ts
index 02371af3..1a82f28a 100644
--- a/src/translations/strawberry_id_ID.ts
+++ b/src/translations/strawberry_id_ID.ts
@@ -5697,7 +5697,7 @@ Apakah Anda yakin ingin melanjutkan?</translation>
<translation>Fungsikan</translation>
</message>
<message>
- <source>Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
+ <source>Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
<translation>Lagu akan di-scrobble jika memiliki metadata yang benar dan lebih panjang dari 30 detik, sudah berputar setidaknya setengah dari durasinya atau 4 menit (yang mana terdahulu terjadi).</translation>
</message>
<message>
diff --git a/src/translations/strawberry_is_IS.ts b/src/translations/strawberry_is_IS.ts
index 0223dac1..f7ce4bd6 100644
--- a/src/translations/strawberry_is_IS.ts
+++ b/src/translations/strawberry_is_IS.ts
@@ -5702,7 +5702,7 @@ Ertu viss um að þú viljir halda áfram?</translation>
<translation>Virkja</translation>
</message>
<message>
- <source>Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
+ <source>Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
<translation>Skráðar eru hlustunarvenjur laga (scrobbling) ef þau eru með gild lýsigögn og eru lengri en 30 sekúndur, hafa verið spiluð að minnsta kosti til hálfs eða í 4 mínútur (hvort sem fyrr gerist).</translation>
</message>
<message>
diff --git a/src/translations/strawberry_it_IT.ts b/src/translations/strawberry_it_IT.ts
index 57a0d812..683a388c 100644
--- a/src/translations/strawberry_it_IT.ts
+++ b/src/translations/strawberry_it_IT.ts
@@ -5710,7 +5710,7 @@ Non possiamo aiutarti a procurarteli.</translation>
<translation>Abilita</translation>
</message>
<message>
- <source>Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
+ <source>Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
<translation>I brani vengono inviate per lo scrobble se hanno dei metadata validi, durano più di 30 secondi e sono state riprodotti per almeno la metà della loro lunghezza totale o per 4 minuti (qualsiasi dei quali avvenga prima)</translation>
</message>
<message>
diff --git a/src/translations/strawberry_ja_JP.ts b/src/translations/strawberry_ja_JP.ts
index 8573ff85..f307e194 100644
--- a/src/translations/strawberry_ja_JP.ts
+++ b/src/translations/strawberry_ja_JP.ts
@@ -5697,7 +5697,7 @@ Are you sure you want to continue?</source>
<translation>有効</translation>
</message>
<message>
- <source>Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
+ <source>Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
<translation>有効なメタデータで30秒以上ある曲で、再生時間が少なくとも半分または4分間どちらか早い方になると、曲は Scrobble されます。</translation>
</message>
<message>
diff --git a/src/translations/strawberry_ko_KR.ts b/src/translations/strawberry_ko_KR.ts
index 1dae09d4..b83c151a 100644
--- a/src/translations/strawberry_ko_KR.ts
+++ b/src/translations/strawberry_ko_KR.ts
@@ -5697,7 +5697,7 @@ Are you sure you want to continue?</source>
<translation>활성화</translation>
</message>
<message>
- <source>Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
+ <source>Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
<translation>곡에 올바른 메타데이터가 있고, 재생 시간이 30초보다 길고, 재생 시간의 절반 이상 재생(최대 4분)되었을 때 스크로블 기록에 추가됩니다.</translation>
</message>
<message>
diff --git a/src/translations/strawberry_nb_NO.ts b/src/translations/strawberry_nb_NO.ts
index f73e8b43..dcb93fb6 100644
--- a/src/translations/strawberry_nb_NO.ts
+++ b/src/translations/strawberry_nb_NO.ts
@@ -5702,7 +5702,7 @@ Er du sikker?</translation>
<translation>Aktiver</translation>
</message>
<message>
- <source>Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
+ <source>Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
<translation>Sanger blir scrobblet når de har gyldig metadata, er lengre enn 30 seconds, og har blitt spilt for minst halve tiden, eller 30 sekunder (det som skjer tidligst).</translation>
</message>
<message>
diff --git a/src/translations/strawberry_nl_NL.ts b/src/translations/strawberry_nl_NL.ts
index e24a97ee..df12582e 100644
--- a/src/translations/strawberry_nl_NL.ts
+++ b/src/translations/strawberry_nl_NL.ts
@@ -5702,8 +5702,8 @@ Weet je zeker dat je verder wilt gaan?</translation>
<translation>Ingeschakeld</translation>
</message>
<message>
- <source>Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
- <translation type="unfinished">Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</translation>
+ <source>Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
+ <translation type="unfinished">Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</translation>
</message>
<message>
<source>Show scrobble button</source>
diff --git a/src/translations/strawberry_pl_PL.ts b/src/translations/strawberry_pl_PL.ts
index 06196ef2..acfb3949 100644
--- a/src/translations/strawberry_pl_PL.ts
+++ b/src/translations/strawberry_pl_PL.ts
@@ -5714,7 +5714,7 @@ Na pewno chcesz usunąć?</translation>
<translation>Włącz</translation>
</message>
<message>
- <source>Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
+ <source>Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
<translation>Utwory są scrobblowane, jeśli mają poprawne metadane, są dłuższe niż&#xa0;30 sekund oraz były odtwarzane przez przynajmniej połowę swojej długości lub przez 4 minuty.</translation>
</message>
<message>
diff --git a/src/translations/strawberry_pt_BR.ts b/src/translations/strawberry_pt_BR.ts
index ca786c8a..742df605 100644
--- a/src/translations/strawberry_pt_BR.ts
+++ b/src/translations/strawberry_pt_BR.ts
@@ -5702,8 +5702,8 @@ Deseja continuar?</translation>
<translation>Habilitar</translation>
</message>
<message>
- <source>Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
- <translation type="unfinished">Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</translation>
+ <source>Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
+ <translation type="unfinished">Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</translation>
</message>
<message>
<source>Show scrobble button</source>
diff --git a/src/translations/strawberry_ru_RU.ts b/src/translations/strawberry_ru_RU.ts
index 7e0af15b..79c0e52e 100644
--- a/src/translations/strawberry_ru_RU.ts
+++ b/src/translations/strawberry_ru_RU.ts
@@ -5712,7 +5712,7 @@ Are you sure you want to continue?</source>
<translation>Включить</translation>
</message>
<message>
- <source>Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
+ <source>Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
<translation>Песни скробблятся, если они содержат допустимые метаданные, длятся более 30 секунд и воспроизводятся не менее половины своей длительности или в течение 4 минут (в зависимости от того, что произойдёт раньше).</translation>
</message>
<message>
diff --git a/src/translations/strawberry_sv_SE.ts b/src/translations/strawberry_sv_SE.ts
index d255a6aa..9fc5b773 100644
--- a/src/translations/strawberry_sv_SE.ts
+++ b/src/translations/strawberry_sv_SE.ts
@@ -5702,7 +5702,7 @@ Are you sure you want to continue?</source>
<translation>Aktivera</translation>
</message>
<message>
- <source>Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
+ <source>Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
<translation>Låtar skrobblas om de har giltiga metadata och är längre än 30 sekunder, har spelats under minst halva dess varaktighet eller i 4 minuter (beroende på vilket som inträffar först).</translation>
</message>
<message>
diff --git a/src/translations/strawberry_tr_CY.ts b/src/translations/strawberry_tr_CY.ts
index 18153843..d2213129 100644
--- a/src/translations/strawberry_tr_CY.ts
+++ b/src/translations/strawberry_tr_CY.ts
@@ -5702,8 +5702,8 @@ Are you sure you want to continue?</translation>
<translation type="unfinished">Enable</translation>
</message>
<message>
- <source>Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
- <translation type="unfinished">Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</translation>
+ <source>Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
+ <translation type="unfinished">Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</translation>
</message>
<message>
<source>Show scrobble button</source>
diff --git a/src/translations/strawberry_tr_TR.ts b/src/translations/strawberry_tr_TR.ts
index 2a9ffa1a..0a0ec467 100644
--- a/src/translations/strawberry_tr_TR.ts
+++ b/src/translations/strawberry_tr_TR.ts
@@ -5702,8 +5702,8 @@ Devam etmek istediğinizden emin misiniz?</translation>
<translation>Etkinleştir</translation>
</message>
<message>
- <source>Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
- <translation type="unfinished">Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</translation>
+ <source>Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
+ <translation type="unfinished">Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</translation>
</message>
<message>
<source>Show scrobble button</source>
diff --git a/src/translations/strawberry_uk_UA.ts b/src/translations/strawberry_uk_UA.ts
index 6f93fa33..a72361ff 100644
--- a/src/translations/strawberry_uk_UA.ts
+++ b/src/translations/strawberry_uk_UA.ts
@@ -5712,7 +5712,7 @@ Are you sure you want to continue?</source>
<translation>Увімкнути</translation>
</message>
<message>
- <source>Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
+ <source>Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
<translation>Композиції скроблюються, якщо вони мають дійсні метадані, мають тривалість більше 30 секунд та відтворюються щонайменше половину тривалості або 4 хвилини (залежно від того, що станеться раніше).</translation>
</message>
<message>
diff --git a/src/translations/strawberry_vi_VN.ts b/src/translations/strawberry_vi_VN.ts
index 4a6c0602..d16c1116 100644
--- a/src/translations/strawberry_vi_VN.ts
+++ b/src/translations/strawberry_vi_VN.ts
@@ -5697,7 +5697,7 @@ Bạn có chắc chắn muốn tiếp tục không?</translation>
<translation>Bật</translation>
</message>
<message>
- <source>Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
+ <source>Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
<translation>Các bài sẽ được scrobble nếu có siêu dữ liệu hợp lệ và dài hơn 30 giây, đã phát ít nhất một nửa thời lượng hoặc 4 phút (cái nào xảy ra trước).</translation>
</message>
<message>
diff --git a/src/translations/strawberry_zh_CN.ts b/src/translations/strawberry_zh_CN.ts
index dac45b7e..16d97460 100644
--- a/src/translations/strawberry_zh_CN.ts
+++ b/src/translations/strawberry_zh_CN.ts
@@ -5697,7 +5697,7 @@ Are you sure you want to continue?</source>
<translation>启用</translation>
</message>
<message>
- <source>Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
+ <source>Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
<translation>如果歌曲具有有效的元数据并且长度超过 30 秒,播放时间至少为其持续时间的一半或 4 分钟(以先发生者为准),则会被记录。</translation>
</message>
<message>
diff --git a/src/translations/strawberry_zh_TW.ts b/src/translations/strawberry_zh_TW.ts
index e585c084..673fe142 100644
--- a/src/translations/strawberry_zh_TW.ts
+++ b/src/translations/strawberry_zh_TW.ts
@@ -5698,8 +5698,8 @@ Are you sure you want to continue?</translation>
<translation type="unfinished">Enable</translation>
</message>
<message>
- <source>Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
- <translation type="unfinished">Songs are scrobbled if they have valid metadata and are longer than 30 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</translation>
+ <source>Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</source>
+ <translation type="unfinished">Songs are scrobbled if they have valid metadata and are longer than 15 seconds, have been playing for at least half its duration or for 4 minutes (whichever occurs earlier).</translation>
</message>
<message>
<source>Show scrobble button</source>
--
2.51.2

View File

@ -1,4 +1,5 @@
{
lib,
fetchFromGitea,
writeShellScript,
writableTmpDirAsHomeHook,
@ -91,4 +92,16 @@ in stdenvNoCC.mkDerivation rec {
runHook postInstall
'';
meta = {
description = "A LaTeX Beamer theme, forked from the metropolis theme (with dragon patches) ";
longDescription = ''
This package cannot be installed or used directly. Please use `texlive.withPackages (ps: [ ps.${lib.strings.escapeNixIdentifier pname} ])`.
'';
homepage = "https://git.lain.faith/haskal/moloch-dragon";
outputsToInstall = [ ];
priority = 10;
platforms = lib.platforms.all;
license = lib.licenses.cc-by-sa-40;
};
}

View File

@ -7,13 +7,17 @@ rec {
dragnpkgs-unstable = getFlake "dragnpkgs-unstable";
pkgs = dragnpkgs.legacyPackages.${currentSystem};
pkgs-unstable = dragnpkgs-unstable.legacyPackages.${currentSystem};
inherit (pkgs) lib;
f = getFlake "git+file:${builtins.getEnv "PWD"}";
fp =
if (builtins.hasAttr "legacyPackages" f) then
f.legacyPackages.${currentSystem}
lib =
if prev ? lib then
prev.lib
else
f.packages.${currentSystem};
fs = f.devShells.${currentSystem};
pkgs.lib;
fp =
if final ? legacyPackages then
final.legacyPackages.${currentSystem}
else
final.packages.${currentSystem};
flp = final.legacyPackages.${currentSystem};
fs = final.devShells.${currentSystem};
}

View File

@ -3,20 +3,19 @@
outputs = { self, dragnpkgs } @ inputs: dragnpkgs.lib.mkFlake {
# Define a texlive environment to use
packages.texlive-custom = { texliveMedium, texliveDragonPackages }:
texliveMedium.withPackages (ps: with ps; [
fontawesome5
texliveDragonPackages.moloch
packages.texlive-custom = { texliveDragonPackages }:
texliveDragonPackages.scheme.withPackages (ps: with ps; [
# add more texlive dependencies here
]);
# Package definition for building the PDF
packages.default = { system, stdenvNoCC }: stdenvNoCC.mkDerivation rec {
packages.default = { stdenv }: stdenv.mkDerivation rec {
pname = "my-beamer-presentation";
name = "${pname}.pdf";
nativeBuildInputs = [
self.packages.${system}.texlive-custom
self.packages.${stdenv.hostPlatform.system}.texlive-custom
];
src = self;
@ -31,16 +30,16 @@
};
# Runnable package (ie `nix run`) to start the presentation
apps.default = { lib, system, writeShellScript, pympress }: {
apps.default = { lib, stdenv, writeShellScript, pympress }: {
type = "app";
program = "${writeShellScript "start-presentation" ''
exec ${lib.getExe pympress} ${self.packages.${system}.default}
exec ${lib.getExe pympress} ${self.packages.${stdenv.hostPlatform.system}.default}
''}";
};
# Devshell definition to expose the texlive environment to eg nvim
devShells.default = { mkShell, system }: mkShell {
packages = [ self.packages.${system}.texlive-custom ];
devShells.default = { mkShell, stdenv }: mkShell {
packages = [ self.packages.${stdenv.hostPlatform.system}.texlive-custom ];
};
};
}