feat: Add a cutler tool for managing our Flutter forks. (#336)
This commit is contained in:
+2
-2
@@ -128,7 +128,7 @@ And save off that hash:
|
||||
We do not need to update our engine fork commits at this time since it already
|
||||
pointed to the (unchanged) forked buildroot in `DEPS`.
|
||||
|
||||
Because this kind of rebase is a non-fastforward commit, we will need to
|
||||
Because this kind of rebase is a non-fast-forward commit, we will need to
|
||||
force push to our fork. A better solution will be for us to tag or branch
|
||||
each of these releases instead of keeping a single release branch.
|
||||
```
|
||||
@@ -164,7 +164,7 @@ git push origin --force
|
||||
https://github.com/shorebirdtech/shorebird/blob/main/packages/shorebird_cli/lib/src/engine_revision.dart
|
||||
|
||||
12. If there were changes to the `patch` binary in the `updater` library we
|
||||
will need to tigger github actions before we can publish the new version of
|
||||
will need to trigger github actions before we can publish the new version of
|
||||
the shorebird engine.
|
||||
|
||||
13. Before we can publish the new version of Shorebird, we need to build the
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# https://dart.dev/guides/libraries/private-files
|
||||
# Created by `dart pub`
|
||||
.dart_tool/
|
||||
@@ -0,0 +1,6 @@
|
||||
# Cutler
|
||||
A tool for managing our fork of Flutter
|
||||
|
||||
"Someone who makes or sells cutlery is a cutler." - Wikipedia
|
||||
|
||||
"Forks are considered cutlery, right?" - Me
|
||||
@@ -0,0 +1,5 @@
|
||||
include: package:very_good_analysis/analysis_options.4.0.0.yaml
|
||||
linter:
|
||||
rules:
|
||||
public_member_api_docs: false
|
||||
avoid_print: false
|
||||
@@ -0,0 +1,364 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:cutler/config.dart';
|
||||
import 'package:cutler/model.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
|
||||
/// Our path constants.
|
||||
enum Paths {
|
||||
engineDEPS('DEPS'),
|
||||
flutterEngineVersion('bin/internal/engine.version'),
|
||||
shorebirdFlutterVersion('bin/internal/flutter.version');
|
||||
|
||||
const Paths(this.path);
|
||||
final String path;
|
||||
}
|
||||
|
||||
String runCommand(
|
||||
String executable,
|
||||
List<String> arguments, {
|
||||
String? workingDirectory,
|
||||
}) {
|
||||
if (config.verbose) {
|
||||
final workingDirectoryString = workingDirectory == null ||
|
||||
p.equals(workingDirectory, Directory.current.path)
|
||||
? ''
|
||||
: ' (in $workingDirectory)';
|
||||
print("$executable ${arguments.join(' ')}$workingDirectoryString");
|
||||
}
|
||||
final result = Process.runSync(
|
||||
executable,
|
||||
arguments,
|
||||
workingDirectory: workingDirectory,
|
||||
);
|
||||
if (result.exitCode != 0) {
|
||||
throw Exception('Failed to run $executable $arguments: ${result.stderr}');
|
||||
}
|
||||
return result.stdout.toString().trim();
|
||||
}
|
||||
|
||||
void dryRunCommand(
|
||||
String executable,
|
||||
List<String> arguments, {
|
||||
String? workingDirectory,
|
||||
}) {
|
||||
print("$executable ${arguments.join(' ')}");
|
||||
}
|
||||
|
||||
extension RepoCommands on Repo {
|
||||
Version versionFrom(String hash, {bool lookupTags = true}) {
|
||||
return Version(
|
||||
hash: hash,
|
||||
repo: this,
|
||||
aliases: lookupTags ? getTagsFor(hash) : [],
|
||||
);
|
||||
}
|
||||
|
||||
String get _workingDirectory => '${config.checkoutsRoot}/$path';
|
||||
|
||||
String getLatestCommit(String branch) {
|
||||
return runCommand(
|
||||
'git',
|
||||
['log', '-1', '--pretty=%H', branch],
|
||||
workingDirectory: _workingDirectory,
|
||||
);
|
||||
}
|
||||
|
||||
List<String> getTagsFor(String commit) {
|
||||
final output = runCommand(
|
||||
'git',
|
||||
['tag', '--points-at', commit],
|
||||
workingDirectory: _workingDirectory,
|
||||
);
|
||||
if (output.isEmpty) {
|
||||
return [];
|
||||
}
|
||||
return output.split('\n');
|
||||
}
|
||||
|
||||
Version getForkPoint() {
|
||||
final hash = runCommand(
|
||||
'git',
|
||||
['merge-base', '--fork-point', upstreamBranch, releaseBranch],
|
||||
workingDirectory: _workingDirectory,
|
||||
);
|
||||
return versionFrom(hash);
|
||||
}
|
||||
|
||||
String contentsAtPath(String commit, String path) {
|
||||
return runCommand(
|
||||
'git',
|
||||
['show', '$commit:$path'],
|
||||
workingDirectory: _workingDirectory,
|
||||
);
|
||||
}
|
||||
|
||||
void writeFile(String path, String contents) {
|
||||
File(path).writeAsStringSync(contents);
|
||||
}
|
||||
|
||||
void commit(String message) {
|
||||
runCommand(
|
||||
'git',
|
||||
['commit', '-a', '-m', message],
|
||||
workingDirectory: _workingDirectory,
|
||||
);
|
||||
}
|
||||
|
||||
Version localHead() {
|
||||
return versionFrom(
|
||||
runCommand(
|
||||
'git',
|
||||
['rev-parse', 'HEAD'],
|
||||
workingDirectory: _workingDirectory,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension VersionCommands on Version {
|
||||
String contentsAtPath(String path) {
|
||||
return repo.contentsAtPath(hash, path);
|
||||
}
|
||||
}
|
||||
|
||||
String printLatestForBranch(Repo repo, String branch) {
|
||||
final hash = repo.getLatestCommit(branch);
|
||||
final tags = repo.getTagsFor(hash);
|
||||
final tagsString = tags.isEmpty ? '' : " (${tags.join(', ')})";
|
||||
print('${repo.name.padRight(10)} ${branch.padRight(25)} $hash$tagsString');
|
||||
return hash;
|
||||
}
|
||||
|
||||
void printVersions(VersionSet versions, int indent) {
|
||||
print("${' ' * indent}engine ${versions.engine}");
|
||||
print("${' ' * indent}flutter ${versions.flutter}");
|
||||
print("${' ' * indent}buildroot ${versions.buildroot}");
|
||||
}
|
||||
|
||||
VersionSet getFlutterVersions(String flutterHash) {
|
||||
final engineHash = Repo.flutter
|
||||
.contentsAtPath(flutterHash, 'bin/internal/engine.version')
|
||||
.trim();
|
||||
final depsContents =
|
||||
Repo.engine.contentsAtPath(engineHash, Paths.engineDEPS.path);
|
||||
final buildrootVersion = parseBuildRoot(depsContents);
|
||||
return VersionSet(
|
||||
engine: Repo.engine.versionFrom(engineHash),
|
||||
flutter: Repo.flutter.versionFrom(flutterHash),
|
||||
buildroot: Repo.buildroot.versionFrom(buildrootVersion),
|
||||
);
|
||||
}
|
||||
|
||||
String parseBuildRoot(String depsContents) {
|
||||
final lines = depsContents.split('\n');
|
||||
// Example:
|
||||
// 'src': 'https://github.com/flutter/buildroot.git' + '@' + '059d155b4d452efd9c4427c45cddfd9445144869',
|
||||
final buildrootLine = lines.firstWhere((line) => line.contains("'src': "));
|
||||
final regexp = RegExp('([0-9a-f]{40})');
|
||||
final match = regexp.firstMatch(buildrootLine);
|
||||
if (match == null) {
|
||||
throw Exception('Failed to parse buildroot version from $buildrootLine');
|
||||
}
|
||||
return match.group(0)!;
|
||||
}
|
||||
|
||||
VersionSet getForkpoints() {
|
||||
final flutterForkpoint = Repo.flutter.getForkPoint();
|
||||
// final engineForkpoint = Repo.engine.getForkPoint();
|
||||
// final buildrootForkpoint = Repo.buildroot.getForkPoint();
|
||||
// return VersionSet(
|
||||
// engine: engineForkpoint,
|
||||
// flutter: flutterForkpoint,
|
||||
// buildroot: buildrootForkpoint,
|
||||
// );
|
||||
|
||||
// This is slightly error-prone in that we're assuming that our engine and
|
||||
// buildroot forks started from the correct commit. But I'm not sure how
|
||||
// to determine the forkpoint otherwise. engine and buildroot don't have
|
||||
// a stable branch, yet they do seem to "branch" for stable releases at the
|
||||
// x.x.0 release.
|
||||
return getFlutterVersions(flutterForkpoint.hash);
|
||||
}
|
||||
|
||||
/// Generate rebase commands for the repo given the version sets.
|
||||
String rebaseRepo(
|
||||
Repo repo, {
|
||||
required VersionSet forkpoints,
|
||||
required VersionSet upstream,
|
||||
required VersionSet shorebird,
|
||||
bool dryRun = true,
|
||||
}) {
|
||||
final run = dryRun ? dryRunCommand : runCommand;
|
||||
if (upstream[repo] != forkpoints[repo]) {
|
||||
print('Rebasing ${repo.name}...');
|
||||
run(
|
||||
'git',
|
||||
[
|
||||
'rebase',
|
||||
'--onto',
|
||||
upstream[repo].ref,
|
||||
forkpoints[repo].ref,
|
||||
shorebird[repo].ref
|
||||
],
|
||||
workingDirectory: repo._workingDirectory,
|
||||
);
|
||||
|
||||
return dryRun ? 'new-${repo.name}-hash' : repo.getLatestCommit('HEAD');
|
||||
} else {
|
||||
print('Skipping ${repo.name} (unchanged: ${upstream[repo].ref})');
|
||||
}
|
||||
return shorebird[repo].ref;
|
||||
}
|
||||
|
||||
/// Cutler will always try to upgrade to the latest flutter version
|
||||
/// on the stable branch.
|
||||
void main(List<String> args) {
|
||||
config = parseArgs(args);
|
||||
if (config.doUpdate) {
|
||||
for (final repo in Repo.values) {
|
||||
print('Updating ${repo.name}...');
|
||||
runCommand(
|
||||
'git',
|
||||
['fetch', '--all'],
|
||||
workingDirectory: repo._workingDirectory,
|
||||
);
|
||||
}
|
||||
}
|
||||
// This prints the latest versions on our branches, not necessarily
|
||||
// the ones shorebird depends on.
|
||||
// for (final repo in Repo.values) {
|
||||
// printLatestForBranch(repo, repo.releaseBranch);
|
||||
// }
|
||||
|
||||
// FIXME: This is wrong, but 0.0.7 doesn't have a flutter.version file yet.
|
||||
final shorebirdFlutter =
|
||||
Repo.flutter.getLatestCommit(Repo.flutter.releaseBranch);
|
||||
// final shorebirdStable =
|
||||
// Repo.shorebird.getLatestCommit(Repo.shorebird.releaseBranch);
|
||||
// final shorebirdFlutter = Repo.flutter
|
||||
// .contentsAtPath(shorebirdStable, 'bin/internal/flutter.version');
|
||||
final shorebird = getFlutterVersions(shorebirdFlutter);
|
||||
print('Shorebird stable:');
|
||||
printVersions(shorebird, 2);
|
||||
|
||||
final forkpoints = getForkpoints();
|
||||
print('Forkpoints:');
|
||||
printVersions(forkpoints, 2);
|
||||
|
||||
// Figure out the latest version of Flutter.
|
||||
final upstreamFlutter =
|
||||
Repo.flutter.getLatestCommit(Repo.flutter.upstreamBranch);
|
||||
// Figure out what versions that Flutter depends on.
|
||||
final upstream = getFlutterVersions(upstreamFlutter);
|
||||
print('Upstream stable:');
|
||||
printVersions(upstream, 2);
|
||||
|
||||
Version doRebase(Repo repo) {
|
||||
final newHash = rebaseRepo(
|
||||
repo,
|
||||
forkpoints: forkpoints,
|
||||
upstream: upstream,
|
||||
shorebird: shorebird,
|
||||
dryRun: config.dryRun,
|
||||
);
|
||||
return repo.versionFrom(newHash, lookupTags: !config.dryRun);
|
||||
}
|
||||
|
||||
// Rebase our repos.
|
||||
var newHead = VersionSet(
|
||||
buildroot: doRebase(Repo.buildroot),
|
||||
engine: doRebase(Repo.engine),
|
||||
flutter: doRebase(Repo.flutter),
|
||||
);
|
||||
// Make sure engine points to this buildroot.
|
||||
// If not, update it and commit.
|
||||
if (shorebird[Repo.buildroot] != newHead.buildroot) {
|
||||
print('Updating engine DEPS...');
|
||||
final depsContents =
|
||||
shorebird[Repo.engine].contentsAtPath(Paths.engineDEPS.path);
|
||||
final newDepsContents = depsContents.replaceAll(
|
||||
shorebird[Repo.buildroot].hash,
|
||||
newHead.buildroot.hash,
|
||||
);
|
||||
if (newDepsContents != depsContents) {
|
||||
if (config.dryRun) {
|
||||
print('Would have changed DEPS lines:');
|
||||
final changes = newDepsContents.split('\n').where((line) {
|
||||
return line.contains(newHead.buildroot.hash);
|
||||
});
|
||||
print(changes);
|
||||
} else {
|
||||
Repo.engine.writeFile(Paths.engineDEPS.path, newDepsContents);
|
||||
Repo.engine.commit('Update DEPS.');
|
||||
}
|
||||
} else {
|
||||
print('ERROR: engine DEPS is already up to date?');
|
||||
exit(1);
|
||||
}
|
||||
newHead = newHead.copyWith(engine: Repo.engine.localHead());
|
||||
}
|
||||
|
||||
// Update our forked flutter's engine version.
|
||||
if (shorebird[Repo.engine] != newHead.engine) {
|
||||
print('Updating flutter engine version...');
|
||||
final existingEngineVersion = shorebird[Repo.flutter]
|
||||
.contentsAtPath(Paths.flutterEngineVersion.path)
|
||||
.trim();
|
||||
if (newHead.engine.hash != existingEngineVersion) {
|
||||
if (config.dryRun) {
|
||||
print(
|
||||
' Change engine.version: ${newHead.engine.hash} from '
|
||||
'$existingEngineVersion',
|
||||
);
|
||||
} else {
|
||||
Repo.flutter
|
||||
.writeFile(Paths.flutterEngineVersion.path, newHead.engine.hash);
|
||||
Repo.flutter.commit('Update engine.version');
|
||||
}
|
||||
} else {
|
||||
print('ERROR: flutter engine.version is already up to date?');
|
||||
exit(1);
|
||||
}
|
||||
newHead = newHead.copyWith(flutter: Repo.flutter.localHead());
|
||||
}
|
||||
// Update Shorebird's version of Flutter.
|
||||
if (shorebird[Repo.flutter] != newHead.flutter) {
|
||||
print('Updating shorebird flutter version...');
|
||||
if (config.dryRun) {
|
||||
print(
|
||||
' Change flutter.version: ${newHead.flutter.hash} from '
|
||||
'${shorebird[Repo.flutter].hash}',
|
||||
);
|
||||
} else {
|
||||
Repo.shorebird
|
||||
.writeFile(Paths.shorebirdFlutterVersion.path, newHead.flutter.hash);
|
||||
Repo.shorebird.commit('Update flutter.version');
|
||||
}
|
||||
}
|
||||
|
||||
// To push a new engine:
|
||||
// git branch stable_codepush HEAD --force
|
||||
// git push origin stable_codepush --force
|
||||
|
||||
// Engine rev: d470ae25d21f583abe128f7b838476afd5e45bde
|
||||
|
||||
// To push new flutter:
|
||||
// % git rebase --onto 3.7.12 3.7.10 \
|
||||
// 45fc514f1a9c347a3af76b02baf980a4d88b7879
|
||||
// Auto-merging bin/internal/engine.version
|
||||
// CONFLICT (content): Merge conflict in bin/internal/engine.version
|
||||
// error: could not apply c2185f5f6c... chore: Update engine version to
|
||||
// shorebird-3.7.10
|
||||
// hint: Resolve all conflicts manually, mark them as resolved with
|
||||
// hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
|
||||
// hint: You can instead skip this commit: run "git rebase --skip".
|
||||
// hint: To abort and get back to the state before "git rebase", run "git
|
||||
// rebase --abort".
|
||||
// Could not apply c2185f5f6c... chore: Update engine version to
|
||||
// shorebird-3.7.10
|
||||
|
||||
// Flutter revision: 58dff390738f9c512ab7e0638af9573515b0409c
|
||||
|
||||
// To push new shorebird:
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:args/args.dart';
|
||||
|
||||
// https://github.com/dart-lang/sdk/issues/18466
|
||||
// https://github.com/dart-lang/path/issues/117#issuecomment-1034313012
|
||||
String expandUser(String path) {
|
||||
// This is not "well written", but eventually I guess we should
|
||||
// write one and publish it if Dart doesn't add an equivalent method.
|
||||
// If we're in CMD or PowerShell, we need to expand %USERPROFILE%. If we're
|
||||
// in WSL, we need to expand $HOME.
|
||||
// This should handle ~ and ~user.
|
||||
if (path.startsWith('~')) {
|
||||
final home = Platform.environment['HOME'];
|
||||
if (home == null) {
|
||||
throw Exception('Failed to expand $path');
|
||||
}
|
||||
return path.replaceFirst('~', home);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
// Config is basically just our typed ArgResults held as a global.
|
||||
class Config {
|
||||
Config({
|
||||
required this.checkoutsRoot,
|
||||
required this.verbose,
|
||||
required this.dryRun,
|
||||
required this.doUpdate,
|
||||
});
|
||||
final String checkoutsRoot;
|
||||
final bool verbose;
|
||||
final bool dryRun;
|
||||
final bool doUpdate;
|
||||
}
|
||||
|
||||
late final Config config;
|
||||
|
||||
Config parseArgs(List<String> args) {
|
||||
final parser = ArgParser()
|
||||
..addFlag('verbose', abbr: 'v')
|
||||
..addOption(
|
||||
'root',
|
||||
defaultsTo: '.',
|
||||
help: 'Directory in which to find checkouts.',
|
||||
)
|
||||
..addFlag('dry-run', defaultsTo: true, help: 'Do not actually run git.')
|
||||
..addFlag('update', defaultsTo: true, help: 'Update checkouts.');
|
||||
final results = parser.parse(args);
|
||||
return Config(
|
||||
verbose: results['verbose'] as bool,
|
||||
checkoutsRoot: expandUser(results['root'] as String),
|
||||
dryRun: results['dry-run'] as bool,
|
||||
doUpdate: results['update'] as bool,
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
enum Repo {
|
||||
shorebird(
|
||||
name: 'shorebird',
|
||||
path: '_shorebird/shorebird',
|
||||
url: 'https://github.com/shorebirdtech/shorebird.git',
|
||||
releaseBranch: 'origin/stable',
|
||||
upstreamBranch: 'origin/main',
|
||||
),
|
||||
flutter(
|
||||
name: 'flutter',
|
||||
path: 'flutter',
|
||||
url: 'https://github.com/shorebirdtech/flutter.git',
|
||||
releaseBranch: 'origin/stable',
|
||||
upstreamBranch: 'upstream/stable',
|
||||
),
|
||||
engine(
|
||||
name: 'engine',
|
||||
path: 'engine/src/flutter',
|
||||
url: 'https://github.com/shorebirdtech/engine.git',
|
||||
releaseBranch: 'origin/stable_codepush',
|
||||
upstreamBranch: 'upstream/master',
|
||||
),
|
||||
buildroot(
|
||||
name: 'buildroot',
|
||||
path: 'engine/src',
|
||||
url: 'https://github.com/shorebirdtech/builddoor.git',
|
||||
releaseBranch: 'origin/stable_codepush',
|
||||
upstreamBranch: 'upstream/master',
|
||||
);
|
||||
|
||||
const Repo({
|
||||
required this.name,
|
||||
required this.path,
|
||||
required this.url,
|
||||
required this.releaseBranch,
|
||||
required this.upstreamBranch,
|
||||
});
|
||||
|
||||
final String name;
|
||||
final String path;
|
||||
final String url;
|
||||
final String releaseBranch;
|
||||
final String upstreamBranch;
|
||||
}
|
||||
|
||||
@immutable
|
||||
class Version {
|
||||
const Version({
|
||||
required this.hash,
|
||||
required this.repo,
|
||||
this.aliases = const [],
|
||||
});
|
||||
|
||||
final String hash;
|
||||
final List<String> aliases;
|
||||
final Repo repo;
|
||||
|
||||
String get ref => aliases.isEmpty ? hash : aliases.first;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
final aliasesString = aliases.isEmpty ? '' : " (${aliases.join(', ')})";
|
||||
return '$hash$aliasesString';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other is! Version) {
|
||||
return false;
|
||||
}
|
||||
return other.hash == hash && other.repo == repo;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hashAll([hash, repo]);
|
||||
}
|
||||
|
||||
class VersionSet {
|
||||
const VersionSet({
|
||||
required this.engine,
|
||||
required this.flutter,
|
||||
required this.buildroot,
|
||||
});
|
||||
final Version engine;
|
||||
final Version flutter;
|
||||
final Version buildroot;
|
||||
|
||||
Version operator [](Repo repo) => {
|
||||
Repo.engine: engine,
|
||||
Repo.flutter: flutter,
|
||||
Repo.buildroot: buildroot,
|
||||
}[repo]!;
|
||||
|
||||
VersionSet copyWith({Version? engine, Version? flutter, Version? buildroot}) {
|
||||
return VersionSet(
|
||||
engine: engine ?? this.engine,
|
||||
flutter: flutter ?? this.flutter,
|
||||
buildroot: buildroot ?? this.buildroot,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,373 @@
|
||||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
_fe_analyzer_shared:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: _fe_analyzer_shared
|
||||
sha256: a36ec4843dc30ea6bf652bf25e3448db6c5e8bcf4aa55f063a5d1dad216d8214
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "58.0.0"
|
||||
analyzer:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: analyzer
|
||||
sha256: cc4242565347e98424ce9945c819c192ec0838cb9d1f6aa4a97cc96becbc5b27
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.10.0"
|
||||
args:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: args
|
||||
sha256: "4cab82a83ffef80b262ddedf47a0a8e56ee6fbf7fe21e6e768b02792034dd440"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.0"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.11.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: boolean_selector
|
||||
sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.17.1"
|
||||
convert:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: convert
|
||||
sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.1"
|
||||
coverage:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: coverage
|
||||
sha256: "2fb815080e44a09b85e0f2ca8a820b15053982b2e714b59267719e8a9ff17097"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.6.3"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.2"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.4"
|
||||
frontend_server_client:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: frontend_server_client
|
||||
sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.0"
|
||||
glob:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: glob
|
||||
sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
http_multi_server:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_multi_server
|
||||
sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.1"
|
||||
http_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_parser
|
||||
sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.2"
|
||||
io:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: io
|
||||
sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: js
|
||||
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.7"
|
||||
logging:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: logging
|
||||
sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.12.15"
|
||||
meta:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: meta
|
||||
sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
mime:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: mime
|
||||
sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
node_preamble:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: node_preamble
|
||||
sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
package_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_config
|
||||
sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
path:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: path
|
||||
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.8.3"
|
||||
pool:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pool
|
||||
sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.5.1"
|
||||
pub_semver:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pub_semver
|
||||
sha256: "307de764d305289ff24ad257ad5c5793ce56d04947599ad68b3baa124105fc17"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
shelf:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf
|
||||
sha256: c24a96135a2ccd62c64b69315a14adc5c3419df63b4d7c05832a346fdb73682c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
shelf_packages_handler:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf_packages_handler
|
||||
sha256: aef74dc9195746a384843102142ab65b6a4735bb3beea791e63527b88cc83306
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
shelf_static:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf_static
|
||||
sha256: e792b76b96a36d4a41b819da593aff4bdd413576b3ba6150df5d8d9996d2e74c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
shelf_web_socket:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf_web_socket
|
||||
sha256: a988c0e8d8ffbdb8a28aa7ec8e449c260f3deb808781fe1284d22c5bba7156e8
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.3"
|
||||
source_map_stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_map_stack_trace
|
||||
sha256: "84cf769ad83aa6bb61e0aa5a18e53aea683395f196a6f39c4c881fb90ed4f7ae"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
source_maps:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_maps
|
||||
sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.10.12"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_span
|
||||
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_scanner
|
||||
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: term_glyph
|
||||
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
test:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: test
|
||||
sha256: "4f92f103ef63b1bbac6f4bd1930624fca81b2574464482512c4f0896319be575"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.24.2"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: daadc9baabec998b062c9091525aa95786508b1c48e9c30f1f891b8bf6ff2e64
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.2"
|
||||
test_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_core
|
||||
sha256: "3642b184882f79e76ca57a9230fb971e494c3c1fd09c21ae3083ce891bcc0aa1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.2"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: typed_data
|
||||
sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
very_good_analysis:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: very_good_analysis
|
||||
sha256: ebc48c51db35beeeec8c414e32f7bd78e612bd7f5992ccb0d46e19edaeb40b08
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.0+1"
|
||||
vm_service:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
sha256: f6deed8ed625c52864792459709183da231ebf66ff0cf09e69b573227c377efe
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "11.3.0"
|
||||
watcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: watcher
|
||||
sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.2"
|
||||
web_socket_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web_socket_channel
|
||||
sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.0"
|
||||
webkit_inspection_protocol:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: webkit_inspection_protocol
|
||||
sha256: "67d3a8b6c79e1987d19d848b0892e582dbb0c66c57cc1fef58a177dd2aa2823d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: yaml
|
||||
sha256: "23812a9b125b48d4007117254bca50abb6c712352927eece9e155207b1db2370"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.1"
|
||||
sdks:
|
||||
dart: ">=2.19.6 <3.0.0"
|
||||
@@ -0,0 +1,16 @@
|
||||
name: cutler
|
||||
description: A tool for managing Flutter forks.
|
||||
version: 1.0.0
|
||||
repository: https://github.com/shorebirdtech/shorebird
|
||||
|
||||
environment:
|
||||
sdk: '>=2.19.6 <3.0.0'
|
||||
|
||||
dev_dependencies:
|
||||
test: ^1.21.0
|
||||
very_good_analysis: ^4.0.0
|
||||
|
||||
dependencies:
|
||||
args: ^2.4.0
|
||||
meta: ^1.9.1
|
||||
path: ^1.8.3
|
||||
Reference in New Issue
Block a user