blob: 090b6b8133dc85bf8af81db9d32b1478fbe9c8e0 [file] [log] [blame]
// Copyright (c) 2023, 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';
import 'shared.dart' as util;
// Abstraction over files fetched from the `unicode.org/Public` UCD repository.
// If any of these URIs stop working, find out where they have moved to.
final graphemeBreakPropertyData = DataFile(
'https://unicode.org/Public/UCD/latest/ucd/auxiliary/GraphemeBreakProperty.txt',
'third_party/Unicode_Consortium/GraphemeBreakProperty.txt');
final emojiData = DataFile(
'https://unicode.org/Public/UCD/latest/ucd/emoji/emoji-data.txt',
'third_party/Unicode_Consortium/emoji_data.txt');
final graphemeTestData = DataFile(
'https://unicode.org/Public/UCD/latest/ucd/auxiliary/GraphemeBreakTest.txt',
'third_party/Unicode_Consortium/GraphemeBreakTest.txt');
final emojiTestData = DataFile(
'https://unicode.org/Public/emoji/latest/emoji-test.txt',
'third_party/Unicode_Consortium/emoji_test.txt');
final licenseFile = DataFile('https://www.unicode.org/license.txt',
'third_party/Unicode_Consortium/UNICODE_LICENSE.txt');
final derivedData = DataFile(
'https://unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt',
'third_party/Unicode_Consortium/DerivedCoreProperties.txt');
class DataFile {
/// Source URI.
final String sourceLocation;
/// Target file path relative to package root.
final String targetLocation;
/// Cached contents.
String? _contents;
DataFile(this.sourceLocation, this.targetLocation);
Future<String> get contents async => _contents ??= await load();
/// Loads file, fetching it from the source first if necessary.
///
/// If [checkForUpdate] is `false`, the content of an existing file at
/// [targetLocation] is read. If there is no file or if [checkForUpdate]
/// is `true`, new content is fetched from the [sourceLocation] URI
/// and written to the [targetLocation] file.
Future<String> load({bool checkForUpdate = false}) async =>
(checkForUpdate ? null : _contents) ??
(_contents = await util.fetch(sourceLocation,
targetFile: _targetFile, forceLoad: checkForUpdate));
/// Fetches content, compares to existing content.
///
/// Returns `null` if no change, a path to a temporary file containing the
/// new content if there are changes.
Future<String?> checkChange([bool Function(String, String)? equals]) async {
equals ??= _eq;
var contents = await this.contents;
var tmpFile = File(util.tmpPath(targetLocation));
var newContents =
await util.fetch(sourceLocation, targetFile: tmpFile, forceLoad: true);
if (equals(contents, newContents)) {
return null;
}
return tmpFile.path;
}
static bool _eq(String a, String b) => a == b;
void copyFrom(String contentPath) {
_contents = null;
File(contentPath).copySync(_targetFile.path);
}
File get _targetFile => File(util.packagePath(targetLocation));
}