graphhopper: init at 10.2

- Adds the graphhopper package.nix to nixpkgs -> This is an open source
routing engine written in java and built with maven using the
"double-invocation" pattern - see `doc/languages-frameworks/maven.md`.
- Additionally, comes with a patch to it's pom.xml because it includes
[frontend-maven-plugin](https://github.com/eirslett/frontend-maven-plugin),
which tries to install node/npm during the build phase, which does not
work. Hence, we fetch the single npm package required manually.

+317
+152
pkgs/by-name/gr/graphhopper/package.nix
··· 1 + { 2 + fetchFromGitHub, 3 + fetchurl, 4 + lib, 5 + stdenv, 6 + testers, 7 + 8 + jre, 9 + makeWrapper, 10 + maven, 11 + ... 12 + }: 13 + let 14 + version = builtins.fromTOML (builtins.readFile ./version.toml); 15 + 16 + src = fetchFromGitHub { 17 + owner = "graphhopper"; 18 + repo = "graphhopper"; 19 + tag = version.patch; 20 + hash = version.hash.src; 21 + }; 22 + 23 + # Patch graphhopper to remove the npm download 24 + patches = [ ./remove-npm-dependency.patch ]; 25 + 26 + # Graphhopper also relies on a maps bundle downloaded from npm 27 + # By default it installs nodejs and npm during the build, 28 + # But we patch that out so we much fetch it ourselves 29 + mapsBundle = fetchurl { 30 + name = "@graphhopper/graphhopper-maps-bundle-${version.mapsBundle}"; 31 + url = "https://registry.npmjs.org/@graphhopper/graphhopper-maps-bundle/-/graphhopper-maps-bundle-${version.mapsBundle}.tgz"; 32 + hash = version.hash.mapsBundle; 33 + }; 34 + 35 + # We cannot use `buildMavenPackage` as we need to load in the 36 + # mapsBundle before doing anything 37 + mvnDeps = stdenv.mkDerivation { 38 + name = "graphhopper-dependencies"; 39 + 40 + inherit src patches; 41 + 42 + buildInputs = [ maven ]; 43 + 44 + buildPhase = '' 45 + # Fetching deps with mvn dependency:go-offline does not quite catch everything, so we use this plugin instead 46 + mvn de.qaware.maven:go-offline-maven-plugin:resolve-dependencies \ 47 + -Dmaven.repo.local=$out/.m2 \ 48 + -Dmaven.wagon.rto=5000 49 + ''; 50 + 51 + installPhase = '' 52 + # keep only *.{pom,jar,sha1,nbm} and delete all ephemeral files with lastModified timestamps inside 53 + find $out -type f \( \ 54 + -name \*.lastUpdated \ 55 + -o -name resolver-status.properties \ 56 + -o -name _remote.repositories \) \ 57 + -delete 58 + ''; 59 + 60 + outputHashMode = "recursive"; 61 + outputHash = version.hash.mvnDeps; 62 + }; 63 + in 64 + stdenv.mkDerivation (finalAttrs: { 65 + pname = "graphhopper"; 66 + 67 + inherit src patches; 68 + 69 + version = version.patch; 70 + 71 + buildInputs = [ 72 + makeWrapper 73 + maven 74 + ]; 75 + 76 + configurePhase = '' 77 + runHook preConfigure 78 + 79 + mkdir -p ./web-bundle/target/ 80 + ln -s ${mapsBundle} ./web-bundle/target/graphhopper-graphhopper-maps-bundle-${version.mapsBundle}.tgz 81 + 82 + runHook postConfigure 83 + ''; 84 + 85 + # Build and skip tests because downloading of 86 + # test deps seems to not work with the go-offline plugin 87 + buildPhase = '' 88 + runHook preBuild 89 + 90 + mvn package --offline \ 91 + -Dmaven.repo.local=${mvnDeps}/.m2 \ 92 + -DskipTests 93 + 94 + runHook postBuild 95 + ''; 96 + 97 + installPhase = '' 98 + runHook preInstall 99 + 100 + mkdir -p $out/bin 101 + 102 + ln -s ${mvnDeps}/.m2 $out/lib 103 + 104 + # Grapphopper versions are seemingly compiled under the major release name, 105 + # not the patch name, which is the version we want for our package 106 + cp ./web/target/graphhopper-web-${version.major}-SNAPSHOT.jar $out/bin/graphhopper-web-${version.major}-SNAPSHOT.jar 107 + 108 + makeWrapper ${jre}/bin/java $out/bin/graphhopper \ 109 + --add-flags "-jar $out/bin/graphhopper-web-${version.major}-SNAPSHOT.jar" \ 110 + --chdir $out 111 + 112 + runHook postInstall 113 + ''; 114 + 115 + fixupPhase = '' 116 + runHook preFixup 117 + 118 + # keep only *.{pom,jar,sha1,nbm} and delete all ephemeral files with lastModified timestamps inside 119 + find $out -type f \( \ 120 + -name \*.lastUpdated \ 121 + -o -name resolver-status.properties \ 122 + -o -name _remote.repositories \) \ 123 + -delete 124 + 125 + runHook postFixup 126 + ''; 127 + 128 + meta = { 129 + description = "Fast and memory-efficient routing engine for OpenStreetMap"; 130 + homepage = "https://www.graphhopper.com/"; 131 + changelog = "https://github.com/graphhopper/graphhopper/releases/tag/${version.patch}"; 132 + license = lib.licenses.asl20; 133 + maintainers = with lib.maintainers; [ baileylu ]; 134 + teams = [ lib.teams.geospatial ]; 135 + platforms = lib.platforms.all; 136 + mainProgram = "graphhopper"; 137 + sourceProvenance = with lib.sourceTypes; [ 138 + fromSource 139 + binaryBytecode 140 + ]; 141 + }; 142 + 143 + passthru = { 144 + updateScript = ./update.nu; 145 + tests.version = testers.testVersion { 146 + package = finalAttrs.finalPackage; 147 + # `graphhopper --version` does not work as the source does not specify `Implementation-Version` 148 + command = "graphhopper --help"; 149 + version = "graphhopper-web-${version.major}-SNAPSHOT.jar"; 150 + }; 151 + }; 152 + })
+55
pkgs/by-name/gr/graphhopper/remove-npm-dependency.patch
··· 1 + From ad687709cfca51603264ff565f296cfb5dceb15a Mon Sep 17 00:00:00 2001 2 + From: Luke Bailey <baileylu@tcd.ie> 3 + Date: Wed, 19 Mar 2025 22:25:44 +0000 4 + Subject: [PATCH] Swap out frontend maven plugin which downloads npm 5 + for fetching it through nix instead 6 + 7 + --- 8 + web-bundle/pom.xml | 31 ------------------------------- 9 + 1 file changed, 31 deletions(-) 10 + 11 + diff --git a/web-bundle/pom.xml b/web-bundle/pom.xml 12 + index 9a4d83b62..1d995cbaf 100644 13 + --- a/web-bundle/pom.xml 14 + +++ b/web-bundle/pom.xml 15 + @@ -129,37 +129,6 @@ 16 + 17 + <build> 18 + <plugins> 19 + - <plugin> 20 + - <groupId>com.github.eirslett</groupId> 21 + - <artifactId>frontend-maven-plugin</artifactId> 22 + - <version>1.12.1</version> 23 + - <executions> 24 + - <execution> 25 + - <id>install node and npm</id> 26 + - <goals> 27 + - <goal>install-node-and-npm</goal> 28 + - </goals> 29 + - <configuration> 30 + - <nodeVersion>v20.14.0</nodeVersion> 31 + - <npmVersion>10.7.0</npmVersion> 32 + - </configuration> 33 + - </execution> 34 + - <execution> 35 + - <id>download graphhopper maps</id> 36 + - <phase>generate-resources</phase> 37 + - <goals> 38 + - <goal>npm</goal> 39 + - </goals> 40 + - <configuration> 41 + - <!--suppress UnresolvedMavenProperty (IntelliJ shows an error otherwise...)--> 42 + - <arguments> 43 + - pack --pack-destination=${basedir}/target 44 + - @graphhopper/graphhopper-maps-bundle@${graphhopper-maps.version} 45 + - </arguments> 46 + - </configuration> 47 + - </execution> 48 + - </executions> 49 + - </plugin> 50 + <plugin> 51 + <artifactId>maven-antrun-plugin</artifactId> 52 + <executions> 53 + -- 54 + 2.48.1 55 +
+102
pkgs/by-name/gr/graphhopper/update.nu
··· 1 + #!/usr/bin/env nix-shell 2 + #! nix-shell -i nu -p nushell nix-prefetch-github common-updater-scripts 3 + 4 + use std/log 5 + 6 + let version_info = "./pkgs/by-name/gr/graphhopper/version.toml" 7 + 8 + let current_version = open $version_info 9 + 10 + let latest_tag = list-git-tags --url=https://github.com/graphhopper/graphhopper 11 + | lines 12 + | sort --natural 13 + | where ($it =~ '^[\d.]+$') 14 + | last 15 + 16 + if $current_version.patch == $latest_tag { 17 + log debug "Current graphhopper version matched latest version of graphhopper, no update is needed, exiting..." 18 + exit 0 19 + } 20 + 21 + let major = $latest_tag 22 + | str replace -ar '(\d+)\.\d+' '$1.0' 23 + 24 + log debug $"Fetching source for graphhopper patch ($latest_tag) on version ($major)" 25 + let source = nix-prefetch-github graphhopper graphhopper --rev $latest_tag 26 + | from json 27 + 28 + log debug $"Reading maps bundle version for ($latest_tag)" 29 + let web_bundle_pom = http get $"https://api.github.com/repos/graphhopper/graphhopper/contents/web-bundle/pom.xml?ref=($latest_tag)" 30 + | $in.content 31 + | base64 --decode 32 + | into string 33 + | from xml 34 + 35 + let maps_bundle_properties = $web_bundle_pom.content 36 + | where ($it.tag =~ "properties") 37 + | first 38 + 39 + let maps_bundle_version = $maps_bundle_properties.content 40 + | where ($it.tag =~ "graphhopper-maps.version") 41 + | first 42 + | $in.content 43 + | first 44 + | $in.content 45 + 46 + log debug $"Fetching maps bundle ($maps_bundle_version)" 47 + let maps_bundle_hash = nix-prefetch-url $"https://registry.npmjs.org/@graphhopper/graphhopper-maps-bundle/-/graphhopper-maps-bundle-($maps_bundle_version).tgz" 48 + | nix-hash --type sha256 --to-base64 $in 49 + | ["sha256-", $in] 50 + | str join 51 + 52 + log debug $"Writing to ($version_info) without mvnDeps hash..." 53 + 54 + { 55 + major: $major, 56 + patch: $latest_tag, 57 + mapsBundle: $maps_bundle_version, 58 + 59 + hash: { 60 + src: $source.hash 61 + mapsBundle: $maps_bundle_hash 62 + mvnDeps: "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" 63 + } 64 + } 65 + | to toml 66 + | save $version_info -f 67 + 68 + log debug "Calculating mvnDeps hash..." 69 + let graphhopper_build_logs = nix-build -A graphhopper o+e>| cat 70 + 71 + let mvn_hash_lines = $graphhopper_build_logs 72 + | lines 73 + | find "got:" 74 + 75 + if ($mvn_hash_lines | length) == 0 { 76 + log error $"Could not find any maven hash in the graphhopper build logs - maybe a different error occurred: \n$($graphhopper_build_logs)" 77 + exit 1 78 + } 79 + 80 + log debug $"Found relevant hash lines: ($mvn_hash_lines)" 81 + let mvn_hash = $mvn_hash_lines 82 + | first 83 + | ansi strip 84 + | str replace 'got:' '' 85 + | str trim 86 + 87 + log debug $"Writing to ($version_info) with mvnDeps hash ($mvn_hash).." 88 + { 89 + major: $major, 90 + patch: $latest_tag, 91 + mapsBundle: $maps_bundle_version, 92 + 93 + hash: { 94 + src: $source.hash 95 + mapsBundle: $maps_bundle_hash 96 + mvnDeps: $mvn_hash 97 + } 98 + } 99 + | to toml 100 + | save $version_info -f 101 + 102 + log debug $"Successfully updated graphhopper package!"
+8
pkgs/by-name/gr/graphhopper/version.toml
··· 1 + major = "10.0" 2 + patch = "10.2" 3 + mapsBundle = "0.0.0-4718098d1db1798841a4d12f1727e8e8f7eab202" 4 + 5 + [hash] 6 + src = "sha256-E6G9JR1lrXhNJ4YgMM0n0RsQcMZQM2QldGc74f5FALo=" 7 + mapsBundle = "sha256-jZTNJfmMWJQHpJ8um3yTBx/KtIfdr0EwKJ9kSFalWJQ=" 8 + mvnDeps = "sha256-KidbIBnW//IiKPFy3plFWOED8gP/ZCg4buwMgzttaY8="