1{ lib
2, stdenv
3, system
4, snapshotPath
5, autoPatchelfHook
6, python3
7, libxcrypt-legacy
8}:
9
10let
11 # Mapping from GCS component architecture names to Nix archictecture names
12 arches = {
13 x86 = "i686";
14 x86_64 = "x86_64";
15 arm = "aarch64";
16 };
17
18 # Mapping from GCS component operating systems to Nix operating systems
19 oses = {
20 LINUX = "linux";
21 MACOSX = "darwin";
22 WINDOWS = "windows";
23 CYGWIN = "cygwin";
24 };
25
26 # Convert an archicecture + OS to a Nix platform
27 toNixPlatform = arch: os:
28 let
29 arch' = arches.${arch} or (throw "unsupported architecture '${arch}'");
30 os' = oses.${os} or (throw "unsupported OS '${os}'");
31 in
32 "${arch'}-${os'}";
33
34 # All architectures that are supported by GCS
35 allArches = builtins.attrNames arches;
36
37 # A description of all available google-cloud-sdk components.
38 # It's a JSON file with a list of components, along with some metadata
39 snapshot = lib.importJSON snapshotPath;
40
41 # Generate a snapshot file for a single component. It has the same format as
42 # `snapshot`, but only contains a single component. These files are
43 # installed with google-cloud-sdk to let it know which components are
44 # available.
45 snapshotFromComponent =
46 { component
47 , revision
48 , schema_version
49 , version
50 }:
51 builtins.toJSON {
52 components = [ component ];
53 inherit revision schema_version version;
54 };
55
56 # Generate a set of components from a JSON file describing these components
57 componentsFromSnapshot =
58 { components
59 , revision
60 , schema_version
61 , version
62 , ...
63 }:
64 lib.fix (
65 self:
66 builtins.listToAttrs (
67 builtins.map
68 (component: {
69 name = component.id;
70 value = componentFromSnapshot self { inherit component revision schema_version version; };
71 })
72 components
73 )
74 );
75
76 # Generate a single component from its snapshot, along with a set of
77 # available dependencies to choose from.
78 componentFromSnapshot =
79 # Component derivations that can be used as dependencies
80 components:
81 # This component's snapshot
82 { component
83 , revision
84 , schema_version
85 , version
86 } @ attrs:
87 let
88 baseUrl = builtins.dirOf schema_version.url;
89 # Architectures supported by this component. Defaults to all available
90 # architectures.
91 architectures = builtins.filter
92 (arch: builtins.elem arch (builtins.attrNames arches))
93 (lib.attrByPath [ "platform" "architectures" ] allArches component);
94 # Operating systems supported by this component
95 operating_systems = builtins.filter
96 (os: builtins.elem os (builtins.attrNames oses))
97 component.platform.operating_systems;
98 in
99 mkComponent
100 {
101 pname = component.id;
102 version = component.version.version_string;
103 src =
104 lib.optionalString (lib.hasAttrByPath [ "data" "source" ] component) "${baseUrl}/${component.data.source}";
105 sha256 = lib.attrByPath [ "data" "checksum" ] "" component;
106 dependencies = builtins.map (dep: builtins.getAttr dep components) component.dependencies;
107 platforms =
108 if component.platform == { }
109 then lib.platforms.all
110 else
111 builtins.concatMap
112 (arch: builtins.map (os: toNixPlatform arch os) operating_systems)
113 architectures;
114 snapshot = snapshotFromComponent attrs;
115 };
116
117 # Filter out dependencies not supported by current system
118 filterForSystem = builtins.filter (drv: builtins.elem system drv.meta.platforms);
119
120 # Make a google-cloud-sdk component
121 mkComponent =
122 { pname
123 , version
124 # Source tarball, if any
125 , src ? ""
126 # Checksum for the source tarball, if there is a source
127 , sha256 ? ""
128 # Other components this one depends on
129 , dependencies ? [ ]
130 # Short text describing the component
131 , description ? ""
132 # Platforms supported
133 , platforms ? lib.platforms.all
134 # The snapshot corresponding to this component
135 , snapshot
136 }: stdenv.mkDerivation {
137 inherit pname version snapshot;
138 src =
139 lib.optionalString (src != "")
140 (builtins.fetchurl
141 {
142 url = src;
143 inherit sha256;
144 });
145 dontUnpack = true;
146 installPhase = ''
147 mkdir -p $out/google-cloud-sdk/.install
148
149 # If there is a source, unpack it
150 if [ ! -z "$src" ]; then
151 tar -xf $src -C $out/google-cloud-sdk/
152
153 # If the source has binaries, link them to `$out/bin`
154 if [ -d "$out/google-cloud-sdk/bin" ]; then
155 mkdir $out/bin
156 find $out/google-cloud-sdk/bin/ -type f -exec ln -s {} $out/bin/ \;
157 fi
158 fi
159
160 # Write the snapshot file to the `.install` folder
161 cp $snapshotPath $out/google-cloud-sdk/.install/${pname}.snapshot.json
162 '';
163 nativeBuildInputs = [
164 python3
165 stdenv.cc.cc
166 ] ++ lib.optionals stdenv.isLinux [
167 autoPatchelfHook
168 ];
169 buildInputs = [
170 libxcrypt-legacy
171 ];
172 passthru = {
173 dependencies = filterForSystem dependencies;
174 };
175 passAsFile = [ "snapshot" ];
176 meta = {
177 inherit description platforms;
178 };
179 };
180in
181componentsFromSnapshot snapshot