1414 # Coerces a string to an int.
1515 coerceInt = val : if lib . isInt val then val else lib . toIntBase10 val ;
1616
17- coerceIntVersion = v : coerceInt ( lib . versions . major v ) ;
17+ coerceIntVersion = v : coerceInt ( lib . versions . major ( toString v ) ) ;
1818
1919 # Parses a single version, substituting "latest" with the latest version.
2020 parseVersion =
144144
145145let
146146 # Resolve all the platform versions.
147- platformVersions' = map coerceInt ( parseVersions repo "platforms" platformVersions ) ;
147+ platformVersions' = map coerceIntVersion ( parseVersions repo "platforms" platformVersions ) ;
148148
149149 # Determine the Android os identifier from Nix's system identifier
150150 os =
220220 extras = fetchArchives repo . extras ;
221221 } ;
222222
223+ # Latest packages that are typically keyed by the API level.
224+ archivesByApiLevel =
225+ let
226+ # Transforms the given attrset mapping API levels (with possible suffixes and minor versions)
227+ # into the latest API level for each major version.
228+ mkLatestByApiLevel =
229+ packages :
230+ lib . filterAttrs ( _ : value : value != null ) (
231+ lib . mapAttrs (
232+ _ : value :
233+ ( lib . findFirst ( x : x . name == lib . versions . majorMinor x . name ) { value = null ; } (
234+ lib . lists . sort ( x : y : lib . strings . versionOlder y . name x . name ) value
235+ ) ) . value
236+ ) ( lib . groupBy ( x : lib . versions . major x . name ) ( lib . attrsToList packages ) )
237+ ) ;
238+ in
239+ {
240+ platforms = mkLatestByApiLevel allArchives . packages . platforms ;
241+ sources = mkLatestByApiLevel allArchives . packages . sources ;
242+ system-images = mkLatestByApiLevel allArchives . system-images ;
243+ } ;
244+
223245 # Lift the archives to the package level for easy search,
224246 # and add recurseIntoAttrs to all of them.
225247 allPackages =
@@ -284,17 +306,28 @@ let
284306 lib . hasAttrByPath [ package ( toString version ) ] packages ;
285307
286308 # Displays a nice error message that includes the available options if a version doesn't exist.
309+ # Note that allPackages can be a list of package sets, or a single package set. Pass a list if
310+ # you want to prioritize elements to the left (e.g. for passing a platform major version).
287311 checkVersion =
288- packages : package : version :
289- if hasVersion packages package version then
290- packages . ${ package } . ${ toString version }
291- else
312+ allPackages : package : version :
313+ let
314+ # Convert the package sets to a list.
315+ allPackages' = if lib . isList allPackages then allPackages else lib . singleton allPackages ;
316+
317+ # Pick the first package set where we have the version.
318+ packageSet = lib . findFirst ( packages : hasVersion packages package version ) null allPackages' ;
319+ in
320+ if packageSet == null then
292321 throw ''
293322 The version ${ toString version } is missing in package ${ package } .
294323 The only available versions are ${
295- builtins . concatStringsSep ", " ( builtins . attrNames packages . ${ package } )
324+ lib . concatStringsSep ", " (
325+ lib . attrNames ( lib . foldl ( s : x : s // ( x . ${ package } or { } ) ) { } allPackages' )
326+ )
296327 } .
297- '' ;
328+ ''
329+ else
330+ packageSet . ${ package } . ${ toString version } ;
298331
299332 # Returns true if we should link the specified plugins.
300333 shouldLink =
@@ -508,19 +541,23 @@ lib.recurseIntoAttrs rec {
508541 '' ;
509542 } ;
510543
544+ # This is a list of the chosen API levels, as integers.
511545 platformVersions = platformVersions' ;
512546
513547 platforms = map (
514548 version :
515549 deployAndroidPackage {
516- package = checkVersion allArchives . packages "platforms" version ;
550+ package = checkVersion [ archivesByApiLevel allArchives . packages ] "platforms" version ;
517551 }
518552 ) platformVersions' ;
519553
554+ # This exposes the version strings (e.g. "36.1" for API 36).
555+ platformVersionStrings = map ( platform : platform . version ) platforms ;
556+
520557 sources = map (
521558 version :
522559 deployAndroidPackage {
523- package = checkVersion allArchives . packages "sources" version ;
560+ package = checkVersion [ archivesByApiLevel allArchives . packages ] "sources" version ;
524561 }
525562 ) platformVersions' ;
526563
@@ -539,14 +576,19 @@ lib.recurseIntoAttrs rec {
539576 # ```
540577 let
541578 availablePackages =
542- map ( abiVersion : allArchives . system-images . ${ toString apiVersion } . ${ type } . ${ abiVersion } )
579+ map
580+ (
581+ abiVersion :
582+ archivesByApiLevel . system-images . ${ toString apiVersion } . ${ type } . ${ abiVersion }
583+ or allArchives . system-images . ${ toString apiVersion } . ${ type } . ${ abiVersion }
584+ )
543585 (
544586 builtins . filter (
545587 abiVersion : lib . hasAttrByPath [ ( toString apiVersion ) type abiVersion ] allArchives . system-images
546588 ) abiVersions
547589 ) ;
548590
549- instructions = builtins . listToAttrs (
591+ instructions = lib . listToAttrs (
550592 map ( package : {
551593 name = package . name ;
552594 value = lib . optionalString ( lib . hasPrefix "google_apis" type ) ''
0 commit comments