| // Copyright 2023 The Flutter Authors. 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:async'; | |
| import 'dart:io'; | |
| import 'package:github/github.dart'; | |
| const Duration clockSkew = Duration(seconds: 5); | |
| int minApiPoints = 250; // number of points to leave for debugging, etc | |
| class Abort implements Exception {} | |
| enum Mode { full, abbreviated, aborted } | |
| Mode mode = Mode.full; | |
| final Completer<void> aborter = Completer<void>(); | |
| Future<void> rateLimit( | |
| final GitHub github, | |
| final String status, | |
| final String next, | |
| ) async { | |
| if (mode == Mode.aborted) { | |
| throw Abort(); | |
| } | |
| stdout.write( | |
| '$status${github.rateLimitRemaining != null ? ". Rate limits: ${github.rateLimitRemaining}/${github.rateLimitLimit} per hour" : ""}.\x1B[K\r', | |
| ); | |
| if (github.rateLimitRemaining != null && | |
| github.rateLimitRemaining! < minApiPoints) { | |
| var delay = github.rateLimitReset!.difference(DateTime.now()); | |
| if (delay > Duration.zero) { | |
| delay += clockSkew; | |
| print( | |
| '\nWaiting until ${DateTime.now().add(delay).toLocal()} to continue with $next...', | |
| ); | |
| await Future.any<void>(<Future<void>>[ | |
| Future<void>.delayed(delay), | |
| aborter.future, | |
| ]); | |
| minApiPoints = 50; | |
| } | |
| } | |
| } | |
| void verifyStringSanity( | |
| final String value, | |
| final Set<String> disallowedSubstrings, | |
| ) { | |
| for (final substring in disallowedSubstrings) { | |
| if (value.contains(substring)) { | |
| throw FormatException('Found "$disallowedSubstrings" in "$value".'); | |
| } | |
| } | |
| } | |
| DateTime maxAge(final Duration maxAge) => DateTime.now().subtract(maxAge); |