Unverified Commit c9400889 authored by Greg Spencer's avatar Greg Spencer Committed by GitHub

Add SHA256 checksums to published metadata (#28472)

Adds SHA256 checksums to the released package database, in preparation for showing them on the download website. (I'll update the existing data by hand).

Fixes #28465
parent d2a76414
......@@ -8,10 +8,12 @@ import 'dart:io' hide Platform;
import 'dart:typed_data';
import 'package:args/args.dart';
import 'package:crypto/crypto.dart';
import 'package:crypto/src/digest_sink.dart';
import 'package:http/http.dart' as http;
import 'package:path/path.dart' as path;
import 'package:process/process.dart';
import 'package:platform/platform.dart' show Platform, LocalPlatform;
import 'package:process/process.dart';
const String chromiumRepo = 'https://chromium.googlesource.com/external/github.com/flutter/flutter';
const String githubRepo = 'https://github.com/flutter/flutter.git';
......@@ -196,14 +198,14 @@ class ArchiveCreator {
bool subprocessOutput = true,
this.platform = const LocalPlatform(),
HttpReader httpReader,
}) : assert(revision.length == 40),
flutterRoot = Directory(path.join(tempDir.path, 'flutter')),
httpReader = httpReader ?? http.readBytes,
_processRunner = ProcessRunner(
processManager: processManager,
subprocessOutput: subprocessOutput,
platform: platform,
) {
}) : assert(revision.length == 40),
flutterRoot = Directory(path.join(tempDir.path, 'flutter')),
httpReader = httpReader ?? http.readBytes,
_processRunner = ProcessRunner(
processManager: processManager,
subprocessOutput: subprocessOutput,
platform: platform,
) {
_flutter = path.join(
flutterRoot.absolute.path,
'bin',
......@@ -311,8 +313,7 @@ class ArchiveCreator {
final File gitFile = File(path.join(tempDir.absolute.path, 'mingit.zip'));
await gitFile.writeAsBytes(data, flush: true);
final Directory minGitPath =
Directory(path.join(flutterRoot.absolute.path, 'bin', 'mingit'));
final Directory minGitPath = Directory(path.join(flutterRoot.absolute.path, 'bin', 'mingit'));
await minGitPath.create(recursive: true);
await _unzipArchive(gitFile, workingDirectory: minGitPath);
}
......@@ -435,13 +436,13 @@ class ArchivePublisher {
ProcessManager processManager,
bool subprocessOutput = true,
this.platform = const LocalPlatform(),
}) : assert(revision.length == 40),
platformName = platform.operatingSystem.toLowerCase(),
metadataGsPath = '$gsReleaseFolder/${getMetadataFilename(platform)}',
_processRunner = ProcessRunner(
processManager: processManager,
subprocessOutput: subprocessOutput,
);
}) : assert(revision.length == 40),
platformName = platform.operatingSystem.toLowerCase(),
metadataGsPath = '$gsReleaseFolder/${getMetadataFilename(platform)}',
_processRunner = ProcessRunner(
processManager: processManager,
subprocessOutput: subprocessOutput,
);
final Platform platform;
final String platformName;
......@@ -456,6 +457,18 @@ class ArchivePublisher {
String get destinationArchivePath => '$branchName/$platformName/${path.basename(outputFile.path)}';
static String getMetadataFilename(Platform platform) => 'releases_${platform.operatingSystem.toLowerCase()}.json';
Future<String> _getChecksum(File archiveFile) async {
final DigestSink digestSink = DigestSink();
final ByteConversionSink sink = sha256.startChunkedConversion(digestSink);
final Stream<List<int>> stream = archiveFile.openRead();
await stream.forEach((List<int> chunk) {
sink.add(chunk);
});
sink.close();
return digestSink.value.toString();
}
/// Publish the archive to Google Storage.
Future<void> publishArchive() async {
final String destGsPath = '$gsReleaseFolder/$destinationArchivePath';
......@@ -464,7 +477,7 @@ class ArchivePublisher {
await _updateMetadata();
}
Map<String, dynamic> _addRelease(Map<String, dynamic> jsonData) {
Future<Map<String, dynamic>> _addRelease(Map<String, dynamic> jsonData) async {
jsonData['base_url'] = '$baseUrl$releaseFolder';
if (!jsonData.containsKey('current_release')) {
jsonData['current_release'] = <String, String>{};
......@@ -480,6 +493,7 @@ class ArchivePublisher {
newEntry['version'] = version;
newEntry['release_date'] = DateTime.now().toUtc().toIso8601String();
newEntry['archive'] = destinationArchivePath;
newEntry['sha256'] = await _getChecksum(outputFile);
// Search for any entries with the same hash and channel and remove them.
final List<dynamic> releases = jsonData['releases'];
......@@ -521,7 +535,7 @@ class ArchivePublisher {
throw ProcessRunnerException('Unable to parse JSON metadata received from cloud: $e');
}
jsonData = _addRelease(jsonData);
jsonData = await _addRelease(jsonData);
const JsonEncoder encoder = JsonEncoder.withIndent(' ');
metadataFile.writeAsStringSync(encoder.convert(jsonData));
......
......@@ -238,26 +238,30 @@ void main() {
"channel": "dev",
"version": "v0.2.3",
"release_date": "2018-03-20T01:47:02.851729Z",
"archive": "dev/$platformName/flutter_${platformName}_v0.2.3-dev.zip"
"archive": "dev/$platformName/flutter_${platformName}_v0.2.3-dev.zip",
"sha256": "4fe85a822093e81cb5a66c7fc263f68de39b5797b294191b6d75e7afcc86aff8"
},
{
"hash": "b9bd51cc36b706215915711e580851901faebb40",
"channel": "beta",
"version": "v0.2.2",
"release_date": "2018-03-16T18:48:13.375013Z",
"archive": "dev/$platformName/flutter_${platformName}_v0.2.2-dev.zip"
"archive": "dev/$platformName/flutter_${platformName}_v0.2.2-dev.zip",
"sha256": "6073331168cdb37a4637a5dc073d6a7ef4e466321effa2c529fa27d2253a4d4b"
},
{
"hash": "$testRef",
"channel": "stable",
"version": "v0.0.0",
"release_date": "2018-03-20T01:47:02.851729Z",
"archive": "stable/$platformName/flutter_${platformName}_v0.0.0-dev.zip"
"archive": "stable/$platformName/flutter_${platformName}_v0.0.0-dev.zip",
"sha256": "5dd34873b3a3e214a32fd30c2c319a0f46e608afb72f0d450b2d621a6d02aebd"
}
]
}
''';
File(jsonPath).writeAsStringSync(releasesJson);
File(archivePath).writeAsStringSync('archive contents');
final String gsutilCall = platform.isWindows
? 'python ${path.join("D:", "depot_tools", "gsutil.py")}'
: 'gsutil.py';
......@@ -291,6 +295,7 @@ void main() {
expect(contents, contains('"hash": "$testRef"'));
expect(contents, contains('"channel": "stable"'));
expect(contents, contains('"archive": "stable/$platformName/$archiveName"'));
expect(contents, contains('"sha256": "f69f4865f861193a91d1c5544a894167a7137b788d10bac8edbf5d095f45cb4d"'));
// Make sure existing entries are preserved.
expect(contents, contains('"hash": "5a58b36e36b8d7aace89d3950e6deb307956a6a0"'));
expect(contents, contains('"hash": "b9bd51cc36b706215915711e580851901faebb40"'));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment