@@ -168,23 +168,37 @@ std::pair<Tree, time_t> downloadTarball(
168168 };
169169}
170170
171- struct TarballInputScheme : InputScheme
171+ struct CurlInputScheme : InputScheme
172172{
173+ const std::string inputType = " url" ;
174+
175+ // For backwards-compatibility.
176+ // An alias for `url`, except that setting type to `tarball` will cause
177+ // `unpack` to default to `true`
178+ const std::string tarballInputType = " tarball" ;
179+
180+ const std::string unpackParam = " unpack" ;
181+
173182 std::optional<Input> inputFromURL (const ParsedURL & url) override
174183 {
175184 if (url.scheme != " file" && url.scheme != " http" && url.scheme != " https" ) return {};
176185
177- if (!hasSuffix (url.path , " .zip" )
178- && !hasSuffix (url.path , " .tar" )
179- && !hasSuffix (url.path , " .tgz" )
180- && !hasSuffix (url.path , " .tar.gz" )
181- && !hasSuffix (url.path , " .tar.xz" )
182- && !hasSuffix (url.path , " .tar.bz2" )
183- && !hasSuffix (url.path , " .tar.zst" ))
184- return {};
185-
186186 Input input;
187- input.attrs .insert_or_assign (" type" , " tarball" );
187+
188+ bool defaultUnpack = (hasSuffix (url.path , " .zip" )
189+ || hasSuffix (url.path , " .tar" )
190+ || hasSuffix (url.path , " .tgz" )
191+ || hasSuffix (url.path , " .tar.gz" )
192+ || hasSuffix (url.path , " .tar.xz" )
193+ || hasSuffix (url.path , " .tar.bz2" )
194+ || hasSuffix (url.path , " .tar.zst" ));
195+
196+ if (auto unpack = url.query .find (unpackParam); unpack != url.query .end ())
197+ input.attrs .insert_or_assign (unpackParam, Explicit<bool > { unpack->second == " 1" });
198+
199+ // To keep things backwards-compatible use the "tarball" input type for
200+ // everything that used to be a "tarball" before.
201+ input.attrs .insert_or_assign (" type" , defaultUnpack ? tarballInputType : inputType);
188202 input.attrs .insert_or_assign (" url" , url.to_string ());
189203 auto narHash = url.query .find (" narHash" );
190204 if (narHash != url.query .end ())
@@ -194,14 +208,17 @@ struct TarballInputScheme : InputScheme
194208
195209 std::optional<Input> inputFromAttrs (const Attrs & attrs) override
196210 {
197- if (maybeGetStrAttr (attrs, " type" ) != " tarball" ) return {};
211+ auto type = maybeGetStrAttr (attrs, " type" );
212+ if (type != inputType && type != tarballInputType) return {};
198213
214+ std::set<std::string> allowedNames = {" type" , " url" , " narHash" , " name" , " unpack" };
199215 for (auto & [name, value] : attrs)
200- if (name != " type " && name != " url " && /* name != "hash" && */ name != " narHash " && name != " name " )
201- throw Error (" unsupported tarball input attribute '%s'" , name);
216+ if (!allowedNames. count ( name) )
217+ throw Error (" unsupported %s input attribute '%s'" , *type , name);
202218
203219 Input input;
204220 input.attrs = attrs;
221+
205222 // input.locked = (bool) maybeGetStrAttr(input.attrs, "hash");
206223 return input;
207224 }
@@ -213,6 +230,8 @@ struct TarballInputScheme : InputScheme
213230 // don't have a canonical representation.
214231 if (auto narHash = input.getNarHash ())
215232 url.query .insert_or_assign (" narHash" , narHash->to_string (SRI, true ));
233+ if (auto unpack = maybeGetBoolAttr (input.attrs , unpackParam))
234+ url.query .insert_or_assign (unpackParam, unpack.value () ? " 1" : " 0" );
216235 /*
217236 else if (auto hash = maybeGetStrAttr(input.attrs, "hash"))
218237 url.query.insert_or_assign("hash", Hash(*hash).to_string(SRI, true));
@@ -225,13 +244,32 @@ struct TarballInputScheme : InputScheme
225244 return true ;
226245 }
227246
247+ /* *
248+ * Whether this url input should be unpacked when we fetch it
249+ */
250+ const bool shouldUnpack (const Input & input) const
251+ {
252+ auto type = getStrAttr (input.attrs , " type" );
253+ // For backwards-compatibility, we unpack by default if the type is
254+ // set to "tarball"
255+ return maybeGetBoolAttr (input.attrs , unpackParam).value_or (type == " tarball" );
256+ }
257+
228258 std::pair<StorePath, Input> fetch (ref<Store> store, const Input & input) override
229259 {
230- auto tree = downloadTarball (store, getStrAttr (input.attrs , " url" ), input.getName (), false ).first ;
231- return {std::move (tree.storePath ), input};
260+ StorePath outPath = [&]() {
261+ if (shouldUnpack (input)) {
262+ auto tree = downloadTarball (store, getStrAttr (input.attrs , " url" ), input.getName (), false ).first ;
263+ return tree.storePath ;
264+ } else {
265+ auto file = downloadFile (store, getStrAttr (input.attrs , " url" ), input.getName (), false );
266+ return file.storePath ;
267+ }
268+ }();
269+ return {std::move (outPath), input};
232270 }
233271};
234272
235- static auto rTarballInputScheme = OnStartup([] { registerInputScheme (std::make_unique<TarballInputScheme >()); });
273+ static auto rCurlInputScheme = OnStartup([] { registerInputScheme (std::make_unique<CurlInputScheme >()); });
236274
237275}
0 commit comments