| // Copyright 2024, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| import 'dart:io' as io; |
| |
| import 'command.dart'; |
| import 'package.dart'; |
| import 'useful_directory.dart'; |
| import 'package:file/file.dart'; |
| |
| mixin GsUtilDownloader on Package { |
| /// Fetch the [source] into the [target] [Directory] using `gsutil.py`. |
| @override |
| Future<List<FileSystemEntity>> fetch(Directory target) async { |
| final arguments = ['cp', '$source', target.path]; |
| final result = |
| await Command('gsutil.py', arguments, runInShell: io.Platform.isWindows) |
| .run(); |
| if (result.exitCode == 1 && |
| result.stderr.contains('401 Anonymous caller')) { |
| throw StateError( |
| 'You need to authenticate by running:\n gsutil.py config\n'); |
| } |
| if (result.exitCode != 0) { |
| throw io.ProcessException('gsutil.py', arguments, |
| 'Failed to cp $source:\n${result.stderr}', result.exitCode); |
| } |
| return await target.list().toList(); |
| } |
| } |
| |
| mixin HttpDownloader on Package { |
| /// Fetch the [source] into the [target] [Directory] using [HttpClient]. |
| @override |
| Future<List<FileSystemEntity>> fetch(Directory target) async { |
| final file = target.resolveFile(source.pathSegments.last); |
| final request = await io.HttpClient().getUrl(source); |
| final response = await request.close(); |
| if (response.statusCode != 200) { |
| throw io.HttpException( |
| 'Failed to download $source: ${response.statusCode}', |
| uri: source); |
| } |
| await response.pipe(file.openWrite()); |
| return [file]; |
| } |
| } |