lol

Merge pull request #31333 from ElvishJerricco/unextracted-all-cabal-hashes

Unextracted all cabal hashes

authored by

Peter Simons and committed by
GitHub
c7203efb bb0b0822

+13 -238
+5 -33
pkgs/data/misc/hackage/default.nix
··· 1 - { fetchFromGitHub 2 - , stdenv 3 - , pkgconfig 4 - , libarchive 5 - , glib 6 - , # Override this to use a different revision 7 - src-spec ? 8 - { owner = "commercialhaskell"; 9 - repo = "all-cabal-hashes"; 10 - rev = "5e87c40f2cd96bd5dd953758e82f302107c7895e"; 11 - sha256 = "12rw5fld64s0a2zjsdijfs0dv6vc6z7gcf24h4m2dmymzms4namg"; 12 - } 13 - , lib 14 - }: 1 + { fetchurl }: 15 2 16 - # Use builtins.fetchTarball "https://github.com/commercialhaskell/all-cabal-hashes/archive/hackage.tar.gz" 17 - # instead if you want the latest Hackage automatically at the price of frequent re-downloads. 18 - let partition-all-cabal-hashes = stdenv.mkDerivation 19 - { name = "partition-all-cabal-hashes"; 20 - src = ./partition-all-cabal-hashes.c; 21 - unpackPhase = "true"; 22 - buildInputs = [ libarchive glib ]; 23 - nativeBuildInputs = [ pkgconfig ]; 24 - buildPhase = 25 - "cc -O3 $(pkg-config --cflags --libs libarchive glib-2.0) $src -o partition-all-cabal-hashes"; 26 - installPhase = 27 - '' 28 - mkdir -p $out/bin 29 - install -m755 partition-all-cabal-hashes $out/bin 30 - ''; 31 - }; 32 - in fetchFromGitHub (src-spec // 33 - { postFetch = "${partition-all-cabal-hashes}/bin/partition-all-cabal-hashes $downloadedFile $out"; 34 - }) 3 + fetchurl { 4 + url = "https://github.com/commercialhaskell/all-cabal-hashes/archive/5e87c40f2cd96bd5dd953758e82f302107c7895e.tar.gz"; 5 + sha256 = "0hjkddda9mdm21nb9bkhr9n5r9jllisif1qmzha91a9cps5w1mx5"; 6 + }
-190
pkgs/data/misc/hackage/partition-all-cabal-hashes.c
··· 1 - #include <stdio.h> 2 - #include <ctype.h> 3 - #include <glib.h> 4 - #include <string.h> 5 - #include <locale.h> 6 - #include <archive.h> 7 - #include <archive_entry.h> 8 - 9 - static char * case_normalize(char * str) { 10 - for (char * iter = str; *iter; ++iter) { 11 - *iter = tolower(*iter); 12 - } 13 - return str; 14 - } 15 - 16 - static gint compare_str(const void * a, const void * b, void * _) { 17 - return strcmp(a, b); 18 - } 19 - 20 - int main(int argc, char ** argv) { 21 - if (argc != 3) { 22 - fprintf(stderr, "Usage: %s TARBALL OUTPUT\n", argv[0]); 23 - return 1; 24 - } 25 - 26 - size_t output_len = strlen(argv[2]); 27 - 28 - /* Switch to standard locale to ensure consistency in case-folding. 29 - */ 30 - setlocale(LC_CTYPE, "C"); 31 - 32 - /* Map from case-normalized package name to a sorted sequence of 33 - * package names in the equivalence class defined by 34 - * case-normalization. 35 - */ 36 - GHashTable * equivalence_classes = 37 - g_hash_table_new(g_str_hash, g_str_equal); 38 - 39 - /* Open up the tarball. 40 - */ 41 - struct archive * ar = archive_read_new(); 42 - if (!ar) { 43 - perror("Allocating archive structure"); 44 - return 1; 45 - } 46 - archive_read_support_filter_gzip(ar); 47 - archive_read_support_format_tar(ar); 48 - if (archive_read_open_filename( ar 49 - , argv[1] 50 - , 10240 51 - ) == ARCHIVE_FATAL) { 52 - fprintf( stderr 53 - , "Error opening %s: %s\n" 54 - , argv[0] 55 - , archive_error_string(ar) 56 - ); 57 - return 1; 58 - } 59 - 60 - /* Extract the length of the output directory that prefixes all 61 - * tarball entries from the first entry in the tarball. 62 - */ 63 - struct archive_entry * ent; 64 - int err = archive_read_next_header(ar, &ent); 65 - if (err != ARCHIVE_OK) { 66 - if (err == ARCHIVE_EOF) { 67 - fprintf( stderr 68 - , "No entries in %s, surely this is an error!\n" 69 - , argv[1] 70 - ); 71 - } else { 72 - fprintf( stderr 73 - , "Error reading entry from %s: %s\n" 74 - , argv[1] 75 - , archive_error_string(ar) 76 - ); 77 - } 78 - return 1; 79 - } 80 - const char * path = archive_entry_pathname(ent); 81 - /* Number of characters from the start of the path name until after 82 - * the slash after the leading directory. 83 - */ 84 - size_t prefix_len = strchr(path, '/') - path + 1; 85 - 86 - /* Extract each entry to the right partition. 87 - */ 88 - do { 89 - path = archive_entry_pathname(ent) + prefix_len; 90 - const char * pkg_end = strchr(path, '/'); 91 - if (!pkg_end) 92 - /* If there is no second slash, then this is either just the entry 93 - * corresponding to the root or some non-package file (e.g. 94 - * travis.yml). In either case, we don't care. 95 - */ 96 - continue; 97 - 98 - /* Find our package in the equivalence class map. 99 - */ 100 - char * pkg_name = g_strndup(path, pkg_end - path); 101 - char * pkg_normalized = 102 - case_normalize(g_strndup(path, pkg_end - path)); 103 - GSequence * pkg_class = 104 - g_hash_table_lookup(equivalence_classes, pkg_normalized); 105 - gint partition_num; 106 - if (!pkg_class) { 107 - /* We haven't seen any packages with this normalized name yet, 108 - * so we need to initialize the sequence and add it to the map. 109 - */ 110 - pkg_class = g_sequence_new(NULL); 111 - g_sequence_append(pkg_class, pkg_name); 112 - g_hash_table_insert( equivalence_classes 113 - , pkg_normalized 114 - , pkg_class 115 - ); 116 - partition_num = 1; 117 - } else { 118 - g_free(pkg_normalized); 119 - /* Find the package name in the equivalence class */ 120 - GSequenceIter * pkg_iter = 121 - g_sequence_search( pkg_class 122 - , pkg_name 123 - , compare_str 124 - , NULL 125 - ); 126 - if (!g_sequence_iter_is_end(pkg_iter)) { 127 - /* If there are any packages after this one in the list, bail 128 - * out. In principle we could solve this by moving them up to 129 - * the next partition, but so far I've never seen any github 130 - * tarballs out of order so let's save ourselves the work 131 - * until we know we need it. 132 - */ 133 - fprintf( stderr 134 - , "Out of order github tarball: %s is after %s\n" 135 - , pkg_name 136 - , (char *) g_sequence_get(pkg_iter) 137 - ); 138 - return 1; 139 - } 140 - pkg_iter = g_sequence_iter_prev(pkg_iter); 141 - if (strcmp( g_sequence_get(pkg_iter) 142 - , pkg_name 143 - ) != 0) { 144 - /* This package doesn't have the same name as the one right 145 - * before where it should be in the sequence, which means it's 146 - * new and needs to be added to the sequence. 147 - * 148 - * !!! We need to change this to use g_sequence_insert_before 149 - * if we ever get an out-of-order github tarball, see comment 150 - * after the check for !g_sequence_iter_is_end(pkg_iter). 151 - */ 152 - pkg_iter = g_sequence_append(pkg_class, pkg_name); 153 - } else { 154 - g_free(pkg_name); 155 - } 156 - /* Get the partition number, starting with 1. 157 - */ 158 - partition_num = g_sequence_iter_get_position(pkg_iter) + 1; 159 - } 160 - 161 - /* Set the destination path. 162 - * The 3 below is for the length of /#/, the partition number part 163 - * of the path. If we have more than 9 partitions, we deserve to 164 - * segfault. The 1 at the end is for the trailing null. 165 - */ 166 - char * dest_path = g_malloc(output_len + 3 + strlen(path) + 1); 167 - sprintf(dest_path, "%s/%d/%s", argv[2], partition_num, path); 168 - archive_entry_set_pathname(ent, dest_path); 169 - 170 - if (archive_read_extract(ar, ent, 0) != ARCHIVE_OK) { 171 - fprintf( stderr 172 - , "Error extracting entry %s from %s: %s\n" 173 - , dest_path 174 - , argv[1] 175 - , archive_error_string(ar) 176 - ); 177 - return 1; 178 - } 179 - } while ((err = archive_read_next_header(ar, &ent)) == ARCHIVE_OK); 180 - if (err != ARCHIVE_EOF) { 181 - fprintf( stderr 182 - , "Error reading entry from %s: %s\n" 183 - , argv[1] 184 - , archive_error_string(ar) 185 - ); 186 - return 1; 187 - } 188 - 189 - return 0; 190 - }
+8 -15
pkgs/development/haskell-modules/make-package-set.nix
··· 118 118 ''; 119 119 }; 120 120 121 - all-cabal-hashes-component = name: import (pkgs.runCommand "all-cabal-hashes-component-${name}.nix" {} 122 - '' 123 - set +o pipefail 124 - for component in ${all-cabal-hashes}/*; do 125 - if ls $component | grep -q "^${name}$"; then 126 - echo "builtins.storePath $component" > $out 127 - exit 0 128 - fi 129 - done 130 - echo "${name} not found in any all-cabal-hashes component, are you sure it's in hackage?" >&2 131 - exit 1 132 - ''); 121 + all-cabal-hashes-component = name: version: pkgs.runCommand "all-cabal-hashes-component-${name}-${version}" {} '' 122 + tar --wildcards -xzvf ${all-cabal-hashes} \*/${name}/${version}/${name}.{json,cabal} 123 + mkdir -p $out 124 + mv */${name}/${version}/${name}.{json,cabal} $out 125 + ''; 133 126 134 - hackage2nix = name: version: let component = all-cabal-hashes-component name; in self.haskellSrc2nix { 127 + hackage2nix = name: version: let component = all-cabal-hashes-component name version; in self.haskellSrc2nix { 135 128 name = "${name}-${version}"; 136 - sha256 = ''$(sed -e 's/.*"SHA256":"//' -e 's/".*$//' "${component}/${name}/${version}/${name}.json")''; 137 - src = "${component}/${name}/${version}/${name}.cabal"; 129 + sha256 = ''$(sed -e 's/.*"SHA256":"//' -e 's/".*$//' "${component}/${name}.json")''; 130 + src = "${component}/${name}.cabal"; 138 131 }; 139 132 140 133 in package-set { inherit pkgs stdenv callPackage; } self // {