diff --git a/.cirrus.yml b/.cirrus.yml index 16e84e60f2..b7b1062d04 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -4,7 +4,7 @@ # YAML anchors used to share fields between tasks. # See https://confluence.atlassian.com/bitbucket/yaml-anchors-960154027.html web_shard_template: &WEB_SHARD_TEMPLATE - only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'packages/flutter_web_plugins/**', 'bin/internal/**') || $CIRRUS_PR == ''" + only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'packages/flutter_web_plugins/**', 'bin/**') || $CIRRUS_PR == ''" environment: # As of March 2020, the Web shards needed 16G of RAM and 4 CPUs to run all framework tests with goldens without flaking. WEB_SHARD_COUNT: 8 @@ -24,12 +24,12 @@ linux_shard_template: &LINUX_SHARD_TEMPLATE - dart --enable-asserts ./dev/bots/test.dart windows_shard_template: &WINDOWS_SHARD_TEMPLATE - only_if: "changesInclude('.cirrus.yml', 'dev/**', 'bin/internal/**') || $CIRRUS_PR == ''" # https://github.com/flutter/flutter/issues/41941 + only_if: "changesInclude('.cirrus.yml', 'dev/**', 'bin/**') || $CIRRUS_PR == ''" # https://github.com/flutter/flutter/issues/41941 script: - dart --enable-asserts ./dev/bots/test.dart macos_shard_template: &MACOS_SHARD_TEMPLATE - only_if: "changesInclude('.cirrus.yml', 'dev/**', 'bin/internal/**') || $CIRRUS_PR == ''" # https://github.com/flutter/flutter/issues/41941 + only_if: "changesInclude('.cirrus.yml', 'dev/**', 'bin/**') || $CIRRUS_PR == ''" # https://github.com/flutter/flutter/issues/41941 script: - ulimit -S -n 2048 # https://github.com/flutter/flutter/issues/2976 - dart --enable-asserts ./dev/bots/test.dart @@ -127,7 +127,7 @@ task: - flutter precache --flutter_runner --no-android --no-ios - name: framework_tests-widgets-linux - only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'bin/internal/**') || $CIRRUS_PR == ''" + only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'bin/**') || $CIRRUS_PR == ''" environment: # We use 3 CPUs because that's the minimum required to get framework_tests-widgets-linux # running fast enough that it is not the long pole, as of October 2019. @@ -137,7 +137,7 @@ task: - dart --enable-asserts ./dev/bots/test.dart - name: framework_tests-libraries-linux - only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'bin/internal/**') || $CIRRUS_PR == ''" + only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'bin/**') || $CIRRUS_PR == ''" environment: # We use 3 CPUs because that's the minimum required to get the # framework_tests-libraries-linux shard running fast enough that it is not the long pole, as @@ -149,7 +149,7 @@ task: - name: framework_tests-misc-linux # this includes the tests for directories in dev/ - only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_goldens/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'bin/internal/**') || $CIRRUS_PR == ''" + only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_goldens/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'bin/**') || $CIRRUS_PR == ''" environment: # We use 3 CPUs because that's the minimum required to get framework_tests-misc-linux # running fast enough that it is not the long pole, as of October 2019. @@ -158,7 +158,7 @@ task: - dart --enable-asserts ./dev/bots/test.dart - name: tool_tests-general-linux - only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter_tools/**', 'bin/internal/**') || $CIRRUS_PR == ''" + only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter_tools/**', 'bin/**') || $CIRRUS_PR == ''" environment: # As of November 2019, the tool_tests-general-linux shard got faster with more CPUs up to 4 # CPUs, and needed at least 10G of RAM to not run out of memory. @@ -168,7 +168,7 @@ task: - dart --enable-asserts ./dev/bots/test.dart - name: tool_tests-commands-linux - only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter_tools/**', 'bin/internal/**') || $CIRRUS_PR == ''" + only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter_tools/**', 'bin/**') || $CIRRUS_PR == ''" environment: # As of October 2019, the tool_tests-commands-linux shard got faster with more CPUs up to 6 # CPUs, and needed at least 8G of RAM to not run out of memory. @@ -179,7 +179,7 @@ task: - dart --enable-asserts ./dev/bots/test.dart - name: tool_tests-integration-linux - only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter_tools/**', 'bin/internal/**') || $CIRRUS_PR == ''" + only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter_tools/**', 'bin/**') || $CIRRUS_PR == ''" environment: # As of October 2019, the tool_tests-integration-linux shard got faster with more CPUs up to # 6 CPUs, and needed at least 8G of RAM to not run out of memory. @@ -202,7 +202,7 @@ task: - bash <(curl -s https://codecov.io/bash) -c -f packages/flutter_tools/coverage/lcov.info -F flutter_tool - name: web_integration_tests - only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/**', 'packages/flutter_web_plugins/**', 'bin/internal/**') || $CIRRUS_PR == ''" + only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/**', 'packages/flutter_web_plugins/**', 'bin/**') || $CIRRUS_PR == ''" environment: # As of October 2019, the Web shards needed more than 6G of RAM. CPU: 2 @@ -271,7 +271,7 @@ task: # TODO(ianh): name: add_to_app_tests-linux - name: docs-linux # linux-only - only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_drive/**', 'packages/flutter_localizations/**', 'packages/flutter_goldens/**', 'bin/internal/**') || $CIRRUS_PR == ''" + only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_drive/**', 'packages/flutter_localizations/**', 'packages/flutter_goldens/**', 'bin/**') || $CIRRUS_PR == ''" environment: # Empirically, as of October 2019, the docs-linux shard took about 30 minutes when run with # 1 CPU and 4G of RAM. 2 CPUs reduced that to 20 minutes, more CPUs did not improve matters. @@ -303,7 +303,7 @@ task: <<: *FIREBASE_SHARD_TEMPLATE - name: web_smoke_test - only_if: "changesInclude('.cirrus.yml', 'examples/hello_world/**' ,'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'packages/flutter_web_plugins/**', 'bin/internal/**') || $CIRRUS_PR == ''" + only_if: "changesInclude('.cirrus.yml', 'examples/hello_world/**' ,'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'packages/flutter_web_plugins/**', 'bin/**') || $CIRRUS_PR == ''" environment: # Tests Hello World with Flutter Web Engine using Flutter Driver. Should not need more resources. CPU: 2 @@ -370,7 +370,7 @@ task: - git fetch origin master matrix: - name: framework_tests-widgets-windows - only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'bin/internal/**') || $CIRRUS_PR == ''" + only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'bin/**') || $CIRRUS_PR == ''" environment: # As of December 2019, framework_tests-widgets-windows needs 4 CPUs to pass reliably. # With a min of 4 CPUs and 4 GB of RAM, it ran in about 50 minutes. Increasing to 8 CPUs and @@ -385,7 +385,7 @@ task: - dart --enable-asserts dev\bots\test.dart - name: framework_tests-libraries-windows - only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'bin/internal/**') || $CIRRUS_PR == ''" + only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'bin/**') || $CIRRUS_PR == ''" environment: # As of December 2019, the framework_tests-libraries-windows shard needed 2 CPUs to pass. # With a min of 2 CPUs and 2 GB RAM, it ran in about 60 minutes. Increasing to 8 CPUs made @@ -401,7 +401,7 @@ task: - name: framework_tests-misc-windows # this includes the tests for directories in dev/ - only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_goldens/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'bin/internal/**') || $CIRRUS_PR == ''" + only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_goldens/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'bin/**') || $CIRRUS_PR == ''" environment: # As of December 2019, the framework_tests-misc-windows shard needed 2 CPUs and 3 GB RAM # to pass (taking ~40 minutes). Increasing to 4 CPUs (necessitating 4 GB RAM per Cirrus) @@ -412,7 +412,7 @@ task: - dart --enable-asserts dev\bots\test.dart - name: tool_tests-general-windows - only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter_tools/**', 'bin/internal/**') || $CIRRUS_PR == ''" + only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter_tools/**', 'bin/**') || $CIRRUS_PR == ''" environment: # As of December 2019, the tool_tests-general-windows shard required 2 CPUs and 8 GB RAM to # pass. Raising that to 4 CPUs sped it up to ~30 minutes, with further provisioning yielding @@ -423,7 +423,7 @@ task: - dart --enable-asserts ./dev/bots/test.dart - name: tool_tests-commands-windows - only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter_tools/**', 'bin/internal/**') || $CIRRUS_PR == ''" + only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter_tools/**', 'bin/**') || $CIRRUS_PR == ''" environment: # As of December 2019, the tool_tests-commands-windows shard needed 4 CPUs and 8 GB RAM to # reliably pass and not be the long pole, running in about 25 minutes. Bumping beyond these @@ -434,7 +434,7 @@ task: - dart --enable-asserts ./dev/bots/test.dart - name: tool_tests-integration-windows - only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter_tools/**', 'bin/internal/**') || $CIRRUS_PR == ''" + only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter_tools/**', 'bin/**') || $CIRRUS_PR == ''" environment: # As of December 2019, the tool_tests-integration-windows shard required 6 GB RAM to pass. # Emperically, 4 CPUs and 10 GB RAM yielded optimal results (~22 minutes); bumping beyond @@ -447,7 +447,7 @@ task: # TODO(ianh): Enable Web tests on Windows - name: build_tests-0-windows - only_if: "changesInclude('.cirrus.yml', 'dev/**', 'bin/internal/**') || $CIRRUS_PR == ''" # https://github.com/flutter/flutter/issues/41941 + only_if: "changesInclude('.cirrus.yml', 'dev/**', 'bin/**') || $CIRRUS_PR == ''" # https://github.com/flutter/flutter/issues/41941 environment: # As of December 2019, the build_tests-windows shard requires 6 GB RAM to pass. # Emperically, using 6 CPUs and 10 GB RAM yielded optimal results (~33 minutes); @@ -458,7 +458,7 @@ task: - dart --enable-asserts dev\bots\test.dart - name: build_tests-1_last-windows - only_if: "changesInclude('.cirrus.yml', 'dev/**', 'bin/internal/**') || $CIRRUS_PR == ''" # https://github.com/flutter/flutter/issues/41941 + only_if: "changesInclude('.cirrus.yml', 'dev/**', 'bin/**') || $CIRRUS_PR == ''" # https://github.com/flutter/flutter/issues/41941 environment: # As of December 2019, the build_tests-windows shard requires 6 GB RAM to pass. # Emperically, using 6 CPUs and 10 GB RAM yielded optimal results (~33 minutes); @@ -552,7 +552,7 @@ task: - which flutter matrix: - name: framework_tests-widgets-macos - only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'bin/internal/**') || $CIRRUS_PR == ''" + only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'bin/**') || $CIRRUS_PR == ''" environment: GOLDCTL: "$CIRRUS_WORKING_DIR/depot_tools/goldctl" GOLD_SERVICE_ACCOUNT: ENCRYPTED[3afeea5ac7201151c3d0dc9648862f0462b5e4f55dc600ca8b692319622f7c3eda3d577b1b16cc2ef0311b7314c1c095] @@ -562,7 +562,7 @@ task: - dart --enable-asserts dev/bots/test.dart - name: framework_tests-libraries-macos - only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'bin/internal/**') || $CIRRUS_PR == ''" + only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'bin/**') || $CIRRUS_PR == ''" environment: GOLDCTL: "$CIRRUS_WORKING_DIR/depot_tools/goldctl" GOLD_SERVICE_ACCOUNT: ENCRYPTED[3afeea5ac7201151c3d0dc9648862f0462b5e4f55dc600ca8b692319622f7c3eda3d577b1b16cc2ef0311b7314c1c095] @@ -573,25 +573,25 @@ task: - name: framework_tests-misc-macos # this includes the tests for directories in dev/ - only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_goldens/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'bin/internal/**') || $CIRRUS_PR == ''" + only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter/**', 'packages/flutter_goldens/**', 'packages/flutter_test/**', 'packages/flutter_tools/lib/src/test/**', 'bin/**') || $CIRRUS_PR == ''" script: - ulimit -S -n 2048 # https://github.com/flutter/flutter/issues/2976 - dart --enable-asserts dev/bots/test.dart - name: tool_tests-general-macos - only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter_tools/**', 'bin/internal/**') || $CIRRUS_PR == ''" + only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter_tools/**', 'bin/**') || $CIRRUS_PR == ''" script: - ulimit -S -n 2048 # https://github.com/flutter/flutter/issues/2976 - dart --enable-asserts ./dev/bots/test.dart - name: tool_tests-commands-macos - only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter_tools/**', 'bin/internal/**') || $CIRRUS_PR == ''" + only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter_tools/**', 'bin/**') || $CIRRUS_PR == ''" script: - ulimit -S -n 2048 # https://github.com/flutter/flutter/issues/2976 - dart --enable-asserts ./dev/bots/test.dart - name: tool_tests-integration-macos - only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter_tools/**', 'bin/internal/**') || $CIRRUS_PR == ''" + only_if: "changesInclude('.cirrus.yml', 'dev/**', 'packages/flutter_tools/**', 'bin/**') || $CIRRUS_PR == ''" script: - ulimit -S -n 2048 # https://github.com/flutter/flutter/issues/2976 - dart --enable-asserts ./dev/bots/test.dart @@ -599,12 +599,12 @@ task: # TODO(ianh): Enable Web tests on macOS. - name: build_tests-0-macos - only_if: "changesInclude('.cirrus.yml', 'dev/**', 'bin/internal/**') || $CIRRUS_PR == ''" # https://github.com/flutter/flutter/issues/41940 + only_if: "changesInclude('.cirrus.yml', 'dev/**', 'bin/**') || $CIRRUS_PR == ''" # https://github.com/flutter/flutter/issues/41940 script: - dart --enable-asserts ./dev/bots/test.dart - name: build_tests-1_last-macos - only_if: "changesInclude('.cirrus.yml', 'dev/**', 'bin/internal/**') || $CIRRUS_PR == ''" # https://github.com/flutter/flutter/issues/41940 + only_if: "changesInclude('.cirrus.yml', 'dev/**', 'bin/**') || $CIRRUS_PR == ''" # https://github.com/flutter/flutter/issues/41940 script: - dart --enable-asserts ./dev/bots/test.dart @@ -621,7 +621,7 @@ task: << : *MACOS_SHARD_TEMPLATE - name: add_to_app_tests-macos - only_if: "changesInclude('.cirrus.yml', 'dev/**', 'bin/internal/**') || $CIRRUS_PR == ''" # https://github.com/flutter/flutter/issues/41940 + only_if: "changesInclude('.cirrus.yml', 'dev/**', 'bin/**') || $CIRRUS_PR == ''" # https://github.com/flutter/flutter/issues/41940 skip: true # https://github.com/flutter/flutter/pull/42444 script: - ulimit -S -n 2048 # https://github.com/flutter/flutter/issues/2976 diff --git a/bin/dart b/bin/dart new file mode 100755 index 0000000000..a2d317f79c --- /dev/null +++ b/bin/dart @@ -0,0 +1,43 @@ +#!/usr/bin/env bash +# Copyright 2014 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. + +# ---------------------------------- NOTE ---------------------------------- # +# +# Please keep the logic in this file consistent with the logic in the +# `dart.bat` script in the same directory to ensure that Flutter & Dart continue +# to work across all platforms! +# +# -------------------------------------------------------------------------- # + +set -e + +unset CDPATH + +function follow_links() { + cd -P "${1%/*}" + local file="$PWD/${1##*/}" + while [[ -h "$file" ]]; do + # On Mac OS, readlink -f doesn't work. + cd -P "${file%/*}" + file="$(readlink "$file")" + cd -P "${file%/*}" + file="$PWD/${file##*/}" + done + echo "$PWD/${file##*/}" +} + +# Convert a filesystem path to a format usable by Dart's URI parser. +function path_uri() { + # Reduce multiple leading slashes to a single slash. + echo "$1" | sed -E -e "s,^/+,/," +} + +PROG_NAME="$(path_uri "$(follow_links "$BASH_SOURCE")")" +BIN_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)" + +# To define `shared::execute()` function +source "$BIN_DIR/shared.sh" + +shared::execute "$@" diff --git a/bin/dart.bat b/bin/dart.bat new file mode 100644 index 0000000000..4927aaefa7 --- /dev/null +++ b/bin/dart.bat @@ -0,0 +1,37 @@ +@ECHO off +REM Copyright 2014 The Flutter Authors. All rights reserved. +REM Use of this source code is governed by a BSD-style license that can be +REM found in the LICENSE file. + +REM ---------------------------------- NOTE ---------------------------------- +REM +REM Please keep the logic in this file consistent with the logic in the +REM `dart` script in the same directory to ensure that Flutter & Dart continue to +REM work across all platforms! +REM +REM -------------------------------------------------------------------------- + +SETLOCAL ENABLEDELAYEDEXPANSION + +FOR %%i IN ("%~dp0..") DO SET FLUTTER_ROOT=%%~fi + +REM Include shared scripts in shared.bat +SET shared_bin=%FLUTTER_ROOT%/bin/internal/shared.bat +CALL "%shared_bin%" + +SET cache_dir=%FLUTTER_ROOT%\bin\cache +SET dart_sdk_path=%cache_dir%\dart-sdk +SET dart=%dart_sdk_path%\bin\dart.exe + +REM Chaining the call to 'dart' and 'exit' with an ampersand ensures that +REM Windows reads both commands into memory once before executing them. This +REM avoids nasty errors that may otherwise occur when the dart command (e.g. as +REM part of 'flutter upgrade') modifies this batch script while it is executing. +REM +REM Do not use the CALL command in the next line to execute Dart. CALL causes +REM Windows to re-read the line from disk after the CALL command has finished +REM regardless of the ampersand chain. +"%dart%" %* & exit /B !ERRORLEVEL! + +:final_exit +EXIT /B %exit_code% diff --git a/bin/flutter b/bin/flutter index 87bd597110..89ec060c89 100755 --- a/bin/flutter +++ b/bin/flutter @@ -3,7 +3,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. - # ---------------------------------- NOTE ---------------------------------- # # # Please keep the logic in this file consistent with the logic in the @@ -35,158 +34,10 @@ function path_uri() { echo "$1" | sed -E -e "s,^/+,/," } -function _rmlock () { - [ -n "$FLUTTER_UPGRADE_LOCK" ] && rm -f "$FLUTTER_UPGRADE_LOCK" -} - -function retry_upgrade { - local total_tries="10" - local remaining_tries=$((total_tries - 1)) - while [[ "$remaining_tries" -gt 0 ]]; do - (cd "$FLUTTER_TOOLS_DIR" && "$PUB" upgrade "$VERBOSITY" --no-precompile) && break - echo "Error: Unable to 'pub upgrade' flutter tool. Retrying in five seconds... ($remaining_tries tries left)" - remaining_tries=$((remaining_tries - 1)) - sleep 5 - done - - if [[ "$remaining_tries" == 0 ]]; then - echo "Command 'pub upgrade' still failed after $total_tries tries, giving up." - return 1 - fi - return 0 -} - -function upgrade_flutter () { - mkdir -p "$FLUTTER_ROOT/bin/cache" - - # This function is executed with a redirect that pipes the source of - # this script into file descriptor 3. - # - # To ensure that we don't simultaneously update Dart in multiple - # parallel instances, we try to obtain an exclusive lock on this - # file descriptor (and thus this script's source file) while we are - # updating Dart and compiling the script. To do this, we try to use - # the command line program "flock", which is available on many - # Unix-like platforms, in particular on most Linux distributions. - # You give it a file descriptor, and it locks the corresponding - # file, having inherited the file descriptor from the shell. - # - # Complicating matters, there are two major scenarios where this - # will not work. - # - # The first is if the platform doesn't have "flock", for example on Mac. - # There is not a direct equivalent, so on platforms that don't have flock, - # we fall back to using a lockfile and spinlock with "shlock". This - # doesn't work as well over NFS as it relies on PIDs. Any platform - # without either of these tools has no locking at all. To determine if we - # have "flock" or "shlock" available, we abuse the "hash" shell built-in. - # - # The second complication is NFS. On NFS, to obtain an exclusive - # lock you need a file descriptor that is open for writing, because - # NFS implements exclusive locks by writing, or some such. Thus, we - # ignore errors from flock. We do so by using the '|| true' trick, - # since we are running in a 'set -e' environment wherein all errors - # are fatal, and by redirecting all output to /dev/null, since - # users will typically not care about errors from flock and are - # more likely to be confused by them than helped. - # - # For "flock", the lock is released when the file descriptor goes out of - # scope, i.e. when this function returns. The lock is released via - # a trap when using "shlock". - if hash flock 2>/dev/null; then - flock 3 2>/dev/null || true - elif hash shlock 2>/dev/null; then - FLUTTER_UPGRADE_LOCK="$FLUTTER_ROOT/bin/cache/.upgrade_lock" - while ! shlock -f "$FLUTTER_UPGRADE_LOCK" -p $$ ; do sleep .1 ; done - trap _rmlock EXIT - fi - - local revision="$(cd "$FLUTTER_ROOT"; git rev-parse HEAD)" - - # Invalidate cache if: - # * SNAPSHOT_PATH is not a file, or - # * STAMP_PATH is not a file with nonzero size, or - # * Contents of STAMP_PATH is not our local git HEAD revision, or - # * pubspec.yaml last modified after pubspec.lock - if [[ ! -f "$SNAPSHOT_PATH" || ! -s "$STAMP_PATH" || "$(cat "$STAMP_PATH")" != "$revision" || "$FLUTTER_TOOLS_DIR/pubspec.yaml" -nt "$FLUTTER_TOOLS_DIR/pubspec.lock" ]]; then - rm -f "$FLUTTER_ROOT/version" - touch "$FLUTTER_ROOT/bin/cache/.dartignore" - "$FLUTTER_ROOT/bin/internal/update_dart_sdk.sh" - VERBOSITY="--verbosity=error" - - echo Building flutter tool... - if [[ "$CI" == "true" || "$BOT" == "true" || "$CONTINUOUS_INTEGRATION" == "true" || "$CHROME_HEADLESS" == "1" ]]; then - PUB_ENVIRONMENT="$PUB_ENVIRONMENT:flutter_bot" - VERBOSITY="--verbosity=normal" - fi - export PUB_ENVIRONMENT="$PUB_ENVIRONMENT:flutter_install" - - if [[ -d "$FLUTTER_ROOT/.pub-cache" ]]; then - export PUB_CACHE="${PUB_CACHE:-"$FLUTTER_ROOT/.pub-cache"}" - fi - - retry_upgrade - - "$DART" --disable-dart-dev $FLUTTER_TOOL_ARGS --snapshot="$SNAPSHOT_PATH" --packages="$FLUTTER_TOOLS_DIR/.packages" --no-enable-mirrors "$SCRIPT_PATH" - echo "$revision" > "$STAMP_PATH" - fi - # The exit here is duplicitous since the function is run in a subshell, - # but this serves as documentation that running the function in a - # subshell is required to make sure any lockfile created by shlock - # is cleaned up. - exit $? -} - PROG_NAME="$(path_uri "$(follow_links "$BASH_SOURCE")")" BIN_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)" -export FLUTTER_ROOT="$(cd "${BIN_DIR}/.." ; pwd -P)" -FLUTTER_TOOLS_DIR="$FLUTTER_ROOT/packages/flutter_tools" -SNAPSHOT_PATH="$FLUTTER_ROOT/bin/cache/flutter_tools.snapshot" -STAMP_PATH="$FLUTTER_ROOT/bin/cache/flutter_tools.stamp" -SCRIPT_PATH="$FLUTTER_TOOLS_DIR/bin/flutter_tools.dart" -DART_SDK_PATH="$FLUTTER_ROOT/bin/cache/dart-sdk" +# To define `shared::execute()` function +source "$BIN_DIR/shared.sh" -DART="$DART_SDK_PATH/bin/dart" -PUB="$DART_SDK_PATH/bin/pub" - -# If running over git-bash, overrides the default UNIX -# executables with win32 executables -case "$(uname -s)" in - MINGW32*) - DART="$DART.exe" - PUB="$PUB.bat" - ;; -esac - -# Test if running as superuser – but don't warn if running within Docker -if [[ "$EUID" == "0" && ! -f /.dockerenv ]]; then - echo " Woah! You appear to be trying to run flutter as root." - echo " We strongly recommend running the flutter tool without superuser privileges." - echo " /" - echo "📎" -fi - -# Test if Git is available on the Host -if ! hash git 2>/dev/null; then - echo "Error: Unable to find git in your PATH." - exit 1 -fi -# Test if the flutter directory is a git clone (otherwise git rev-parse HEAD would fail) -if [[ ! -e "$FLUTTER_ROOT/.git" ]]; then - echo "Error: The Flutter directory is not a clone of the GitHub project." - echo " The flutter tool requires Git in order to operate properly;" - echo " to set up Flutter, run the following command:" - echo " git clone -b stable https://github.com/flutter/flutter.git" - exit 1 -fi - -# To debug the tool, you can uncomment the following lines to enable checked mode and set an observatory port: -# FLUTTER_TOOL_ARGS="--enable-asserts $FLUTTER_TOOL_ARGS" -# FLUTTER_TOOL_ARGS="$FLUTTER_TOOL_ARGS --observe=65432" - -(upgrade_flutter) 3< "$PROG_NAME" - -# FLUTTER_TOOL_ARGS isn't quoted below, because it is meant to be considered as -# separate space-separated args. -"$DART" --disable-dart-dev --packages="$FLUTTER_TOOLS_DIR/.packages" $FLUTTER_TOOL_ARGS "$SNAPSHOT_PATH" "$@" +shared::execute "$@" diff --git a/bin/flutter.bat b/bin/flutter.bat index d118e80d99..36b96fd0f8 100644 --- a/bin/flutter.bat +++ b/bin/flutter.bat @@ -6,7 +6,7 @@ REM found in the LICENSE file. REM ---------------------------------- NOTE ---------------------------------- REM REM Please keep the logic in this file consistent with the logic in the -REM `flutter` script in the same directory to ensure that Flutter continues to +REM `flutter` script in the same directory to ensure that Flutter & Dart continue to REM work across all platforms! REM REM -------------------------------------------------------------------------- @@ -15,171 +15,18 @@ SETLOCAL ENABLEDELAYEDEXPANSION FOR %%i IN ("%~dp0..") DO SET FLUTTER_ROOT=%%~fi +REM Include shared scripts in shared.bat +SET shared_bin=%FLUTTER_ROOT%/bin/internal/shared.bat +CALL "%shared_bin%" + SET flutter_tools_dir=%FLUTTER_ROOT%\packages\flutter_tools SET cache_dir=%FLUTTER_ROOT%\bin\cache SET snapshot_path=%cache_dir%\flutter_tools.snapshot -SET stamp_path=%cache_dir%\flutter_tools.stamp -SET script_path=%flutter_tools_dir%\bin\flutter_tools.dart SET dart_sdk_path=%cache_dir%\dart-sdk -SET engine_stamp=%cache_dir%\engine-dart-sdk.stamp -SET engine_version_path=%FLUTTER_ROOT%\bin\internal\engine.version -SET pub_cache_path=%FLUTTER_ROOT%\.pub-cache - SET dart=%dart_sdk_path%\bin\dart.exe -SET pub=%dart_sdk_path%\bin\pub.bat - -REM If available, add location of bundled mingit to PATH -SET mingit_path=%FLUTTER_ROOT%\bin\mingit\cmd -IF EXIST "%mingit_path%" SET PATH=%PATH%;%mingit_path% - -REM Test if Git is available on the Host -where /q git || ECHO Error: Unable to find git in your PATH. && EXIT /B 1 -REM Test if the flutter directory is a git clone, otherwise git rev-parse HEAD would fail -IF NOT EXIST "%flutter_root%\.git" ( - ECHO Error: The Flutter directory is not a clone of the GitHub project. - ECHO The flutter tool requires Git in order to operate properly; - ECHO to set up Flutter, run the following command: - ECHO git clone -b stable https://github.com/flutter/flutter.git - EXIT /B 1 -) - -REM Detect which PowerShell executable is available on the Host -REM PowerShell version <= 5: PowerShell.exe -REM PowerShell version >= 6: pwsh.exe -WHERE /Q pwsh.exe && ( - SET powershell_executable=pwsh.exe -) || WHERE /Q PowerShell.exe && ( - SET powershell_executable=PowerShell.exe -) || ( - ECHO Error: PowerShell executable not found. - ECHO Either pwsh.exe or PowerShell.exe must be in your PATH. - EXIT /B 1 -) - -REM Ensure that bin/cache exists. -IF NOT EXIST "%cache_dir%" MKDIR "%cache_dir%" - -REM If the cache still doesn't exist, fail with an error that we probably don't have permissions. -IF NOT EXIST "%cache_dir%" ( - ECHO Error: Unable to create cache directory at - ECHO %cache_dir% - ECHO. - ECHO This may be because flutter doesn't have write permissions for - ECHO this path. Try moving the flutter directory to a writable location, - ECHO such as within your home directory. - EXIT /B 1 -) - REM To debug the tool, you can uncomment the following lines to enable checked mode and set an observatory port: REM SET FLUTTER_TOOL_ARGS="--enable-asserts %FLUTTER_TOOL_ARGS%" -REM SET FLUTTER_TOOL_ARGS="%FLUTTER_TOOL_ARGS% --observe=65432" - -:acquire_lock -2>NUL ( - REM "3" is now stderr because of "2>NUL". - CALL :subroutine %* 2>&3 9> "%cache_dir%\flutter.bat.lock" || GOTO acquire_lock -) -GOTO :after_subroutine - -:subroutine - PUSHD "%flutter_root%" - FOR /f %%r IN ('git rev-parse HEAD') DO SET revision=%%r - POPD - - REM The following IF conditions are all linked with a logical OR. However, - REM there is no OR operator in batch and a GOTO construct is used as replacement. - - IF NOT EXIST "%engine_stamp%" GOTO do_sdk_update_and_snapshot - SET /P dart_required_version=<"%engine_version_path%" - SET /P dart_installed_version=<"%engine_stamp%" - IF !dart_required_version! NEQ !dart_installed_version! GOTO do_sdk_update_and_snapshot - IF NOT EXIST "%snapshot_path%" GOTO do_snapshot - IF NOT EXIST "%stamp_path%" GOTO do_snapshot - SET /P stamp_value=<"%stamp_path%" - IF !stamp_value! NEQ !revision! GOTO do_snapshot - SET pubspec_yaml_path=%flutter_tools_dir%\pubspec.yaml - SET pubspec_lock_path=%flutter_tools_dir%\pubspec.lock - FOR /F %%i IN ('DIR /B /O:D "%pubspec_yaml_path%" "%pubspec_lock_path%"') DO SET newer_file=%%i - FOR %%i IN (%pubspec_yaml_path%) DO SET pubspec_yaml_timestamp=%%~ti - FOR %%i IN (%pubspec_lock_path%) DO SET pubspec_lock_timestamp=%%~ti - IF "%pubspec_yaml_timestamp%" == "%pubspec_lock_timestamp%" SET newer_file="" - IF "%newer_file%" EQU "pubspec.yaml" GOTO do_snapshot - - REM Everything is up-to-date - exit subroutine - EXIT /B - - :do_sdk_update_and_snapshot - ECHO Checking Dart SDK version... - SET update_dart_bin=%FLUTTER_ROOT%/bin/internal/update_dart_sdk.ps1 - REM Escape apostrophes from the executable path - SET "update_dart_bin=!update_dart_bin:'=''!" - %powershell_executable% -ExecutionPolicy Bypass -Command "Unblock-File -Path '%update_dart_bin%'; & '%update_dart_bin%'" - IF "%ERRORLEVEL%" NEQ "0" ( - ECHO Error: Unable to update Dart SDK. Retrying... - timeout /t 5 /nobreak - GOTO :do_sdk_update_and_snapshot - ) - - :do_snapshot - IF EXIST "%FLUTTER_ROOT%\version" DEL "%FLUTTER_ROOT%\version" - ECHO: > "%cache_dir%\.dartignore" - ECHO Building flutter tool... - PUSHD "%flutter_tools_dir%" - - REM Makes changes to PUB_ENVIRONMENT only visible to commands within SETLOCAL/ENDLOCAL - SETLOCAL - SET VERBOSITY=--verbosity=error - IF "%CI%" == "true" GOTO on_bot - IF "%BOT%" == "true" GOTO on_bot - IF "%CONTINUOUS_INTEGRATION%" == "true" GOTO on_bot - IF "%CHROME_HEADLESS%" == "1" GOTO on_bot - GOTO not_on_bot - :on_bot - SET PUB_ENVIRONMENT=%PUB_ENVIRONMENT%:flutter_bot - SET VERBOSITY=--verbosity=normal - :not_on_bot - SET PUB_ENVIRONMENT=%PUB_ENVIRONMENT%:flutter_install - IF "%PUB_CACHE%" == "" ( - IF EXIST "%pub_cache_path%" SET PUB_CACHE=%pub_cache_path% - ) - - SET /A total_tries=10 - SET /A remaining_tries=%total_tries%-1 - :retry_pub_upgrade - ECHO Running pub upgrade... - CALL "%pub%" upgrade "%VERBOSITY%" --no-precompile - IF "%ERRORLEVEL%" EQU "0" goto :upgrade_succeeded - 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 - GOTO :retry_pub_upgrade - :upgrade_retries_exhausted - SET exit_code=%ERRORLEVEL% - ECHO Error: 'pub upgrade' still failing after %total_tries% tries, giving up. - GOTO final_exit - :upgrade_succeeded - ENDLOCAL - - POPD - - IF "%FLUTTER_TOOL_ARGS%" == "" ( - "%dart%" --disable-dart-dev --snapshot="%snapshot_path%" --packages="%flutter_tools_dir%\.packages" --no-enable-mirrors "%script_path%" - ) else ( - "%dart%" --disable-dart-dev "%FLUTTER_TOOL_ARGS%" --snapshot="%snapshot_path%" --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% - GOTO :final_exit - ) - >"%stamp_path%" ECHO %revision% - - REM Exit Subroutine - EXIT /B - -:after_subroutine REM Chaining the call to 'dart' and 'exit' with an ampersand ensures that REM Windows reads both commands into memory once before executing them. This diff --git a/bin/internal/shared.bat b/bin/internal/shared.bat new file mode 100644 index 0000000000..cd95979065 --- /dev/null +++ b/bin/internal/shared.bat @@ -0,0 +1,175 @@ +@ECHO off +REM Copyright 2014 The Flutter Authors. All rights reserved. +REM Use of this source code is governed by a BSD-style license that can be +REM found in the LICENSE file. + +REM ---------------------------------- NOTE ---------------------------------- +REM +REM Please keep the logic in this file consistent with the logic in the +REM `shared.sh` script in the same directory to ensure that Flutter & Dart continue to +REM work across all platforms! +REM +REM -------------------------------------------------------------------------- + +SETLOCAL ENABLEDELAYEDEXPANSION + +SET flutter_tools_dir=%FLUTTER_ROOT%\packages\flutter_tools +SET cache_dir=%FLUTTER_ROOT%\bin\cache +SET snapshot_path=%cache_dir%\flutter_tools.snapshot +SET stamp_path=%cache_dir%\flutter_tools.stamp +SET script_path=%flutter_tools_dir%\bin\flutter_tools.dart +SET dart_sdk_path=%cache_dir%\dart-sdk +SET engine_stamp=%cache_dir%\engine-dart-sdk.stamp +SET engine_version_path=%FLUTTER_ROOT%\bin\internal\engine.version +SET pub_cache_path=%FLUTTER_ROOT%\.pub-cache + +SET dart=%dart_sdk_path%\bin\dart.exe +SET pub=%dart_sdk_path%\bin\pub.bat + +REM If available, add location of bundled mingit to PATH +SET mingit_path=%FLUTTER_ROOT%\bin\mingit\cmd +IF EXIST "%mingit_path%" SET PATH=%PATH%;%mingit_path% + +REM Test if Git is available on the Host +where /q git || ECHO Error: Unable to find git in your PATH. && EXIT /B 1 +REM Test if the flutter directory is a git clone, otherwise git rev-parse HEAD would fail +IF NOT EXIST "%flutter_root%\.git" ( + ECHO Error: The Flutter directory is not a clone of the GitHub project. + ECHO The flutter tool requires Git in order to operate properly; + ECHO to set up Flutter, run the following command: + ECHO git clone -b stable https://github.com/flutter/flutter.git + EXIT /B 1 +) + +REM Detect which PowerShell executable is available on the Host +REM PowerShell version <= 5: PowerShell.exe +REM PowerShell version >= 6: pwsh.exe +WHERE /Q pwsh.exe && ( + SET powershell_executable=pwsh.exe +) || WHERE /Q PowerShell.exe && ( + SET powershell_executable=PowerShell.exe +) || ( + ECHO Error: PowerShell executable not found. + ECHO Either pwsh.exe or PowerShell.exe must be in your PATH. + EXIT /B 1 +) + +REM Ensure that bin/cache exists. +IF NOT EXIST "%cache_dir%" MKDIR "%cache_dir%" + +REM If the cache still doesn't exist, fail with an error that we probably don't have permissions. +IF NOT EXIST "%cache_dir%" ( + ECHO Error: Unable to create cache directory at + ECHO %cache_dir% + ECHO. + ECHO This may be because flutter doesn't have write permissions for + ECHO this path. Try moving the flutter directory to a writable location, + ECHO such as within your home directory. + EXIT /B 1 +) + +:acquire_lock +2>NUL ( + REM "3" is now stderr because of "2>NUL". + CALL :subroutine %* 2>&3 9> "%cache_dir%\flutter.bat.lock" || GOTO acquire_lock +) +GOTO :after_subroutine + +:subroutine + PUSHD "%flutter_root%" + FOR /f %%r IN ('git rev-parse HEAD') DO SET revision=%%r + POPD + + REM The following IF conditions are all linked with a logical OR. However, + REM there is no OR operator in batch and a GOTO construct is used as replacement. + + IF NOT EXIST "%engine_stamp%" GOTO do_sdk_update_and_snapshot + SET /P dart_required_version=<"%engine_version_path%" + SET /P dart_installed_version=<"%engine_stamp%" + IF !dart_required_version! NEQ !dart_installed_version! GOTO do_sdk_update_and_snapshot + IF NOT EXIST "%snapshot_path%" GOTO do_snapshot + IF NOT EXIST "%stamp_path%" GOTO do_snapshot + SET /P stamp_value=<"%stamp_path%" + IF !stamp_value! NEQ !revision! GOTO do_snapshot + SET pubspec_yaml_path=%flutter_tools_dir%\pubspec.yaml + SET pubspec_lock_path=%flutter_tools_dir%\pubspec.lock + FOR /F %%i IN ('DIR /B /O:D "%pubspec_yaml_path%" "%pubspec_lock_path%"') DO SET newer_file=%%i + FOR %%i IN (%pubspec_yaml_path%) DO SET pubspec_yaml_timestamp=%%~ti + FOR %%i IN (%pubspec_lock_path%) DO SET pubspec_lock_timestamp=%%~ti + IF "%pubspec_yaml_timestamp%" == "%pubspec_lock_timestamp%" SET newer_file="" + IF "%newer_file%" EQU "pubspec.yaml" GOTO do_snapshot + + REM Everything is up-to-date - exit subroutine + EXIT /B + + :do_sdk_update_and_snapshot + ECHO Checking Dart SDK version... + SET update_dart_bin=%FLUTTER_ROOT%/bin/internal/update_dart_sdk.ps1 + REM Escape apostrophes from the executable path + SET "update_dart_bin=!update_dart_bin:'=''!" + %powershell_executable% -ExecutionPolicy Bypass -Command "Unblock-File -Path '%update_dart_bin%'; & '%update_dart_bin%'" + IF "%ERRORLEVEL%" NEQ "0" ( + ECHO Error: Unable to update Dart SDK. Retrying... + timeout /t 5 /nobreak + GOTO :do_sdk_update_and_snapshot + ) + + :do_snapshot + IF EXIST "%FLUTTER_ROOT%\version" DEL "%FLUTTER_ROOT%\version" + ECHO: > "%cache_dir%\.dartignore" + ECHO Building flutter tool... + PUSHD "%flutter_tools_dir%" + + REM Makes changes to PUB_ENVIRONMENT only visible to commands within SETLOCAL/ENDLOCAL + SETLOCAL + SET VERBOSITY=--verbosity=error + IF "%CI%" == "true" GOTO on_bot + IF "%BOT%" == "true" GOTO on_bot + IF "%CONTINUOUS_INTEGRATION%" == "true" GOTO on_bot + IF "%CHROME_HEADLESS%" == "1" GOTO on_bot + GOTO not_on_bot + :on_bot + SET PUB_ENVIRONMENT=%PUB_ENVIRONMENT%:flutter_bot + SET VERBOSITY=--verbosity=normal + :not_on_bot + SET PUB_ENVIRONMENT=%PUB_ENVIRONMENT%:flutter_install + IF "%PUB_CACHE%" == "" ( + IF EXIST "%pub_cache_path%" SET PUB_CACHE=%pub_cache_path% + ) + + SET /A total_tries=10 + SET /A remaining_tries=%total_tries%-1 + :retry_pub_upgrade + ECHO Running pub upgrade... + CALL "%pub%" upgrade "%VERBOSITY%" --no-precompile + IF "%ERRORLEVEL%" EQU "0" goto :upgrade_succeeded + 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 + GOTO :retry_pub_upgrade + :upgrade_retries_exhausted + SET exit_code=%ERRORLEVEL% + ECHO Error: 'pub upgrade' still failing after %total_tries% tries, giving up. + GOTO final_exit + :upgrade_succeeded + ENDLOCAL + + POPD + + IF "%FLUTTER_TOOL_ARGS%" == "" ( + "%dart%" --snapshot="%snapshot_path%" --packages="%flutter_tools_dir%\.packages" --no-enable-mirrors "%script_path%" + ) else ( + "%dart%" "%FLUTTER_TOOL_ARGS%" --snapshot="%snapshot_path%" --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% + GOTO :final_exit + ) + >"%stamp_path%" ECHO %revision% + + REM Exit Subroutine + EXIT /B + +:after_subroutine diff --git a/bin/shared.sh b/bin/shared.sh new file mode 100755 index 0000000000..22a5b98209 --- /dev/null +++ b/bin/shared.sh @@ -0,0 +1,189 @@ +#!/usr/bin/env bash +# Copyright 2014 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. + + +# ---------------------------------- NOTE ---------------------------------- # +# +# Please keep the logic in this file consistent with the logic in the +# `shared.bat` script in the same directory to ensure that Flutter & Dart continue +# to work across all platforms! +# +# -------------------------------------------------------------------------- # + +set -e + +unset CDPATH + +function _rmlock () { + [ -n "$FLUTTER_UPGRADE_LOCK" ] && rm -f "$FLUTTER_UPGRADE_LOCK" +} + +function retry_upgrade { + local total_tries="10" + local remaining_tries=$((total_tries - 1)) + while [[ "$remaining_tries" -gt 0 ]]; do + (cd "$FLUTTER_TOOLS_DIR" && "$PUB" upgrade "$VERBOSITY" --no-precompile) && break + echo "Error: Unable to 'pub upgrade' flutter tool. Retrying in five seconds... ($remaining_tries tries left)" + remaining_tries=$((remaining_tries - 1)) + sleep 5 + done + + if [[ "$remaining_tries" == 0 ]]; then + echo "Command 'pub upgrade' still failed after $total_tries tries, giving up." + return 1 + fi + return 0 +} + +function upgrade_flutter () { + mkdir -p "$FLUTTER_ROOT/bin/cache" + + # This function is executed with a redirect that pipes the source of + # this script into file descriptor 3. + # + # To ensure that we don't simultaneously update Dart in multiple + # parallel instances, we try to obtain an exclusive lock on this + # file descriptor (and thus this script's source file) while we are + # updating Dart and compiling the script. To do this, we try to use + # the command line program "flock", which is available on many + # Unix-like platforms, in particular on most Linux distributions. + # You give it a file descriptor, and it locks the corresponding + # file, having inherited the file descriptor from the shell. + # + # Complicating matters, there are two major scenarios where this + # will not work. + # + # The first is if the platform doesn't have "flock", for example on Mac. + # There is not a direct equivalent, so on platforms that don't have flock, + # we fall back to using a lockfile and spinlock with "shlock". This + # doesn't work as well over NFS as it relies on PIDs. Any platform + # without either of these tools has no locking at all. To determine if we + # have "flock" or "shlock" available, we abuse the "hash" shell built-in. + # + # The second complication is NFS. On NFS, to obtain an exclusive + # lock you need a file descriptor that is open for writing, because + # NFS implements exclusive locks by writing, or some such. Thus, we + # ignore errors from flock. We do so by using the '|| true' trick, + # since we are running in a 'set -e' environment wherein all errors + # are fatal, and by redirecting all output to /dev/null, since + # users will typically not care about errors from flock and are + # more likely to be confused by them than helped. + # + # For "flock", the lock is released when the file descriptor goes out of + # scope, i.e. when this function returns. The lock is released via + # a trap when using "shlock". + if hash flock 2>/dev/null; then + flock 3 2>/dev/null || true + elif hash shlock 2>/dev/null; then + FLUTTER_UPGRADE_LOCK="$FLUTTER_ROOT/bin/cache/.upgrade_lock" + while ! shlock -f "$FLUTTER_UPGRADE_LOCK" -p $$ ; do sleep .1 ; done + trap _rmlock EXIT + fi + + local revision="$(cd "$FLUTTER_ROOT"; git rev-parse HEAD)" + + # Invalidate cache if: + # * SNAPSHOT_PATH is not a file, or + # * STAMP_PATH is not a file with nonzero size, or + # * Contents of STAMP_PATH is not our local git HEAD revision, or + # * pubspec.yaml last modified after pubspec.lock + if [[ ! -f "$SNAPSHOT_PATH" || ! -s "$STAMP_PATH" || "$(cat "$STAMP_PATH")" != "$revision" || "$FLUTTER_TOOLS_DIR/pubspec.yaml" -nt "$FLUTTER_TOOLS_DIR/pubspec.lock" ]]; then + rm -f "$FLUTTER_ROOT/version" + touch "$FLUTTER_ROOT/bin/cache/.dartignore" + "$FLUTTER_ROOT/bin/internal/update_dart_sdk.sh" + VERBOSITY="--verbosity=error" + + echo Building flutter tool... + if [[ "$CI" == "true" || "$BOT" == "true" || "$CONTINUOUS_INTEGRATION" == "true" || "$CHROME_HEADLESS" == "1" ]]; then + PUB_ENVIRONMENT="$PUB_ENVIRONMENT:flutter_bot" + VERBOSITY="--verbosity=normal" + fi + export PUB_ENVIRONMENT="$PUB_ENVIRONMENT:flutter_install" + + if [[ -d "$FLUTTER_ROOT/.pub-cache" ]]; then + export PUB_CACHE="${PUB_CACHE:-"$FLUTTER_ROOT/.pub-cache"}" + fi + + retry_upgrade + + "$DART" --disable-dart-dev $FLUTTER_TOOL_ARGS --snapshot="$SNAPSHOT_PATH" --packages="$FLUTTER_TOOLS_DIR/.packages" --no-enable-mirrors "$SCRIPT_PATH" + echo "$revision" > "$STAMP_PATH" + fi + # The exit here is duplicitous since the function is run in a subshell, + # but this serves as documentation that running the function in a + # subshell is required to make sure any lockfile created by shlock + # is cleaned up. + exit $? +} + +# This function is intended to be executed by entrypoints (e.g. `//bin/flutter` +# and `//bin/dart`) +function shared::execute() { + export FLUTTER_ROOT="$(cd "${BIN_DIR}/.." ; pwd -P)" + + FLUTTER_TOOLS_DIR="$FLUTTER_ROOT/packages/flutter_tools" + SNAPSHOT_PATH="$FLUTTER_ROOT/bin/cache/flutter_tools.snapshot" + STAMP_PATH="$FLUTTER_ROOT/bin/cache/flutter_tools.stamp" + SCRIPT_PATH="$FLUTTER_TOOLS_DIR/bin/flutter_tools.dart" + DART_SDK_PATH="$FLUTTER_ROOT/bin/cache/dart-sdk" + + DART="$DART_SDK_PATH/bin/dart" + PUB="$DART_SDK_PATH/bin/pub" + + # If running over git-bash, overrides the default UNIX + # executables with win32 executables + case "$(uname -s)" in + MINGW32*) + DART="$DART.exe" + PUB="$PUB.bat" + ;; + esac + + # Test if running as superuser – but don't warn if running within Docker + if [[ "$EUID" == "0" && ! -f /.dockerenv ]]; then + echo " Woah! You appear to be trying to run flutter as root." + echo " We strongly recommend running the flutter tool without superuser privileges." + echo " /" + echo "📎" + fi + + # Test if Git is available on the Host + if ! hash git 2>/dev/null; then + echo "Error: Unable to find git in your PATH." + exit 1 + fi + # Test if the flutter directory is a git clone (otherwise git rev-parse HEAD + # would fail) + if [[ ! -e "$FLUTTER_ROOT/.git" ]]; then + echo "Error: The Flutter directory is not a clone of the GitHub project." + echo " The flutter tool requires Git in order to operate properly;" + echo " to set up Flutter, run the following command:" + echo " git clone -b stable https://github.com/flutter/flutter.git" + exit 1 + fi + + # To debug the tool, you can uncomment the following lines to enable checked + # mode and set an observatory port: + # FLUTTER_TOOL_ARGS="--enable-asserts $FLUTTER_TOOL_ARGS" + # FLUTTER_TOOL_ARGS="$FLUTTER_TOOL_ARGS --observe=65432" + + (upgrade_flutter) 3< "$PROG_NAME" + + BIN_NAME="$(basename "$PROG_NAME")" + case "$BIN_NAME" in + flutter*) + # FLUTTER_TOOL_ARGS aren't quoted below, because it is meant to + # be considered as separate space-separated args. + "$DART" --disable-dart-dev --packages="$FLUTTER_TOOLS_DIR/.packages" $FLUTTER_TOOL_ARGS "$SNAPSHOT_PATH" "$@" + ;; + dart*) + "$DART" "$@" + ;; + *) + echo "Error! Executable name $BIN_NAME not recognized!" + exit 1 + ;; + esac +}