nixpkgs mirror (for testing) github.com/NixOS/nixpkgs
nix
at python-updates 277 lines 10 kB view raw
1{ 2 mitm-cache, 3 lib, 4 pkgs, 5 stdenv, 6 callPackage, 7}: 8 9let 10 getPkg = attrPath: lib.getAttrFromPath (lib.splitString "." (toString attrPath)) pkgs; 11in 12# the derivation to fetch/update deps for 13{ 14 pkg ? getPkg attrPath, 15 pname ? null, 16 attrPath ? pname, 17 # bwrap flags for the update script (this will be put in bash as-is) 18 # this is relevant for downstream users 19 bwrapFlags ? "--ro-bind \"$PWD\" \"$PWD\"", 20 # deps path (relative to the package directory, or absolute) 21 data, 22 # redirect stdout to stderr to allow the update script to be used with update script combinators 23 silent ? true, 24 useBwrap ? stdenv.hostPlatform.isLinux, 25}@attrs: 26 27let 28 data' = 29 removeAttrs 30 ( 31 if builtins.isPath data then 32 lib.importJSON data 33 else if builtins.isString data then 34 lib.importJSON "${dirOf pkg.meta.position}/${data}" 35 else 36 data 37 ) 38 [ 39 "!comment" 40 "!version" 41 ]; 42 43 parseArtifactUrl = 44 url: 45 let 46 extension = lib.last (lib.splitString "." url); 47 splitUrl = lib.splitString "/" url; 48 artifactId = builtins.elemAt splitUrl (builtins.length splitUrl - 3); 49 baseVer = builtins.elemAt splitUrl (builtins.length splitUrl - 2); 50 filename = builtins.elemAt splitUrl (builtins.length splitUrl - 1); 51 filenameNoExt = lib.removeSuffix ".${extension}" filename; 52 verCls = lib.removePrefix "${artifactId}-" filenameNoExt; 53 in 54 rec { 55 inherit 56 artifactId 57 baseVer 58 filename 59 extension 60 ; 61 isSnapshot = lib.hasSuffix "-SNAPSHOT" baseVer; 62 version = 63 if isSnapshot && !lib.hasPrefix "SNAPSHOT" verCls then 64 builtins.concatStringsSep "-" (lib.take 3 (lib.splitString "-" verCls)) 65 else 66 baseVer; 67 classifier = if verCls == version then null else lib.removePrefix "${version}-" verCls; 68 # for snapshots 69 timestamp = builtins.elemAt (lib.splitString "-" version) 1; 70 buildNum = builtins.elemAt (lib.splitString "-" version) 2; 71 }; 72 73 parseMetadataUrl = 74 url: 75 let 76 xmlBase = lib.removeSuffix "/maven-metadata.xml" url; 77 vMeta = lib.hasSuffix "-SNAPSHOT" xmlBase; 78 splitBase = lib.splitString "/" xmlBase; 79 in 80 if vMeta then 81 { 82 vMeta = true; 83 baseVer = builtins.elemAt splitBase (builtins.length splitBase - 1); 84 artifactId = builtins.elemAt splitBase (builtins.length splitBase - 2); 85 } 86 else 87 { 88 vMeta = false; 89 baseVer = null; 90 artifactId = builtins.elemAt splitBase (builtins.length splitBase - 1); 91 }; 92 93 extractHashArtifact = 94 afterHash: 95 let 96 nameVer = builtins.match "([^/]*)/([^/]*)(/SNAPSHOT)?(/.*)?" afterHash; 97 artifactId = builtins.elemAt nameVer 0; 98 version = builtins.elemAt nameVer 1; 99 isSnapshot = builtins.elemAt nameVer 2 != null; 100 cls = builtins.elemAt nameVer 3; 101 in 102 rec { 103 inherit artifactId version isSnapshot; 104 baseVer = 105 if !isSnapshot then 106 version 107 else 108 builtins.head (builtins.match "(.*)-([^-]*)-([^-]*)" version) + "-SNAPSHOT"; 109 classifier = if cls == null then null else lib.removePrefix "/" cls; 110 clsSuf = if classifier == null then "" else "-${classifier}"; 111 }; 112 113 # replace base#name/ver with base/name/ver/name-ver 114 decompressNameVer = 115 prefix: 116 let 117 splitHash = lib.splitString "#" (builtins.concatStringsSep "/" prefix); 118 inherit (extractHashArtifact (lib.last splitHash)) 119 artifactId 120 baseVer 121 version 122 clsSuf 123 ; 124 in 125 if builtins.length splitHash == 1 then 126 builtins.head splitHash 127 else 128 builtins.concatStringsSep "/${artifactId}/${baseVer}/" ( 129 lib.init splitHash ++ [ "${artifactId}-${version}${clsSuf}" ] 130 ); 131 132 # `visit` all elements in attrs and merge into a set 133 # attrs will be passed as parent1, parent1 will be passed as parent2 134 visitAttrs = 135 parent1: prefix: attrs: 136 builtins.foldl' (a: b: a // b) { } (lib.mapAttrsToList (visit parent1 attrs prefix) attrs); 137 138 # convert a compressed deps.json into an uncompressed json used for mitm-cache.fetch 139 visit = 140 parent2: parent1: prefix: k: v: 141 # groupId being present means this is a metadata xml "leaf" and we shouldn't descend further 142 if builtins.isAttrs v && !v ? groupId then 143 visitAttrs parent1 (prefix ++ [ k ]) v 144 else 145 let 146 url = "${decompressNameVer prefix}.${k}"; 147 in 148 { 149 ${url} = 150 if builtins.isString v then 151 { hash = v; } 152 else 153 { 154 text = 155 let 156 xmlBase = lib.removeSuffix "/maven-metadata.xml" url; 157 meta = parseMetadataUrl url // v; 158 inherit (meta) 159 groupId 160 vMeta 161 artifactId 162 baseVer 163 ; 164 165 fileList = builtins.filter (x: lib.hasPrefix xmlBase x && x != url) (builtins.attrNames finalData); 166 jarPomList = map parseArtifactUrl fileList; 167 168 sortByVersion = a: b: (builtins.compareVersions a.version b.version) < 0; 169 sortedJarPomList = lib.sort sortByVersion jarPomList; 170 171 uniqueVersionFiles = map ({ i, x }: x) ( 172 builtins.filter ( 173 { i, x }: i == 0 || (builtins.elemAt sortedJarPomList (i - 1)).version != x.version 174 ) (lib.imap0 (i: x: { inherit i x; }) sortedJarPomList) 175 ); 176 uniqueVersions' = map (x: x.version) uniqueVersionFiles; 177 releaseVersions = map (x: x.version) (builtins.filter (x: !x.isSnapshot) uniqueVersionFiles); 178 latestVer = v.latest or v.release or (lib.last uniqueVersions'); 179 releaseVer = v.release or (lib.last releaseVersions); 180 181 # The very latest version isn't necessarily used by Gradle, so it may not be present in the MITM data. 182 # In order to generate better metadata xml, if the latest version is known but wasn't fetched by Gradle, 183 # add it anyway. 184 uniqueVersions = 185 uniqueVersions' 186 ++ lib.optional (!builtins.elem releaseVer uniqueVersions') releaseVer 187 ++ lib.optional (!builtins.elem latestVer uniqueVersions' && releaseVer != latestVer) latestVer; 188 189 lastUpdated = 190 v.lastUpdated 191 or (if vMeta then builtins.replaceStrings [ "." ] [ "" ] snapshotTs else "20240101123456"); 192 193 # the following are only used for snapshots 194 snapshotTsAndNum = lib.splitString "-" latestVer; 195 snapshotTs = builtins.elemAt snapshotTsAndNum 1; 196 snapshotNum = lib.last snapshotTsAndNum; 197 198 indent = x: s: builtins.concatStringsSep "\n" (map (s: x + s) (lib.splitString "\n" s)); 199 containsSpecialXmlChars = s: builtins.match ''.*[<>"'&].*'' s != null; 200 in 201 # make sure all user-provided data is safe 202 assert lib.hasInfix "${builtins.replaceStrings [ "." ] [ "/" ] groupId}/${artifactId}" url; 203 assert !containsSpecialXmlChars groupId; 204 assert !containsSpecialXmlChars lastUpdated; 205 if vMeta then 206 '' 207 <?xml version="1.0" encoding="UTF-8"?> 208 <metadata modelVersion="1.1.0"> 209 <groupId>${groupId}</groupId> 210 <artifactId>${artifactId}</artifactId> 211 <version>${baseVer}</version> 212 <versioning> 213 <snapshot> 214 <timestamp>${snapshotTs}</timestamp> 215 <buildNumber>${snapshotNum}</buildNumber> 216 </snapshot> 217 <lastUpdated>${lastUpdated}</lastUpdated> 218 <snapshotVersions> 219 ${builtins.concatStringsSep "\n" ( 220 map ( 221 x: 222 indent " " '' 223 <snapshotVersion>${ 224 lib.optionalString (x.classifier != null) "\n <classifier>${x.classifier}</classifier>" 225 } 226 <extension>${x.extension}</extension> 227 <value>${x.version}</value> 228 <updated>${builtins.replaceStrings [ "." ] [ "" ] x.timestamp}</updated> 229 </snapshotVersion>'' 230 ) sortedJarPomList 231 )} 232 </snapshotVersions> 233 </versioning> 234 </metadata> 235 '' 236 else 237 assert !containsSpecialXmlChars latestVer; 238 assert !containsSpecialXmlChars releaseVer; 239 '' 240 <?xml version="1.0" encoding="UTF-8"?> 241 <metadata modelVersion="1.1.0"> 242 <groupId>${groupId}</groupId> 243 <artifactId>${artifactId}</artifactId> 244 <versioning> 245 <latest>${latestVer}</latest> 246 <release>${releaseVer}</release> 247 <versions> 248 ${builtins.concatStringsSep "\n" (map (x: " <version>${x}</version>") uniqueVersions)} 249 </versions> 250 <lastUpdated>${lastUpdated}</lastUpdated> 251 </versioning> 252 </metadata> 253 ''; 254 }; 255 }; 256 257 finalData = visitAttrs { } [ ] data'; 258in 259mitm-cache.fetch { 260 name = "${pkg.pname or pkg.name}-deps"; 261 data = finalData // { 262 "!version" = 1; 263 }; 264 passthru = lib.optionalAttrs (!builtins.isAttrs data) { 265 updateScript = callPackage ./update-deps.nix { } { 266 inherit 267 pkg 268 pname 269 attrPath 270 bwrapFlags 271 data 272 silent 273 useBwrap 274 ; 275 }; 276 }; 277}