81
.cirrus.yml
81
.cirrus.yml
@@ -10,6 +10,7 @@ task:
|
||||
PATH: "$CIRRUS_WORKING_DIR/bin:$CIRRUS_WORKING_DIR/bin/cache/dart-sdk/bin:$PATH"
|
||||
ANDROID_SDK_ROOT: "/opt/android_sdk"
|
||||
git_fetch_script:
|
||||
- git clean -xfd
|
||||
- git fetch origin
|
||||
- git fetch origin master # To set FETCH_HEAD for "git merge-base" to work
|
||||
pub_cache:
|
||||
@@ -27,9 +28,9 @@ task:
|
||||
env:
|
||||
SHARD: docs
|
||||
# For uploading master docs to Firebase master branch staging site
|
||||
FIREBASE_MASTER_TOKEN: ENCRYPTED[37e8b82f167864cae9a3f4d2cf3f37dea331d9375c295327c45de524f6c588fa6f6d63e5784f10f6d43ce29689f36c92]
|
||||
FIREBASE_MASTER_TOKEN: ENCRYPTED[eb768d18798fdc5abfe09b224e1724c4d82831d715ccf90df2c79d618c317216cbd99493278361f6fe7948b409b603f0]
|
||||
# For uploading beta docs to Firebase public live site
|
||||
FIREBASE_PUBLIC_TOKEN: ENCRYPTED[c422da192f06da7b4449ca8e7aa866dabeb8a0f8d7488497c2e7e447e6fd31d917e6c813db081dc4e2a7a63afdf41864]
|
||||
FIREBASE_PUBLIC_TOKEN: ENCRYPTED[37e8b82f167864cae9a3f4d2cf3f37dea331d9375c295327c45de524f6c588fa6f6d63e5784f10f6d43ce29689f36c92]
|
||||
docs_script: ./dev/bots/docs.sh
|
||||
- name: deploy_gallery
|
||||
only_if: $CIRRUS_BRANCH == 'dev'
|
||||
@@ -49,6 +50,7 @@ task:
|
||||
- dart --enable-asserts ./dev/bots/analyze.dart
|
||||
- name: tests-linux
|
||||
env:
|
||||
GCLOUD_SERVICE_ACCOUNT_KEY: ENCRYPTED[f12abe60f5045d619ef4c79b83dd1e0722a0b0b13dbea95fbe334e2db7fffbcd841a5a92da8824848b539a19afe0c9fb]
|
||||
SHARD: tests
|
||||
test_script:
|
||||
- dart --enable-asserts ./dev/bots/test.dart
|
||||
@@ -57,6 +59,7 @@ task:
|
||||
memory: 12G
|
||||
- name: tool_tests-linux
|
||||
env:
|
||||
GCLOUD_SERVICE_ACCOUNT_KEY: ENCRYPTED[f12abe60f5045d619ef4c79b83dd1e0722a0b0b13dbea95fbe334e2db7fffbcd841a5a92da8824848b539a19afe0c9fb]
|
||||
SHARD: tool_tests
|
||||
test_script:
|
||||
- dart --enable-asserts ./dev/bots/test.dart
|
||||
@@ -66,6 +69,9 @@ task:
|
||||
- name: build_tests-linux
|
||||
env:
|
||||
SHARD: build_tests
|
||||
- name: integration_tests-linux
|
||||
env:
|
||||
SHARD: integration_tests
|
||||
test_script:
|
||||
# Unsetting CIRRUS_CHANGE_MESSAGE and CIRRUS_COMMIT_MESSAGE as they
|
||||
# might include non-ASCII characters which makes Gradle crash.
|
||||
@@ -83,21 +89,18 @@ task:
|
||||
container:
|
||||
cpu: 4
|
||||
memory: 12G
|
||||
- name: codelabs-build-test
|
||||
env:
|
||||
SHARD: codelabs-build-test
|
||||
build_test_script: ./dev/bots/codelabs_build_test.sh
|
||||
|
||||
|
||||
task:
|
||||
use_compute_credits: $CIRRUS_USER_COLLABORATOR == 'true' && $CIRRUS_PR == ''
|
||||
windows_container:
|
||||
image: cirrusci/windowsservercore:2016
|
||||
image: cirrusci/android-sdk:28-windowsservercore-ltsc2016
|
||||
os_version: 2016
|
||||
cpu: 4
|
||||
env:
|
||||
CIRRUS_WORKING_DIR: "C:\\Windows\\Temp\\flutter sdk"
|
||||
git_fetch_script:
|
||||
- git clean -xfd
|
||||
- git fetch origin
|
||||
- git fetch origin master # To set FETCH_HEAD for "git merge-base" to work
|
||||
pub_cache:
|
||||
@@ -119,9 +122,11 @@ task:
|
||||
matrix:
|
||||
- name: tests-windows
|
||||
env:
|
||||
GCLOUD_SERVICE_ACCOUNT_KEY: ENCRYPTED[f12abe60f5045d619ef4c79b83dd1e0722a0b0b13dbea95fbe334e2db7fffbcd841a5a92da8824848b539a19afe0c9fb]
|
||||
SHARD: tests
|
||||
- name: tool_tests-windows
|
||||
env:
|
||||
GCLOUD_SERVICE_ACCOUNT_KEY: ENCRYPTED[f12abe60f5045d619ef4c79b83dd1e0722a0b0b13dbea95fbe334e2db7fffbcd841a5a92da8824848b539a19afe0c9fb]
|
||||
SHARD: tool_tests
|
||||
- name: build_tests-windows
|
||||
env:
|
||||
@@ -129,6 +134,12 @@ task:
|
||||
container:
|
||||
cpu: 4
|
||||
memory: 12G
|
||||
- name: integration_tests-windows
|
||||
env:
|
||||
SHARD: integration_tests
|
||||
container:
|
||||
cpu: 4
|
||||
memory: 12G
|
||||
|
||||
task:
|
||||
use_compute_credits: $CIRRUS_USER_COLLABORATOR == 'true'
|
||||
@@ -141,6 +152,7 @@ task:
|
||||
- tests-macos
|
||||
- tool_tests-macos
|
||||
- build_tests-macos
|
||||
- add2app-macos
|
||||
env:
|
||||
# Name the SDK directory to include a space so that we constantly
|
||||
# test path names with spaces in them.
|
||||
@@ -155,8 +167,13 @@ task:
|
||||
# Private repo for publishing certificates.
|
||||
PUBLISHING_MATCH_CERTIFICATE_REPO: git@github.com:flutter/private_publishing_certificates.git
|
||||
osx_instance:
|
||||
image: high-sierra-xcode-9.4.1
|
||||
image: mojave-xcode-10.1
|
||||
# occasionally the clock on these machines is out of sync
|
||||
# with the actual time - this should help to verify
|
||||
print_date_script:
|
||||
- date
|
||||
git_fetch_script:
|
||||
- git clean -xfd
|
||||
- git fetch origin
|
||||
- git fetch origin master # To set FETCH_HEAD
|
||||
setup_script:
|
||||
@@ -168,14 +185,42 @@ task:
|
||||
task:
|
||||
use_compute_credits: $CIRRUS_USER_COLLABORATOR == 'true'
|
||||
osx_instance:
|
||||
image: high-sierra-xcode-9.4.1
|
||||
image: mojave-xcode-10.1
|
||||
depends_on:
|
||||
- analyze
|
||||
env:
|
||||
CIRRUS_WORKING_DIR: "/tmp/flutter sdk"
|
||||
COCOAPODS_DISABLE_STATS: true
|
||||
matrix:
|
||||
- name: tests-macos
|
||||
env:
|
||||
GCLOUD_SERVICE_ACCOUNT_KEY: ENCRYPTED[f12abe60f5045d619ef4c79b83dd1e0722a0b0b13dbea95fbe334e2db7fffbcd841a5a92da8824848b539a19afe0c9fb]
|
||||
SHARD: tests
|
||||
- name: tool_tests-macos
|
||||
env:
|
||||
GCLOUD_SERVICE_ACCOUNT_KEY: ENCRYPTED[f12abe60f5045d619ef4c79b83dd1e0722a0b0b13dbea95fbe334e2db7fffbcd841a5a92da8824848b539a19afe0c9fb]
|
||||
SHARD: tool_tests
|
||||
- name: $SHARD-macos
|
||||
env:
|
||||
matrix:
|
||||
- SHARD: integration_tests
|
||||
- SHARD: build_tests
|
||||
COCOAPODS_DISABLE_STATS: true
|
||||
FLUTTER_FRAMEWORK_DIR: "/tmp/flutter sdk/bin/cache/artifacts/engine/ios/"
|
||||
osx_instance:
|
||||
image: mojave-flutter
|
||||
remove_preinstalled_fluuter_script: rm -rf $FLUTTER_HOME
|
||||
- name: add2app-macos
|
||||
env:
|
||||
SHARD: add2app_test
|
||||
# occasionally the clock on these machines is out of sync
|
||||
# with the actual time - this should help to verify
|
||||
print_date_script:
|
||||
- date
|
||||
install_cocoapods_script:
|
||||
- sudo gem install cocoapods
|
||||
git_fetch_script:
|
||||
- git clean -xfd
|
||||
- git fetch origin
|
||||
- git fetch origin master # To set FETCH_HEAD for "git merge-base" to work
|
||||
pub_cache:
|
||||
@@ -193,22 +238,6 @@ task:
|
||||
test_all_script: |
|
||||
ulimit -S -n 2048 # https://github.com/flutter/flutter/issues/2976
|
||||
bin/cache/dart-sdk/bin/dart --enable-asserts dev/bots/test.dart
|
||||
matrix:
|
||||
- name: tests-macos
|
||||
env:
|
||||
SHARD: tests
|
||||
- name: tool_tests-macos
|
||||
env:
|
||||
SHARD: tool_tests
|
||||
- name: build_tests-macos
|
||||
env:
|
||||
SHARD: build_tests
|
||||
COCOAPODS_DISABLE_STATS: true
|
||||
FLUTTER_FRAMEWORK_DIR: "/tmp/flutter sdk/bin/cache/artifacts/engine/ios/"
|
||||
container:
|
||||
cpu: 4
|
||||
memory: 12G
|
||||
|
||||
|
||||
docker_builder:
|
||||
# Only build a new docker image when we tag a release (for dev, beta, or release.)
|
||||
@@ -221,7 +250,7 @@ docker_builder:
|
||||
- tests-linux
|
||||
- tool_tests-linux
|
||||
- build_tests-linux
|
||||
- integration_tests-linux
|
||||
build_script: "$CIRRUS_WORKING_DIR/dev/ci/docker_linux/docker_build.sh"
|
||||
login_script: "$CIRRUS_WORKING_DIR/dev/ci/docker_linux/docker_login.sh"
|
||||
push_script: "$CIRRUS_WORKING_DIR/dev/ci/docker_linux/docker_push.sh"
|
||||
|
||||
|
||||
36
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
36
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
## Description
|
||||
|
||||
*Replace this paragraph with a description of what this PR is doing. If you're modifying existing behavior, describe the existing behavior, how this PR is changing it, and what motivated the change. If you're changing visual properties, consider including before/after screenshots (and runnable code snippets to reproduce them).*
|
||||
|
||||
## Related Issues
|
||||
|
||||
*Replace this paragraph with a list of issues related to this PR from our [issue database]. Indicate, which of these issues are resolved or fixed by this PR.*
|
||||
|
||||
## Checklist
|
||||
|
||||
Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes (`[x]`). This will ensure a smooth and quick review process.
|
||||
|
||||
- [ ] I read the [Contributor Guide] and followed the process outlined there for submitting PRs.
|
||||
- [ ] My PR includes tests for *all* changed/updated/fixed behaviors (See [Test Coverage]).
|
||||
- [ ] All existing and new tests are passing.
|
||||
- [ ] I updated/added relevant documentation (doc comments with `///`).
|
||||
- [ ] The analyzer (`flutter analyze --flutter-repo`) does not report any problems on my PR.
|
||||
- [ ] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement].
|
||||
- [ ] I signed the [CLA].
|
||||
- [ ] I am willing to follow-up on review comments in a timely manner.
|
||||
|
||||
## Breaking Change
|
||||
|
||||
Does your PR require Flutter developers to manually update their apps to accommodate your change?
|
||||
|
||||
- [ ] Yes, this is a breaking change (Please read [Handling breaking changes]).
|
||||
- [ ] No, this is *not* a breaking change.
|
||||
|
||||
<!-- Links -->
|
||||
[issue database]: https://github.com/flutter/flutter/issues
|
||||
[Contributor Guide]: https://github.com/flutter/flutter/wiki/Tree-hygiene#overview
|
||||
[Test Coverage]: https://github.com/flutter/flutter/wiki/Test-coverage-for-package%3Aflutter
|
||||
[Flutter Style Guide]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo
|
||||
[Features we expect every widget to implement]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#features-we-expect-every-widget-to-implement
|
||||
[CLA]: https://cla.developers.google.com/
|
||||
[Handling breaking changes]: https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -32,6 +32,9 @@
|
||||
/packages/flutter/coverage/
|
||||
version
|
||||
|
||||
# packages file containing multi-root paths
|
||||
.packages.generated
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
**/doc/api/
|
||||
.dart_tool/
|
||||
|
||||
2
AUTHORS
2
AUTHORS
@@ -32,8 +32,10 @@ Chema Molins <chemamolins@gmail.com>
|
||||
Stefan Mitev <mr.mitew@gmail.com>
|
||||
Jasper van Riet <jaspervanriet@gmail.com>
|
||||
Mattijs Fuijkschot <mattijs.fuijkschot@gmail.com>
|
||||
Volodymyr Lykhonis <vladimirlichonos@gmail.com>
|
||||
TruongSinh Tran-Nguyen <i@truongsinh.pro>
|
||||
Sander Dalby Larsen <srdlarsen@gmail.com>
|
||||
Marco Scannadinari <m@scannadinari.co.uk>
|
||||
Frederik Schweiger <mail@flschweiger.net>
|
||||
Martin Staadecker <machstg@gmail.com>
|
||||
Igor Katsuba <katsuba.igor@gmail.com>
|
||||
|
||||
26
README.md
26
README.md
@@ -9,10 +9,10 @@ Flutter is Google’s mobile app SDK for crafting high-quality native interfaces
|
||||
|
||||
### Documentation
|
||||
|
||||
**Main site: [flutter.io][]**
|
||||
* [Install](https://flutter.io/get-started/install/)
|
||||
* [Get started](https://flutter.io/get-started/)
|
||||
* [API documentation](https://docs.flutter.io/)
|
||||
**Main site: [flutter.dev][]**
|
||||
* [Install](https://flutter.dev/get-started/install/)
|
||||
* [Get started](https://flutter.dev/get-started/)
|
||||
* [API documentation](https://docs.flutter.dev/)
|
||||
* [Changelog](https://github.com/flutter/flutter/wiki/Changelog)
|
||||
* [How to contribute](https://github.com/flutter/flutter/blob/master/CONTRIBUTING.md)
|
||||
|
||||
@@ -42,12 +42,12 @@ Cupertino (iOS-flavor) widgets, rich motion APIs,
|
||||
smooth natural scrolling, and platform awareness.
|
||||
|
||||
[<img src="https://github.com/flutter/website/blob/master/src/images/homepage/screenshot-1.png" width="270" height="480" alt="Brand-first shopping design" align="left">](https://github.com/flutter/flutter/tree/master/examples/flutter_gallery/lib/demo/animation)
|
||||
[<img src="https://github.com/flutter/website/blob/master/src/images/homepage/screenshot-2.png" width="270" height="480" alt="Fitness app design">](https://github.com/flutter/posse_gallery)
|
||||
<img src="https://github.com/flutter/website/blob/master/src/images/homepage/screenshot-2.png" width="270" height="480" alt="Fitness app design">
|
||||
|
||||
[<img src="https://github.com/flutter/website/blob/master/src/images/homepage/screenshot-3.png" width="270" height="480" alt="Contact app design" align="left">](https://github.com/flutter/flutter/blob/master/examples/flutter_gallery/lib/demo/contacts_demo.dart)
|
||||
[<img src="https://github.com/flutter/website/blob/master/src/images/homepage/ios-friendlychat.png" width="270" height="480" alt="iOS chat app design">](https://codelabs.developers.google.com/codelabs/flutter/)
|
||||
|
||||
Browse the <a href="https://flutter.io/widgets/">widget catalog</a>.
|
||||
Browse the <a href="https://flutter.dev/widgets/">widget catalog</a>.
|
||||
|
||||
## Modern, reactive framework
|
||||
|
||||
@@ -89,9 +89,9 @@ class CounterState extends State<Counter> {
|
||||
}
|
||||
```
|
||||
|
||||
Browse the <a href="https://flutter.io/widgets/">widget catalog</a>
|
||||
Browse the <a href="https://flutter.dev/widgets/">widget catalog</a>
|
||||
and learn more about the
|
||||
<a href="https://flutter.io/widgets-intro/">functional-reactive framework</a>.
|
||||
<a href="https://flutter.dev/widgets-intro/">functional-reactive framework</a>.
|
||||
|
||||
## Access native features and SDKs
|
||||
|
||||
@@ -118,8 +118,8 @@ Future<void> getBatteryLevel() async {
|
||||
}
|
||||
```
|
||||
|
||||
Learn how to use <a href="https://flutter.io/using-packages/">packages</a> or
|
||||
write <a href="https://flutter.io/platform-channels/">platform channels</a>
|
||||
Learn how to use <a href="https://flutter.dev/using-packages/">packages</a> or
|
||||
write <a href="https://flutter.dev/platform-channels/">platform channels</a>
|
||||
to access native code, APIs, and SDKs.
|
||||
|
||||
## Unified app development
|
||||
@@ -133,7 +133,7 @@ you can use Flutter for your views and leverage much of your
|
||||
existing Java/Kotlin/ObjC/Swift investment.
|
||||
|
||||
Learn more about what makes Flutter special in the
|
||||
<a href="https://flutter.io/technical-overview/">technical overview</a>.
|
||||
<a href="https://flutter.dev/technical-overview/">technical overview</a>.
|
||||
|
||||
# More resources
|
||||
|
||||
@@ -146,7 +146,7 @@ To join the team working on Flutter, see our [contributor guide](CONTRIBUTING.md
|
||||
|
||||
[Build Status - Cirrus]: https://api.cirrus-ci.com/github/flutter/flutter.svg
|
||||
[Build status]: https://cirrus-ci.com/github/flutter/flutter/master
|
||||
[flutter.io]: https://flutter.io
|
||||
[flutter.dev]: https://flutter.dev
|
||||
[Flutter logo]: https://github.com/dart-lang/site-shared/blob/master/src/_assets/image/flutter/icon/64.png?raw=1
|
||||
[Gitter Channel]: https://badges.gitter.im/flutter/flutter.svg
|
||||
[Gitter badge]: https://gitter.im/flutter/flutter?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
|
||||
[Gitter badge]: https://gitter.im/flutter/flutter?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
|
||||
@@ -121,7 +121,7 @@ function upgrade_flutter () {
|
||||
|
||||
retry_upgrade
|
||||
|
||||
"$DART" --snapshot="$SNAPSHOT_PATH" --packages="$FLUTTER_TOOLS_DIR/.packages" "$SCRIPT_PATH"
|
||||
"$DART" --snapshot="$SNAPSHOT_PATH" --snapshot-kind=app-jit --packages="$FLUTTER_TOOLS_DIR/.packages" "$SCRIPT_PATH" training
|
||||
echo "$revision" > "$STAMP_PATH"
|
||||
fi
|
||||
# The exit here is duplicitous since the function is run in a subshell,
|
||||
|
||||
@@ -138,7 +138,7 @@ GOTO :after_subroutine
|
||||
ECHO Running pub upgrade...
|
||||
CALL "%pub%" upgrade "%VERBOSITY%"
|
||||
IF "%ERRORLEVEL%" EQU "0" goto :upgrade_succeeded
|
||||
ECHO Error Unable to 'pub upgrade' flutter tool. Retrying in five seconds... (%remaining_tries% tries left)
|
||||
ECHO Error (%ERRORLEVEL%): Unable to 'pub upgrade' flutter tool. Retrying in five seconds... (%remaining_tries% tries left)
|
||||
timeout /t 5 /nobreak 2>NUL
|
||||
SET /A remaining_tries-=1
|
||||
IF "%remaining_tries%" EQU "0" GOTO upgrade_retries_exhausted
|
||||
@@ -152,7 +152,7 @@ GOTO :after_subroutine
|
||||
|
||||
POPD
|
||||
|
||||
"%dart%" --snapshot="%snapshot_path%" --packages="%flutter_tools_dir%\.packages" "%script_path%"
|
||||
"%dart%" --snapshot="%snapshot_path%" --snapshot-kind=app-jit --packages="%flutter_tools_dir%\.packages" "%script_path%"
|
||||
IF "%ERRORLEVEL%" NEQ "0" (
|
||||
ECHO Error: Unable to create dart snapshot for flutter tool.
|
||||
SET exit_code=%ERRORLEVEL%
|
||||
|
||||
@@ -1 +1 @@
|
||||
3757390fa4b00d2d261bfdf5182d2e87c9113ff9
|
||||
0d83a2ecd1bb78f8e1f0ed9719ff3751cdfdd064
|
||||
|
||||
@@ -1 +1 @@
|
||||
ec90c64e598804d691c1c6bfcd191a63480e3053
|
||||
894e9634cda6eb940d1ad4efb20b63a174bb7797
|
||||
|
||||
@@ -44,9 +44,11 @@ if [ ! -f "$ENGINE_STAMP" ] || [ "$ENGINE_VERSION" != `cat "$ENGINE_STAMP"` ]; t
|
||||
case "$(uname -s)" in
|
||||
Darwin)
|
||||
DART_ZIP_NAME="dart-sdk-darwin-x64.zip"
|
||||
IS_USER_EXECUTABLE="-perm +100"
|
||||
;;
|
||||
Linux)
|
||||
DART_ZIP_NAME="dart-sdk-linux-x64.zip"
|
||||
IS_USER_EXECUTABLE="-perm /u+x"
|
||||
;;
|
||||
*)
|
||||
echo "Unknown operating system. Cannot install Dart SDK."
|
||||
@@ -65,7 +67,7 @@ if [ ! -f "$ENGINE_STAMP" ] || [ "$ENGINE_VERSION" != `cat "$ENGINE_STAMP"` ]; t
|
||||
|
||||
# install the new sdk
|
||||
rm -rf -- "$DART_SDK_PATH"
|
||||
mkdir -p -- "$DART_SDK_PATH"
|
||||
mkdir -m 755 -p -- "$DART_SDK_PATH"
|
||||
DART_SDK_ZIP="$FLUTTER_ROOT/bin/cache/$DART_ZIP_NAME"
|
||||
|
||||
curl --continue-at - --location --output "$DART_SDK_ZIP" "$DART_SDK_URL" 2>&1 || {
|
||||
@@ -87,6 +89,8 @@ if [ ! -f "$ENGINE_STAMP" ] || [ "$ENGINE_VERSION" != `cat "$ENGINE_STAMP"` ]; t
|
||||
exit 1
|
||||
}
|
||||
rm -f -- "$DART_SDK_ZIP"
|
||||
find "$DART_SDK_PATH" -type d -exec chmod 755 {} \;
|
||||
find "$DART_SDK_PATH" -type f $IS_USER_EXECUTABLE -exec chmod a+x,a+r {} \;
|
||||
echo "$ENGINE_VERSION" > "$ENGINE_STAMP"
|
||||
|
||||
# delete any temporary sdk path
|
||||
|
||||
@@ -11,7 +11,7 @@ dependencies:
|
||||
sdk: flutter
|
||||
test: 1.5.3
|
||||
|
||||
analyzer: 0.35.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
analyzer: 0.35.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
args: 1.5.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
@@ -20,16 +20,16 @@ dependencies:
|
||||
convert: 2.1.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
front_end: 0.1.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
front_end: 0.1.13 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
html: 0.13.4+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
http: 0.12.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
http_multi_server: 2.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
http_parser: 3.1.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
kernel: 0.3.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
kernel: 0.3.13 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
meta: 1.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
@@ -37,9 +37,9 @@ dependencies:
|
||||
multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
node_preamble: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
package_resolver: 1.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
package_resolver: 1.0.10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
path: 1.6.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pedantic: 1.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pedantic: 1.5.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
plugin: 0.2.0+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pool: 1.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pub_semver: 1.4.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
@@ -50,7 +50,7 @@ dependencies:
|
||||
shelf_web_socket: 0.2.2+4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
source_map_stack_trace: 1.1.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
source_maps: 0.10.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
source_span: 1.5.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
source_span: 1.5.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
stack_trace: 1.9.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
stream_channel: 1.6.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
string_scanner: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
@@ -68,4 +68,4 @@ dependencies:
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
|
||||
# PUBSPEC CHECKSUM: 0823
|
||||
# PUBSPEC CHECKSUM: 9655
|
||||
|
||||
@@ -71,7 +71,7 @@ class TileScrollLayout extends StatelessWidget {
|
||||
child: IconBar(),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
drawer: const GalleryDrawer(),
|
||||
);
|
||||
@@ -101,8 +101,8 @@ class ComplexLayoutState extends State<ComplexLayout> {
|
||||
print('Pressed search');
|
||||
},
|
||||
),
|
||||
TopBarMenu()
|
||||
]
|
||||
TopBarMenu(),
|
||||
],
|
||||
),
|
||||
body: Column(
|
||||
children: <Widget>[
|
||||
@@ -115,7 +115,7 @@ class ComplexLayoutState extends State<ComplexLayout> {
|
||||
else
|
||||
return FancyGalleryItem(index, key: PageStorageKey<int>(index));
|
||||
},
|
||||
)
|
||||
),
|
||||
),
|
||||
BottomBar(),
|
||||
],
|
||||
@@ -133,45 +133,45 @@ class TopBarMenu extends StatelessWidget {
|
||||
itemBuilder: (BuildContext context) => <PopupMenuItem<String>>[
|
||||
const PopupMenuItem<String>(
|
||||
value: 'Friends',
|
||||
child: MenuItemWithIcon(Icons.people, 'Friends', '5 new')
|
||||
child: MenuItemWithIcon(Icons.people, 'Friends', '5 new'),
|
||||
),
|
||||
const PopupMenuItem<String>(
|
||||
value: 'Events',
|
||||
child: MenuItemWithIcon(Icons.event, 'Events', '12 upcoming')
|
||||
child: MenuItemWithIcon(Icons.event, 'Events', '12 upcoming'),
|
||||
),
|
||||
const PopupMenuItem<String>(
|
||||
value: 'Events',
|
||||
child: MenuItemWithIcon(Icons.group, 'Groups', '14')
|
||||
child: MenuItemWithIcon(Icons.group, 'Groups', '14'),
|
||||
),
|
||||
const PopupMenuItem<String>(
|
||||
value: 'Events',
|
||||
child: MenuItemWithIcon(Icons.image, 'Pictures', '12')
|
||||
child: MenuItemWithIcon(Icons.image, 'Pictures', '12'),
|
||||
),
|
||||
const PopupMenuItem<String>(
|
||||
value: 'Events',
|
||||
child: MenuItemWithIcon(Icons.near_me, 'Nearby', '33')
|
||||
child: MenuItemWithIcon(Icons.near_me, 'Nearby', '33'),
|
||||
),
|
||||
const PopupMenuItem<String>(
|
||||
value: 'Friends',
|
||||
child: MenuItemWithIcon(Icons.people, 'Friends', '5')
|
||||
child: MenuItemWithIcon(Icons.people, 'Friends', '5'),
|
||||
),
|
||||
const PopupMenuItem<String>(
|
||||
value: 'Events',
|
||||
child: MenuItemWithIcon(Icons.event, 'Events', '12')
|
||||
child: MenuItemWithIcon(Icons.event, 'Events', '12'),
|
||||
),
|
||||
const PopupMenuItem<String>(
|
||||
value: 'Events',
|
||||
child: MenuItemWithIcon(Icons.group, 'Groups', '14')
|
||||
child: MenuItemWithIcon(Icons.group, 'Groups', '14'),
|
||||
),
|
||||
const PopupMenuItem<String>(
|
||||
value: 'Events',
|
||||
child: MenuItemWithIcon(Icons.image, 'Pictures', '12')
|
||||
child: MenuItemWithIcon(Icons.image, 'Pictures', '12'),
|
||||
),
|
||||
const PopupMenuItem<String>(
|
||||
value: 'Events',
|
||||
child: MenuItemWithIcon(Icons.near_me, 'Nearby', '33')
|
||||
)
|
||||
]
|
||||
child: MenuItemWithIcon(Icons.near_me, 'Nearby', '33'),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -190,10 +190,10 @@ class MenuItemWithIcon extends StatelessWidget {
|
||||
Icon(icon),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 8.0, right: 8.0),
|
||||
child: Text(title)
|
||||
child: Text(title),
|
||||
),
|
||||
Text(subtitle, style: Theme.of(context).textTheme.caption)
|
||||
]
|
||||
Text(subtitle, style: Theme.of(context).textTheme.caption),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -213,11 +213,11 @@ class FancyImageItem extends StatelessWidget {
|
||||
InfoBar(),
|
||||
const Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8.0),
|
||||
child: Divider()
|
||||
child: Divider(),
|
||||
),
|
||||
IconBar(),
|
||||
FatDivider()
|
||||
]
|
||||
FatDivider(),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -235,11 +235,11 @@ class FancyGalleryItem extends StatelessWidget {
|
||||
InfoBar(),
|
||||
const Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8.0),
|
||||
child: Divider()
|
||||
child: Divider(),
|
||||
),
|
||||
IconBar(),
|
||||
FatDivider()
|
||||
]
|
||||
FatDivider(),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -253,9 +253,9 @@ class InfoBar extends StatelessWidget {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: <Widget>[
|
||||
const MiniIconWithText(Icons.thumb_up, '42'),
|
||||
Text('3 Comments', style: Theme.of(context).textTheme.caption)
|
||||
]
|
||||
)
|
||||
Text('3 Comments', style: Theme.of(context).textTheme.caption),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -271,8 +271,8 @@ class IconBar extends StatelessWidget {
|
||||
IconWithText(Icons.thumb_up, 'Like'),
|
||||
IconWithText(Icons.comment, 'Comment'),
|
||||
IconWithText(Icons.share, 'Share'),
|
||||
]
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -290,10 +290,10 @@ class IconWithText extends StatelessWidget {
|
||||
children: <Widget>[
|
||||
IconButton(
|
||||
icon: Icon(icon),
|
||||
onPressed: () { print('Pressed $title button'); }
|
||||
onPressed: () { print('Pressed $title button'); },
|
||||
),
|
||||
Text(title)
|
||||
]
|
||||
Text(title),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -316,13 +316,13 @@ class MiniIconWithText extends StatelessWidget {
|
||||
height: 16.0,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).primaryColor,
|
||||
shape: BoxShape.circle
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Icon(icon, color: Colors.white, size: 12.0)
|
||||
)
|
||||
child: Icon(icon, color: Colors.white, size: 12.0),
|
||||
),
|
||||
),
|
||||
Text(title, style: Theme.of(context).textTheme.caption)
|
||||
]
|
||||
Text(title, style: Theme.of(context).textTheme.caption),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -354,8 +354,8 @@ class UserHeader extends StatelessWidget {
|
||||
child: Image(
|
||||
image: AssetImage('packages/flutter_gallery_assets/people/square/ali.png'),
|
||||
width: 32.0,
|
||||
height: 32.0
|
||||
)
|
||||
height: 32.0,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
@@ -367,21 +367,21 @@ class UserHeader extends StatelessWidget {
|
||||
children: <TextSpan>[
|
||||
TextSpan(text: userName, style: const TextStyle(fontWeight: FontWeight.bold)),
|
||||
const TextSpan(text: ' shared a new '),
|
||||
const TextSpan(text: 'photo', style: TextStyle(fontWeight: FontWeight.bold))
|
||||
]
|
||||
const TextSpan(text: 'photo', style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
],
|
||||
)),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Text('Yesterday at 11:55 • ', style: Theme.of(context).textTheme.caption),
|
||||
Icon(Icons.people, size: 16.0, color: Theme.of(context).textTheme.caption.color)
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
Icon(Icons.people, size: 16.0, color: Theme.of(context).textTheme.caption.color),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
TopBarMenu()
|
||||
]
|
||||
)
|
||||
TopBarMenu(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -391,7 +391,7 @@ class ItemDescription extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return const Padding(
|
||||
padding: EdgeInsets.all(8.0),
|
||||
child: Text('Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.')
|
||||
child: Text('Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.'),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -411,7 +411,7 @@ class ItemImageBox extends StatelessWidget {
|
||||
height: 230.0,
|
||||
child: Image(
|
||||
image: AssetImage('packages/flutter_gallery_assets/places/india_chettinad_silk_maker.png')
|
||||
)
|
||||
),
|
||||
),
|
||||
Theme(
|
||||
data: ThemeData.dark(),
|
||||
@@ -420,14 +420,14 @@ class ItemImageBox extends StatelessWidget {
|
||||
children: <Widget>[
|
||||
IconButton(
|
||||
icon: const Icon(Icons.edit),
|
||||
onPressed: () { print('Pressed edit button'); }
|
||||
onPressed: () { print('Pressed edit button'); },
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.zoom_in),
|
||||
onPressed: () { print('Pressed zoom button'); }
|
||||
onPressed: () { print('Pressed zoom button'); },
|
||||
),
|
||||
]
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
bottom: 4.0,
|
||||
@@ -435,7 +435,7 @@ class ItemImageBox extends StatelessWidget {
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.black54,
|
||||
borderRadius: BorderRadius.circular(2.0)
|
||||
borderRadius: BorderRadius.circular(2.0),
|
||||
),
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
child: const RichText(
|
||||
@@ -447,14 +447,14 @@ class ItemImageBox extends StatelessWidget {
|
||||
),
|
||||
TextSpan(
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
text: 'Chris Godley'
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
]
|
||||
text: 'Chris Godley',
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
,
|
||||
Padding(
|
||||
@@ -464,13 +464,13 @@ class ItemImageBox extends StatelessWidget {
|
||||
children: <Widget>[
|
||||
Text('Artisans of Southern India', style: Theme.of(context).textTheme.body2),
|
||||
Text('Silk Spinners', style: Theme.of(context).textTheme.body1),
|
||||
Text('Sivaganga, Tamil Nadu', style: Theme.of(context).textTheme.caption)
|
||||
]
|
||||
)
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
Text('Sivaganga, Tamil Nadu', style: Theme.of(context).textTheme.caption),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -483,7 +483,7 @@ class ItemGalleryBox extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final List<String> tabNames = <String>[
|
||||
'A', 'B', 'C', 'D'
|
||||
'A', 'B', 'C', 'D',
|
||||
];
|
||||
|
||||
return SizedBox(
|
||||
@@ -507,8 +507,8 @@ class ItemGalleryBox extends StatelessWidget {
|
||||
color: Theme.of(context).primaryColor,
|
||||
child: Center(
|
||||
child: Text(tabName, style: Theme.of(context).textTheme.headline.copyWith(color: Colors.white)),
|
||||
)
|
||||
)
|
||||
),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
@@ -524,24 +524,24 @@ class ItemGalleryBox extends StatelessWidget {
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 8.0),
|
||||
child: Text('This is item $tabName'),
|
||||
)
|
||||
)
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}).toList()
|
||||
)
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
child: const TabPageSelector()
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
child: const TabPageSelector(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -554,9 +554,9 @@ class BottomBar extends StatelessWidget {
|
||||
border: Border(
|
||||
top: BorderSide(
|
||||
color: Theme.of(context).dividerColor,
|
||||
width: 1.0
|
||||
)
|
||||
)
|
||||
width: 1.0,
|
||||
),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
@@ -586,11 +586,11 @@ class BottomBarButton extends StatelessWidget {
|
||||
children: <Widget>[
|
||||
IconButton(
|
||||
icon: Icon(icon),
|
||||
onPressed: () { print('Pressed: $title'); }
|
||||
onPressed: () { print('Pressed: $title'); },
|
||||
),
|
||||
Text(title, style: Theme.of(context).textTheme.caption)
|
||||
]
|
||||
)
|
||||
Text(title, style: Theme.of(context).textTheme.caption),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -625,7 +625,7 @@ class GalleryDrawer extends StatelessWidget {
|
||||
_changeScrollMode(context, currentMode == ScrollMode.complex ? ScrollMode.tile : ScrollMode.complex);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
trailing: Text(currentMode == ScrollMode.complex ? 'Tile' : 'Complex')
|
||||
trailing: Text(currentMode == ScrollMode.complex ? 'Tile' : 'Complex'),
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.brightness_5),
|
||||
@@ -635,7 +635,7 @@ class GalleryDrawer extends StatelessWidget {
|
||||
trailing: Radio<bool>(
|
||||
value: true,
|
||||
groupValue: ComplexLayoutApp.of(context).lightTheme,
|
||||
onChanged: (bool value) { _changeTheme(context, value); }
|
||||
onChanged: (bool value) { _changeTheme(context, value); },
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
@@ -657,7 +657,7 @@ class GalleryDrawer extends StatelessWidget {
|
||||
onTap: () { ComplexLayoutApp.of(context).toggleAnimationSpeed(); },
|
||||
trailing: Checkbox(
|
||||
value: timeDilation != 1.0,
|
||||
onChanged: (bool value) { ComplexLayoutApp.of(context).toggleAnimationSpeed(); }
|
||||
onChanged: (bool value) { ComplexLayoutApp.of(context).toggleAnimationSpeed(); },
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -15,7 +15,7 @@ dependencies:
|
||||
# //packages/flutter_tools/lib/src/commands/update_packages.dart
|
||||
# and run
|
||||
# flutter update-packages --force-upgrade
|
||||
flutter_gallery_assets: 0.1.6
|
||||
flutter_gallery_assets: 0.1.8
|
||||
|
||||
async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
charcode: 1.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
@@ -28,7 +28,7 @@ dependencies:
|
||||
meta: 1.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
path: 1.6.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pub_semver: 1.4.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
source_span: 1.5.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
source_span: 1.5.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
stack_trace: 1.9.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
stream_channel: 1.6.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
term_glyph: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
@@ -42,27 +42,27 @@ dev_dependencies:
|
||||
sdk: flutter
|
||||
test: 1.5.3
|
||||
|
||||
analyzer: 0.35.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
analyzer: 0.35.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
args: 1.5.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
front_end: 0.1.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
front_end: 0.1.13 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
html: 0.13.4+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
http: 0.12.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
http_multi_server: 2.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
http_parser: 3.1.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
kernel: 0.3.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
kernel: 0.3.13 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
node_preamble: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
package_resolver: 1.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pedantic: 1.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
package_resolver: 1.0.10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pedantic: 1.5.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
plugin: 0.2.0+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pool: 1.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
quiver: 2.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
@@ -85,4 +85,4 @@ flutter:
|
||||
- packages/flutter_gallery_assets/people/square/ali.png
|
||||
- packages/flutter_gallery_assets/places/india_chettinad_silk_maker.png
|
||||
|
||||
# PUBSPEC CHECKSUM: 4ff3
|
||||
# PUBSPEC CHECKSUM: ca28
|
||||
|
||||
@@ -1 +1,6 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
const String kCullOpacityRouteName = '/cull_opacity';
|
||||
const String kCubicBezierRouteName = '/cubic_bezier';
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
// Copyright 2015 The Chromium 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 'package:flutter/material.dart';
|
||||
|
||||
import 'common.dart';
|
||||
import 'src/cubic_bezier.dart';
|
||||
import 'src/cull_opacity.dart';
|
||||
|
||||
const String kMacrobenchmarks ='Macrobenchmarks';
|
||||
@@ -16,6 +21,7 @@ class MacrobenchmarksApp extends StatelessWidget {
|
||||
routes: <String, WidgetBuilder>{
|
||||
'/': (BuildContext context) => HomePage(),
|
||||
kCullOpacityRouteName: (BuildContext context) => CullOpacityPage(),
|
||||
kCubicBezierRouteName: (BuildContext context) => CubicBezierPage(),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -34,7 +40,14 @@ class HomePage extends StatelessWidget {
|
||||
onPressed: (){
|
||||
Navigator.pushNamed(context, kCullOpacityRouteName);
|
||||
},
|
||||
)
|
||||
),
|
||||
RaisedButton(
|
||||
key: const Key(kCubicBezierRouteName),
|
||||
child: const Text('Cubic Bezier'),
|
||||
onPressed: (){
|
||||
Navigator.pushNamed(context, kCubicBezierRouteName);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
380
dev/benchmarks/macrobenchmarks/lib/src/cubic_bezier.dart
Normal file
380
dev/benchmarks/macrobenchmarks/lib/src/cubic_bezier.dart
Normal file
@@ -0,0 +1,380 @@
|
||||
// Copyright 2019 The Chromium 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:math';
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter/animation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
// Based on https://github.com/eseidelGoogle/bezier_perf/blob/master/lib/main.dart
|
||||
class CubicBezierPage extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: const <Widget>[
|
||||
Bezier(Colors.amber, 1.0),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Bezier extends StatelessWidget {
|
||||
const Bezier(this.color, this.scale, {this.blur = 0.0, this.delay = 0.0});
|
||||
|
||||
final Color color;
|
||||
final double scale;
|
||||
final double blur;
|
||||
final double delay;
|
||||
|
||||
List<PathDetail> _getLogoPath() {
|
||||
final List<PathDetail> paths = <PathDetail>[];
|
||||
|
||||
final Path path = Path();
|
||||
path.moveTo(100.0, 97.0);
|
||||
path.cubicTo(100.0, 97.0, 142.0, 59.0, 169.91, 41.22);
|
||||
path.cubicTo(197.82, 23.44, 249.24, 5.52, 204.67, 85.84);
|
||||
|
||||
paths.add(PathDetail(path));
|
||||
|
||||
// Path 2
|
||||
final Path bezier2Path = Path();
|
||||
bezier2Path.moveTo(0.0, 70.55);
|
||||
bezier2Path.cubicTo(0.0, 70.55, 42.0, 31.55, 69.91, 14.77);
|
||||
bezier2Path.cubicTo(97.82, -2.01, 149.24, -20.93, 104.37, 59.39);
|
||||
|
||||
paths.add(PathDetail(bezier2Path,
|
||||
translate: <double>[29.45, 151.0], rotation: -1.5708));
|
||||
|
||||
// Path 3
|
||||
final Path bezier3Path = Path();
|
||||
bezier3Path.moveTo(0.0, 69.48);
|
||||
bezier3Path.cubicTo(0.0, 69.48, 44.82, 27.92, 69.91, 13.7);
|
||||
bezier3Path.cubicTo(95.0, -0.52, 149.24, -22.0, 104.37, 58.32);
|
||||
|
||||
paths.add(PathDetail(bezier3Path,
|
||||
translate: <double>[53.0, 200.48], rotation: -3.14159));
|
||||
|
||||
// Path 4
|
||||
final Path bezier4Path = Path();
|
||||
bezier4Path.moveTo(0.0, 69.48);
|
||||
bezier4Path.cubicTo(0.0, 69.48, 43.82, 27.92, 69.91, 13.7);
|
||||
bezier4Path.cubicTo(96.0, -0.52, 149.24, -22.0, 104.37, 58.32);
|
||||
|
||||
paths.add(PathDetail(bezier4Path,
|
||||
translate: <double>[122.48, 77.0], rotation: -4.71239));
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(children: <Widget>[
|
||||
CustomPaint(
|
||||
foregroundPainter:
|
||||
BezierPainter(Colors.grey, 0.0, _getLogoPath(), false),
|
||||
size: const Size(100.0, 100.0),
|
||||
),
|
||||
AnimatedBezier(color, scale, blur: blur, delay: delay),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
class PathDetail {
|
||||
PathDetail(this.path, {this.translate, this.rotation});
|
||||
|
||||
Path path;
|
||||
List<double> translate = <double>[];
|
||||
double rotation;
|
||||
}
|
||||
|
||||
class AnimatedBezier extends StatefulWidget {
|
||||
const AnimatedBezier(this.color, this.scale, {this.blur = 0.0, this.delay});
|
||||
|
||||
final Color color;
|
||||
final double scale;
|
||||
final double blur;
|
||||
final double delay;
|
||||
|
||||
@override
|
||||
State createState() => AnimatedBezierState();
|
||||
}
|
||||
|
||||
class Point {
|
||||
Point(this.x, this.y);
|
||||
|
||||
double x;
|
||||
double y;
|
||||
}
|
||||
|
||||
class AnimatedBezierState extends State<AnimatedBezier>
|
||||
with SingleTickerProviderStateMixin {
|
||||
double scale;
|
||||
AnimationController controller;
|
||||
CurvedAnimation curve;
|
||||
bool isPlaying = false;
|
||||
List<List<Point>> pointList = <List<Point>>[]
|
||||
..add(<Point>[])
|
||||
..add(<Point>[])
|
||||
..add(<Point>[])
|
||||
..add(<Point>[]);
|
||||
bool isReversed = false;
|
||||
|
||||
List<PathDetail> _playForward() {
|
||||
final List<PathDetail> paths = <PathDetail>[];
|
||||
final double t = curve.value;
|
||||
final double b = controller.upperBound;
|
||||
double pX;
|
||||
double pY;
|
||||
|
||||
final Path path = Path();
|
||||
|
||||
if (t < b / 2) {
|
||||
pX = _getCubicPoint(t * 2, 100.0, 100.0, 142.0, 169.91);
|
||||
pY = _getCubicPoint(t * 2, 97.0, 97.0, 59.0, 41.22);
|
||||
pointList[0].add(Point(pX, pY));
|
||||
} else {
|
||||
pX = _getCubicPoint(t * 2 - b, 169.91, 197.80, 249.24, 204.67);
|
||||
pY = _getCubicPoint(t * 2 - b, 41.22, 23.44, 5.52, 85.84);
|
||||
pointList[0].add(Point(pX, pY));
|
||||
}
|
||||
|
||||
path.moveTo(100.0, 97.0);
|
||||
|
||||
for (Point p in pointList[0]) {
|
||||
path.lineTo(p.x, p.y);
|
||||
}
|
||||
|
||||
paths.add(PathDetail(path));
|
||||
|
||||
// Path 2
|
||||
final Path bezier2Path = Path();
|
||||
|
||||
if (t <= b / 2) {
|
||||
final double pX = _getCubicPoint(t * 2, 0.0, 0.0, 42.0, 69.91);
|
||||
final double pY = _getCubicPoint(t * 2, 70.55, 70.55, 31.55, 14.77);
|
||||
pointList[1].add(Point(pX, pY));
|
||||
} else {
|
||||
final double pX = _getCubicPoint(t * 2 - b, 69.91, 97.82, 149.24, 104.37);
|
||||
final double pY = _getCubicPoint(t * 2 - b, 14.77, -2.01, -20.93, 59.39);
|
||||
pointList[1].add(Point(pX, pY));
|
||||
}
|
||||
|
||||
bezier2Path.moveTo(0.0, 70.55);
|
||||
|
||||
for (Point p in pointList[1]) {
|
||||
bezier2Path.lineTo(p.x, p.y);
|
||||
}
|
||||
|
||||
paths.add(PathDetail(bezier2Path,
|
||||
translate: <double>[29.45, 151.0], rotation: -1.5708));
|
||||
|
||||
// Path 3
|
||||
final Path bezier3Path = Path();
|
||||
if (t <= b / 2) {
|
||||
pX = _getCubicPoint(t * 2, 0.0, 0.0, 44.82, 69.91);
|
||||
pY = _getCubicPoint(t * 2, 69.48, 69.48, 27.92, 13.7);
|
||||
pointList[2].add(Point(pX, pY));
|
||||
} else {
|
||||
pX = _getCubicPoint(t * 2 - b, 69.91, 95.0, 149.24, 104.37);
|
||||
pY = _getCubicPoint(t * 2 - b, 13.7, -0.52, -22.0, 58.32);
|
||||
pointList[2].add(Point(pX, pY));
|
||||
}
|
||||
|
||||
bezier3Path.moveTo(0.0, 69.48);
|
||||
|
||||
for (Point p in pointList[2]) {
|
||||
bezier3Path.lineTo(p.x, p.y);
|
||||
}
|
||||
|
||||
paths.add(PathDetail(bezier3Path,
|
||||
translate: <double>[53.0, 200.48], rotation: -3.14159));
|
||||
|
||||
// Path 4
|
||||
final Path bezier4Path = Path();
|
||||
|
||||
if (t < b / 2) {
|
||||
final double pX = _getCubicPoint(t * 2, 0.0, 0.0, 43.82, 69.91);
|
||||
final double pY = _getCubicPoint(t * 2, 69.48, 69.48, 27.92, 13.7);
|
||||
pointList[3].add(Point(pX, pY));
|
||||
} else {
|
||||
final double pX = _getCubicPoint(t * 2 - b, 69.91, 96.0, 149.24, 104.37);
|
||||
final double pY = _getCubicPoint(t * 2 - b, 13.7, -0.52, -22.0, 58.32);
|
||||
pointList[3].add(Point(pX, pY));
|
||||
}
|
||||
|
||||
bezier4Path.moveTo(0.0, 69.48);
|
||||
|
||||
for (Point p in pointList[3]) {
|
||||
bezier4Path.lineTo(p.x, p.y);
|
||||
}
|
||||
|
||||
paths.add(PathDetail(bezier4Path,
|
||||
translate: <double>[122.48, 77.0], rotation: -4.71239));
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
List<PathDetail> _playReversed() {
|
||||
for (List<Point> list in pointList) {
|
||||
if (list.isNotEmpty) {
|
||||
list.removeLast();
|
||||
}
|
||||
}
|
||||
|
||||
final List<Point> points = pointList[0];
|
||||
final Path path = Path();
|
||||
|
||||
path.moveTo(100.0, 97.0);
|
||||
|
||||
for (Point point in points) {
|
||||
path.lineTo(point.x, point.y);
|
||||
}
|
||||
|
||||
final Path bezier2Path = Path();
|
||||
|
||||
bezier2Path.moveTo(0.0, 70.55);
|
||||
|
||||
for (Point p in pointList[1]) {
|
||||
bezier2Path.lineTo(p.x, p.y);
|
||||
}
|
||||
|
||||
final Path bezier3Path = Path();
|
||||
bezier3Path.moveTo(0.0, 69.48);
|
||||
|
||||
for (Point p in pointList[2]) {
|
||||
bezier3Path.lineTo(p.x, p.y);
|
||||
}
|
||||
|
||||
final Path bezier4Path = Path();
|
||||
|
||||
bezier4Path.moveTo(0.0, 69.48);
|
||||
|
||||
for (Point p in pointList[3]) {
|
||||
bezier4Path.lineTo(p.x, p.y);
|
||||
}
|
||||
|
||||
return <PathDetail>[
|
||||
PathDetail(path),
|
||||
PathDetail(bezier2Path, translate: <double>[29.45, 151.0], rotation: -1.5708),
|
||||
PathDetail(bezier3Path,
|
||||
translate: <double>[53.0, 200.48], rotation: -3.14159),
|
||||
PathDetail(bezier4Path, translate: <double>[122.48, 77.0], rotation: -4.71239),
|
||||
];
|
||||
}
|
||||
|
||||
List<PathDetail> _getLogoPath() {
|
||||
if (!isReversed) {
|
||||
return _playForward();
|
||||
}
|
||||
|
||||
return _playReversed();
|
||||
}
|
||||
|
||||
//From http://wiki.roblox.com/index.php?title=File:Beziereq4.png
|
||||
double _getCubicPoint(double t, double p0, double p1, double p2, double p3) {
|
||||
return pow(1 - t, 3) * p0 +
|
||||
3 * pow(1 - t, 2) * t * p1 +
|
||||
3 * (1 - t) * pow(t, 2) * p2 +
|
||||
pow(t, 3) * p3;
|
||||
}
|
||||
|
||||
void playAnimation() {
|
||||
isPlaying = true;
|
||||
isReversed = false;
|
||||
for (List<Point> list in pointList) {
|
||||
list.clear();
|
||||
}
|
||||
controller.reset();
|
||||
controller.forward();
|
||||
}
|
||||
|
||||
void stopAnimation() {
|
||||
isPlaying = false;
|
||||
controller.stop();
|
||||
for (List<Point> list in pointList) {
|
||||
list.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void reverseAnimation() {
|
||||
isReversed = true;
|
||||
controller.reverse();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
controller = AnimationController(
|
||||
vsync: this, duration: const Duration(milliseconds: 1000));
|
||||
curve = CurvedAnimation(parent: controller, curve: Curves.linear)
|
||||
..addListener(() {
|
||||
setState(() {});
|
||||
})
|
||||
..addStatusListener((AnimationStatus state) {
|
||||
if (state == AnimationStatus.completed) {
|
||||
reverseAnimation();
|
||||
} else if (state == AnimationStatus.dismissed) {
|
||||
playAnimation();
|
||||
}
|
||||
});
|
||||
|
||||
playAnimation();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CustomPaint(
|
||||
foregroundPainter: BezierPainter(widget.color,
|
||||
curve.value * widget.blur, _getLogoPath(), isPlaying),
|
||||
size: const Size(100.0, 100.0));
|
||||
}
|
||||
}
|
||||
|
||||
class BezierPainter extends CustomPainter {
|
||||
BezierPainter(this.color, this.blur, this.path, this.isPlaying);
|
||||
|
||||
Color color;
|
||||
final double blur;
|
||||
List<PathDetail> path;
|
||||
bool isPlaying;
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
final Paint paint = Paint();
|
||||
paint.strokeWidth = 18.0;
|
||||
paint.style = PaintingStyle.stroke;
|
||||
paint.strokeCap = StrokeCap.round;
|
||||
paint.color = color;
|
||||
canvas.scale(0.5, 0.5);
|
||||
|
||||
for (int i = 0; i < path.length; i++) {
|
||||
if (path[i].translate != null) {
|
||||
canvas.translate(path[i].translate[0], path[i].translate[1]);
|
||||
}
|
||||
|
||||
if (path[i].rotation != null) {
|
||||
canvas.rotate(path[i].rotation);
|
||||
}
|
||||
|
||||
if (blur > 0) {
|
||||
final MaskFilter blur = MaskFilter.blur(BlurStyle.normal, this.blur);
|
||||
paint.maskFilter = blur;
|
||||
canvas.drawPath(path[i].path, paint);
|
||||
}
|
||||
|
||||
paint.maskFilter = null;
|
||||
canvas.drawPath(path[i].path, paint);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(BezierPainter oldDelegate) => true;
|
||||
|
||||
@override
|
||||
bool shouldRebuildSemantics(BezierPainter oldDelegate) => false;
|
||||
}
|
||||
@@ -15,7 +15,7 @@ dependencies:
|
||||
# //packages/flutter_tools/lib/src/commands/update_packages.dart
|
||||
# and run
|
||||
# flutter update-packages --force-upgrade
|
||||
flutter_gallery_assets: 0.1.6
|
||||
flutter_gallery_assets: 0.1.8
|
||||
|
||||
async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
charcode: 1.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
@@ -28,7 +28,7 @@ dependencies:
|
||||
meta: 1.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
path: 1.6.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pub_semver: 1.4.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
source_span: 1.5.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
source_span: 1.5.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
stack_trace: 1.9.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
stream_channel: 1.6.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
term_glyph: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
@@ -42,27 +42,27 @@ dev_dependencies:
|
||||
sdk: flutter
|
||||
test: 1.5.3
|
||||
|
||||
analyzer: 0.35.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
analyzer: 0.35.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
args: 1.5.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
front_end: 0.1.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
front_end: 0.1.13 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
html: 0.13.4+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
http: 0.12.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
http_multi_server: 2.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
http_parser: 3.1.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
kernel: 0.3.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
kernel: 0.3.13 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
node_preamble: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
package_resolver: 1.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pedantic: 1.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
package_resolver: 1.0.10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pedantic: 1.5.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
plugin: 0.2.0+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pool: 1.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
quiver: 2.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
@@ -82,4 +82,4 @@ dev_dependencies:
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
|
||||
# PUBSPEC CHECKSUM: 4ff3
|
||||
# PUBSPEC CHECKSUM: ca28
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
// Copyright 2019 The Chromium 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:ui';
|
||||
|
||||
import 'package:flutter_driver/driver_extension.dart';
|
||||
import 'package:flutter/painting.dart' show DefaultShaderWarmUp, PaintingBinding;
|
||||
import 'package:macrobenchmarks/main.dart' as app;
|
||||
|
||||
class CubicBezierShaderWarmUp extends DefaultShaderWarmUp {
|
||||
@override
|
||||
Future<void> warmUpOnCanvas(Canvas canvas) async {
|
||||
await super.warmUpOnCanvas(canvas);
|
||||
|
||||
// Warm up the cubic shaders used by CubicBezierPage.
|
||||
//
|
||||
// This tests that our custom shader warm up is working properly.
|
||||
// Without this custom shader warm up, the worst frame time is about 115ms.
|
||||
// With this, the worst frame time is about 70ms. (Data collected on a Moto
|
||||
// G4 based on Flutter version 704814c67a874077710524d30412337884bf0254.
|
||||
final Path path = Path();
|
||||
path.moveTo(20.0, 20.0);
|
||||
// This cubic path is based on
|
||||
// https://skia.org/user/api/SkPath_Reference#SkPath_cubicTo
|
||||
path.cubicTo(300.0, 80.0, -140.0, 90.0, 220.0, 10.0);
|
||||
final Paint paint = Paint();
|
||||
paint.isAntiAlias = true;
|
||||
paint.strokeWidth = 18.0;
|
||||
paint.style = PaintingStyle.stroke;
|
||||
paint.strokeCap = StrokeCap.round;
|
||||
canvas.drawPath(path, paint);
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
PaintingBinding.shaderWarmUp = CubicBezierShaderWarmUp();
|
||||
enableFlutterDriverExtension();
|
||||
app.main();
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// Copyright 2019 The Chromium 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 'package:macrobenchmarks/common.dart';
|
||||
|
||||
import 'util.dart';
|
||||
|
||||
void main() {
|
||||
macroPerfTest('cubic_bezier_perf', kCubicBezierRouteName);
|
||||
}
|
||||
@@ -2,42 +2,15 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter_driver/flutter_driver.dart';
|
||||
import 'package:test/test.dart' hide TypeMatcher, isInstanceOf;
|
||||
|
||||
import 'package:macrobenchmarks/common.dart';
|
||||
|
||||
import 'util.dart';
|
||||
|
||||
void main() {
|
||||
const String kName = 'cull_opacity_perf';
|
||||
|
||||
test(kName, () async {
|
||||
final FlutterDriver driver = await FlutterDriver.connect();
|
||||
|
||||
// The slight initial delay avoids starting the timing during a
|
||||
// period of increased load on the device. Without this delay, the
|
||||
// benchmark has greater noise.
|
||||
// See: https://github.com/flutter/flutter/issues/19434
|
||||
await Future<void>.delayed(const Duration(milliseconds: 250));
|
||||
|
||||
await driver.forceGC();
|
||||
|
||||
final SerializableFinder button = find.byValueKey(kCullOpacityRouteName);
|
||||
expect(button, isNotNull);
|
||||
await driver.tap(button);
|
||||
|
||||
// Wait for the page to load
|
||||
await Future<void>.delayed(const Duration(seconds: 1));
|
||||
|
||||
final Timeline timeline = await driver.traceAction(() async {
|
||||
await Future<void>.delayed(const Duration(seconds: 10));
|
||||
});
|
||||
|
||||
final TimelineSummary summary = TimelineSummary.summarize(timeline);
|
||||
summary.writeSummaryToFile(kName, pretty: true);
|
||||
summary.writeTimelineToFile(kName, pretty: true);
|
||||
|
||||
driver.close();
|
||||
});
|
||||
macroPerfTest(
|
||||
'cull_opacity_perf',
|
||||
kCullOpacityRouteName,
|
||||
pageDelay: const Duration(seconds: 1),
|
||||
duration: const Duration(seconds: 10),
|
||||
);
|
||||
}
|
||||
|
||||
44
dev/benchmarks/macrobenchmarks/test_driver/util.dart
Normal file
44
dev/benchmarks/macrobenchmarks/test_driver/util.dart
Normal file
@@ -0,0 +1,44 @@
|
||||
// Copyright 2019 The Chromium 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 'package:flutter_driver/flutter_driver.dart';
|
||||
import 'package:test/test.dart' hide TypeMatcher, isInstanceOf;
|
||||
|
||||
void macroPerfTest(
|
||||
String testName,
|
||||
String routeName,
|
||||
{Duration pageDelay, Duration duration = const Duration(seconds: 3)}) {
|
||||
test(testName, () async {
|
||||
final FlutterDriver driver = await FlutterDriver.connect();
|
||||
|
||||
// The slight initial delay avoids starting the timing during a
|
||||
// period of increased load on the device. Without this delay, the
|
||||
// benchmark has greater noise.
|
||||
// See: https://github.com/flutter/flutter/issues/19434
|
||||
await Future<void>.delayed(const Duration(milliseconds: 250));
|
||||
|
||||
await driver.forceGC();
|
||||
|
||||
final SerializableFinder button = find.byValueKey(routeName);
|
||||
expect(button, isNotNull);
|
||||
await driver.tap(button);
|
||||
|
||||
if (pageDelay != null) {
|
||||
// Wait for the page to load
|
||||
await Future<void>.delayed(pageDelay);
|
||||
}
|
||||
|
||||
final Timeline timeline = await driver.traceAction(() async {
|
||||
await Future<void>.delayed(duration);
|
||||
});
|
||||
|
||||
final TimelineSummary summary = TimelineSummary.summarize(timeline);
|
||||
summary.writeSummaryToFile(testName, pretty: true);
|
||||
summary.writeTimelineToFile(testName, pretty: true);
|
||||
|
||||
driver.close();
|
||||
});
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,7 +15,7 @@ dependencies:
|
||||
path: ../../../examples/stocks
|
||||
test: 1.5.3
|
||||
|
||||
analyzer: 0.35.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
analyzer: 0.35.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
args: 1.5.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
@@ -25,9 +25,9 @@ dependencies:
|
||||
crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
dart_style: 1.2.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
front_end: 0.1.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
front_end: 0.1.13 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
html: 0.13.4+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
http: 0.12.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
http_multi_server: 2.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
http_parser: 3.1.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
@@ -37,17 +37,17 @@ dependencies:
|
||||
isolate: 2.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
kernel: 0.3.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
kernel: 0.3.13 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
node_preamble: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
package_resolver: 1.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
package_resolver: 1.0.10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
path: 1.6.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pedantic: 1.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
petitparser: 2.1.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pedantic: 1.5.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
petitparser: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
plugin: 0.2.0+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pool: 1.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pub_semver: 1.4.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
@@ -58,7 +58,7 @@ dependencies:
|
||||
shelf_web_socket: 0.2.2+4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
source_map_stack_trace: 1.1.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
source_maps: 0.10.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
source_span: 1.5.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
source_span: 1.5.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
stack_trace: 1.9.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
stream_channel: 1.6.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
string_scanner: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
@@ -76,4 +76,4 @@ dependencies:
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
|
||||
# PUBSPEC CHECKSUM: 7d7d
|
||||
# PUBSPEC CHECKSUM: a9b0
|
||||
|
||||
@@ -5,41 +5,37 @@ This directory exists to support building Flutter on our build infrastructure.
|
||||
The results of such builds are viewable at:
|
||||
* https://cirrus-ci.com/github/flutter/flutter/master
|
||||
- Testing done on PRs and submitted changes on GitHub.
|
||||
* https://build.chromium.org/p/client.flutter/console
|
||||
* https://ci.chromium.org/p/flutter/
|
||||
- Additional testing and processing done after changes are submitted.
|
||||
|
||||
The Chromium infra bots do not allow forcing new builds from outside
|
||||
the Google network. Contact @eseidelGoogle or another Google member of
|
||||
the Flutter team if you need to do that.
|
||||
The LUCI infra requires permissions to retrigger or schedule builds. Contact
|
||||
@kf6gpe or another Google member of the Flutter team if you need to do that.
|
||||
|
||||
The [Cirrus](https://cirrus-ci.org)-based bots run the
|
||||
[`test.dart`](test.dart) script for each PR and submission. This does
|
||||
testing for the tools, for the framework, and (for submitted changes
|
||||
only) rebuilds and updates the master branch API docs
|
||||
[staging site](https://master-docs-flutter-io.firebaseapp.com).
|
||||
For tagged dev and beta builds, it also builds and deploys the gallery
|
||||
app to the app stores. It is configured by the
|
||||
[.cirrus.yml](/.cirrus.yml).
|
||||
The [Cirrus](https://cirrus-ci.org)-based bots run the [`test.dart`](test.dart)
|
||||
script for each PR and submission. This does testing for the tools, for the
|
||||
framework, and (for submitted changes only) rebuilds and updates the master
|
||||
branch API docs [staging site](https://master-docs.flutter.dev/).
|
||||
For tagged dev and beta builds, it also builds and deploys the gallery app to
|
||||
the app stores. It is configured by the [.cirrus.yml](/.cirrus.yml).
|
||||
|
||||
We also have post-commit testing with actual devices, in what we call
|
||||
our [devicelab](../dev/devicelab/README.md).
|
||||
We also have post-commit testing with actual devices, in what we call our
|
||||
[devicelab](../devicelab/README.md).
|
||||
|
||||
## Chromium infra bots
|
||||
## LUCI (Layered Universal Continuous Intergration)
|
||||
|
||||
This part of our infrastructure is broken into two parts. A buildbot
|
||||
master specified by our
|
||||
[builders.pyl](https://chromium.googlesource.com/chromium/tools/build.git/+/master/masters/master.client.flutter/builders.pyl)
|
||||
file, and a [set of
|
||||
recipes](https://chromium.googlesource.com/chromium/tools/build.git/+/master/scripts/slave/recipes/flutter)
|
||||
which we run on that master. Both of these technologies are highly
|
||||
specific to Google's Chromium project. We're just borrowing some of
|
||||
their infrastructure.
|
||||
A [set of recipes](https://chromium.googlesource.com/chromium/tools/build.git/+/master/scripts/slave/recipes/flutter)
|
||||
are run on Windows, Linux, and Mac machines. The configuration for how many
|
||||
machines and what kind are managed internally by Google. Contact @kf6gpe or
|
||||
another Google member of the Flutter team if you suspect changes are needed
|
||||
there. Both of these technologies are highly specific to the [LUCI](https://github.com/luci)
|
||||
project, which is the successor to Chromium's infra. We're just borrowing some
|
||||
of their infrastructure.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
To work on this infrastructure you will need:
|
||||
|
||||
- [depot_tools](http://www.chromium.org/developers/how-tos/install-depot-tools)
|
||||
- [depot_tools](https://commondatastorage.googleapis.com/chrome-infra-docs/flat/depot_tools/docs/html/depot_tools_tutorial.html#_setting_up)
|
||||
- Python package installer: `sudo apt-get install python-pip`
|
||||
- Python coverage package (only needed for `training_simulation`): `sudo pip install coverage`
|
||||
|
||||
@@ -48,8 +44,7 @@ To run prepare_package.dart locally:
|
||||
- Make sure the depot_tools is in your PATH. If you're on Windows, you also need
|
||||
an environment variable called DEPOT_TOOLS with the path to depot_tools as value.
|
||||
- Run `gsutil.py config` (or `python %DEPOT_TOOLS%\gsutil.py` on Windows) to
|
||||
authenticate with your auth token. When asked, the GCP project ID is
|
||||
`turquoise-dev`.
|
||||
authenticate with your auth token.
|
||||
- Create a local temp directory. `cd` into it.
|
||||
- Run `dart [path to your normal Flutter repo]/dev/bots/prepare_package.dart
|
||||
--temp_dir=. --revision=[revision to package] --branch=[branch to deploy to]
|
||||
@@ -59,7 +54,8 @@ To run prepare_package.dart locally:
|
||||
|
||||
### Getting the code
|
||||
|
||||
The following will get way more than just recipe code, but it _will_ get the recipe code:
|
||||
The following will get way more than just recipe code, but it _will_ get the
|
||||
recipe code:
|
||||
|
||||
```bash
|
||||
mkdir chrome_infra
|
||||
@@ -83,7 +79,7 @@ and
|
||||
- build/scripts/slave/recipes/flutter/flutter.py
|
||||
- build/scripts/slave/recipes/flutter/engine.py
|
||||
|
||||
Recipes are just Python. They are
|
||||
Recipes are just Python with some limitations on what can be imported. They are
|
||||
[documented](https://github.com/luci/recipes-py/blob/master/doc/user_guide.md)
|
||||
by the [luci/recipes-py github project](https://github.com/luci/recipes-py).
|
||||
|
||||
@@ -91,33 +87,27 @@ The typical cycle for editing a recipe is:
|
||||
|
||||
1. Make your edits (probably to files in
|
||||
`//chrome_infra/build/scripts/slave/recipes/flutter`).
|
||||
1. Update the tests. Run `build/scripts/slave/recipes.py test train` to update
|
||||
2. Update the tests. Run `build/scripts/slave/recipes.py test train` to update
|
||||
existing expected output to match the new output. Verify completely new test
|
||||
cases by altering the `GenTests` method of the recipe.
|
||||
The recipe is required to have 100% test coverage.
|
||||
1. Run `build/scripts/slave/recipes.py run flutter/<repo> slavename=<slavename>
|
||||
mastername=client.flutter buildername=<buildername> buildnumber=1234` where `<repo>` is one
|
||||
of `flutter` or `engine`, and `slavename` and `buildername` can be looked up
|
||||
from the *Build Properties* section of a [recent
|
||||
build](https://build.chromium.org/p/client.flutter/one_line_per_build).
|
||||
1. To submit a CL, you need a local branch first (`git checkout -b [some branch name]`).
|
||||
1. Upload the patch (`git commit`, `git cl upload`) and send it to someone in
|
||||
cases by altering the `GenTests` method of the recipe. The recipe is required
|
||||
to have 100% test coverage.
|
||||
3. Run `led get-builder 'luci.flutter.prod:BUILDER_NAME' | led edit -p 'revision="GIT_HASH"' | led edit-recipe-bundle | led launch`, where `BUILDER_NAME` is the builder name (e.g. `Linux Engine`), and
|
||||
`GIT_HASH` is the hash to build (which is important for the engine but not
|
||||
for the framework).
|
||||
4. To submit a CL, you need a local branch first (`git checkout -b [some branch name]`).
|
||||
5. Upload the patch (`git commit`, `git cl upload`) and send it to someone in
|
||||
the `recipes/flutter/OWNERS` file for review.
|
||||
|
||||
### Editing the client.flutter buildbot master
|
||||
### The infra config repository
|
||||
|
||||
Flutter uses Chromium's fancy
|
||||
[builders.pyl](https://chromium.googlesource.com/infra/infra/+/master/doc/users/services/buildbot/builders.pyl.md)
|
||||
master generation system. Chromium hosts 100s (if not 1000s) of buildbot
|
||||
masters and thus has lots of infrastructure for turning them up and down.
|
||||
Eventually all of buildbot is planned to be replaced by other infrastructure,
|
||||
but for now flutter has its own client.flutter master.
|
||||
The [flutter/infra](https://github.com/flutter/infra) repository contains
|
||||
configuration files for the dashboard, builder groups, scheduling, and
|
||||
individual builders. Edits to this may require changes other internal Google
|
||||
repositories - e.g., to change the operating system or number of machines. If
|
||||
you want to do that, reach out to @kf6gpe or another member of the Google team.
|
||||
|
||||
You would need to edit client.flutter's master in order to add slaves (talk to
|
||||
@eseidelGoogle), add builder groups, or to change the html layout of
|
||||
https://build.chromium.org/p/client.flutter. Carefully follow the [builders.pyl
|
||||
docs](https://chromium.googlesource.com/infra/infra/+/master/doc/users/services/buildbot/builders.pyl.md)
|
||||
to do so.
|
||||
Each configuration file in that repository has a link in the top comments to a
|
||||
schema that describes available properties.
|
||||
|
||||
### Future Directions
|
||||
|
||||
@@ -131,11 +121,13 @@ tried, but it's not quite ready.
|
||||
|
||||
### Android Tools
|
||||
|
||||
The Android SDK and NDK used by Flutter's Chrome infra bots are stored in Google Cloud. During the build a bot runs the
|
||||
`download_android_tools.py` script that downloads the required version of the Android SDK into `dev/bots/android_tools`.
|
||||
The Android SDK and NDK used by Flutter's Chrome infra bots are stored in Google
|
||||
Cloud. During the build a bot runs the `download_android_tools.py` script that
|
||||
downloads the required version of the Android SDK into `dev/bots/android_tools`.
|
||||
|
||||
To check which components are currently installed, download the current SDK stored in Google Cloud using the
|
||||
`download_android_tools.py` script, then `dev/bots/android_tools/sdk/tools/bin/sdkmanager --list`. If you find that some
|
||||
To check which components are currently installed, download the current SDK
|
||||
stored in Google Cloud using the `download_android_tools.py` script, then
|
||||
`dev/bots/android_tools/sdk/tools/bin/sdkmanager --list`. If you find that some
|
||||
components need to be updated or installed, follow the steps below:
|
||||
|
||||
#### How to update Android SDK on Google Cloud Storage
|
||||
@@ -146,13 +138,17 @@ components need to be updated or installed, follow the steps below:
|
||||
|
||||
2. Use the UI to choose the packages you want to install and/or update.
|
||||
|
||||
3. Run `dev/bots/android_tools/sdk/tools/bin/sdkmanager --update`. On Windows, run `sdkmanager.bat` instead. If the
|
||||
process fails with an error saying that it is unable to move files (Windows makes files and directories read-only
|
||||
when another process is holding them open), make a copy of the `dev/bots/android_tools/sdk/tools` directory, run
|
||||
the `sdkmanager.bat` from the copy, and use the `--sdk_root` option pointing at `dev/bots/android_tools/sdk`.
|
||||
3. Run `dev/bots/android_tools/sdk/tools/bin/sdkmanager --update`. On Windows,
|
||||
run `sdkmanager.bat` instead. If the process fails with an error saying that
|
||||
it is unable to move files (Windows makes files and directories read-only
|
||||
when another process is holding them open), make a copy of the
|
||||
`dev/bots/android_tools/sdk/tools` directory, run the `sdkmanager.bat` from
|
||||
the copy, and use the `--sdk_root` option pointing at
|
||||
`dev/bots/android_tools/sdk`.
|
||||
|
||||
4. Run `dev/bots/android_tools/sdk/tools/bin/sdkmanager --licenses` and accept the licenses for the newly installed
|
||||
components. It also helps to run this command a second time and make sure that it prints "All SDK package licenses
|
||||
4. Run `dev/bots/android_tools/sdk/tools/bin/sdkmanager --licenses` and accept
|
||||
the licenses for the newly installed components. It also helps to run this
|
||||
command a second time and make sure that it prints "All SDK package licenses
|
||||
accepted".
|
||||
|
||||
5. Run upload_android_tools.py -t sdk
|
||||
|
||||
@@ -87,12 +87,42 @@ void main(List<String> arguments) {
|
||||
|
||||
Directory tempDirectory;
|
||||
if (parsedArguments.wasParsed('temp')) {
|
||||
tempDirectory = Directory(parsedArguments['temp']);
|
||||
if (!tempDirectory.existsSync()) {
|
||||
tempDirectory.createSync(recursive: true);
|
||||
tempDirectory = Directory(path.join(Directory.systemTemp.absolute.path, path.basename(parsedArguments['temp'])));
|
||||
if (path.basename(parsedArguments['temp']) != parsedArguments['temp']) {
|
||||
stderr.writeln('Supplied temporary directory name should be a name, not a path. Using ${tempDirectory.absolute.path} instead.');
|
||||
}
|
||||
print('Leaving temporary output in ${tempDirectory.absolute.path}.');
|
||||
// Make sure that any directory left around from a previous run is cleared
|
||||
// out.
|
||||
if (tempDirectory.existsSync()) {
|
||||
tempDirectory.deleteSync(recursive: true);
|
||||
}
|
||||
tempDirectory.createSync();
|
||||
}
|
||||
try {
|
||||
exitCode = SampleChecker(flutterPackage, tempDirectory: tempDirectory).checkSamples();
|
||||
} on SampleCheckerException catch (e) {
|
||||
stderr.write(e);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
class SampleCheckerException implements Exception {
|
||||
SampleCheckerException(this.message, {this.file, this.line});
|
||||
final String message;
|
||||
final String file;
|
||||
final int line;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
if (file != null || line != null) {
|
||||
final String fileStr = file == null ? '' : '$file:';
|
||||
final String lineStr = line == null ? '' : '$line:';
|
||||
return '$fileStr$lineStr Error: $message';
|
||||
} else {
|
||||
return 'Error: $message';
|
||||
}
|
||||
}
|
||||
exitCode = SampleChecker(flutterPackage, tempDirectory: tempDirectory).checkSamples();
|
||||
}
|
||||
|
||||
/// Checks samples and code snippets for analysis errors.
|
||||
@@ -129,10 +159,10 @@ class SampleChecker {
|
||||
static final RegExp _dartDocSampleEndRegex = RegExp(r'{@end-tool}');
|
||||
|
||||
/// A RegExp that matches the start of a code block within dartdoc.
|
||||
static final RegExp _codeBlockStartRegex = RegExp(r'/// ```dart.*$');
|
||||
static final RegExp _codeBlockStartRegex = RegExp(r'///\s+```dart.*$');
|
||||
|
||||
/// A RegExp that matches the end of a code block within dartdoc.
|
||||
static final RegExp _codeBlockEndRegex = RegExp(r'/// ```\s*$');
|
||||
static final RegExp _codeBlockEndRegex = RegExp(r'///\s+```\s*$');
|
||||
|
||||
/// A RegExp that matches a Dart constructor.
|
||||
static final RegExp _constructorRegExp = RegExp(r'[A-Z][a-zA-Z0-9<>.]*\(');
|
||||
@@ -173,10 +203,7 @@ class SampleChecker {
|
||||
}
|
||||
|
||||
static List<File> _listDartFiles(Directory directory, {bool recursive = false}) {
|
||||
return directory.listSync(recursive: recursive, followLinks: false)
|
||||
.whereType<File>()
|
||||
.where((File file) => path.extension(file.path) == '.dart')
|
||||
.toList();
|
||||
return directory.listSync(recursive: recursive, followLinks: false).whereType<File>().where((File file) => path.extension(file.path) == '.dart').toList();
|
||||
}
|
||||
|
||||
/// Computes the headers needed for each sample file.
|
||||
@@ -218,14 +245,14 @@ class SampleChecker {
|
||||
}
|
||||
stderr.writeln('\nFound ${errors.length} sample code errors.');
|
||||
}
|
||||
if (!_keepTmp) {
|
||||
if (_keepTmp) {
|
||||
print('Leaving temporary directory ${_tempDirectory.path} around for your perusal.');
|
||||
} else {
|
||||
try {
|
||||
_tempDirectory.deleteSync(recursive: true);
|
||||
} on FileSystemException catch (e) {
|
||||
stderr.writeln('Failed to delete ${_tempDirectory.path}: $e');
|
||||
}
|
||||
} else {
|
||||
print('Leaving temporary directory ${_tempDirectory.path} around for your perusal.');
|
||||
}
|
||||
// If we made a snapshot, remove it (so as not to clutter up the tree).
|
||||
if (_snippetsSnapshotPath != null) {
|
||||
@@ -288,8 +315,12 @@ class SampleChecker {
|
||||
print('Generating snippet for ${snippet.start?.filename}:${snippet.start?.line}');
|
||||
final ProcessResult process = _runSnippetsScript(args);
|
||||
if (process.exitCode != 0) {
|
||||
throw 'Unable to create snippet for ${snippet.start.filename}:${snippet.start.line} '
|
||||
'(using input from ${inputFile.path}):\n${process.stdout}\n${process.stderr}';
|
||||
throw SampleCheckerException(
|
||||
'Unable to create snippet for ${snippet.start.filename}:${snippet.start.line} '
|
||||
'(using input from ${inputFile.path}):\n${process.stdout}\n${process.stderr}',
|
||||
file: snippet.start.filename,
|
||||
line: snippet.start.line,
|
||||
);
|
||||
}
|
||||
return outputFile;
|
||||
}
|
||||
@@ -304,11 +335,14 @@ class SampleChecker {
|
||||
final String relativeFilePath = path.relative(file.path, from: _flutterPackage.path);
|
||||
final List<String> sampleLines = file.readAsLinesSync();
|
||||
final List<Section> preambleSections = <Section>[];
|
||||
// Whether or not we're in the file-wide preamble section ("Examples can assume").
|
||||
bool inPreamble = false;
|
||||
// Whether or not we're in a code sample
|
||||
bool inSampleSection = false;
|
||||
// Whether or not we're in a snippet code sample (with template) specifically.
|
||||
bool inSnippet = false;
|
||||
// Whether or not we're in a '```dart' segment.
|
||||
bool inDart = false;
|
||||
bool foundDart = false;
|
||||
int lineNumber = 0;
|
||||
final List<String> block = <String>[];
|
||||
List<String> snippetArgs = <String>[];
|
||||
@@ -318,7 +352,7 @@ class SampleChecker {
|
||||
final String trimmedLine = line.trim();
|
||||
if (inSnippet) {
|
||||
if (!trimmedLine.startsWith(_dartDocPrefix)) {
|
||||
throw '$relativeFilePath:$lineNumber: Snippet section unterminated.';
|
||||
throw SampleCheckerException('Snippet section unterminated.', file: relativeFilePath, line: lineNumber);
|
||||
}
|
||||
if (_dartDocSampleEndRegex.hasMatch(trimmedLine)) {
|
||||
snippets.add(
|
||||
@@ -342,53 +376,51 @@ class SampleChecker {
|
||||
preambleSections.add(_processBlock(startLine, block));
|
||||
block.clear();
|
||||
} else if (!line.startsWith('// ')) {
|
||||
throw '$relativeFilePath:$lineNumber: Unexpected content in sample code preamble.';
|
||||
throw SampleCheckerException('Unexpected content in sample code preamble.', file: relativeFilePath, line: lineNumber);
|
||||
} else {
|
||||
block.add(line.substring(3));
|
||||
}
|
||||
} else if (inSampleSection) {
|
||||
if (!trimmedLine.startsWith(_dartDocPrefix) || trimmedLine.startsWith('$_dartDocPrefix ## ')) {
|
||||
if (_dartDocSampleEndRegex.hasMatch(trimmedLine)) {
|
||||
if (inDart) {
|
||||
throw '$relativeFilePath:$lineNumber: Dart section inexplicably unterminated.';
|
||||
}
|
||||
if (!foundDart) {
|
||||
throw '$relativeFilePath:$lineNumber: No dart block found in sample code section';
|
||||
throw SampleCheckerException("Dart section didn't terminate before end of sample", file: relativeFilePath, line: lineNumber);
|
||||
}
|
||||
inSampleSection = false;
|
||||
} else {
|
||||
if (inDart) {
|
||||
if (_codeBlockEndRegex.hasMatch(trimmedLine)) {
|
||||
inDart = false;
|
||||
final Section processed = _processBlock(startLine, block);
|
||||
if (preambleSections.isEmpty) {
|
||||
sections.add(processed);
|
||||
} else {
|
||||
sections.add(Section.combine(preambleSections
|
||||
..toList()
|
||||
..add(processed)));
|
||||
}
|
||||
block.clear();
|
||||
} else if (trimmedLine == _dartDocPrefix) {
|
||||
block.add('');
|
||||
}
|
||||
if (inDart) {
|
||||
if (_codeBlockEndRegex.hasMatch(trimmedLine)) {
|
||||
inDart = false;
|
||||
final Section processed = _processBlock(startLine, block);
|
||||
if (preambleSections.isEmpty) {
|
||||
sections.add(processed);
|
||||
} else {
|
||||
final int index = line.indexOf(_dartDocPrefixWithSpace);
|
||||
if (index < 0) {
|
||||
throw '$relativeFilePath:$lineNumber: Dart section inexplicably did not '
|
||||
'contain "$_dartDocPrefixWithSpace" prefix.';
|
||||
}
|
||||
block.add(line.substring(index + 4));
|
||||
sections.add(Section.combine(preambleSections
|
||||
..toList()
|
||||
..add(processed)));
|
||||
}
|
||||
} else if (_codeBlockStartRegex.hasMatch(trimmedLine)) {
|
||||
assert(block.isEmpty);
|
||||
startLine = Line(
|
||||
'',
|
||||
filename: relativeFilePath,
|
||||
line: lineNumber + 1,
|
||||
indent: line.indexOf(_dartDocPrefixWithSpace) + _dartDocPrefixWithSpace.length,
|
||||
);
|
||||
inDart = true;
|
||||
foundDart = true;
|
||||
block.clear();
|
||||
} else if (trimmedLine == _dartDocPrefix) {
|
||||
block.add('');
|
||||
} else {
|
||||
final int index = line.indexOf(_dartDocPrefixWithSpace);
|
||||
if (index < 0) {
|
||||
throw SampleCheckerException(
|
||||
'Dart section inexplicably did not contain "$_dartDocPrefixWithSpace" prefix.',
|
||||
file: relativeFilePath,
|
||||
line: lineNumber,
|
||||
);
|
||||
}
|
||||
block.add(line.substring(index + 4));
|
||||
}
|
||||
} else if (_codeBlockStartRegex.hasMatch(trimmedLine)) {
|
||||
assert(block.isEmpty);
|
||||
startLine = Line(
|
||||
'',
|
||||
filename: relativeFilePath,
|
||||
line: lineNumber + 1,
|
||||
indent: line.indexOf(_dartDocPrefixWithSpace) + _dartDocPrefixWithSpace.length,
|
||||
);
|
||||
inDart = true;
|
||||
}
|
||||
}
|
||||
if (!inSampleSection) {
|
||||
@@ -397,11 +429,7 @@ class SampleChecker {
|
||||
assert(block.isEmpty);
|
||||
startLine = Line('', filename: relativeFilePath, line: lineNumber + 1, indent: 3);
|
||||
inPreamble = true;
|
||||
} else if (trimmedLine == '/// ## Sample code' ||
|
||||
trimmedLine.startsWith('/// ## Sample code:') ||
|
||||
trimmedLine == '/// ### Sample code' ||
|
||||
trimmedLine.startsWith('/// ### Sample code:') ||
|
||||
sampleMatch != null) {
|
||||
} else if (sampleMatch != null) {
|
||||
inSnippet = sampleMatch != null ? sampleMatch[1] == 'snippet' : false;
|
||||
if (inSnippet) {
|
||||
startLine = Line(
|
||||
@@ -418,7 +446,12 @@ class SampleChecker {
|
||||
}
|
||||
}
|
||||
inSampleSection = !inSnippet;
|
||||
foundDart = false;
|
||||
} else if (RegExp(r'///\s*#+\s+[Ss]ample\s+[Cc]ode:?$').hasMatch(trimmedLine)) {
|
||||
throw SampleCheckerException(
|
||||
"Found deprecated '## Sample code' section: use {@tool sample}...{@end-tool} instead.",
|
||||
file: relativeFilePath,
|
||||
line: lineNumber,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -598,14 +631,17 @@ linter:
|
||||
),
|
||||
),
|
||||
);
|
||||
throw 'Cannot analyze dartdocs; analysis errors exist in ${file.path}: $error';
|
||||
throw SampleCheckerException(
|
||||
'Cannot analyze dartdocs; analysis errors exist: $error',
|
||||
file: file.path,
|
||||
line: lineNumber,
|
||||
);
|
||||
}
|
||||
|
||||
if (errorCode == 'unused_element' || errorCode == 'unused_local_variable') {
|
||||
// We don't really care if sample code isn't used!
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isSnippet) {
|
||||
addAnalysisError(
|
||||
file,
|
||||
@@ -630,14 +666,20 @@ linter:
|
||||
Line('', filename: file.path, line: lineNumber),
|
||||
),
|
||||
);
|
||||
throw 'Failed to parse error message (read line number as $lineNumber; '
|
||||
'total number of lines is ${fileContents.length}): $error';
|
||||
throw SampleCheckerException('Failed to parse error message: $error', file: file.path, line: lineNumber);
|
||||
}
|
||||
|
||||
final Section actualSection = sections[file.path];
|
||||
if (actualSection == null) {
|
||||
throw SampleCheckerException(
|
||||
"Unknown section for ${file.path}. Maybe the temporary directory wasn't empty?",
|
||||
file: file.path,
|
||||
line: lineNumber,
|
||||
);
|
||||
}
|
||||
final Line actualLine = actualSection.code[lineNumber - 1];
|
||||
|
||||
if (actualLine.filename == null) {
|
||||
if (actualLine?.filename == null) {
|
||||
if (errorCode == 'missing_identifier' && lineNumber > 1) {
|
||||
if (fileContents[lineNumber - 2].endsWith(',')) {
|
||||
final Line actualLine = sections[file.path].code[lineNumber - 2];
|
||||
@@ -698,7 +740,7 @@ linter:
|
||||
/// into valid Dart code.
|
||||
Section _processBlock(Line line, List<String> block) {
|
||||
if (block.isEmpty) {
|
||||
throw '$line: Empty ```dart block in sample code.';
|
||||
throw SampleCheckerException('$line: Empty ```dart block in sample code.');
|
||||
}
|
||||
if (block.first.startsWith('new ') || block.first.startsWith('const ') || block.first.startsWith(_constructorRegExp)) {
|
||||
_expressionId += 1;
|
||||
@@ -721,8 +763,8 @@ linter:
|
||||
// treated as a separate code block.
|
||||
if (block[index] == '' || block[index] == '// ...') {
|
||||
if (subline == null)
|
||||
throw '${Line('', filename: line.filename, line: line.line + index, indent: line.indent)}: '
|
||||
'Unexpected blank line or "// ..." line near start of subblock in sample code.';
|
||||
throw SampleCheckerException('${Line('', filename: line.filename, line: line.line + index, indent: line.indent)}: '
|
||||
'Unexpected blank line or "// ..." line near start of subblock in sample code.');
|
||||
subblocks += 1;
|
||||
subsections.add(_processBlock(subline, buffer));
|
||||
buffer.clear();
|
||||
|
||||
@@ -30,6 +30,7 @@ Future<void> main(List<String> args) async {
|
||||
print('The analyze.dart script must be run with --enable-asserts.');
|
||||
exit(1);
|
||||
}
|
||||
await _verifyNoMissingLicense(flutterRoot);
|
||||
await _verifyNoTestImports(flutterRoot);
|
||||
await _verifyNoTestPackageImports(flutterRoot);
|
||||
await _verifyGeneratedPluginRegistrants(flutterRoot);
|
||||
@@ -235,7 +236,7 @@ Future<EvalResult> _evalCommand(String executable, List<String> arguments, {
|
||||
}
|
||||
|
||||
Future<void> _runFlutterAnalyze(String workingDirectory, {
|
||||
List<String> options = const <String>[]
|
||||
List<String> options = const <String>[],
|
||||
}) {
|
||||
return runCommand(flutter, <String>['analyze', '--dartdocs']..addAll(options),
|
||||
workingDirectory: workingDirectory,
|
||||
@@ -400,7 +401,7 @@ Set<String> _findFlutterDependencies(String srcPath, List<String> errors, { bool
|
||||
return Directory(srcPath).listSync(recursive: true).where((FileSystemEntity entity) {
|
||||
return entity is File && path.extension(entity.path) == '.dart';
|
||||
}).map<Set<String>>((FileSystemEntity entity) {
|
||||
final Set<String> result = Set<String>();
|
||||
final Set<String> result = <String>{};
|
||||
final File file = entity;
|
||||
for (String line in file.readAsLinesSync()) {
|
||||
Match match = _importPattern.firstMatch(line);
|
||||
@@ -418,7 +419,7 @@ Set<String> _findFlutterDependencies(String srcPath, List<String> errors, { bool
|
||||
}
|
||||
return result;
|
||||
}).reduce((Set<String> value, Set<String> element) {
|
||||
value ??= Set<String>();
|
||||
value ??= <String>{};
|
||||
value.addAll(element);
|
||||
return value;
|
||||
});
|
||||
@@ -433,7 +434,7 @@ List<T> _deepSearch<T>(Map<T, Set<T>> map, T start, [ Set<T> seen ]) {
|
||||
final List<T> result = _deepSearch<T>(
|
||||
map,
|
||||
key,
|
||||
(seen == null ? Set<T>.from(<T>[start]) : Set<T>.from(seen))..add(key),
|
||||
(seen == null ? <T>{start} : Set<T>.from(seen))..add(key),
|
||||
);
|
||||
if (result != null) {
|
||||
result.insert(0, start);
|
||||
@@ -472,6 +473,30 @@ Future<void> _verifyNoBadImportsInFlutterTools(String workingDirectory) async {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _verifyNoMissingLicense(String workingDirectory) async {
|
||||
final List<String> errors = <String>[];
|
||||
for (FileSystemEntity entity in Directory(path.join(workingDirectory, 'packages'))
|
||||
.listSync(recursive: true)
|
||||
.where((FileSystemEntity entity) => entity is File && path.extension(entity.path) == '.dart')) {
|
||||
final File file = entity;
|
||||
bool hasLicense = false;
|
||||
final List<String> lines = file.readAsLinesSync();
|
||||
if (lines.isNotEmpty)
|
||||
hasLicense = lines.first.startsWith(RegExp(r'// Copyright \d{4}'));
|
||||
if (!hasLicense)
|
||||
errors.add(file.path);
|
||||
}
|
||||
// Fail if any errors
|
||||
if (errors.isNotEmpty) {
|
||||
print('$redLine');
|
||||
final String s = errors.length == 1 ? '' : 's';
|
||||
print('${bold}License headers cannot be found at the beginning of the following file$s.$reset\n');
|
||||
print(errors.join('\n'));
|
||||
print('$redLine\n');
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
final RegExp _testImportPattern = RegExp(r'''import (['"])([^'"]+_test\.dart)\1''');
|
||||
const Set<String> _exemptTestImports = <String>{
|
||||
'package:flutter_test/flutter_test.dart',
|
||||
@@ -518,7 +543,7 @@ Future<void> _verifyGeneratedPluginRegistrants(String flutterRoot) async {
|
||||
}
|
||||
}
|
||||
|
||||
final Set<String> outOfDate = Set<String>();
|
||||
final Set<String> outOfDate = <String>{};
|
||||
|
||||
for (String package in packageToRegistrants.keys) {
|
||||
final Map<File, String> fileToContent = <File, String>{};
|
||||
|
||||
@@ -62,9 +62,9 @@ function move_offline_into_place() {
|
||||
mv flutter.docs.zip doc/offline/flutter.docs.zip
|
||||
du -sh doc/offline/flutter.docs.zip
|
||||
if [[ "$CIRRUS_BRANCH" == "stable" ]]; then
|
||||
echo -e "<entry>\n <version>${FLUTTER_VERSION}</version>\n <url>https://docs.flutter.io/offline/flutter.docset.tar.gz</url>\n</entry>" > doc/offline/flutter.xml
|
||||
echo -e "<entry>\n <version>${FLUTTER_VERSION}</version>\n <url>https://api.flutter.dev/offline/flutter.docset.tar.gz</url>\n</entry>" > doc/offline/flutter.xml
|
||||
else
|
||||
echo -e "<entry>\n <version>${FLUTTER_VERSION}</version>\n <url>https://master-docs.flutter.io/offline/flutter.docset.tar.gz</url>\n</entry>" > doc/offline/flutter.xml
|
||||
echo -e "<entry>\n <version>${FLUTTER_VERSION}</version>\n <url>https://master-api.flutter.dev/offline/flutter.docset.tar.gz</url>\n</entry>" > doc/offline/flutter.xml
|
||||
fi
|
||||
mv flutter.docset.tar.gz doc/offline/flutter.docset.tar.gz
|
||||
du -sh doc/offline/flutter.docset.tar.gz
|
||||
@@ -104,7 +104,7 @@ if [[ -d "$FLUTTER_PUB_CACHE" ]]; then
|
||||
fi
|
||||
|
||||
# Install and activate dartdoc.
|
||||
"$PUB" global activate dartdoc 0.28.1+2
|
||||
"$PUB" global activate dartdoc 0.28.2
|
||||
|
||||
# This script generates a unified doc set, and creates
|
||||
# a custom index.html, placing everything into dev/docs/doc.
|
||||
@@ -125,21 +125,21 @@ cp "$FLUTTER_ROOT/dev/docs/google2ed1af765c529f57.html" "$FLUTTER_ROOT/dev/docs/
|
||||
if [[ -n "$CIRRUS_CI" && -z "$CIRRUS_PR" ]]; then
|
||||
echo "This is not a pull request; considering whether to upload docs... (branch=$CIRRUS_BRANCH)"
|
||||
if [[ "$CIRRUS_BRANCH" == "master" ]]; then
|
||||
echo "Updating $CIRRUS_BRANCH docs: https://master-docs.flutter.io/"
|
||||
echo "Updating $CIRRUS_BRANCH docs: https://master-api.flutter.dev/"
|
||||
# Disable search indexing on the master staging site so searches get only
|
||||
# the stable site.
|
||||
echo -e "User-agent: *\nDisallow: /" > "$FLUTTER_ROOT/dev/docs/doc/robots.txt"
|
||||
export FIREBASE_TOKEN="$FIREBASE_MASTER_TOKEN"
|
||||
deploy 5 master-docs-flutter-io
|
||||
deploy 5 master-docs-flutter-dev
|
||||
fi
|
||||
|
||||
if [[ "$CIRRUS_BRANCH" == "stable" ]]; then
|
||||
# Enable search indexing on the master staging site so searches get only
|
||||
# the stable site.
|
||||
echo "Updating $CIRRUS_BRANCH docs: https://docs.flutter.io/"
|
||||
echo "Updating $CIRRUS_BRANCH docs: https://api.flutter.dev/"
|
||||
echo -e "# All robots welcome!" > "$FLUTTER_ROOT/dev/docs/doc/robots.txt"
|
||||
export FIREBASE_TOKEN="$FIREBASE_PUBLIC_TOKEN"
|
||||
deploy 5 docs-flutter-io
|
||||
deploy 5 docs-flutter-dev
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
27
dev/bots/download_android_sdk.sh
Executable file
27
dev/bots/download_android_sdk.sh
Executable file
@@ -0,0 +1,27 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
if [[ -z $ANDROID_SDK_TOOLS_URL || -z $ANDROID_HOME || -z $ANDROID_SDK_ROOT ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
curl -L $ANDROID_SDK_TOOLS_URL --output android_sdk_tools.zip
|
||||
|
||||
mkdir -p $ANDROID_SDK_ROOT
|
||||
unzip android_sdk_tools.zip -d $ANDROID_SDK_ROOT
|
||||
rm android_sdk_tools.zip
|
||||
|
||||
yes | $ANDROID_SDK_ROOT/tools/bin/sdkmanager --licenses
|
||||
$ANDROID_SDK_ROOT/tools/bin/sdkmanager tools
|
||||
$ANDROID_SDK_ROOT/tools/bin/sdkmanager platform-tools
|
||||
# this is large and we don't need it just yet
|
||||
# $ANDROID_SDK_ROOT/tools/bin/sdkmanager emulator
|
||||
$ANDROID_SDK_ROOT/tools/bin/sdkmanager "platforms;android-28" \
|
||||
"build-tools;28.0.3" \
|
||||
"platforms;android-27" \
|
||||
"build-tools;27.0.3" \
|
||||
"extras;google;m2repository" \
|
||||
"extras;android;m2repository"
|
||||
|
||||
|
||||
14
dev/bots/download_open_jdk.sh
Executable file
14
dev/bots/download_open_jdk.sh
Executable file
@@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
if [[ -z $OPEN_JDK_URL ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
mkdir -p $HOME/Java
|
||||
pushd $HOME/Java
|
||||
curl -L $OPEN_JDK_URL --output open_jdk.tar.gz
|
||||
tar -xvf open_jdk.tar.gz
|
||||
rm open_jdk.tar.gz
|
||||
popd
|
||||
270
dev/bots/flutter_compact_formatter.dart
Normal file
270
dev/bots/flutter_compact_formatter.dart
Normal file
@@ -0,0 +1,270 @@
|
||||
// Copyright 2019 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:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
final Stopwatch _stopwatch = Stopwatch();
|
||||
|
||||
/// A wrapper around package:test's JSON reporter.
|
||||
///
|
||||
/// This class behaves similarly to the compact reporter, but supresses all
|
||||
/// output except for progress until the end of testing. In other words, errors,
|
||||
/// [print] calls, and skipped test messages will not be printed during the run
|
||||
/// of the suite.
|
||||
///
|
||||
/// It also processes the JSON data into a collection of [TestResult]s for any
|
||||
/// other post processing needs, e.g. sending data to analytics.
|
||||
class FlutterCompactFormatter {
|
||||
FlutterCompactFormatter() {
|
||||
_stopwatch.start();
|
||||
}
|
||||
|
||||
/// Whether to use color escape codes in writing to stdout.
|
||||
final bool useColor = stdout.supportsAnsiEscapes;
|
||||
|
||||
/// The terminal escape for green text, or the empty string if this is Windows
|
||||
/// or not outputting to a terminal.
|
||||
String get _green => useColor ? '\u001b[32m' : '';
|
||||
|
||||
/// The terminal escape for red text, or the empty string if this is Windows
|
||||
/// or not outputting to a terminal.
|
||||
String get _red => useColor ? '\u001b[31m' : '';
|
||||
|
||||
/// The terminal escape for yellow text, or the empty string if this is
|
||||
/// Windows or not outputting to a terminal.
|
||||
String get _yellow => useColor ? '\u001b[33m' : '';
|
||||
|
||||
/// The terminal escape for gray text, or the empty string if this is
|
||||
/// Windows or not outputting to a terminal.
|
||||
String get _gray => useColor ? '\u001b[1;30m' : '';
|
||||
|
||||
/// The terminal escape for bold text, or the empty string if this is
|
||||
/// Windows or not outputting to a terminal.
|
||||
String get _bold => useColor ? '\u001b[1m' : '';
|
||||
|
||||
/// The terminal escape for removing test coloring, or the empty string if
|
||||
/// this is Windows or not outputting to a terminal.
|
||||
String get _noColor => useColor ? '\u001b[0m' : '';
|
||||
|
||||
/// The termianl escape for clearing the line, or a carriage return if
|
||||
/// this is Windows or not outputting to a termianl.
|
||||
String get _clearLine => useColor ? '\x1b[2K\r' : '\r';
|
||||
|
||||
final Map<int, TestResult> _tests = <int, TestResult>{};
|
||||
|
||||
/// The test results from this run.
|
||||
Iterable<TestResult> get tests => _tests.values;
|
||||
|
||||
/// The number of tests that were started.
|
||||
int started = 0;
|
||||
|
||||
/// The number of test failures.
|
||||
int failures = 0;
|
||||
|
||||
/// The number of skipped tests.
|
||||
int skips = 0;
|
||||
|
||||
/// The number of successful tests.
|
||||
int successes = 0;
|
||||
|
||||
/// Process a single line of JSON output from the JSON test reporter.
|
||||
///
|
||||
/// Callers are responsible for splitting multiple lines before calling this
|
||||
/// method.
|
||||
TestResult processRawOutput(String raw) {
|
||||
assert(raw != null);
|
||||
// We might be getting messages from Flutter Tool about updating/building.
|
||||
if (!raw.startsWith('{')) {
|
||||
print(raw);
|
||||
return null;
|
||||
}
|
||||
final Map<String, dynamic> decoded = json.decode(raw);
|
||||
final TestResult originalResult = _tests[decoded['testID']];
|
||||
switch (decoded['type']) {
|
||||
case 'done':
|
||||
stdout.write(_clearLine);
|
||||
stdout.write('$_bold${_stopwatch.elapsed}$_noColor ');
|
||||
stdout.writeln(
|
||||
'$_green+$successes $_yellow~$skips $_red-$failures:$_bold$_gray Done.$_noColor');
|
||||
break;
|
||||
case 'testStart':
|
||||
final Map<String, dynamic> testData = decoded['test'];
|
||||
if (testData['url'] == null) {
|
||||
started += 1;
|
||||
stdout.write(_clearLine);
|
||||
stdout.write('$_bold${_stopwatch.elapsed}$_noColor ');
|
||||
stdout.write(
|
||||
'$_green+$successes $_yellow~$skips $_red-$failures: $_gray${testData['name']}$_noColor');
|
||||
break;
|
||||
}
|
||||
_tests[testData['id']] = TestResult(
|
||||
id: testData['id'],
|
||||
name: testData['name'],
|
||||
line: testData['root_line'] ?? testData['line'],
|
||||
column: testData['root_column'] ?? testData['column'],
|
||||
path: testData['root_url'] ?? testData['url'],
|
||||
startTime: decoded['time'],
|
||||
);
|
||||
break;
|
||||
case 'testDone':
|
||||
if (originalResult == null) {
|
||||
break;
|
||||
}
|
||||
originalResult.endTime = decoded['time'];
|
||||
if (decoded['skipped'] == true) {
|
||||
skips += 1;
|
||||
originalResult.status = TestStatus.skipped;
|
||||
} else {
|
||||
if (decoded['result'] == 'success') {
|
||||
originalResult.status =TestStatus.succeeded;
|
||||
successes += 1;
|
||||
} else {
|
||||
originalResult.status = TestStatus.failed;
|
||||
failures += 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'error':
|
||||
final String error = decoded['error'];
|
||||
final String stackTrace = decoded['stackTrace'];
|
||||
if (originalResult != null) {
|
||||
originalResult.errorMessage = error;
|
||||
originalResult.stackTrace = stackTrace;
|
||||
} else {
|
||||
if (error != null)
|
||||
stderr.writeln(error);
|
||||
if (stackTrace != null)
|
||||
stderr.writeln(stackTrace);
|
||||
}
|
||||
break;
|
||||
case 'print':
|
||||
if (originalResult != null) {
|
||||
originalResult.messages.add(decoded['message']);
|
||||
}
|
||||
break;
|
||||
case 'group':
|
||||
case 'allSuites':
|
||||
case 'start':
|
||||
case 'suite':
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return originalResult;
|
||||
}
|
||||
|
||||
/// Print summary of test results.
|
||||
void finish() {
|
||||
final List<String> skipped = <String>[];
|
||||
final List<String> failed = <String>[];
|
||||
for (TestResult result in _tests.values) {
|
||||
switch (result.status) {
|
||||
case TestStatus.started:
|
||||
failed.add('${_red}Unexpectedly failed to complete a test!');
|
||||
failed.add(result.toString() + _noColor);
|
||||
break;
|
||||
case TestStatus.skipped:
|
||||
skipped.add(
|
||||
'${_yellow}Skipped ${result.name} (${result.pathLineColumn}).$_noColor');
|
||||
break;
|
||||
case TestStatus.failed:
|
||||
failed.addAll(<String>[
|
||||
'$_bold${_red}Failed ${result.name} (${result.pathLineColumn}):',
|
||||
result.errorMessage,
|
||||
_noColor + _red,
|
||||
result.stackTrace,
|
||||
]);
|
||||
failed.addAll(result.messages);
|
||||
failed.add(_noColor);
|
||||
break;
|
||||
case TestStatus.succeeded:
|
||||
break;
|
||||
}
|
||||
}
|
||||
skipped.forEach(print);
|
||||
failed.forEach(print);
|
||||
if (failed.isEmpty) {
|
||||
print('${_green}Completed, $successes test(s) passing ($skips skipped).$_noColor');
|
||||
} else {
|
||||
print('$_gray$failures test(s) failed.$_noColor');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The state of a test received from the JSON reporter.
|
||||
enum TestStatus {
|
||||
/// Test execution has started.
|
||||
started,
|
||||
/// Test completed successfully.
|
||||
succeeded,
|
||||
/// Test failed.
|
||||
failed,
|
||||
/// Test was skipped.
|
||||
skipped,
|
||||
}
|
||||
|
||||
/// The detailed status of a test run.
|
||||
class TestResult {
|
||||
TestResult({
|
||||
@required this.id,
|
||||
@required this.name,
|
||||
@required this.line,
|
||||
@required this.column,
|
||||
@required this.path,
|
||||
@required this.startTime,
|
||||
this.status = TestStatus.started,
|
||||
}) : assert(id != null),
|
||||
assert(name != null),
|
||||
assert(line != null),
|
||||
assert(column != null),
|
||||
assert(path != null),
|
||||
assert(startTime != null),
|
||||
assert(status != null),
|
||||
messages = <String>[];
|
||||
|
||||
/// The state of the test.
|
||||
TestStatus status;
|
||||
|
||||
/// The internal ID of the test used by the JSON reporter.
|
||||
final int id;
|
||||
|
||||
/// The name of the test, specified via the `test` method.
|
||||
final String name;
|
||||
|
||||
/// The line number from the original file.
|
||||
final int line;
|
||||
|
||||
/// The column from the original file.
|
||||
final int column;
|
||||
|
||||
/// The path of the original test file.
|
||||
final String path;
|
||||
|
||||
/// A friendly print out of the [path], [line], and [column] of the test.
|
||||
String get pathLineColumn => '$path:$line:$column';
|
||||
|
||||
/// The start time of the test, in milliseconds relative to suite startup.
|
||||
final int startTime;
|
||||
|
||||
/// The stdout of the test.
|
||||
final List<String> messages;
|
||||
|
||||
/// The error message from the test, from an `expect`, an [Exception] or
|
||||
/// [Error].
|
||||
String errorMessage;
|
||||
|
||||
/// The stacktrace from a test failure.
|
||||
String stackTrace;
|
||||
|
||||
/// The time, in milliseconds relative to suite startup, that the test ended.
|
||||
int endTime;
|
||||
|
||||
/// The total time, in milliseconds, that the test took.
|
||||
int get totalTime => (endTime ?? _stopwatch.elapsedMilliseconds) - startTime;
|
||||
|
||||
@override
|
||||
String toString() => '{$runtimeType: {$id, $name, ${totalTime}ms, $pathLineColumn}}';
|
||||
}
|
||||
@@ -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';
|
||||
@@ -24,8 +26,8 @@ const String baseUrl = 'https://storage.googleapis.com/flutter_infra';
|
||||
|
||||
/// Exception class for when a process fails to run, so we can catch
|
||||
/// it and provide something more readable than a stack trace.
|
||||
class ProcessRunnerException implements Exception {
|
||||
ProcessRunnerException(this.message, [this.result]);
|
||||
class PreparePackageException implements Exception {
|
||||
PreparePackageException(this.message, [this.result]);
|
||||
|
||||
final String message;
|
||||
final ProcessResult result;
|
||||
@@ -156,17 +158,17 @@ class ProcessRunner {
|
||||
} on ProcessException catch (e) {
|
||||
final String message = 'Running "${commandLine.join(' ')}" in ${workingDirectory.path} '
|
||||
'failed with:\n${e.toString()}';
|
||||
throw ProcessRunnerException(message);
|
||||
throw PreparePackageException(message);
|
||||
} on ArgumentError catch (e) {
|
||||
final String message = 'Running "${commandLine.join(' ')}" in ${workingDirectory.path} '
|
||||
'failed with:\n${e.toString()}';
|
||||
throw ProcessRunnerException(message);
|
||||
throw PreparePackageException(message);
|
||||
}
|
||||
|
||||
final int exitCode = await allComplete();
|
||||
if (exitCode != 0 && !failOk) {
|
||||
final String message = 'Running "${commandLine.join(' ')}" in ${workingDirectory.path} failed';
|
||||
throw ProcessRunnerException(
|
||||
throw PreparePackageException(
|
||||
message,
|
||||
ProcessResult(0, exitCode, null, 'returned $exitCode'),
|
||||
);
|
||||
@@ -192,18 +194,19 @@ class ArchiveCreator {
|
||||
this.outputDir,
|
||||
this.revision,
|
||||
this.branch, {
|
||||
this.strict = true,
|
||||
ProcessManager processManager,
|
||||
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',
|
||||
@@ -234,6 +237,11 @@ class ArchiveCreator {
|
||||
/// The directory to write the output file to.
|
||||
final Directory outputDir;
|
||||
|
||||
/// True if the creator should be strict about checking requirements or not.
|
||||
///
|
||||
/// In strict mode, will insist that the [revision] be a tagged revision.
|
||||
final bool strict;
|
||||
|
||||
final Uri _minGitUri = Uri.parse(mingitForWindowsUrl);
|
||||
final ProcessRunner _processRunner;
|
||||
|
||||
@@ -283,10 +291,29 @@ class ArchiveCreator {
|
||||
return _outputFile;
|
||||
}
|
||||
|
||||
/// Returns the version number of this release, according the to tags in
|
||||
/// the repo.
|
||||
/// Returns the version number of this release, according the to tags in the
|
||||
/// repo.
|
||||
///
|
||||
/// This looks for the tag attached to [revision] and, if it doesn't find one,
|
||||
/// git will give an error.
|
||||
///
|
||||
/// If [strict] is true, the exact [revision] must be tagged to return the
|
||||
/// version. If [strict] is not true, will look backwards in time starting at
|
||||
/// [revision] to find the most recent version tag.
|
||||
Future<String> _getVersion() async {
|
||||
return _runGit(<String>['describe', '--tags', '--abbrev=0']);
|
||||
if (strict) {
|
||||
try {
|
||||
return _runGit(<String>['describe', '--tags', '--exact-match', revision]);
|
||||
} on PreparePackageException catch (exception) {
|
||||
throw PreparePackageException(
|
||||
'Git error when checking for a version tag attached to revision $revision.\n'
|
||||
'Perhaps there is no tag at that revision?:\n'
|
||||
'$exception'
|
||||
);
|
||||
}
|
||||
} else {
|
||||
return _runGit(<String>['describe', '--tags', '--abbrev=0', revision]);
|
||||
}
|
||||
}
|
||||
|
||||
/// Clone the Flutter repo and make sure that the git environment is sane
|
||||
@@ -311,8 +338,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 +461,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 +482,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 +502,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 +518,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'];
|
||||
@@ -511,17 +550,17 @@ class ArchivePublisher {
|
||||
await _runGsUtil(<String>['cp', metadataGsPath, metadataFile.absolute.path]);
|
||||
final String currentMetadata = metadataFile.readAsStringSync();
|
||||
if (currentMetadata.isEmpty) {
|
||||
throw ProcessRunnerException('Empty metadata received from server');
|
||||
throw PreparePackageException('Empty metadata received from server');
|
||||
}
|
||||
|
||||
Map<String, dynamic> jsonData;
|
||||
try {
|
||||
jsonData = json.decode(currentMetadata);
|
||||
} on FormatException catch (e) {
|
||||
throw ProcessRunnerException('Unable to parse JSON metadata received from cloud: $e');
|
||||
throw PreparePackageException('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));
|
||||
@@ -671,7 +710,7 @@ Future<void> main(List<String> rawArguments) async {
|
||||
}
|
||||
|
||||
final Branch branch = fromBranchName(parsedArguments['branch']);
|
||||
final ArchiveCreator creator = ArchiveCreator(tempDir, outputDir, revision, branch);
|
||||
final ArchiveCreator creator = ArchiveCreator(tempDir, outputDir, revision, branch, strict: parsedArguments['publish']);
|
||||
int exitCode = 0;
|
||||
String message;
|
||||
try {
|
||||
@@ -687,7 +726,7 @@ Future<void> main(List<String> rawArguments) async {
|
||||
);
|
||||
await publisher.publishArchive();
|
||||
}
|
||||
} on ProcessRunnerException catch (e) {
|
||||
} on PreparePackageException catch (e) {
|
||||
exitCode = e.exitCode;
|
||||
message = e.message;
|
||||
} catch (e) {
|
||||
|
||||
@@ -3,7 +3,7 @@ description: Scripts which run on bots.
|
||||
|
||||
environment:
|
||||
# The pub client defaults to an <2.0.0 sdk constraint which we need to explicitly overwrite.
|
||||
sdk: ">=2.0.0-dev.68.0 <3.0.0"
|
||||
sdk: ">=2.2.0 <3.0.0"
|
||||
|
||||
dependencies:
|
||||
path: 1.6.2
|
||||
@@ -14,8 +14,11 @@ dependencies:
|
||||
http: 0.12.0+1
|
||||
http_parser: 3.1.3
|
||||
test: 1.5.3
|
||||
googleapis: 0.53.0
|
||||
googleapis_auth: 0.2.7
|
||||
|
||||
analyzer: 0.35.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
_discoveryapis_commons: 0.1.8+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
analyzer: 0.35.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
charcode: 1.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
@@ -24,23 +27,23 @@ dependencies:
|
||||
crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
file: 5.0.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
front_end: 0.1.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
front_end: 0.1.13 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
html: 0.13.4+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
http_multi_server: 2.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
intl: 0.15.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
kernel: 0.3.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
kernel: 0.3.13 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
node_preamble: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
package_resolver: 1.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pedantic: 1.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
package_resolver: 1.0.10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pedantic: 1.5.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
plugin: 0.2.0+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pool: 1.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pub_semver: 1.4.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
@@ -50,7 +53,7 @@ dependencies:
|
||||
shelf_web_socket: 0.2.2+4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
source_map_stack_trace: 1.1.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
source_maps: 0.10.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
source_span: 1.5.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
source_span: 1.5.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
stack_trace: 1.9.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
stream_channel: 1.6.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
string_scanner: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
@@ -67,4 +70,5 @@ dev_dependencies:
|
||||
mockito: 4.0.0
|
||||
test_api: 0.2.2
|
||||
|
||||
# PUBSPEC CHECKSUM: 7bc7
|
||||
|
||||
# PUBSPEC CHECKSUM: 422e
|
||||
|
||||
@@ -30,6 +30,53 @@ void printProgress(String action, String workingDir, String command) {
|
||||
print('$arrow $action: cd $cyan$workingDir$reset; $yellow$command$reset');
|
||||
}
|
||||
|
||||
Stream<String> runAndGetStdout(String executable, List<String> arguments, {
|
||||
String workingDirectory,
|
||||
Map<String, String> environment,
|
||||
bool expectNonZeroExit = false,
|
||||
int expectedExitCode,
|
||||
String failureMessage,
|
||||
Duration timeout = _kLongTimeout,
|
||||
Function beforeExit,
|
||||
}) async* {
|
||||
final String commandDescription = '${path.relative(executable, from: workingDirectory)} ${arguments.join(' ')}';
|
||||
final String relativeWorkingDir = path.relative(workingDirectory);
|
||||
|
||||
printProgress('RUNNING', relativeWorkingDir, commandDescription);
|
||||
|
||||
final DateTime start = DateTime.now();
|
||||
final Process process = await Process.start(executable, arguments,
|
||||
workingDirectory: workingDirectory,
|
||||
environment: environment,
|
||||
);
|
||||
|
||||
stderr.addStream(process.stderr);
|
||||
final Stream<String> lines = process.stdout.transform(utf8.decoder).transform(const LineSplitter());
|
||||
await for (String line in lines) {
|
||||
yield line;
|
||||
}
|
||||
|
||||
final int exitCode = await process.exitCode.timeout(timeout, onTimeout: () {
|
||||
stderr.writeln('Process timed out after $timeout');
|
||||
return expectNonZeroExit ? 0 : 1;
|
||||
});
|
||||
print('$clock ELAPSED TIME: $bold${elapsedTime(start)}$reset for $commandDescription in $relativeWorkingDir: ');
|
||||
if ((exitCode == 0) == expectNonZeroExit || (expectedExitCode != null && exitCode != expectedExitCode)) {
|
||||
if (failureMessage != null) {
|
||||
print(failureMessage);
|
||||
}
|
||||
print(
|
||||
'$redLine\n'
|
||||
'${bold}ERROR:$red Last command exited with $exitCode (expected: ${expectNonZeroExit ? (expectedExitCode ?? 'non-zero') : 'zero'}).$reset\n'
|
||||
'${bold}Command:$cyan $commandDescription$reset\n'
|
||||
'${bold}Relative working directory:$red $relativeWorkingDir$reset\n'
|
||||
'$redLine'
|
||||
);
|
||||
beforeExit?.call();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> runCommand(String executable, List<String> arguments, {
|
||||
String workingDirectory,
|
||||
Map<String, String> environment,
|
||||
@@ -58,7 +105,7 @@ Future<void> runCommand(String executable, List<String> arguments, {
|
||||
if (printOutput) {
|
||||
await Future.wait<void>(<Future<void>>[
|
||||
stdout.addStream(process.stdout),
|
||||
stderr.addStream(process.stderr)
|
||||
stderr.addStream(process.stderr),
|
||||
]);
|
||||
} else {
|
||||
savedStdout = process.stdout.toList();
|
||||
|
||||
BIN
dev/bots/serviceaccount.enc
Normal file
BIN
dev/bots/serviceaccount.enc
Normal file
Binary file not shown.
@@ -5,8 +5,12 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:googleapis/bigquery/v2.dart' as bq;
|
||||
import 'package:googleapis_auth/auth_io.dart' as auth;
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
import 'flutter_compact_formatter.dart';
|
||||
import 'run_command.dart';
|
||||
|
||||
typedef ShardRunner = Future<void> Function();
|
||||
@@ -18,11 +22,18 @@ final String pub = path.join(flutterRoot, 'bin', 'cache', 'dart-sdk', 'bin', Pla
|
||||
final String pubCache = path.join(flutterRoot, '.pub-cache');
|
||||
final List<String> flutterTestArgs = <String>[];
|
||||
|
||||
|
||||
final bool useFlutterTestFormatter = Platform.environment['FLUTTER_TEST_FORMATTER'] == 'true';
|
||||
|
||||
final bool noUseBuildRunner = Platform.environment['FLUTTER_TEST_NO_BUILD_RUNNER'] == 'true';
|
||||
|
||||
const Map<String, ShardRunner> _kShards = <String, ShardRunner>{
|
||||
'tests': _runTests,
|
||||
'tool_tests': _runToolTests,
|
||||
'build_tests': _runBuildTests,
|
||||
'coverage': _runCoverage,
|
||||
'integration_tests': _runIntegrationTests,
|
||||
'add2app_test': _runAdd2AppTest,
|
||||
};
|
||||
|
||||
const Duration _kLongTimeout = Duration(minutes: 45);
|
||||
@@ -139,13 +150,48 @@ Future<void> _runSmokeTests() async {
|
||||
await _verifyVersion(path.join(flutterRoot, 'version'));
|
||||
}
|
||||
|
||||
Future<bq.BigqueryApi> _getBigqueryApi() async {
|
||||
if (!useFlutterTestFormatter) {
|
||||
return null;
|
||||
}
|
||||
// TODO(dnfield): How will we do this on LUCI?
|
||||
final String privateKey = Platform.environment['GCLOUD_SERVICE_ACCOUNT_KEY'];
|
||||
// If we're on Cirrus and a non-collaborator is doing this, we can't get the key.
|
||||
if (privateKey == null || privateKey.isEmpty || privateKey.startsWith('ENCRYPTED[')) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
final auth.ServiceAccountCredentials accountCredentials = auth.ServiceAccountCredentials(
|
||||
'flutter-ci-test-reporter@flutter-infra.iam.gserviceaccount.com',
|
||||
auth.ClientId.serviceAccount('114390419920880060881.apps.googleusercontent.com'),
|
||||
'-----BEGIN PRIVATE KEY-----\n$privateKey\n-----END PRIVATE KEY-----\n',
|
||||
);
|
||||
final List<String> scopes = <String>[bq.BigqueryApi.BigqueryInsertdataScope];
|
||||
final http.Client client = await auth.clientViaServiceAccount(accountCredentials, scopes);
|
||||
return bq.BigqueryApi(client);
|
||||
} catch (e) {
|
||||
print('Failed to get BigQuery API client.');
|
||||
print(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _runToolTests() async {
|
||||
final bq.BigqueryApi bigqueryApi = await _getBigqueryApi();
|
||||
await _runSmokeTests();
|
||||
|
||||
await _pubRunTest(
|
||||
path.join(flutterRoot, 'packages', 'flutter_tools'),
|
||||
enableFlutterToolAsserts: true,
|
||||
);
|
||||
if (noUseBuildRunner) {
|
||||
await _pubRunTest(
|
||||
path.join(flutterRoot, 'packages', 'flutter_tools'),
|
||||
tableData: bigqueryApi?.tabledata,
|
||||
);
|
||||
} else {
|
||||
await _buildRunnerTest(
|
||||
path.join(flutterRoot, 'packages', 'flutter_tools'),
|
||||
flutterRoot,
|
||||
tableData: bigqueryApi?.tabledata,
|
||||
);
|
||||
}
|
||||
|
||||
print('${bold}DONE: All tests successful.$reset');
|
||||
}
|
||||
@@ -167,10 +213,22 @@ Future<void> _runBuildTests() async {
|
||||
await _flutterBuildApk(path);
|
||||
await _flutterBuildIpa(path);
|
||||
}
|
||||
await _flutterBuildDart2js(path.join('dev', 'integration_tests', 'web'));
|
||||
|
||||
print('${bold}DONE: All build tests successful.$reset');
|
||||
}
|
||||
|
||||
Future<void> _flutterBuildDart2js(String relativePathToApplication) async {
|
||||
print('Running Dart2JS build tests...');
|
||||
await runCommand(flutter,
|
||||
<String>['build', 'web', '-v'],
|
||||
workingDirectory: path.join(flutterRoot, relativePathToApplication),
|
||||
expectNonZeroExit: false,
|
||||
timeout: _kShortTimeout,
|
||||
);
|
||||
print('Done.');
|
||||
}
|
||||
|
||||
Future<void> _flutterBuildAot(String relativePathToApplication) async {
|
||||
print('Running AOT build tests...');
|
||||
await runCommand(flutter,
|
||||
@@ -183,7 +241,6 @@ Future<void> _flutterBuildAot(String relativePathToApplication) async {
|
||||
}
|
||||
|
||||
Future<void> _flutterBuildApk(String relativePathToApplication) async {
|
||||
// TODO(dnfield): See if we can get Android SDK on all Cirrus platforms.
|
||||
if (
|
||||
(Platform.environment['ANDROID_HOME']?.isEmpty ?? true) &&
|
||||
(Platform.environment['ANDROID_SDK_ROOT']?.isEmpty ?? true)) {
|
||||
@@ -224,33 +281,53 @@ Future<void> _flutterBuildIpa(String relativePathToApplication) async {
|
||||
print('Done.');
|
||||
}
|
||||
|
||||
Future<void> _runAdd2AppTest() async {
|
||||
if (!Platform.isMacOS) {
|
||||
return;
|
||||
}
|
||||
print('Running Add2App iOS integration tests...');
|
||||
final String add2AppDir = path.join(flutterRoot, 'dev', 'integration_tests', 'ios_add2app');
|
||||
await runCommand('./build_and_test.sh',
|
||||
<String>[],
|
||||
workingDirectory: add2AppDir,
|
||||
expectNonZeroExit: false,
|
||||
timeout: _kShortTimeout,
|
||||
);
|
||||
print('Done.');
|
||||
}
|
||||
|
||||
Future<void> _runTests() async {
|
||||
final bq.BigqueryApi bigqueryApi = await _getBigqueryApi();
|
||||
await _runSmokeTests();
|
||||
|
||||
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter'));
|
||||
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter'), tableData: bigqueryApi?.tabledata);
|
||||
// Only packages/flutter/test/widgets/widget_inspector_test.dart really
|
||||
// needs to be run with --track-widget-creation but it is nice to run
|
||||
// all of the tests in package:flutter with the flag to ensure that
|
||||
// the Dart kernel transformer triggered by the flag does not break anything.
|
||||
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter'), options: <String>['--track-widget-creation']);
|
||||
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_localizations'));
|
||||
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_driver'));
|
||||
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_test'));
|
||||
await _runFlutterTest(path.join(flutterRoot, 'packages', 'fuchsia_remote_debug_protocol'));
|
||||
await _pubRunTest(path.join(flutterRoot, 'dev', 'bots'));
|
||||
await _pubRunTest(path.join(flutterRoot, 'dev', 'devicelab'));
|
||||
await _pubRunTest(path.join(flutterRoot, 'dev', 'snippets'));
|
||||
await _runFlutterTest(path.join(flutterRoot, 'dev', 'integration_tests', 'android_semantics_testing'));
|
||||
await _runFlutterTest(path.join(flutterRoot, 'dev', 'manual_tests'));
|
||||
await _runFlutterTest(path.join(flutterRoot, 'dev', 'tools', 'vitool'));
|
||||
await _runFlutterTest(path.join(flutterRoot, 'examples', 'hello_world'));
|
||||
await _runFlutterTest(path.join(flutterRoot, 'examples', 'layers'));
|
||||
await _runFlutterTest(path.join(flutterRoot, 'examples', 'stocks'));
|
||||
await _runFlutterTest(path.join(flutterRoot, 'examples', 'flutter_gallery'));
|
||||
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter'), options: <String>['--track-widget-creation'], tableData: bigqueryApi?.tabledata);
|
||||
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_localizations'), tableData: bigqueryApi?.tabledata);
|
||||
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_driver'), tableData: bigqueryApi?.tabledata);
|
||||
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_test'), tableData: bigqueryApi?.tabledata);
|
||||
await _runFlutterTest(path.join(flutterRoot, 'packages', 'fuchsia_remote_debug_protocol'), tableData: bigqueryApi?.tabledata);
|
||||
await _pubRunTest(path.join(flutterRoot, 'dev', 'bots'), tableData: bigqueryApi?.tabledata);
|
||||
await _pubRunTest(path.join(flutterRoot, 'dev', 'devicelab'), tableData: bigqueryApi?.tabledata);
|
||||
await _pubRunTest(path.join(flutterRoot, 'dev', 'snippets'), tableData: bigqueryApi?.tabledata);
|
||||
await _runFlutterTest(path.join(flutterRoot, 'dev', 'integration_tests', 'android_semantics_testing'), tableData: bigqueryApi?.tabledata);
|
||||
await _runFlutterTest(path.join(flutterRoot, 'dev', 'manual_tests'), tableData: bigqueryApi?.tabledata);
|
||||
await _runFlutterTest(path.join(flutterRoot, 'dev', 'tools', 'vitool'), tableData: bigqueryApi?.tabledata);
|
||||
await _runFlutterTest(path.join(flutterRoot, 'examples', 'hello_world'), tableData: bigqueryApi?.tabledata);
|
||||
await _runFlutterTest(path.join(flutterRoot, 'examples', 'layers'), tableData: bigqueryApi?.tabledata);
|
||||
await _runFlutterTest(path.join(flutterRoot, 'examples', 'stocks'), tableData: bigqueryApi?.tabledata);
|
||||
await _runFlutterTest(path.join(flutterRoot, 'examples', 'flutter_gallery'), tableData: bigqueryApi?.tabledata);
|
||||
// Regression test to ensure that code outside of package:flutter can run
|
||||
// with --track-widget-creation.
|
||||
await _runFlutterTest(path.join(flutterRoot, 'examples', 'flutter_gallery'), options: <String>['--track-widget-creation']);
|
||||
await _runFlutterTest(path.join(flutterRoot, 'examples', 'catalog'));
|
||||
await _runFlutterTest(path.join(flutterRoot, 'examples', 'flutter_gallery'), options: <String>['--track-widget-creation'], tableData: bigqueryApi?.tabledata);
|
||||
await _runFlutterTest(path.join(flutterRoot, 'examples', 'catalog'), tableData: bigqueryApi?.tabledata);
|
||||
// Smoke test for code generation.
|
||||
await _runFlutterTest(path.join(flutterRoot, 'dev', 'integration_tests', 'codegen'), tableData: bigqueryApi?.tabledata, environment: <String, String>{
|
||||
'FLUTTER_EXPERIMENTAL_BUILD': 'true',
|
||||
});
|
||||
|
||||
print('${bold}DONE: All tests successful.$reset');
|
||||
}
|
||||
@@ -277,12 +354,62 @@ Future<void> _runCoverage() async {
|
||||
print('${bold}DONE: Coverage collection successful.$reset');
|
||||
}
|
||||
|
||||
Future<void> _buildRunnerTest(
|
||||
String workingDirectory,
|
||||
String flutterRoot, {
|
||||
String testPath,
|
||||
bool enableFlutterToolAsserts = false,
|
||||
bq.TabledataResourceApi tableData,
|
||||
}) async {
|
||||
final List<String> args = <String>['run', 'build_runner', 'test', '--', useFlutterTestFormatter ? '-rjson' : '-rcompact', '-j1'];
|
||||
if (!hasColor) {
|
||||
args.add('--no-color');
|
||||
}
|
||||
if (testPath != null) {
|
||||
args.add(testPath);
|
||||
}
|
||||
final Map<String, String> pubEnvironment = <String, String>{
|
||||
'FLUTTER_ROOT': flutterRoot,
|
||||
};
|
||||
if (Directory(pubCache).existsSync()) {
|
||||
pubEnvironment['PUB_CACHE'] = pubCache;
|
||||
}
|
||||
if (enableFlutterToolAsserts) {
|
||||
// If an existing env variable exists append to it, but only if
|
||||
// it doesn't appear to already include enable-asserts.
|
||||
String toolsArgs = Platform.environment['FLUTTER_TOOL_ARGS'] ?? '';
|
||||
if (!toolsArgs.contains('--enable-asserts'))
|
||||
toolsArgs += ' --enable-asserts';
|
||||
pubEnvironment['FLUTTER_TOOL_ARGS'] = toolsArgs.trim();
|
||||
}
|
||||
|
||||
if (useFlutterTestFormatter) {
|
||||
final FlutterCompactFormatter formatter = FlutterCompactFormatter();
|
||||
final Stream<String> testOutput = runAndGetStdout(
|
||||
pub,
|
||||
args,
|
||||
workingDirectory: workingDirectory,
|
||||
environment: pubEnvironment,
|
||||
beforeExit: formatter.finish
|
||||
);
|
||||
await _processTestOutput(formatter, testOutput, tableData);
|
||||
} else {
|
||||
await runCommand(
|
||||
pub,
|
||||
args,
|
||||
workingDirectory:workingDirectory,
|
||||
environment:pubEnvironment,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _pubRunTest(
|
||||
String workingDirectory, {
|
||||
String testPath,
|
||||
bool enableFlutterToolAsserts = false
|
||||
}) {
|
||||
final List<String> args = <String>['run', 'test', '-rcompact', '-j1'];
|
||||
bool enableFlutterToolAsserts = false,
|
||||
bq.TabledataResourceApi tableData,
|
||||
}) async {
|
||||
final List<String> args = <String>['run', 'test', useFlutterTestFormatter ? '-rjson' : '-rcompact', '-j1'];
|
||||
if (!hasColor)
|
||||
args.add('--no-color');
|
||||
if (testPath != null)
|
||||
@@ -299,11 +426,150 @@ Future<void> _pubRunTest(
|
||||
toolsArgs += ' --enable-asserts';
|
||||
pubEnvironment['FLUTTER_TOOL_ARGS'] = toolsArgs.trim();
|
||||
}
|
||||
return runCommand(
|
||||
pub, args,
|
||||
workingDirectory: workingDirectory,
|
||||
environment: pubEnvironment,
|
||||
if (useFlutterTestFormatter) {
|
||||
final FlutterCompactFormatter formatter = FlutterCompactFormatter();
|
||||
final Stream<String> testOutput = runAndGetStdout(
|
||||
pub,
|
||||
args,
|
||||
workingDirectory: workingDirectory,
|
||||
beforeExit: formatter.finish,
|
||||
);
|
||||
await _processTestOutput(formatter, testOutput, tableData);
|
||||
} else {
|
||||
await runCommand(
|
||||
pub,
|
||||
args,
|
||||
workingDirectory:workingDirectory,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
enum CiProviders {
|
||||
cirrus,
|
||||
luci,
|
||||
}
|
||||
|
||||
CiProviders _getCiProvider() {
|
||||
if (Platform.environment['CIRRUS_CI'] == 'true') {
|
||||
return CiProviders.cirrus;
|
||||
}
|
||||
if (Platform.environment['LUCI_CONTEXT'] != null) {
|
||||
return CiProviders.luci;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
String _getCiProviderName() {
|
||||
switch(_getCiProvider()) {
|
||||
case CiProviders.cirrus:
|
||||
return 'cirrusci';
|
||||
case CiProviders.luci:
|
||||
return 'luci';
|
||||
}
|
||||
return 'unknown';
|
||||
}
|
||||
|
||||
int _getPrNumber() {
|
||||
switch(_getCiProvider()) {
|
||||
case CiProviders.cirrus:
|
||||
return Platform.environment['CIRRUS_PR'] == null
|
||||
? -1
|
||||
: int.tryParse(Platform.environment['CIRRUS_PR']);
|
||||
case CiProviders.luci:
|
||||
return -1; // LUCI doesn't know about this.
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
Future<String> _getAuthors() async {
|
||||
final String exe = Platform.isWindows ? '.exe' : '';
|
||||
final String author = await runAndGetStdout(
|
||||
'git$exe', <String>['log', _getGitHash(), '--pretty="%an <%ae>"'],
|
||||
workingDirectory: flutterRoot,
|
||||
).first;
|
||||
return author;
|
||||
}
|
||||
|
||||
String _getCiUrl() {
|
||||
switch(_getCiProvider()) {
|
||||
case CiProviders.cirrus:
|
||||
return 'https://cirrus-ci.com/task/${Platform.environment['CIRRUS_TASK_ID']}';
|
||||
case CiProviders.luci:
|
||||
return 'https://ci.chromium.org/p/flutter/g/framework/console'; // TODO(dnfield): can we get a direct link to the actual build?
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
String _getGitHash() {
|
||||
switch(_getCiProvider()) {
|
||||
case CiProviders.cirrus:
|
||||
return Platform.environment['CIRRUS_CHANGE_IN_REPO'];
|
||||
case CiProviders.luci:
|
||||
return 'HEAD'; // TODO(dnfield): Set this in the env for LUCI.
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
Future<void> _processTestOutput(
|
||||
FlutterCompactFormatter formatter,
|
||||
Stream<String> testOutput,
|
||||
bq.TabledataResourceApi tableData,
|
||||
) async {
|
||||
final Timer heartbeat = Timer.periodic(const Duration(seconds: 30), (Timer timer) {
|
||||
print('Processing...');
|
||||
});
|
||||
|
||||
await testOutput.forEach(formatter.processRawOutput);
|
||||
heartbeat.cancel();
|
||||
formatter.finish();
|
||||
if (tableData == null || formatter.tests.isEmpty) {
|
||||
return;
|
||||
}
|
||||
final bq.TableDataInsertAllRequest request = bq.TableDataInsertAllRequest();
|
||||
final String authors = await _getAuthors();
|
||||
request.rows = List<bq.TableDataInsertAllRequestRows>.from(
|
||||
formatter.tests.map<bq.TableDataInsertAllRequestRows>((TestResult result) =>
|
||||
bq.TableDataInsertAllRequestRows.fromJson(<String, dynamic> {
|
||||
'json': <String, dynamic>{
|
||||
'source': <String, dynamic>{
|
||||
'provider': _getCiProviderName(),
|
||||
'url': _getCiUrl(),
|
||||
'platform': <String, dynamic>{
|
||||
'os': Platform.operatingSystem,
|
||||
'version': Platform.operatingSystemVersion,
|
||||
},
|
||||
},
|
||||
'test': <String, dynamic>{
|
||||
'name': result.name,
|
||||
'result': result.status.toString(),
|
||||
'file': result.path,
|
||||
'line': result.line,
|
||||
'column': result.column,
|
||||
'time': result.totalTime,
|
||||
},
|
||||
'git': <String, dynamic>{
|
||||
'author': authors,
|
||||
'pull_request': _getPrNumber(),
|
||||
'commit': _getGitHash(),
|
||||
'organization': 'flutter',
|
||||
'repository': 'flutter',
|
||||
},
|
||||
'error': result.status != TestStatus.failed ? null : <String, dynamic>{
|
||||
'message': result.errorMessage,
|
||||
'stack_trace': result.stackTrace,
|
||||
},
|
||||
'information': result.messages,
|
||||
},
|
||||
}),
|
||||
),
|
||||
growable: false,
|
||||
);
|
||||
final bq.TableDataInsertAllResponse response = await tableData.insertAll(request, 'flutter-infra', 'tests', 'ci');
|
||||
if (response.insertErrors != null && response.insertErrors.isNotEmpty) {
|
||||
print('${red}BigQuery insert errors:');
|
||||
print(response.toJson());
|
||||
print(reset);
|
||||
}
|
||||
}
|
||||
|
||||
class EvalResult {
|
||||
@@ -325,10 +591,18 @@ Future<void> _runFlutterTest(String workingDirectory, {
|
||||
List<String> options = const <String>[],
|
||||
bool skip = false,
|
||||
Duration timeout = _kLongTimeout,
|
||||
}) {
|
||||
bq.TabledataResourceApi tableData,
|
||||
Map<String, String> environment,
|
||||
}) async {
|
||||
final List<String> args = <String>['test']..addAll(options);
|
||||
if (flutterTestArgs != null && flutterTestArgs.isNotEmpty)
|
||||
args.addAll(flutterTestArgs);
|
||||
|
||||
final bool shouldProcessOutput = useFlutterTestFormatter && !expectFailure && !options.contains('--coverage');
|
||||
if (shouldProcessOutput) {
|
||||
args.add('--machine');
|
||||
}
|
||||
|
||||
if (script != null) {
|
||||
final String fullScriptPath = path.join(workingDirectory, script);
|
||||
if (!FileSystemEntity.isFileSync(fullScriptPath)) {
|
||||
@@ -343,13 +617,38 @@ Future<void> _runFlutterTest(String workingDirectory, {
|
||||
}
|
||||
args.add(script);
|
||||
}
|
||||
return runCommand(flutter, args,
|
||||
if (!shouldProcessOutput) {
|
||||
return runCommand(flutter, args,
|
||||
workingDirectory: workingDirectory,
|
||||
expectNonZeroExit: expectFailure,
|
||||
printOutput: printOutput,
|
||||
skip: skip,
|
||||
timeout: timeout,
|
||||
environment: environment,
|
||||
);
|
||||
}
|
||||
|
||||
if (useFlutterTestFormatter) {
|
||||
final FlutterCompactFormatter formatter = FlutterCompactFormatter();
|
||||
final Stream<String> testOutput = runAndGetStdout(
|
||||
flutter,
|
||||
args,
|
||||
workingDirectory: workingDirectory,
|
||||
expectNonZeroExit: expectFailure,
|
||||
printOutput: printOutput,
|
||||
skip: skip,
|
||||
timeout: timeout,
|
||||
beforeExit: formatter.finish,
|
||||
environment: environment,
|
||||
);
|
||||
await _processTestOutput(formatter, testOutput, tableData);
|
||||
} else {
|
||||
await runCommand(
|
||||
flutter,
|
||||
args,
|
||||
workingDirectory: workingDirectory,
|
||||
expectNonZeroExit: expectFailure,
|
||||
timeout: timeout,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _verifyVersion(String filename) async {
|
||||
@@ -374,3 +673,51 @@ Future<void> _verifyVersion(String filename) async {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _runIntegrationTests() async {
|
||||
print('Platform env vars:');
|
||||
|
||||
await _runDevicelabTest('dartdocs');
|
||||
|
||||
if (Platform.isLinux) {
|
||||
await _runDevicelabTest('flutter_create_offline_test_linux');
|
||||
} else if (Platform.isWindows) {
|
||||
await _runDevicelabTest('flutter_create_offline_test_windows');
|
||||
} else if (Platform.isMacOS) {
|
||||
await _runDevicelabTest('flutter_create_offline_test_mac');
|
||||
await _runDevicelabTest('module_test_ios');
|
||||
}
|
||||
await _integrationTestsAndroidSdk();
|
||||
}
|
||||
|
||||
Future<void> _runDevicelabTest(String testName, {Map<String, String> env}) async {
|
||||
await runCommand(
|
||||
dart,
|
||||
<String>['bin/run.dart', '-t', testName],
|
||||
workingDirectory: path.join(flutterRoot, 'dev', 'devicelab'),
|
||||
environment: env,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _integrationTestsAndroidSdk() async {
|
||||
final String androidSdkRoot = (Platform.environment['ANDROID_HOME']?.isEmpty ?? true)
|
||||
? Platform.environment['ANDROID_SDK_ROOT']
|
||||
: Platform.environment['ANDROID_HOME'];
|
||||
if (androidSdkRoot == null || androidSdkRoot.isEmpty) {
|
||||
print('No Android SDK detected, skipping Android Integration Tests');
|
||||
return;
|
||||
}
|
||||
|
||||
final Map<String, String> env = <String, String> {
|
||||
'ANDROID_HOME': androidSdkRoot,
|
||||
'ANDROID_SDK_ROOT': androidSdkRoot,
|
||||
};
|
||||
|
||||
// TODO(dnfield): gradlew is crashing on the cirrus image and it's not clear why.
|
||||
if (!Platform.isWindows) {
|
||||
await _runDevicelabTest('gradle_plugin_test', env: env);
|
||||
await _runDevicelabTest('module_test', env: env);
|
||||
}
|
||||
// note: this also covers plugin_test_win as long as Windows has an Android SDK available.
|
||||
await _runDevicelabTest('plugin_test', env: env);
|
||||
}
|
||||
|
||||
@@ -18,8 +18,7 @@
|
||||
/// blabla 0.0, the penzance blabla is blabla not blabla at all. Bla the blabla
|
||||
/// 1.0, the blabla is blabla blabla blabla an blabla blabla.
|
||||
///
|
||||
/// ### Sample code
|
||||
///
|
||||
/// {@tool sample}
|
||||
/// Bla blabla blabla some [Text] when the `_blabla` blabla blabla is true, and
|
||||
/// blabla it when it is blabla:
|
||||
///
|
||||
@@ -29,9 +28,9 @@
|
||||
/// child: const Text('Poor wandering ones!'),
|
||||
/// )
|
||||
/// ```
|
||||
/// {@end-tool}
|
||||
///
|
||||
/// ## Sample code
|
||||
///
|
||||
/// {@tool sample}
|
||||
/// Bla blabla blabla some [Text] when the `_blabla` blabla blabla is true, and
|
||||
/// blabla finale blabla:
|
||||
///
|
||||
@@ -41,3 +40,4 @@
|
||||
/// child: const Text('Poor wandering ones!'),
|
||||
/// )
|
||||
/// ```
|
||||
/// {@end-tool}
|
||||
|
||||
@@ -17,9 +17,9 @@ void main() {
|
||||
..removeWhere((String line) => line.startsWith('Analyzer output:'));
|
||||
expect(process.exitCode, isNot(equals(0)));
|
||||
expect(stderrLines, <String>[
|
||||
'known_broken_documentation.dart:27:9: new Opacity(',
|
||||
'known_broken_documentation.dart:26:9: new Opacity(',
|
||||
'>>> Unnecessary new keyword (unnecessary_new)',
|
||||
'known_broken_documentation.dart:39:9: new Opacity(',
|
||||
'known_broken_documentation.dart:38:9: new Opacity(',
|
||||
'>>> Unnecessary new keyword (unnecessary_new)',
|
||||
'',
|
||||
'Found 1 sample code errors.',
|
||||
|
||||
@@ -103,7 +103,7 @@ class FakeProcessManager extends Mock implements ProcessManager {
|
||||
when(runSync(
|
||||
any,
|
||||
environment: anyNamed('environment'),
|
||||
workingDirectory: anyNamed('workingDirectory')
|
||||
workingDirectory: anyNamed('workingDirectory'),
|
||||
)).thenAnswer(_nextResultSync);
|
||||
|
||||
when(runSync(any)).thenAnswer(_nextResultSync);
|
||||
|
||||
@@ -27,10 +27,10 @@ void main() {
|
||||
test('start works', () async {
|
||||
final Map<String, List<ProcessResult>> calls = <String, List<ProcessResult>>{
|
||||
'gsutil acl get gs://flutter_infra/releases/releases.json': <ProcessResult>[
|
||||
ProcessResult(0, 0, 'output1', '')
|
||||
ProcessResult(0, 0, 'output1', ''),
|
||||
],
|
||||
'gsutil cat gs://flutter_infra/releases/releases.json': <ProcessResult>[
|
||||
ProcessResult(0, 0, 'output2', '')
|
||||
ProcessResult(0, 0, 'output2', ''),
|
||||
],
|
||||
};
|
||||
processManager.fakeResults = calls;
|
||||
@@ -49,10 +49,10 @@ void main() {
|
||||
test('run works', () async {
|
||||
final Map<String, List<ProcessResult>> calls = <String, List<ProcessResult>>{
|
||||
'gsutil acl get gs://flutter_infra/releases/releases.json': <ProcessResult>[
|
||||
ProcessResult(0, 0, 'output1', '')
|
||||
ProcessResult(0, 0, 'output1', ''),
|
||||
],
|
||||
'gsutil cat gs://flutter_infra/releases/releases.json': <ProcessResult>[
|
||||
ProcessResult(0, 0, 'output2', '')
|
||||
ProcessResult(0, 0, 'output2', ''),
|
||||
],
|
||||
};
|
||||
processManager.fakeResults = calls;
|
||||
@@ -66,10 +66,10 @@ void main() {
|
||||
test('runSync works', () async {
|
||||
final Map<String, List<ProcessResult>> calls = <String, List<ProcessResult>>{
|
||||
'gsutil acl get gs://flutter_infra/releases/releases.json': <ProcessResult>[
|
||||
ProcessResult(0, 0, 'output1', '')
|
||||
ProcessResult(0, 0, 'output1', ''),
|
||||
],
|
||||
'gsutil cat gs://flutter_infra/releases/releases.json': <ProcessResult>[
|
||||
ProcessResult(0, 0, 'output2', '')
|
||||
ProcessResult(0, 0, 'output2', ''),
|
||||
],
|
||||
};
|
||||
processManager.fakeResults = calls;
|
||||
@@ -83,10 +83,10 @@ void main() {
|
||||
test('captures stdin', () async {
|
||||
final Map<String, List<ProcessResult>> calls = <String, List<ProcessResult>>{
|
||||
'gsutil acl get gs://flutter_infra/releases/releases.json': <ProcessResult>[
|
||||
ProcessResult(0, 0, 'output1', '')
|
||||
ProcessResult(0, 0, 'output1', ''),
|
||||
],
|
||||
'gsutil cat gs://flutter_infra/releases/releases.json': <ProcessResult>[
|
||||
ProcessResult(0, 0, 'output2', '')
|
||||
ProcessResult(0, 0, 'output2', ''),
|
||||
],
|
||||
};
|
||||
processManager.fakeResults = calls;
|
||||
|
||||
@@ -25,10 +25,10 @@ void main() {
|
||||
expectAsync1((List<String> commandLine) async {
|
||||
return processRunner.runProcess(commandLine);
|
||||
})(<String>['this_executable_better_not_exist_2857632534321']),
|
||||
throwsA(isInstanceOf<ProcessRunnerException>()));
|
||||
throwsA(isInstanceOf<PreparePackageException>()));
|
||||
try {
|
||||
await processRunner.runProcess(<String>['this_executable_better_not_exist_2857632534321']);
|
||||
} on ProcessRunnerException catch (e) {
|
||||
} on PreparePackageException catch (e) {
|
||||
expect(
|
||||
e.message,
|
||||
contains('Invalid argument(s): Cannot find executable for this_executable_better_not_exist_2857632534321.'),
|
||||
@@ -64,7 +64,7 @@ void main() {
|
||||
expectAsync1((List<String> commandLine) async {
|
||||
return processRunner.runProcess(commandLine);
|
||||
})(<String>['echo', 'test']),
|
||||
throwsA(isInstanceOf<ProcessRunnerException>()));
|
||||
throwsA(isInstanceOf<PreparePackageException>()));
|
||||
});
|
||||
});
|
||||
group('ArchiveCreator for $platformName', () {
|
||||
@@ -110,7 +110,7 @@ void main() {
|
||||
'git clone -b dev https://chromium.googlesource.com/external/github.com/flutter/flutter': null,
|
||||
'git reset --hard $testRef': null,
|
||||
'git remote set-url origin https://github.com/flutter/flutter.git': null,
|
||||
'git describe --tags --abbrev=0': <ProcessResult>[ProcessResult(0, 0, 'v1.2.3', '')],
|
||||
'git describe --tags --exact-match $testRef': <ProcessResult>[ProcessResult(0, 0, 'v1.2.3', '')],
|
||||
};
|
||||
if (platform.isWindows) {
|
||||
calls['7za x ${path.join(tempDir.path, 'mingit.zip')}'] = null;
|
||||
@@ -153,7 +153,7 @@ void main() {
|
||||
'git clone -b dev https://chromium.googlesource.com/external/github.com/flutter/flutter': null,
|
||||
'git reset --hard $testRef': null,
|
||||
'git remote set-url origin https://github.com/flutter/flutter.git': null,
|
||||
'git describe --tags --abbrev=0': <ProcessResult>[ProcessResult(0, 0, 'v1.2.3', '')],
|
||||
'git describe --tags --exact-match $testRef': <ProcessResult>[ProcessResult(0, 0, 'v1.2.3', '')],
|
||||
};
|
||||
if (platform.isWindows) {
|
||||
calls['7za x ${path.join(tempDir.path, 'mingit.zip')}'] = null;
|
||||
@@ -201,7 +201,54 @@ void main() {
|
||||
};
|
||||
processManager.fakeResults = calls;
|
||||
expect(expectAsync0(creator.initializeRepo),
|
||||
throwsA(isInstanceOf<ProcessRunnerException>()));
|
||||
throwsA(isInstanceOf<PreparePackageException>()));
|
||||
});
|
||||
|
||||
test('non-strict mode calls the right commands', () async {
|
||||
final String createBase = path.join(tempDir.absolute.path, 'create_');
|
||||
final Map<String, List<ProcessResult>> calls = <String, List<ProcessResult>>{
|
||||
'git clone -b dev https://chromium.googlesource.com/external/github.com/flutter/flutter': null,
|
||||
'git reset --hard $testRef': null,
|
||||
'git remote set-url origin https://github.com/flutter/flutter.git': null,
|
||||
'git describe --tags --abbrev=0 $testRef': <ProcessResult>[ProcessResult(0, 0, 'v1.2.3', '')],
|
||||
};
|
||||
if (platform.isWindows) {
|
||||
calls['7za x ${path.join(tempDir.path, 'mingit.zip')}'] = null;
|
||||
}
|
||||
calls.addAll(<String, List<ProcessResult>>{
|
||||
'$flutter doctor': null,
|
||||
'$flutter update-packages': null,
|
||||
'$flutter precache': null,
|
||||
'$flutter ide-config': null,
|
||||
'$flutter create --template=app ${createBase}app': null,
|
||||
'$flutter create --template=package ${createBase}package': null,
|
||||
'$flutter create --template=plugin ${createBase}plugin': null,
|
||||
'git clean -f -X **/.packages': null,
|
||||
});
|
||||
final String archiveName = path.join(tempDir.absolute.path,
|
||||
'flutter_${platformName}_v1.2.3-dev${platform.isLinux ? '.tar.xz' : '.zip'}');
|
||||
if (platform.isWindows) {
|
||||
calls['7za a -tzip -mx=9 $archiveName flutter'] = null;
|
||||
} else if (platform.isMacOS) {
|
||||
calls['zip -r -9 $archiveName flutter'] = null;
|
||||
} else if (platform.isLinux) {
|
||||
calls['tar cJf $archiveName flutter'] = null;
|
||||
}
|
||||
processManager.fakeResults = calls;
|
||||
creator = ArchiveCreator(
|
||||
tempDir,
|
||||
tempDir,
|
||||
testRef,
|
||||
Branch.dev,
|
||||
strict: false,
|
||||
processManager: processManager,
|
||||
subprocessOutput: false,
|
||||
platform: platform,
|
||||
httpReader: fakeHttpReader,
|
||||
);
|
||||
await creator.initializeRepo();
|
||||
await creator.createArchive();
|
||||
processManager.verifyCalls(calls.keys.toList());
|
||||
});
|
||||
});
|
||||
|
||||
@@ -238,26 +285,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 +342,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"'));
|
||||
|
||||
20
dev/devicelab/bin/tasks/codegen_integration_linux.dart
Normal file
20
dev/devicelab/bin/tasks/codegen_integration_linux.dart
Normal file
@@ -0,0 +1,20 @@
|
||||
// Copyright 2019 The Chromium 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:path/path.dart' as path;
|
||||
|
||||
import 'package:flutter_devicelab/framework/adb.dart';
|
||||
import 'package:flutter_devicelab/framework/framework.dart';
|
||||
import 'package:flutter_devicelab/framework/utils.dart';
|
||||
import 'package:flutter_devicelab/tasks/integration_tests.dart';
|
||||
|
||||
final Directory codegenAppPath = dir(path.join(flutterDirectory.path, 'dev/integration_tests/codegen'));
|
||||
|
||||
Future<void> main() async {
|
||||
deviceOperatingSystem = DeviceOperatingSystem.android;
|
||||
await task(createCodegenerationIntegrationTest());
|
||||
}
|
||||
20
dev/devicelab/bin/tasks/codegen_integration_mac.dart
Normal file
20
dev/devicelab/bin/tasks/codegen_integration_mac.dart
Normal file
@@ -0,0 +1,20 @@
|
||||
// Copyright 2019 The Chromium 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:path/path.dart' as path;
|
||||
|
||||
import 'package:flutter_devicelab/framework/adb.dart';
|
||||
import 'package:flutter_devicelab/framework/framework.dart';
|
||||
import 'package:flutter_devicelab/framework/utils.dart';
|
||||
import 'package:flutter_devicelab/tasks/integration_tests.dart';
|
||||
|
||||
final Directory codegenAppPath = dir(path.join(flutterDirectory.path, 'dev/integration_tests/codegen'));
|
||||
|
||||
Future<void> main() async {
|
||||
deviceOperatingSystem = DeviceOperatingSystem.ios;
|
||||
await task(createCodegenerationIntegrationTest());
|
||||
}
|
||||
20
dev/devicelab/bin/tasks/codegen_integration_win.dart
Normal file
20
dev/devicelab/bin/tasks/codegen_integration_win.dart
Normal file
@@ -0,0 +1,20 @@
|
||||
// Copyright 2019 The Chromium 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:path/path.dart' as path;
|
||||
|
||||
import 'package:flutter_devicelab/framework/adb.dart';
|
||||
import 'package:flutter_devicelab/framework/framework.dart';
|
||||
import 'package:flutter_devicelab/framework/utils.dart';
|
||||
import 'package:flutter_devicelab/tasks/integration_tests.dart';
|
||||
|
||||
final Directory codegenAppPath = dir(path.join(flutterDirectory.path, 'dev/integration_tests/codegen'));
|
||||
|
||||
Future<void> main() async {
|
||||
deviceOperatingSystem = DeviceOperatingSystem.android;
|
||||
await task(createCodegenerationIntegrationTest());
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// Copyright 2019 The Chromium 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 'package:flutter_devicelab/tasks/perf_tests.dart';
|
||||
import 'package:flutter_devicelab/framework/adb.dart';
|
||||
import 'package:flutter_devicelab/framework/framework.dart';
|
||||
|
||||
Future<void> main() async {
|
||||
deviceOperatingSystem = DeviceOperatingSystem.android;
|
||||
await task(createCubicBezierPerfTest());
|
||||
}
|
||||
@@ -41,7 +41,7 @@ Future<TaskResult> createFlutterRunTask() async {
|
||||
startProcess(
|
||||
path.join(flutterDirectory.path, 'bin', 'flutter'),
|
||||
<String>['run']..addAll(options),
|
||||
environment: null
|
||||
environment: null,
|
||||
);
|
||||
final Completer<void> finished = Completer<void>();
|
||||
final StreamSubscription<void> subscription = device.logcat.listen((String line) {
|
||||
|
||||
@@ -272,11 +272,14 @@ Future<ProcessResult> _resultOfGradleTask({String workingDirectory, String task,
|
||||
if (options != null) {
|
||||
args.addAll(options);
|
||||
}
|
||||
final String gradle = Platform.isWindows ? 'gradlew.bat' : './gradlew';
|
||||
print('Running Gradle: ${path.join(workingDirectory, gradle)} ${args.join(' ')}');
|
||||
print(File(path.join(workingDirectory, gradle)).readAsStringSync());
|
||||
return Process.run(
|
||||
'./gradlew',
|
||||
gradle,
|
||||
args,
|
||||
workingDirectory: workingDirectory,
|
||||
environment: <String, String>{ 'JAVA_HOME': javaHome }
|
||||
environment: <String, String>{ 'JAVA_HOME': javaHome },
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,9 @@ import 'package:flutter_devicelab/framework/framework.dart';
|
||||
import 'package:flutter_devicelab/framework/utils.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
final String gradlew = Platform.isWindows ? 'gradlew.bat' : 'gradlew';
|
||||
final String gradlewExecutable = Platform.isWindows ? gradlew : './$gradlew';
|
||||
|
||||
/// Tests that the Flutter module project template works and supports
|
||||
/// adding Flutter to an existing Android app.
|
||||
Future<void> main() async {
|
||||
@@ -53,7 +56,7 @@ Future<void> main() async {
|
||||
|
||||
await inDirectory(Directory(path.join(projectDir.path, '.android')), () async {
|
||||
await exec(
|
||||
'./gradlew',
|
||||
gradlewExecutable,
|
||||
<String>['flutter:assembleDebug'],
|
||||
environment: <String, String>{ 'JAVA_HOME': javaHome },
|
||||
);
|
||||
@@ -143,7 +146,7 @@ Future<void> main() async {
|
||||
hostApp,
|
||||
);
|
||||
copy(
|
||||
File(path.join(projectDir.path, '.android', 'gradlew')),
|
||||
File(path.join(projectDir.path, '.android', gradlew)),
|
||||
hostApp,
|
||||
);
|
||||
copy(
|
||||
@@ -152,8 +155,10 @@ Future<void> main() async {
|
||||
);
|
||||
|
||||
await inDirectory(hostApp, () async {
|
||||
await exec('chmod', <String>['+x', 'gradlew']);
|
||||
await exec('./gradlew',
|
||||
if (!Platform.isWindows) {
|
||||
await exec('chmod', <String>['+x', 'gradlew']);
|
||||
}
|
||||
await exec(gradlewExecutable,
|
||||
<String>['app:assembleDebug'],
|
||||
environment: <String, String>{ 'JAVA_HOME': javaHome },
|
||||
);
|
||||
|
||||
@@ -26,7 +26,7 @@ Future<void> main() async {
|
||||
'--org',
|
||||
'io.flutter.devicelab',
|
||||
'--template=module',
|
||||
'hello'
|
||||
'hello',
|
||||
],
|
||||
);
|
||||
});
|
||||
@@ -37,7 +37,7 @@ Future<void> main() async {
|
||||
await inDirectory(projectDir, () async {
|
||||
await flutter(
|
||||
'build',
|
||||
options: <String>['ios'],
|
||||
options: <String>['ios', '--no-codesign'],
|
||||
);
|
||||
});
|
||||
|
||||
@@ -80,7 +80,7 @@ Future<void> main() async {
|
||||
await inDirectory(projectDir, () async {
|
||||
await flutter(
|
||||
'build',
|
||||
options: <String>['ios'],
|
||||
options: <String>['ios', '--no-codesign'],
|
||||
);
|
||||
});
|
||||
|
||||
@@ -116,7 +116,7 @@ Future<void> main() async {
|
||||
await inDirectory(projectDir, () async {
|
||||
await flutter(
|
||||
'build',
|
||||
options: <String>['ios'],
|
||||
options: <String>['ios', '--no-codesign'],
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ void main() {
|
||||
final Map<String, dynamic> req = <String, dynamic>{
|
||||
'id': requestId,
|
||||
'method': method,
|
||||
'params': params
|
||||
'params': params,
|
||||
};
|
||||
final String jsonEncoded = json.encode(<Map<String, dynamic>>[req]);
|
||||
print('run:stdin: $jsonEncoded');
|
||||
|
||||
14
dev/devicelab/bin/tasks/run_without_leak_linux.dart
Normal file
14
dev/devicelab/bin/tasks/run_without_leak_linux.dart
Normal file
@@ -0,0 +1,14 @@
|
||||
// Copyright (c) 2019 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 'package:flutter_devicelab/framework/utils.dart';
|
||||
import 'package:flutter_devicelab/tasks/run_without_leak.dart';
|
||||
import 'package:flutter_devicelab/framework/framework.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
Future<void> main() async {
|
||||
await task(createRunWithoutLeakTest(path.join(flutterDirectory.path, 'examples', 'hello_world')));
|
||||
}
|
||||
14
dev/devicelab/bin/tasks/run_without_leak_mac.dart
Normal file
14
dev/devicelab/bin/tasks/run_without_leak_mac.dart
Normal file
@@ -0,0 +1,14 @@
|
||||
// Copyright (c) 2019 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 'package:flutter_devicelab/framework/utils.dart';
|
||||
import 'package:flutter_devicelab/tasks/run_without_leak.dart';
|
||||
import 'package:flutter_devicelab/framework/framework.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
Future<void> main() async {
|
||||
await task(createRunWithoutLeakTest(path.join(flutterDirectory.path, 'examples', 'hello_world')));
|
||||
}
|
||||
14
dev/devicelab/bin/tasks/run_without_leak_win.dart
Normal file
14
dev/devicelab/bin/tasks/run_without_leak_win.dart
Normal file
@@ -0,0 +1,14 @@
|
||||
// Copyright (c) 2019 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 'package:flutter_devicelab/framework/utils.dart';
|
||||
import 'package:flutter_devicelab/tasks/run_without_leak.dart';
|
||||
import 'package:flutter_devicelab/framework/framework.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
Future<void> main() async {
|
||||
await task(createRunWithoutLeakTest(path.join(flutterDirectory.path, 'examples', 'hello_world')));
|
||||
}
|
||||
@@ -296,7 +296,16 @@ class AndroidDevice implements Device {
|
||||
stream = StreamController<String>(
|
||||
onListen: () async {
|
||||
await adb(<String>['logcat', '--clear']);
|
||||
final Process process = await startProcess(adbPath, <String>['-s', deviceId, 'logcat']);
|
||||
final Process process = await startProcess(
|
||||
adbPath,
|
||||
// Make logcat less chatty by filtering down to just ActivityManager
|
||||
// (to let us know when app starts), flutter (needed by tests to see
|
||||
// log output), and fatal messages (hopefully catches tombstones).
|
||||
// For local testing, this can just be:
|
||||
// <String>['-s', deviceId, 'logcat']
|
||||
// to view the whole log, or just run logcat alongside this.
|
||||
<String>['-s', deviceId, 'logcat', 'ActivityManager:I', 'flutter:V', '*:F'],
|
||||
);
|
||||
process.stdout
|
||||
.transform<String>(utf8.decoder)
|
||||
.transform<String>(const LineSplitter())
|
||||
|
||||
@@ -11,6 +11,7 @@ import 'dart:isolate';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:stack_trace/stack_trace.dart';
|
||||
|
||||
import 'running_processes.dart';
|
||||
import 'utils.dart';
|
||||
|
||||
/// Maximum amount of time a single task is allowed to take to run.
|
||||
@@ -82,7 +83,35 @@ class _TaskRunner {
|
||||
try {
|
||||
_taskStarted = true;
|
||||
print('Running task.');
|
||||
final TaskResult result = await _performTask().timeout(taskTimeout);
|
||||
final String exe = Platform.isWindows ? '.exe' : '';
|
||||
section('Checking running Dart$exe processes');
|
||||
final Set<RunningProcessInfo> beforeRunningDartInstances = await getRunningProcesses(
|
||||
processName: 'dart$exe',
|
||||
).toSet();
|
||||
beforeRunningDartInstances.forEach(print);
|
||||
|
||||
TaskResult result = await _performTask().timeout(taskTimeout);
|
||||
|
||||
section('Checking running Dart$exe processes after task...');
|
||||
final List<RunningProcessInfo> afterRunningDartInstances = await getRunningProcesses(
|
||||
processName: 'dart$exe',
|
||||
).toList();
|
||||
for (final RunningProcessInfo info in afterRunningDartInstances) {
|
||||
if (!beforeRunningDartInstances.contains(info)) {
|
||||
print('$info was leaked by this test.');
|
||||
// TODO(dnfield): remove this special casing after https://github.com/flutter/flutter/issues/29141 is resolved.
|
||||
if (result is TaskResultCheckProcesses) {
|
||||
result = TaskResult.failure('This test leaked dart processes');
|
||||
}
|
||||
final bool killed = await killProcess(info.pid);
|
||||
if (!killed) {
|
||||
print('Failed to kill process ${info.pid}.');
|
||||
} else {
|
||||
print('Killed process id ${info.pid}.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_completer.complete(result);
|
||||
return result;
|
||||
} on TimeoutException catch (_) {
|
||||
@@ -231,3 +260,7 @@ class TaskResult {
|
||||
return json;
|
||||
}
|
||||
}
|
||||
|
||||
class TaskResultCheckProcesses extends TaskResult {
|
||||
TaskResultCheckProcesses() : super.success(null);
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ Future<void> _patchXcconfigFilesIfNotPatched(String flutterProjectPath) async {
|
||||
final List<File> xcconfigFiles = <File>[
|
||||
_fs.file(path.join(flutterProjectPath, 'ios/Flutter/Flutter.xcconfig')),
|
||||
_fs.file(path.join(flutterProjectPath, 'ios/Flutter/Debug.xcconfig')),
|
||||
_fs.file(path.join(flutterProjectPath, 'ios/Flutter/Release.xcconfig'))
|
||||
_fs.file(path.join(flutterProjectPath, 'ios/Flutter/Release.xcconfig')),
|
||||
];
|
||||
|
||||
bool xcconfigFileExists = false;
|
||||
|
||||
261
dev/devicelab/lib/framework/running_processes.dart
Normal file
261
dev/devicelab/lib/framework/running_processes.dart
Normal file
@@ -0,0 +1,261 @@
|
||||
// Copyright 2019 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:io';
|
||||
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:process/process.dart';
|
||||
|
||||
@immutable
|
||||
class RunningProcessInfo {
|
||||
const RunningProcessInfo(this.pid, this.creationDate, this.commandLine)
|
||||
: assert(pid != null),
|
||||
assert(commandLine != null);
|
||||
|
||||
final String commandLine;
|
||||
final int pid;
|
||||
final DateTime creationDate;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is RunningProcessInfo &&
|
||||
other.pid == pid &&
|
||||
other.commandLine == commandLine &&
|
||||
other.creationDate == creationDate;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
// TODO(dnfield): Replace this when Object.hashValues lands.
|
||||
int hash = 17;
|
||||
if (pid != null) {
|
||||
hash = hash * 23 + pid.hashCode;
|
||||
}
|
||||
if (commandLine != null) {
|
||||
hash = hash * 23 + commandLine.hashCode;
|
||||
}
|
||||
if (creationDate != null) {
|
||||
hash = hash * 23 + creationDate.hashCode;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'RunningProcesses{pid: $pid, commandLine: $commandLine, creationDate: $creationDate}';
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> killProcess(int pid, {ProcessManager processManager}) async {
|
||||
assert(pid != null, 'Must specify a pid to kill');
|
||||
processManager ??= const LocalProcessManager();
|
||||
ProcessResult result;
|
||||
if (Platform.isWindows) {
|
||||
result = await processManager.run(<String>[
|
||||
'taskkill.exe',
|
||||
'/pid',
|
||||
pid.toString(),
|
||||
'/f',
|
||||
]);
|
||||
} else {
|
||||
result = await processManager.run(<String>[
|
||||
'kill',
|
||||
'-9',
|
||||
pid.toString(),
|
||||
]);
|
||||
}
|
||||
return result.exitCode == 0;
|
||||
}
|
||||
|
||||
Stream<RunningProcessInfo> getRunningProcesses({
|
||||
String processName,
|
||||
ProcessManager processManager,
|
||||
}) {
|
||||
processManager ??= const LocalProcessManager();
|
||||
if (Platform.isWindows) {
|
||||
return windowsRunningProcesses(processName);
|
||||
}
|
||||
return posixRunningProcesses(processName, processManager);
|
||||
}
|
||||
|
||||
@visibleForTesting
|
||||
Stream<RunningProcessInfo> windowsRunningProcesses(String processName) async* {
|
||||
// PowerShell script to get the command line arguments and create time of
|
||||
// a process.
|
||||
// See: https://docs.microsoft.com/en-us/windows/desktop/cimwin32prov/win32-process
|
||||
final String script = processName != null
|
||||
? '"Get-CimInstance Win32_Process -Filter \\\"name=\'$processName\'\\\" | Select-Object ProcessId,CreationDate,CommandLine | Format-Table -AutoSize | Out-String -Width 4096"'
|
||||
: '"Get-CimInstance Win32_Process | Select-Object ProcessId,CreationDate,CommandLine | Format-Table -AutoSize | Out-String -Width 4096"';
|
||||
// Unfortunately, there doesn't seem to be a good way to get ProcessManager to
|
||||
// run this. May be a bug in Dart.
|
||||
// TODO(dnfield): fix this when https://github.com/dart-lang/sdk/issues/36175 is resolved.
|
||||
final ProcessResult result = await Process.run(
|
||||
'powershell -command $script',
|
||||
<String>[],
|
||||
);
|
||||
if (result.exitCode != 0) {
|
||||
print('Could not list processes!');
|
||||
print(result.stderr);
|
||||
print(result.stdout);
|
||||
return;
|
||||
}
|
||||
for (RunningProcessInfo info in processPowershellOutput(result.stdout)) {
|
||||
yield info;
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses the output of the PowerShell script from [windowsRunningProcesses].
|
||||
///
|
||||
/// E.g.:
|
||||
/// ProcessId CreationDate CommandLine
|
||||
/// --------- ------------ -----------
|
||||
/// 2904 3/11/2019 11:01:54 AM "C:\Program Files\Android\Android Studio\jre\bin\java.exe" -Xmx1536M -Dfile.encoding=windows-1252 -Duser.country=US -Duser.language=en -Duser.variant -cp C:\Users\win1\.gradle\wrapper\dists\gradle-4.10.2-all\9fahxiiecdb76a5g3aw9oi8rv\gradle-4.10.2\lib\gradle-launcher-4.10.2.jar org.gradle.launcher.daemon.bootstrap.GradleDaemon 4.10.2
|
||||
@visibleForTesting
|
||||
Iterable<RunningProcessInfo> processPowershellOutput(String output) sync* {
|
||||
if (output == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int processIdHeaderSize = 'ProcessId'.length;
|
||||
const int creationDateHeaderStart = processIdHeaderSize + 1;
|
||||
int creationDateHeaderEnd;
|
||||
int commandLineHeaderStart;
|
||||
bool inTableBody = false;
|
||||
for (String line in output.split('\n')) {
|
||||
if (line.startsWith('ProcessId')) {
|
||||
commandLineHeaderStart = line.indexOf('CommandLine');
|
||||
creationDateHeaderEnd = commandLineHeaderStart - 1;
|
||||
}
|
||||
if (line.startsWith('--------- ------------')) {
|
||||
inTableBody = true;
|
||||
continue;
|
||||
}
|
||||
if (!inTableBody || line.isEmpty) {
|
||||
continue;
|
||||
}
|
||||
if (line.length < commandLineHeaderStart) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 3/11/2019 11:01:54 AM
|
||||
// 12/11/2019 11:01:54 AM
|
||||
String rawTime = line.substring(
|
||||
creationDateHeaderStart,
|
||||
creationDateHeaderEnd,
|
||||
).trim();
|
||||
|
||||
if (rawTime[1] == '/') {
|
||||
rawTime = '0$rawTime';
|
||||
}
|
||||
if (rawTime[4] == '/') {
|
||||
rawTime = rawTime.substring(0, 3) + '0' + rawTime.substring(3);
|
||||
}
|
||||
final String year = rawTime.substring(6, 10);
|
||||
final String month = rawTime.substring(3, 5);
|
||||
final String day = rawTime.substring(0, 2);
|
||||
String time = rawTime.substring(11, 19);
|
||||
if (time[7] == ' ') {
|
||||
time = '0$time'.trim();
|
||||
}
|
||||
if (rawTime.endsWith('PM')) {
|
||||
final int hours = int.parse(time.substring(0, 2));
|
||||
time = '${hours + 12}${time.substring(2)}';
|
||||
}
|
||||
|
||||
final int pid = int.parse(line.substring(0, processIdHeaderSize).trim());
|
||||
final DateTime creationDate = DateTime.parse('$year-$month-${day}T$time');
|
||||
final String commandLine = line.substring(commandLineHeaderStart).trim();
|
||||
yield RunningProcessInfo(pid, creationDate, commandLine);
|
||||
}
|
||||
}
|
||||
|
||||
@visibleForTesting
|
||||
Stream<RunningProcessInfo> posixRunningProcesses(
|
||||
String processName,
|
||||
ProcessManager processManager,
|
||||
) async* {
|
||||
// Cirrus is missing this in Linux for some reason.
|
||||
if (!processManager.canRun('ps')) {
|
||||
print('Cannot list processes on this system: `ps` not available.');
|
||||
return;
|
||||
}
|
||||
final ProcessResult result = await processManager.run(<String>[
|
||||
'ps',
|
||||
'-eo',
|
||||
'lstart,pid,command',
|
||||
]);
|
||||
if (result.exitCode != 0) {
|
||||
print('Could not list processes!');
|
||||
print(result.stderr);
|
||||
print(result.stdout);
|
||||
return;
|
||||
}
|
||||
for (RunningProcessInfo info in processPsOutput(result.stdout, processName)) {
|
||||
yield info;
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses the output of the command in [posixRunningProcesses].
|
||||
///
|
||||
/// E.g.:
|
||||
///
|
||||
/// STARTED PID COMMAND
|
||||
/// Sat Mar 9 20:12:47 2019 1 /sbin/launchd
|
||||
/// Sat Mar 9 20:13:00 2019 49 /usr/sbin/syslogd
|
||||
@visibleForTesting
|
||||
Iterable<RunningProcessInfo> processPsOutput(
|
||||
String output,
|
||||
String processName,
|
||||
) sync* {
|
||||
if (output == null) {
|
||||
return;
|
||||
}
|
||||
bool inTableBody = false;
|
||||
for (String line in output.split('\n')) {
|
||||
if (line.trim().startsWith('STARTED')) {
|
||||
inTableBody = true;
|
||||
continue;
|
||||
}
|
||||
if (!inTableBody || line.isEmpty) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (processName != null && !line.contains(processName)) {
|
||||
continue;
|
||||
}
|
||||
if (line.length < 25) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 'Sat Feb 16 02:29:55 2019'
|
||||
// 'Sat Mar 9 20:12:47 2019'
|
||||
const Map<String, String> months = <String, String>{
|
||||
'Jan': '01',
|
||||
'Feb': '02',
|
||||
'Mar': '03',
|
||||
'Apr': '04',
|
||||
'May': '05',
|
||||
'Jun': '06',
|
||||
'Jul': '07',
|
||||
'Aug': '08',
|
||||
'Sep': '09',
|
||||
'Oct': '10',
|
||||
'Nov': '11',
|
||||
'Dec': '12',
|
||||
};
|
||||
final String rawTime = line.substring(0, 24);
|
||||
|
||||
final String year = rawTime.substring(20, 24);
|
||||
final String month = months[rawTime.substring(4, 7)];
|
||||
final String day = rawTime.substring(8, 10).replaceFirst(' ', '0');
|
||||
final String time = rawTime.substring(11, 19);
|
||||
|
||||
final DateTime creationDate = DateTime.parse('$year-$month-${day}T$time');
|
||||
line = line.substring(24).trim();
|
||||
final int nextSpace = line.indexOf(' ');
|
||||
final int pid = int.parse(line.substring(0, nextSpace));
|
||||
final String commandLine = line.substring(nextSpace + 1);
|
||||
yield RunningProcessInfo(pid, creationDate, commandLine);
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ TaskFunction createHotModeTest() {
|
||||
final File benchmarkFile = file(path.join(_editedFlutterGalleryDir.path, 'hot_benchmark.json'));
|
||||
rm(benchmarkFile);
|
||||
final List<String> options = <String>[
|
||||
'--hot', '-d', device.deviceId, '--benchmark', '--verbose', '--resident'
|
||||
'--hot', '-d', device.deviceId, '--benchmark', '--verbose', '--resident',
|
||||
];
|
||||
setLocalEngineOptionIfNecessary(options);
|
||||
int hotReloadCount = 0;
|
||||
@@ -40,7 +40,7 @@ TaskFunction createHotModeTest() {
|
||||
final Process process = await startProcess(
|
||||
path.join(flutterDirectory.path, 'bin', 'flutter'),
|
||||
<String>['run']..addAll(options),
|
||||
environment: null
|
||||
environment: null,
|
||||
);
|
||||
|
||||
final Completer<void> stdoutDone = Completer<void>();
|
||||
@@ -53,11 +53,11 @@ TaskFunction createHotModeTest() {
|
||||
if (hotReloadCount == 0) {
|
||||
// Update the file and reload again.
|
||||
final File appDartSource = file(path.join(
|
||||
_editedFlutterGalleryDir.path, 'lib/gallery/app.dart'
|
||||
_editedFlutterGalleryDir.path, 'lib/gallery/app.dart',
|
||||
));
|
||||
appDartSource.writeAsStringSync(
|
||||
appDartSource.readAsStringSync().replaceFirst(
|
||||
"'Flutter Gallery'", "'Updated Flutter Gallery'"
|
||||
"'Flutter Gallery'", "'Updated Flutter Gallery'",
|
||||
)
|
||||
);
|
||||
process.stdin.writeln('r');
|
||||
@@ -94,7 +94,7 @@ TaskFunction createHotModeTest() {
|
||||
final Process process = await startProcess(
|
||||
path.join(flutterDirectory.path, 'bin', 'flutter'),
|
||||
<String>['run']..addAll(options),
|
||||
environment: null
|
||||
environment: null,
|
||||
);
|
||||
final Completer<void> stdoutDone = Completer<void>();
|
||||
final Completer<void> stderrDone = Completer<void>();
|
||||
@@ -156,7 +156,7 @@ TaskFunction createHotModeTest() {
|
||||
'hotReloadFlutterReassembleMillisecondsAfterChange',
|
||||
'hotReloadVMReloadMillisecondsAfterChange',
|
||||
'hotReloadInitialDevFSSyncAfterRelaunchMilliseconds',
|
||||
]
|
||||
],
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ TaskFunction createFlavorsTest() {
|
||||
return DriverTest(
|
||||
'${flutterDirectory.path}/dev/integration_tests/flavors',
|
||||
'lib/main.dart',
|
||||
extraOptions: <String>['--flavor', 'paid']
|
||||
extraOptions: <String>['--flavor', 'paid'],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -61,6 +61,16 @@ TaskFunction createAndroidSemanticsIntegrationTest() {
|
||||
);
|
||||
}
|
||||
|
||||
TaskFunction createCodegenerationIntegrationTest() {
|
||||
return DriverTest(
|
||||
'${flutterDirectory.path}/dev/integration_tests/codegen',
|
||||
'lib/main.dart',
|
||||
environment: <String, String>{
|
||||
'FLUTTER_EXPERIMENTAL_BUILD': 'true',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
TaskFunction createFlutterCreateOfflineTest() {
|
||||
return () async {
|
||||
final Directory tempDir = Directory.systemTemp.createTempSync('flutter_create_test.');
|
||||
@@ -83,12 +93,14 @@ class DriverTest {
|
||||
this.testDirectory,
|
||||
this.testTarget, {
|
||||
this.extraOptions = const <String>[],
|
||||
this.environment = const <String, String>{},
|
||||
}
|
||||
);
|
||||
|
||||
final String testDirectory;
|
||||
final String testTarget;
|
||||
final List<String> extraOptions;
|
||||
final Map<String, String> environment;
|
||||
|
||||
Future<TaskResult> call() {
|
||||
return inDirectory<TaskResult>(testDirectory, () async {
|
||||
@@ -107,7 +119,7 @@ class DriverTest {
|
||||
deviceId,
|
||||
];
|
||||
options.addAll(extraOptions);
|
||||
await flutter('drive', options: options);
|
||||
await flutter('drive', options: options, environment: Map<String, String>.from(environment));
|
||||
|
||||
return TaskResult.success(null);
|
||||
});
|
||||
|
||||
@@ -46,6 +46,14 @@ TaskFunction createCullOpacityPerfTest() {
|
||||
).run;
|
||||
}
|
||||
|
||||
TaskFunction createCubicBezierPerfTest() {
|
||||
return PerfTest(
|
||||
'${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
|
||||
'test_driver/cubic_bezier_perf.dart',
|
||||
'cubic_bezier_perf',
|
||||
).run;
|
||||
}
|
||||
|
||||
TaskFunction createFlutterGalleryStartupTest() {
|
||||
return StartupTest(
|
||||
'${flutterDirectory.path}/examples/flutter_gallery',
|
||||
@@ -412,7 +420,7 @@ class MemoryTest {
|
||||
_receivedNextMessage = Completer<void>();
|
||||
}
|
||||
|
||||
int get iterationCount => 15;
|
||||
int get iterationCount => 10;
|
||||
|
||||
Device get device => _device;
|
||||
Device _device;
|
||||
|
||||
@@ -65,7 +65,7 @@ class FlutterProject {
|
||||
await inDirectory(directory, () async {
|
||||
await flutter(
|
||||
'create',
|
||||
options: <String>['--template=app', '--org', 'io.flutter.devicelab']..addAll(options)..add('plugintest')
|
||||
options: <String>['--template=app', '--org', 'io.flutter.devicelab']..addAll(options)..add('plugintest'),
|
||||
);
|
||||
});
|
||||
return FlutterProject(directory, 'plugintest');
|
||||
|
||||
61
dev/devicelab/lib/tasks/run_without_leak.dart
Normal file
61
dev/devicelab/lib/tasks/run_without_leak.dart
Normal file
@@ -0,0 +1,61 @@
|
||||
// Copyright 2019 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:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
import '../framework/adb.dart';
|
||||
import '../framework/framework.dart';
|
||||
import '../framework/utils.dart';
|
||||
|
||||
TaskFunction createRunWithoutLeakTest(dynamic dir) {
|
||||
return () async {
|
||||
final Device device = await devices.workingDevice;
|
||||
await device.unlock();
|
||||
final List<String> options = <String>[
|
||||
'-d', device.deviceId, '--verbose',
|
||||
];
|
||||
setLocalEngineOptionIfNecessary(options);
|
||||
int exitCode;
|
||||
await inDirectory<void>(dir, () async {
|
||||
final Process process = await startProcess(
|
||||
path.join(flutterDirectory.path, 'bin', 'flutter'),
|
||||
<String>['run']..addAll(options),
|
||||
environment: null,
|
||||
);
|
||||
final Completer<void> stdoutDone = Completer<void>();
|
||||
final Completer<void> stderrDone = Completer<void>();
|
||||
process.stdout
|
||||
.transform<String>(utf8.decoder)
|
||||
.transform<String>(const LineSplitter())
|
||||
.listen((String line) {
|
||||
if (line.contains('\] For a more detailed help message, press "h". To detach, press "d"; to quit, press "q"')) {
|
||||
process.stdin.writeln('q');
|
||||
}
|
||||
print('stdout: $line');
|
||||
}, onDone: () {
|
||||
stdoutDone.complete();
|
||||
});
|
||||
process.stderr
|
||||
.transform<String>(utf8.decoder)
|
||||
.transform<String>(const LineSplitter())
|
||||
.listen((String line) {
|
||||
print('stderr: $line');
|
||||
}, onDone: () {
|
||||
stderrDone.complete();
|
||||
});
|
||||
|
||||
await Future.wait<void>(
|
||||
<Future<void>>[stdoutDone.future, stderrDone.future]);
|
||||
exitCode = await process.exitCode;
|
||||
});
|
||||
|
||||
return exitCode == 0
|
||||
? TaskResultCheckProcesses()
|
||||
: TaskResult.failure('Failed to run $dir');
|
||||
};
|
||||
}
|
||||
@@ -76,6 +76,27 @@ tasks:
|
||||
stage: devicelab_win
|
||||
required_agent_capabilities: ["windows/android"]
|
||||
|
||||
codegen_integration_win:
|
||||
description: >
|
||||
Runs codegeneration and verifies that it can execute
|
||||
correctly.
|
||||
stage: devicelab_win
|
||||
required_agent_capabilities: ["windows/android"]
|
||||
|
||||
codegen_integration_mac:
|
||||
description: >
|
||||
Runs codegeneration and verifies that it can execute
|
||||
correctly.
|
||||
stage: devicelab_ios
|
||||
required_agent_capabilities: ["mac/ios"]
|
||||
|
||||
codegen_integration_linux:
|
||||
description: >
|
||||
Runs codegeneration and verifies that it can execute
|
||||
correctly.
|
||||
stage: devicelab
|
||||
required_agent_capabilities: ["linux/android"]
|
||||
|
||||
flutter_gallery_android__compile:
|
||||
description: >
|
||||
Collects various performance metrics of compiling the Flutter
|
||||
@@ -118,7 +139,6 @@ tasks:
|
||||
flutter_gallery app on Android.
|
||||
stage: devicelab
|
||||
required_agent_capabilities: ["mac/android"]
|
||||
flaky: true
|
||||
|
||||
cull_opacity_perf__timeline_summary:
|
||||
description: >
|
||||
@@ -126,6 +146,13 @@ tasks:
|
||||
stage: devicelab
|
||||
required_agent_capabilities: ["mac/android"]
|
||||
|
||||
cubic_bezier_perf__timeline_summary:
|
||||
description: >
|
||||
Measures the runtime performance of cubic bezier animations on Android.
|
||||
stage: devicelab
|
||||
required_agent_capabilities: ["mac/android"]
|
||||
flaky: true
|
||||
|
||||
flavors_test:
|
||||
description: >
|
||||
Checks that flavored builds work on Android.
|
||||
@@ -265,23 +292,24 @@ tasks:
|
||||
stage: devicelab
|
||||
required_agent_capabilities: ["linux/android"]
|
||||
|
||||
gradle_plugin_test:
|
||||
description: >
|
||||
Verifies that the Flutter Gradle plugin supports standard and custom Android build types.
|
||||
stage: devicelab
|
||||
required_agent_capabilities: ["linux/android"]
|
||||
# TODO(dnfield): Remove these once we're confident it's all working on cirrus
|
||||
# gradle_plugin_test:
|
||||
# description: >
|
||||
# Verifies that the Flutter Gradle plugin supports standard and custom Android build types.
|
||||
# stage: devicelab
|
||||
# required_agent_capabilities: ["linux/android"]
|
||||
|
||||
plugin_test:
|
||||
description: >
|
||||
Checks that the project template works and supports plugins.
|
||||
stage: devicelab
|
||||
required_agent_capabilities: ["linux/android"]
|
||||
# plugin_test:
|
||||
# description: >
|
||||
# Checks that the project template works and supports plugins.
|
||||
# stage: devicelab
|
||||
# required_agent_capabilities: ["linux/android"]
|
||||
|
||||
module_test:
|
||||
description: >
|
||||
Checks that the module project template works and supports add2app on Android.
|
||||
stage: devicelab
|
||||
required_agent_capabilities: ["linux/android"]
|
||||
# module_test:
|
||||
# description: >
|
||||
# Checks that the module project template works and supports add2app on Android.
|
||||
# stage: devicelab
|
||||
# required_agent_capabilities: ["linux/android"]
|
||||
|
||||
flutter_gallery_instrumentation_test:
|
||||
description: >
|
||||
@@ -303,23 +331,24 @@ tasks:
|
||||
stage: devicelab
|
||||
required_agent_capabilities: ["linux/android"]
|
||||
|
||||
flutter_create_offline_test_linux:
|
||||
description: >
|
||||
Tests the `flutter create --offline` command.
|
||||
stage: devicelab
|
||||
required_agent_capabilities: ["linux/android"]
|
||||
# TODO(dnfield): Remove these once we're confident it's all working on cirrus
|
||||
# flutter_create_offline_test_linux:
|
||||
# description: >
|
||||
# Tests the `flutter create --offline` command.
|
||||
# stage: devicelab
|
||||
# required_agent_capabilities: ["linux/android"]
|
||||
|
||||
flutter_create_offline_test_windows:
|
||||
description: >
|
||||
Tests the `flutter create --offline` command.
|
||||
stage: devicelab
|
||||
required_agent_capabilities: ["windows/android"]
|
||||
# flutter_create_offline_test_windows:
|
||||
# description: >
|
||||
# Tests the `flutter create --offline` command.
|
||||
# stage: devicelab
|
||||
# required_agent_capabilities: ["windows/android"]
|
||||
|
||||
flutter_create_offline_test_mac:
|
||||
description: >
|
||||
Tests the `flutter create --offline` command.
|
||||
stage: devicelab
|
||||
required_agent_capabilities: ["mac/android"]
|
||||
# flutter_create_offline_test_mac:
|
||||
# description: >
|
||||
# Tests the `flutter create --offline` command.
|
||||
# stage: devicelab
|
||||
# required_agent_capabilities: ["mac/android"]
|
||||
|
||||
# iOS on-device tests
|
||||
|
||||
@@ -329,17 +358,18 @@ tasks:
|
||||
stage: devicelab_ios
|
||||
required_agent_capabilities: ["mac/ios"]
|
||||
|
||||
plugin_test_ios:
|
||||
description: >
|
||||
Checks that the project template works and supports plugins on iOS.
|
||||
stage: devicelab_ios
|
||||
required_agent_capabilities: ["mac/ios"]
|
||||
# TODO(dnfield): Remove these once we're confident it's all working on cirrus
|
||||
# plugin_test_ios:
|
||||
# description: >
|
||||
# Checks that the project template works and supports plugins on iOS.
|
||||
# stage: devicelab_ios
|
||||
# required_agent_capabilities: ["mac/ios"]
|
||||
|
||||
module_test_ios:
|
||||
description: >
|
||||
Checks that the module project template works and supports add2app on iOS.
|
||||
stage: devicelab
|
||||
required_agent_capabilities: ["mac/ios"]
|
||||
# module_test_ios:
|
||||
# description: >
|
||||
# Checks that the module project template works and supports add2app on iOS.
|
||||
# stage: devicelab
|
||||
# required_agent_capabilities: ["mac/ios"]
|
||||
|
||||
external_ui_integration_test_ios:
|
||||
description: >
|
||||
@@ -456,6 +486,13 @@ tasks:
|
||||
stage: devicelab_win
|
||||
required_agent_capabilities: ["windows/android"]
|
||||
|
||||
run_without_leak_win:
|
||||
description: >
|
||||
Checks that `flutter run` does not leak dart.exe on Windows.
|
||||
stage: devicelab_win
|
||||
required_agent_capabilities: ["windows/android"]
|
||||
flaky: true
|
||||
|
||||
# Tests running on Linux hosts
|
||||
|
||||
hot_mode_dev_cycle_linux__benchmark:
|
||||
@@ -464,11 +501,12 @@ tasks:
|
||||
stage: devicelab
|
||||
required_agent_capabilities: ["linux/android"]
|
||||
|
||||
dartdocs:
|
||||
description: >
|
||||
Tracks how many members are still lacking documentation.
|
||||
stage: devicelab
|
||||
required_agent_capabilities: ["linux/android"]
|
||||
# TODO(dnfield): Remove these once we're confident it's all working on cirrus
|
||||
# dartdocs:
|
||||
# description: >
|
||||
# Tracks how many members are still lacking documentation.
|
||||
# stage: devicelab
|
||||
# required_agent_capabilities: ["linux/android"]
|
||||
|
||||
flutter_test_performance:
|
||||
description: >
|
||||
@@ -520,6 +558,13 @@ tasks:
|
||||
stage: devicelab
|
||||
required_agent_capabilities: ["linux/android"]
|
||||
|
||||
run_without_leak_linux:
|
||||
description: >
|
||||
Checks that `flutter run` does not leak dart on Linux.
|
||||
stage: devicelab
|
||||
required_agent_capabilities: ["linux/android"]
|
||||
flaky: true
|
||||
|
||||
flutter_gallery_ios32__start_up:
|
||||
description: >
|
||||
Measures the startup time of the Flutter Gallery app on 32-bit iOS.
|
||||
@@ -532,3 +577,10 @@ tasks:
|
||||
32-bit iOS.
|
||||
stage: devicelab_ios
|
||||
required_agent_capabilities: ["mac/ios32"]
|
||||
|
||||
run_without_leak_mac:
|
||||
description: >
|
||||
Checks that `flutter run` does not leak dart on macOS.
|
||||
stage: devicelab
|
||||
required_agent_capabilities: ["mac/android"]
|
||||
flaky: true
|
||||
|
||||
@@ -26,39 +26,39 @@ dependencies:
|
||||
crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
intl: 0.15.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
petitparser: 2.1.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
petitparser: 2.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pub_semver: 1.4.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
source_span: 1.5.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
source_span: 1.5.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
stream_channel: 1.6.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
term_glyph: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
typed_data: 1.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
web_socket_channel: 1.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
xml: 3.3.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
xml: 3.4.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
|
||||
dev_dependencies:
|
||||
# See packages/flutter_test/pubspec.yaml for why we're pinning this version.
|
||||
test: 1.5.3
|
||||
|
||||
analyzer: 0.35.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
analyzer: 0.35.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
front_end: 0.1.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
front_end: 0.1.13 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
html: 0.13.4+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
http: 0.12.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
http_multi_server: 2.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
http_parser: 3.1.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
kernel: 0.3.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
kernel: 0.3.13 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
node_preamble: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
package_resolver: 1.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pedantic: 1.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
package_resolver: 1.0.10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pedantic: 1.5.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
plugin: 0.2.0+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pool: 1.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
shelf: 0.7.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
@@ -74,4 +74,4 @@ dev_dependencies:
|
||||
watcher: 0.9.7+10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
yaml: 2.1.15 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
|
||||
# PUBSPEC CHECKSUM: 2bb2
|
||||
# PUBSPEC CHECKSUM: d7e6
|
||||
|
||||
@@ -80,7 +80,7 @@ tasks:
|
||||
tasks:
|
||||
- a
|
||||
- b
|
||||
'''
|
||||
''',
|
||||
);
|
||||
|
||||
testManifestError(
|
||||
@@ -89,7 +89,7 @@ tasks:
|
||||
'''
|
||||
tasks:
|
||||
1: 2
|
||||
'''
|
||||
''',
|
||||
);
|
||||
|
||||
testManifestError(
|
||||
@@ -98,7 +98,7 @@ tasks:
|
||||
'''
|
||||
tasks:
|
||||
foo: 2
|
||||
'''
|
||||
''',
|
||||
);
|
||||
|
||||
testManifestError(
|
||||
@@ -108,7 +108,7 @@ tasks:
|
||||
tasks:
|
||||
foo:
|
||||
bar: 2
|
||||
'''
|
||||
''',
|
||||
);
|
||||
|
||||
testManifestError(
|
||||
@@ -118,7 +118,7 @@ tasks:
|
||||
tasks:
|
||||
foo:
|
||||
required_agent_capabilities: 1
|
||||
'''
|
||||
''',
|
||||
);
|
||||
|
||||
testManifestError(
|
||||
@@ -128,7 +128,7 @@ tasks:
|
||||
tasks:
|
||||
foo:
|
||||
required_agent_capabilities: [1]
|
||||
'''
|
||||
''',
|
||||
);
|
||||
|
||||
testManifestError(
|
||||
@@ -138,7 +138,7 @@ tasks:
|
||||
tasks:
|
||||
foo:
|
||||
required_agent_capabilities: ["a"]
|
||||
'''
|
||||
''',
|
||||
);
|
||||
|
||||
testManifestError(
|
||||
@@ -149,7 +149,7 @@ tasks:
|
||||
foo:
|
||||
description: b
|
||||
required_agent_capabilities: ["a"]
|
||||
'''
|
||||
''',
|
||||
);
|
||||
|
||||
testManifestError(
|
||||
@@ -161,7 +161,7 @@ tasks:
|
||||
description: b
|
||||
stage: c
|
||||
required_agent_capabilities: []
|
||||
'''
|
||||
''',
|
||||
);
|
||||
|
||||
testManifestError(
|
||||
@@ -174,7 +174,7 @@ tasks:
|
||||
stage: c
|
||||
required_agent_capabilities: ["a"]
|
||||
flaky: not-a-boolean
|
||||
'''
|
||||
''',
|
||||
);
|
||||
|
||||
test('accepts boolean flaky option', () {
|
||||
|
||||
68
dev/devicelab/test/running_processes_test.dart
Normal file
68
dev/devicelab/test/running_processes_test.dart
Normal file
@@ -0,0 +1,68 @@
|
||||
// Copyright 2018 The Chromium 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 'package:flutter_devicelab/framework/running_processes.dart';
|
||||
import 'common.dart';
|
||||
|
||||
void main() {
|
||||
test('Parse PowerShell result', () {
|
||||
const String powershellOutput = r'''
|
||||
|
||||
ProcessId CreationDate CommandLine
|
||||
--------- ------------ -----------
|
||||
6552 3/7/2019 5:00:27 PM "C:\tools\dart-sdk\bin\dart.exe" .\bin\agent.dart ci
|
||||
6553 3/7/2019 10:00:27 PM "C:\tools\dart-sdk1\bin\dart.exe" .\bin\agent.dart ci
|
||||
6554 3/7/2019 11:00:27 AM "C:\tools\dart-sdk2\bin\dart.exe" .\bin\agent.dart ci
|
||||
|
||||
|
||||
''';
|
||||
final List<RunningProcessInfo> results =
|
||||
processPowershellOutput(powershellOutput).toList();
|
||||
expect(results.length, 3);
|
||||
expect(
|
||||
results,
|
||||
equals(<RunningProcessInfo>[
|
||||
RunningProcessInfo(
|
||||
6552,
|
||||
DateTime(2019, 7, 3, 17, 0, 27),
|
||||
r'"C:\tools\dart-sdk\bin\dart.exe" .\bin\agent.dart ci',
|
||||
),
|
||||
RunningProcessInfo(
|
||||
6553,
|
||||
DateTime(2019, 7, 3, 22, 0, 27),
|
||||
r'"C:\tools\dart-sdk1\bin\dart.exe" .\bin\agent.dart ci',
|
||||
),
|
||||
RunningProcessInfo(
|
||||
6554,
|
||||
DateTime(2019, 7, 3, 11, 0, 27),
|
||||
r'"C:\tools\dart-sdk2\bin\dart.exe" .\bin\agent.dart ci',
|
||||
),
|
||||
]));
|
||||
});
|
||||
|
||||
test('Parse Posix output', () {
|
||||
const String psOutput = r'''STARTED PID COMMAND
|
||||
Sat Mar 9 20:12:47 2019 1 /sbin/launchd
|
||||
Sat Mar 9 20:13:00 2019 49 /usr/sbin/syslogd
|
||||
''';
|
||||
|
||||
final List<RunningProcessInfo> results =
|
||||
processPsOutput(psOutput, null).toList();
|
||||
expect(results.length, 2);
|
||||
expect(
|
||||
results,
|
||||
equals(<RunningProcessInfo>[
|
||||
RunningProcessInfo(
|
||||
1,
|
||||
DateTime(2019, 3, 9, 20, 12, 47),
|
||||
'/sbin/launchd',
|
||||
),
|
||||
RunningProcessInfo(
|
||||
49,
|
||||
DateTime(2019, 3, 9, 20, 13, 00),
|
||||
'/usr/sbin/syslogd',
|
||||
),
|
||||
]));
|
||||
});
|
||||
}
|
||||
@@ -13,9 +13,9 @@ SDK.
|
||||
This site hosts Flutter's API documentation. Other documentation can be found at
|
||||
the following locations:
|
||||
|
||||
* [flutter.io](https://flutter.io/) (main site)
|
||||
* [Installation](https://flutter.io/docs/get-started/install)
|
||||
* [Codelabs](https://flutter.io/docs/codelabs)
|
||||
* [flutter.dev](https://flutter.dev) (main site)
|
||||
* [Installation](https://flutter.dev/docs/get-started/install)
|
||||
* [Codelabs](https://flutter.dev/docs/codelabs)
|
||||
* [Contributing to Flutter](https://github.com/flutter/flutter/blob/master/CONTRIBUTING.md)
|
||||
|
||||
### Importing a Library
|
||||
|
||||
25
dev/docs/assets/api_survey.js
Normal file
25
dev/docs/assets/api_survey.js
Normal file
@@ -0,0 +1,25 @@
|
||||
window.ApiSurveyDocs = function(apiPages) {
|
||||
var url = window.location.href;
|
||||
var fragments = url.split('/');
|
||||
if (fragments == null || fragments.length == 0) {
|
||||
return;
|
||||
}
|
||||
var classFragment = fragments[fragments.length -1];
|
||||
if (classFragment == null) {
|
||||
return;
|
||||
}
|
||||
var apiDocClassFragments = classFragment.split('-');
|
||||
if (apiDocClassFragments.length != 2) {
|
||||
return;
|
||||
}
|
||||
var apiDocClass = apiDocClassFragments[0];
|
||||
if (url == null || apiPages.indexOf(apiDocClass) == -1) {
|
||||
return;
|
||||
}
|
||||
scriptElement = document.createElement('script');
|
||||
scriptElement.setAttribute('src', 'https://www.google.com/insights/consumersurveys/async_survey?site=sygvgfetfwmwm7isniaym3m6f4');
|
||||
document.head.appendChild(scriptElement);
|
||||
}
|
||||
scriptElement = document.createElement('script');
|
||||
scriptElement.setAttribute('src', 'https://storage.googleapis.com/flutter-dashboard.appspot.com/api_survey/api_survey_docs.html');
|
||||
document.head.appendChild(scriptElement);
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Styles for handling custom code snippets */
|
||||
.snippet-container {
|
||||
background-color: #45aae8;
|
||||
background-color: #2372a3;
|
||||
padding: 10px;
|
||||
overflow: auto;
|
||||
}
|
||||
@@ -30,8 +30,21 @@
|
||||
color: white;
|
||||
}
|
||||
|
||||
.snippet-description a:link {
|
||||
color: #c7fcf4;
|
||||
}
|
||||
.snippet-description a:visited {
|
||||
color: #c7dbfc;
|
||||
}
|
||||
.snippet-description a:hover {
|
||||
color: white;
|
||||
}
|
||||
.snippet-description a:active {
|
||||
color: #80b0fc;
|
||||
}
|
||||
|
||||
.snippet-buttons button {
|
||||
background-color: #45aae8;
|
||||
background-color: #2372a3;
|
||||
border-style: none;
|
||||
color: white;
|
||||
padding: 10px 24px;
|
||||
@@ -82,7 +95,7 @@
|
||||
height: 28px;
|
||||
width: 28px;
|
||||
transition: .3s ease;
|
||||
background-color: #45aae8;
|
||||
background-color: #2372a3;
|
||||
}
|
||||
|
||||
.copy-button {
|
||||
@@ -102,7 +115,7 @@
|
||||
|
||||
.copy-image {
|
||||
opacity: 0.65;
|
||||
color: #45aae8;
|
||||
color: #2372a3;
|
||||
font-size: 28px;
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
@@ -2,15 +2,10 @@
|
||||
* Scripting for handling custom code snippets
|
||||
*/
|
||||
|
||||
const shortSnippet = 'shortSnippet';
|
||||
const longSnippet = 'longSnippet';
|
||||
var visibleSnippet = shortSnippet;
|
||||
|
||||
/**
|
||||
* Shows the requested snippet. Values for "name" can be "shortSnippet" or
|
||||
* "longSnippet".
|
||||
* Shows the requested snippet, and stores the current state in visibleSnippet.
|
||||
*/
|
||||
function showSnippet(name) {
|
||||
function showSnippet(name, visibleSnippet) {
|
||||
if (visibleSnippet == name) return;
|
||||
if (visibleSnippet != null) {
|
||||
var shown = document.getElementById(visibleSnippet);
|
||||
@@ -39,6 +34,7 @@ function showSnippet(name) {
|
||||
if (button != null) {
|
||||
button.setAttributeNode(selectedAttribute);
|
||||
}
|
||||
return visibleSnippet;
|
||||
}
|
||||
|
||||
// Finds a sibling to given element with the given id.
|
||||
@@ -64,8 +60,8 @@ function supportsCopying() {
|
||||
// Copies the text inside the currently visible snippet to the clipboard, or the
|
||||
// given element, if any.
|
||||
function copyTextToClipboard(element) {
|
||||
if (element == null) {
|
||||
var elementSelector = '#' + visibleSnippet + ' .language-dart';
|
||||
if (typeof element === 'string') {
|
||||
var elementSelector = '#' + element + ' .language-dart';
|
||||
element = document.querySelector(elementSelector);
|
||||
if (element == null) {
|
||||
console.log(
|
||||
|
||||
@@ -10,83 +10,52 @@
|
||||
"allowJS": true,
|
||||
"ExternalURL": "https://docs.flutter.io",
|
||||
"selectors": {
|
||||
|
||||
"#exceptions span.name a": {
|
||||
"type": "Exception"
|
||||
},
|
||||
|
||||
"body > main > div.col-xs-12.col-sm-9.col-md-8.main-content > h1": {
|
||||
"requiretext": " library",
|
||||
"type": "Library",
|
||||
"regexp": " library",
|
||||
"replacement": ""
|
||||
"h1 > span.kind-library": {
|
||||
"type": "Library"
|
||||
},
|
||||
|
||||
"body > main > div.col-xs-12.col-sm-9.main-content > h1": {
|
||||
"requiretext": " class",
|
||||
"type": "Class",
|
||||
"regexp": " class",
|
||||
"replacement": ""
|
||||
"h1 > span.kind-class": {
|
||||
"type": "Class"
|
||||
},
|
||||
|
||||
"body > main > div.col-xs-12.col-md-8.main-content > h1": {
|
||||
"requiretext": " function",
|
||||
"type": "Function",
|
||||
"regexp": " function",
|
||||
"replacement": ""
|
||||
"h1 > span.kind-function": {
|
||||
"type": "Function"
|
||||
},
|
||||
|
||||
"body > main > div.col-sm-9.col-md-8.main-content > h1": {
|
||||
"requiretext": " typedef",
|
||||
"type": "Type",
|
||||
"regexp": " typedef",
|
||||
"replacement": ""
|
||||
"h1 > span.kind-typedef": {
|
||||
"type": "Type"
|
||||
},
|
||||
|
||||
"body > main > .col-xs-12.col-sm-9.col-md-8.main-content > h1": {
|
||||
"requiretext": " enum",
|
||||
"type": "Enum",
|
||||
"regexp": " enum",
|
||||
"replacement": ""
|
||||
"h1 > span.kind-enum": {
|
||||
"type": "Enum"
|
||||
},
|
||||
|
||||
"body > main > .col-md-8.main-content > h1": {
|
||||
"requiretext": " constant",
|
||||
"type": "Constant",
|
||||
"regexp": " constant",
|
||||
"replacement": ""
|
||||
"h1 > span.kind-top-level-constant": {
|
||||
"type": "Constant"
|
||||
},
|
||||
|
||||
"body > main > div.col-xs-12.col-sm-9 > h1": {
|
||||
"requiretext": " method",
|
||||
"type": "Method",
|
||||
"regexp": " method",
|
||||
"replacement": ""
|
||||
"h1 > span.kind-constant": {
|
||||
"type": "Constant"
|
||||
},
|
||||
|
||||
".callables .callable .name a": {
|
||||
"h1 > span.kind-method": {
|
||||
"type": "Method"
|
||||
},
|
||||
|
||||
"body > main > .col-xs-12.col-sm-9.col-md-8 > h1": {
|
||||
"requiretext": " property",
|
||||
"type": "Property",
|
||||
"regexp": " property",
|
||||
"replacement": ""
|
||||
"h1 > span.kind-property": {
|
||||
"type": "Property"
|
||||
},
|
||||
|
||||
"body > main > .col-xs-12.col-md-8 > h1": {
|
||||
"requiretext": " constructor",
|
||||
"type": "Constructor",
|
||||
"regexp": " constructor",
|
||||
"replacement": ""
|
||||
"h1 > span.kind-top-level-property": {
|
||||
"type": "Property"
|
||||
},
|
||||
|
||||
"body > main > .col-xs-12.col-sm-9.main-content > h1": {
|
||||
"requiretext": "operator ",
|
||||
"type": "Operator",
|
||||
"regexp": "operator ",
|
||||
"replacement": ""
|
||||
"h1 > span.kind-constructor": {
|
||||
"type": "Constructor"
|
||||
},
|
||||
|
||||
".callables .callable": {
|
||||
@@ -95,8 +64,6 @@
|
||||
"regexp": "operator ",
|
||||
"replacement": ""
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
"ignore": [
|
||||
"ABOUT"
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
<script async="" defer=""
|
||||
src="//www.google.com/insights/consumersurveys/async_survey?site=i2bdmo2dzky7fqws25nicgx5f4">
|
||||
</script>
|
||||
<script async="" defer="" src="../assets/api_survey.js"></script>
|
||||
|
||||
@@ -8,7 +8,7 @@ dependencies:
|
||||
sdk: flutter
|
||||
test: 1.5.3
|
||||
|
||||
analyzer: 0.35.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
analyzer: 0.35.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
args: 1.5.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
@@ -18,9 +18,9 @@ dependencies:
|
||||
crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
file: 5.0.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
front_end: 0.1.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
front_end: 0.1.13 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
html: 0.13.4+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
http: 0.12.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
http_multi_server: 2.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
http_parser: 3.1.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
@@ -28,7 +28,7 @@ dependencies:
|
||||
io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
kernel: 0.3.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
kernel: 0.3.13 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
meta: 1.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
@@ -36,9 +36,9 @@ dependencies:
|
||||
multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
node_preamble: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
package_resolver: 1.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
package_resolver: 1.0.10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
path: 1.6.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pedantic: 1.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pedantic: 1.5.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
plugin: 0.2.0+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pool: 1.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pub_semver: 1.4.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
@@ -48,7 +48,7 @@ dependencies:
|
||||
shelf_web_socket: 0.2.2+4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
source_map_stack_trace: 1.1.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
source_maps: 0.10.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
source_span: 1.5.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
source_span: 1.5.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
stack_trace: 1.9.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
stream_channel: 1.6.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
string_scanner: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
@@ -66,4 +66,4 @@ dependencies:
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
|
||||
# PUBSPEC CHECKSUM: c26c
|
||||
# PUBSPEC CHECKSUM: 2b9e
|
||||
|
||||
69
dev/integration_tests/android_views/ios/Podfile
Normal file
69
dev/integration_tests/android_views/ios/Podfile
Normal file
@@ -0,0 +1,69 @@
|
||||
# Uncomment this line to define a global platform for your project
|
||||
# platform :ios, '9.0'
|
||||
|
||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||
|
||||
project 'Runner', {
|
||||
'Debug' => :debug,
|
||||
'Profile' => :release,
|
||||
'Release' => :release,
|
||||
}
|
||||
|
||||
def parse_KV_file(file, separator='=')
|
||||
file_abs_path = File.expand_path(file)
|
||||
if !File.exists? file_abs_path
|
||||
return [];
|
||||
end
|
||||
pods_ary = []
|
||||
skip_line_start_symbols = ["#", "/"]
|
||||
File.foreach(file_abs_path) { |line|
|
||||
next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
|
||||
plugin = line.split(pattern=separator)
|
||||
if plugin.length == 2
|
||||
podname = plugin[0].strip()
|
||||
path = plugin[1].strip()
|
||||
podpath = File.expand_path("#{path}", file_abs_path)
|
||||
pods_ary.push({:name => podname, :path => podpath});
|
||||
else
|
||||
puts "Invalid plugin specification: #{line}"
|
||||
end
|
||||
}
|
||||
return pods_ary
|
||||
end
|
||||
|
||||
target 'Runner' do
|
||||
# Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
|
||||
# referring to absolute paths on developers' machines.
|
||||
system('rm -rf .symlinks')
|
||||
system('mkdir -p .symlinks/plugins')
|
||||
|
||||
# Flutter Pods
|
||||
generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig')
|
||||
if generated_xcode_build_settings.empty?
|
||||
puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter packages get is executed first."
|
||||
end
|
||||
generated_xcode_build_settings.map { |p|
|
||||
if p[:name] == 'FLUTTER_FRAMEWORK_DIR'
|
||||
symlink = File.join('.symlinks', 'flutter')
|
||||
File.symlink(File.dirname(p[:path]), symlink)
|
||||
pod 'Flutter', :path => File.join(symlink, File.basename(p[:path]))
|
||||
end
|
||||
}
|
||||
|
||||
# Plugin Pods
|
||||
plugin_pods = parse_KV_file('../.flutter-plugins')
|
||||
plugin_pods.map { |p|
|
||||
symlink = File.join('.symlinks', 'plugins', p[:name])
|
||||
File.symlink(p[:path], symlink)
|
||||
pod p[:name], :path => File.join(symlink, 'ios')
|
||||
}
|
||||
end
|
||||
|
||||
post_install do |installer|
|
||||
installer.pods_project.targets.each do |target|
|
||||
target.build_configurations.each do |config|
|
||||
config.build_settings['ENABLE_BITCODE'] = 'NO'
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -109,9 +109,9 @@ class PlatformViewState extends State<PlatformViewPage> {
|
||||
key: const ValueKey<String>('play'),
|
||||
child: const Text('PLAY FILE'),
|
||||
onPressed: () { playEventsFile(); },
|
||||
)
|
||||
),
|
||||
],
|
||||
)
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ const List<int> kPointerActions = <int>[
|
||||
0, // DOWN
|
||||
1, // UP
|
||||
5, // POINTER_DOWN
|
||||
6 // POINTER_UP
|
||||
6, // POINTER_UP
|
||||
];
|
||||
|
||||
const double kDoubleErrorMargin = 0.0001;
|
||||
@@ -152,7 +152,7 @@ String getActionName(int actionMasked, int action) {
|
||||
'HOVER_ENTER',
|
||||
'HOVER_EXIT',
|
||||
'BUTTON_PRESS',
|
||||
'BUTTON_RELEASE'
|
||||
'BUTTON_RELEASE',
|
||||
];
|
||||
if (actionMasked < actionNames.length)
|
||||
return '${actionNames[actionMasked]}($action)';
|
||||
|
||||
@@ -25,7 +25,7 @@ dependencies:
|
||||
meta: 1.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
path: 1.6.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pub_semver: 1.4.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
source_span: 1.5.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
source_span: 1.5.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
stack_trace: 1.9.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
stream_channel: 1.6.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
term_glyph: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
@@ -39,27 +39,27 @@ dev_dependencies:
|
||||
sdk: flutter
|
||||
test: 1.5.3
|
||||
|
||||
analyzer: 0.35.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
analyzer: 0.35.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
args: 1.5.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
front_end: 0.1.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
front_end: 0.1.13 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
html: 0.13.4+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
http: 0.12.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
http_multi_server: 2.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
http_parser: 3.1.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
kernel: 0.3.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
kernel: 0.3.13 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
mime: 0.9.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
node_preamble: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
package_resolver: 1.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pedantic: 1.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
package_resolver: 1.0.10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pedantic: 1.5.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
plugin: 0.2.0+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pool: 1.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
quiver: 2.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
@@ -79,4 +79,4 @@ dev_dependencies:
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
|
||||
# PUBSPEC CHECKSUM: 997a
|
||||
# PUBSPEC CHECKSUM: 49ac
|
||||
|
||||
@@ -31,7 +31,7 @@ class _TestAppState extends State<TestApp> {
|
||||
0.0,
|
||||
'hello',
|
||||
<dynamic>[
|
||||
<String, dynamic>{'key': 42}
|
||||
<String, dynamic>{'key': 42},
|
||||
],
|
||||
];
|
||||
static final Map<String, dynamic> aMap = <String, dynamic>{
|
||||
@@ -40,7 +40,7 @@ class _TestAppState extends State<TestApp> {
|
||||
'c': 0.0,
|
||||
'd': 'hello',
|
||||
'e': <dynamic>[
|
||||
<String, dynamic>{'key': 42}
|
||||
<String, dynamic>{'key': 42},
|
||||
],
|
||||
};
|
||||
static final Uint8List someUint8s = Uint8List.fromList(<int>[
|
||||
|
||||
@@ -12,7 +12,7 @@ dependencies:
|
||||
sdk: flutter
|
||||
test: 1.5.3
|
||||
|
||||
analyzer: 0.35.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
analyzer: 0.35.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
args: 1.5.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
async: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
boolean_selector: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
@@ -22,9 +22,9 @@ dependencies:
|
||||
crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
csslib: 0.14.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
file: 5.0.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
front_end: 0.1.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
front_end: 0.1.13 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
html: 0.13.3+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
html: 0.13.4+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
http: 0.12.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
http_multi_server: 2.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
http_parser: 3.1.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
@@ -32,7 +32,7 @@ dependencies:
|
||||
io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
json_rpc_2: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
kernel: 0.3.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
kernel: 0.3.13 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
logging: 0.11.3+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
matcher: 0.12.3+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
meta: 1.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
@@ -40,9 +40,9 @@ dependencies:
|
||||
multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
node_preamble: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
package_resolver: 1.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
package_resolver: 1.0.10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
path: 1.6.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pedantic: 1.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pedantic: 1.5.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
plugin: 0.2.0+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pool: 1.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
pub_semver: 1.4.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
@@ -52,7 +52,7 @@ dependencies:
|
||||
shelf_web_socket: 0.2.2+4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
source_map_stack_trace: 1.1.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
source_maps: 0.10.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
source_span: 1.5.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
source_span: 1.5.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
stack_trace: 1.9.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
stream_channel: 1.6.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
string_scanner: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||
@@ -70,4 +70,4 @@ dependencies:
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
|
||||
# PUBSPEC CHECKSUM: c26c
|
||||
# PUBSPEC CHECKSUM: 2b9e
|
||||
|
||||
3
dev/integration_tests/codegen/README.md
Normal file
3
dev/integration_tests/codegen/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# codegen
|
||||
|
||||
A Flutter project for testing code generation.
|
||||
17
dev/integration_tests/codegen/android/.project
Normal file
17
dev/integration_tests/codegen/android/.project
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>android_____</name>
|
||||
<comment>Project android_____ created by Buildship.</comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
@@ -0,0 +1,2 @@
|
||||
connection.project.dir=
|
||||
eclipse.preferences.version=1
|
||||
57
dev/integration_tests/codegen/android/app/build.gradle
Normal file
57
dev/integration_tests/codegen/android/app/build.gradle
Normal file
@@ -0,0 +1,57 @@
|
||||
def localProperties = new Properties()
|
||||
def localPropertiesFile = rootProject.file('local.properties')
|
||||
if (localPropertiesFile.exists()) {
|
||||
localPropertiesFile.withInputStream { stream ->
|
||||
localProperties.load(stream)
|
||||
}
|
||||
}
|
||||
|
||||
def flutterRoot = localProperties.getProperty('flutter.sdk')
|
||||
if (flutterRoot == null) {
|
||||
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
|
||||
lintOptions {
|
||||
disable 'InvalidPackage'
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 28
|
||||
versionCode 1
|
||||
versionName "0.0.1"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
// TODO: Add your own signing config for the release build.
|
||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||
signingConfig signingConfigs.debug
|
||||
}
|
||||
}
|
||||
|
||||
aaptOptions {
|
||||
// TODO(goderbauer): remove when https://github.com/flutter/flutter/issues/8986 is resolved.
|
||||
if(System.getenv("FLUTTER_CI_WIN")) {
|
||||
println "AAPT cruncher disabled when running on Win CI."
|
||||
cruncherEnabled false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flutter {
|
||||
source '../..'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
||||
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.yourcompany.platforminteraction">
|
||||
|
||||
<!-- The INTERNET permission is required for development. Specifically,
|
||||
flutter needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
|
||||
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
|
||||
calls FlutterMain.startInitialization(this); in its onCreate method.
|
||||
In most cases you can leave this as-is, but you if you want to provide
|
||||
additional functionality it is fine to subclass or reimplement
|
||||
FlutterApplication and put your custom class here. -->
|
||||
<application android:name="io.flutter.app.FlutterApplication" android:label="Platform Interaction" android:icon="@mipmap/ic_launcher">
|
||||
<activity android:name="com.yourcompany.platforminteraction.MainActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@android:style/Theme.Black.NoTitleBar"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
||||
@@ -0,0 +1,17 @@
|
||||
// Copyright 2019 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package com.yourcompany.platforminteraction;
|
||||
|
||||
import android.os.Bundle;
|
||||
import io.flutter.app.FlutterActivity;
|
||||
import io.flutter.plugins.GeneratedPluginRegistrant;
|
||||
|
||||
public class MainActivity extends FlutterActivity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
GeneratedPluginRegistrant.registerWith(this);
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 544 B |
Binary file not shown.
|
After Width: | Height: | Size: 442 B |
Binary file not shown.
|
After Width: | Height: | Size: 721 B |
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
29
dev/integration_tests/codegen/android/build.gradle
Normal file
29
dev/integration_tests/codegen/android/build.gradle
Normal file
@@ -0,0 +1,29 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.2.1'
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.buildDir = '../build'
|
||||
subprojects {
|
||||
project.buildDir = "${rootProject.buildDir}/${project.name}"
|
||||
}
|
||||
subprojects {
|
||||
project.evaluationDependsOn(':app')
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
||||
1
dev/integration_tests/codegen/android/gradle.properties
Normal file
1
dev/integration_tests/codegen/android/gradle.properties
Normal file
@@ -0,0 +1 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
6
dev/integration_tests/codegen/android/gradle/wrapper/gradle-wrapper.properties
vendored
Executable file
6
dev/integration_tests/codegen/android/gradle/wrapper/gradle-wrapper.properties
vendored
Executable file
@@ -0,0 +1,6 @@
|
||||
#Fri Jun 23 08:50:38 CEST 2017
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip
|
||||
15
dev/integration_tests/codegen/android/settings.gradle
Normal file
15
dev/integration_tests/codegen/android/settings.gradle
Normal file
@@ -0,0 +1,15 @@
|
||||
include ':app'
|
||||
|
||||
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
|
||||
|
||||
def plugins = new Properties()
|
||||
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
|
||||
if (pluginsFile.exists()) {
|
||||
pluginsFile.withInputStream { stream -> plugins.load(stream) }
|
||||
}
|
||||
|
||||
plugins.each { name, path ->
|
||||
def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
|
||||
include ":$name"
|
||||
project(":$name").projectDir = pluginDirectory
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>App</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>io.flutter.flutter.app</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>App</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>8.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
1
dev/integration_tests/codegen/ios/Flutter/Debug.xcconfig
Normal file
1
dev/integration_tests/codegen/ios/Flutter/Debug.xcconfig
Normal file
@@ -0,0 +1 @@
|
||||
#include "Generated.xcconfig"
|
||||
@@ -0,0 +1 @@
|
||||
#include "Generated.xcconfig"
|
||||
@@ -0,0 +1,506 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||
3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
|
||||
3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; };
|
||||
9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; };
|
||||
978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; };
|
||||
97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; };
|
||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */,
|
||||
9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */,
|
||||
);
|
||||
name = "Embed Frameworks";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||
3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = "<group>"; };
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
||||
7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
||||
7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
||||
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
||||
9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = "<group>"; };
|
||||
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
97C146EB1CF9000F007C117D /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,
|
||||
3B80C3941E831B6300D905FE /* App.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
9740EEB11CF90186004384FC /* Flutter */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3B80C3931E831B6300D905FE /* App.framework */,
|
||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
|
||||
9740EEBA1CF902C7004384FC /* Flutter.framework */,
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */,
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
|
||||
9740EEB31CF90195004384FC /* Generated.xcconfig */,
|
||||
);
|
||||
name = Flutter;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146E51CF9000F007C117D = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9740EEB11CF90186004384FC /* Flutter */,
|
||||
97C146F01CF9000F007C117D /* Runner */,
|
||||
97C146EF1CF9000F007C117D /* Products */,
|
||||
CF3B75C9A7D2FA2A4C99F110 /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146EF1CF9000F007C117D /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
97C146EE1CF9000F007C117D /* Runner.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146F01CF9000F007C117D /* Runner */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */,
|
||||
7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */,
|
||||
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
||||
97C146FD1CF9000F007C117D /* Assets.xcassets */,
|
||||
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
|
||||
97C147021CF9000F007C117D /* Info.plist */,
|
||||
97C146F11CF9000F007C117D /* Supporting Files */,
|
||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
|
||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
|
||||
);
|
||||
path = Runner;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146F11CF9000F007C117D /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
97C146F21CF9000F007C117D /* main.m */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
97C146ED1CF9000F007C117D /* Runner */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||
buildPhases = (
|
||||
9740EEB61CF901F6004384FC /* Run Script */,
|
||||
97C146EA1CF9000F007C117D /* Sources */,
|
||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||
97C146EC1CF9000F007C117D /* Resources */,
|
||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = Runner;
|
||||
productName = Runner;
|
||||
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
97C146E61CF9000F007C117D /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0910;
|
||||
ORGANIZATIONNAME = "The Chromium Authors";
|
||||
TargetAttributes = {
|
||||
97C146ED1CF9000F007C117D = {
|
||||
CreatedOnToolsVersion = 7.3.1;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 97C146E51CF9000F007C117D;
|
||||
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
97C146ED1CF9000F007C117D /* Runner */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
97C146EC1CF9000F007C117D /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
|
||||
9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */,
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
|
||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Thin Binary";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin";
|
||||
};
|
||||
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Run Script";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
97C146EA1CF9000F007C117D /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */,
|
||||
97C146F31CF9000F007C117D /* main.m in Sources */,
|
||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
97C146FB1CF9000F007C117D /* Base */,
|
||||
);
|
||||
name = Main.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
97C147001CF9000F007C117D /* Base */,
|
||||
);
|
||||
name = LaunchScreen.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
249021D3217E4FDB00AE95B9 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
249021D4217E4FDB00AE95B9 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = S8QB4VV633;
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter",
|
||||
);
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.iosExample;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
97C147031CF9000F007C117D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
97C147041CF9000F007C117D /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
97C147061CF9000F007C117D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter",
|
||||
);
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.iosExample;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
97C147071CF9000F007C117D /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter",
|
||||
);
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.iosExample;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
97C147031CF9000F007C117D /* Debug */,
|
||||
97C147041CF9000F007C117D /* Release */,
|
||||
249021D3217E4FDB00AE95B9 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
97C147061CF9000F007C117D /* Debug */,
|
||||
97C147071CF9000F007C117D /* Release */,
|
||||
249021D4217E4FDB00AE95B9 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 97C146E61CF9000F007C117D /* Project object */;
|
||||
}
|
||||
7
dev/integration_tests/codegen/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
dev/integration_tests/codegen/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:Runner.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@@ -0,0 +1,93 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0910"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||
BuildableName = "Runner.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||
BuildableName = "Runner.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||
BuildableName = "Runner.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Profile"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||
BuildableName = "Runner.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
7
dev/integration_tests/codegen/ios/Runner.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
dev/integration_tests/codegen/ios/Runner.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:Runner.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user