diff --git a/pkgs/by-name/rn/rnxcmp/package.nix b/pkgs/by-name/rn/rnxcmp/package.nix new file mode 100644 index 000000000000..788933dc0461 --- /dev/null +++ b/pkgs/by-name/rn/rnxcmp/package.nix @@ -0,0 +1,119 @@ +{ + lib, + stdenv, + fetchurl, + tcsh, + coreutils, + gzip, + gnused, + ncompress, + callPackage, +}: + +stdenv.mkDerivation (finalAttrs: { + pname = "rnxcmp"; + version = "4.2.0"; + + src = fetchurl { + url = "https://terras.gsi.go.jp/ja/crx2rnx/RNXCMP_${finalAttrs.version}_src.tar.gz"; + hash = "sha256-mkUtKQiifFsxUsxCTgSIRyIcBl6X9rHxpYXHsMNPus4="; + }; + + postPatch = + let + cat = lib.getExe' coreutils "cat"; + compress = lib.getExe' ncompress "compress"; + gzipExe = lib.getExe gzip; + rm = lib.getExe' coreutils "rm"; + sed = lib.getExe gnused; + in + '' + substituteInPlace front-end-tools/unix/CRZ2RNX --replace-fail \ + '$CAT $file_in | CRX2RNX - > $file_out' \ + '$CAT $file_in | '"$out"'/bin/CRX2RNX - > $file_out' + + substituteInPlace front-end-tools/unix/RNX2CRZ \ + --replace-fail \ + '$CAT $file_in | RNX2CRX - | $COMPRESS -c > $file_out.$EXT' \ + '$CAT $file_in | '"$out"'/bin/RNX2CRX - | $COMPRESS -c > $file_out.$EXT' \ + --replace-fail \ + 'set COMPRESS = gzip' \ + 'set COMPRESS = ${gzipExe}' \ + --replace-fail \ + 'set COMPRESS = compress' \ + 'set COMPRESS = ${compress}' \ + + substituteInPlace front-end-tools/unix/* \ + --replace-fail /bin/csh '${lib.getExe tcsh}' \ + --replace-fail \ + 'set CAT = cat;' \ + 'set CAT = ${cat};' \ + --replace-fail \ + "set CAT = 'gzip -dc'" \ + "set CAT = '${gzipExe} -dc'" \ + --replace-fail \ + ' sed -e ' \ + ' ${sed} -e ' \ + --replace-fail \ + 'rm $file_in' \ + '${rm} $file_in' + ''; + + buildPhase = '' + runHook preBuild + + # Build commands taken from docs/RNXCMP.txt and adjusted + "$CC" -O2 source/crx2rnx.c -o CRX2RNX + "$CC" -O2 source/rnx2crx.c -o RNX2CRX + + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + + install -D -m555 -t "$out/bin" CRX2RNX RNX2CRX front-end-tools/unix/* + install -D -m555 -t "$out/share/doc" docs/* + install -D -m555 -t "$out/share/licenses" docs/LICENSE.txt + + '' + # The filesystem on macOS is case insensitive, so don't try to create + # a symbolic link where only the case of the name is different. + + lib.optionalString (!stdenv.hostPlatform.isDarwin) '' + # rtkpost_qt wants crx2rnx instead of CRX2RNX + ln --verbose --symbolic CRX2RNX "$out/bin/crx2rnx" + ln --verbose --symbolic RNX2CRX "$out/bin/rnx2crx" + '' + + '' + + runHook postInstall + ''; + + passthru.tests = { + inherit (callPackage ./test.nix { }) crx crz rnx; + }; + + meta = { + description = "Compression/restoration of RINEX observation files developed by Y. Hatanaka of GSI"; + homepage = "https://terras.gsi.go.jp/ja/crx2rnx.html"; + changelog = "https://terras.gsi.go.jp/ja/crx2rnx/CHANGES.txt"; + # The license text in docs/LICENSE.txt just refers to a website + # (with one section excluded) and does not contain the actual license text. + # The website also does not contain the full license text. + # You need to refer to https://www.digital.go.jp/en/resources/open_data/public_data_license_v1.0 as well. + # The license on the website is a modified version of the Public Data License (Version 1.0) (PDL 1.0). + # The official license text is in Japanese. A "Data" license seems like an odd choice for software. + # This license has seemingly not been approved by the FSF or the OSI. + # It's still marked as free software since as far as I can tell, the + # license does not disallow any of the Four Essential Freedoms as long + # as modified versions of the software include a statement expressing + # that the content has been edited and the source is cited. + # The full PDL 1.0 license text also says that it is compatible + # with the Creative Commons Attribution License 4.0. + license = lib.licenses.free; + platforms = lib.platforms.unix; + maintainers = with lib.maintainers; [ + Luflosi + ]; + }; +}) diff --git a/pkgs/by-name/rn/rnxcmp/test.nix b/pkgs/by-name/rn/rnxcmp/test.nix new file mode 100644 index 000000000000..2b492fe31cc2 --- /dev/null +++ b/pkgs/by-name/rn/rnxcmp/test.nix @@ -0,0 +1,143 @@ +# Data flow for testing CRX2RNX and RNX2CRX (file type after each step in paranthesis): +# Example file --(.crx.gz)--> unzip --(.crx)--> CRX2RNX --(.rnx)--> RNX2CRX --(.crx)--> compare two crx files + +# Data flow for testing CRZ2RNX and RNX2CRZ (file type after each step in paranthesis): +# Example files --(.crx.gz)--> CRZ2RNX --(.rnx)--> RNX2CRZ --(.crx.gz)--> unzip --(.crx)--v +# \--> unzip --(.crx)-------------------------------------------> compare crx files +# The last unzip step is needed because the .crx files themselves contain +# one line with the version number of the program and the current date, +# so they are not reproducible. This line needs to be removed to properly +# compare the files. To do this, we need to first unzip the files. The +# compression itself might also not be reproducible. + +# Also compare the RINEX file (.rnx) from the CRX2RNX program to the one output by CRZ2RNX. + +# Before running each of the four commands, we unset the PATH variable to make +# sure that the program does not depend on any external programs from the environment. + +{ + lib, + linkFarm, + writeShellApplication, + fetchurl, + runCommand, + rnxcmp, +}: +let + # Download two small example files (<1M each) + file-1-name = "ZARA00ESP_S_20260020100_15M_01S_MO"; + files = linkFarm "files" [ + rec { + name = "${file-1-name}.crx.gz"; + path = fetchurl { + url = "https://igs.bkg.bund.de/root_ftp/EUREF/highrate/2026/002/b/${name}"; + hash = "sha256-HUpzgFfwCf0N/OyJjJEStrOPPecmC4cr66DPbMjNyzc="; + }; + } + rec { + name = "ZARA00ESP_S_20260020115_15M_01S_MO.crx.gz"; + path = fetchurl { + url = "https://igs.bkg.bund.de/root_ftp/EUREF/highrate/2026/002/b/${name}"; + hash = "sha256-cnoYjcUwJMSvNB7f1HNCBi1hBKsuduOxrRw9S2Evopw="; + }; + } + ]; + + assert-dir-not-empty-app = writeShellApplication { + name = "assert-dir-not-empty"; + text = '' + # From https://mywiki.wooledge.org/BashFAQ/004 + shopt -s nullglob dotglob + files=("$1/"*) + if ! (( ''${#files[*]} )); then + echo "ERROR: Previous command did not produce any files!" + exit 1 + fi + ''; + }; + assert-dir-not-empty = lib.getExe assert-dir-not-empty-app; + + # unzip GZIP archives + unzip = + files: + runCommand "unzipped" { } '' + mkdir "$out" + cd '${files}' + for filename in *; do + gzip --verbose --decompress --keep --to-stdout "$filename" > "$out/$(basename "$filename" .gz)" + done + '${assert-dir-not-empty}' "$out" + ''; + files-unzipped = unzip files; + + # Convert the file from CompactRINEX format to RINEX + file-rnx = runCommand "file-rnx" { } '' + mkdir "$out" + unset PATH + '${lib.getExe' rnxcmp "CRX2RNX"}' '${files-unzipped}/${file-1-name}.crx' - > "$out/${file-1-name}.rnx" + '${assert-dir-not-empty}' "$out" + ''; + + # "Recompress" the file again + file-recompressed = runCommand "file-recompressed" { } '' + mkdir "$out" + unset PATH + '${lib.getExe' rnxcmp "RNX2CRX"}' '${file-rnx}/${file-1-name}.rnx' - > "$out/${file-1-name}.crx" + '${assert-dir-not-empty}' "$out" + ''; + + file-comparison = compare files-unzipped file-recompressed; + + # Convert the files from CompactRINEX format to RINEX + files-rnx = runCommand "files-rnx" { } '' + mkdir "$out" + cd "$out" + unset PATH + '${lib.getExe' rnxcmp "CRZ2RNX"}' -v -c '${files}/'* + '${assert-dir-not-empty}' "$out" + ''; + + # "Recompress" the files again + files-recompressed = runCommand "files-recompressed" { } '' + mkdir "$out" + cd "$out" + unset PATH + '${lib.getExe' rnxcmp "RNX2CRZ"}' -v -c '${files-rnx}/'* + '${assert-dir-not-empty}' "$out" + ''; + + files-recompressed-unzipped = unzip files-recompressed; + + compare = + files-before: files-after: + runCommand "comparison" { } '' + for filename in '${files-after}/'*; do + filename="$(basename "$filename")" + echo "Comparing old and new versions of $filename" + + # Delete software version and timestamp (second line) + sed -e '2d' < "${files-before}/$filename" > before.crx + sed -e '2d' < "${files-after}/$filename" > after.crx + + diff before.crx after.crx + done + touch "$out" + ''; + files-comparison = compare files-unzipped files-recompressed-unzipped; + + comparison-rnx = runCommand "comparison-rnx" { } '' + for filename in '${file-rnx}/'*; do + filename="$(basename "$filename")" + echo "Comparing old and new versions of $filename" + + diff "${files-rnx}/$filename" "${file-rnx}/$filename" + done + touch "$out" + ''; + +in +{ + crx = file-comparison; + crz = files-comparison; + rnx = comparison-rnx; +}