Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
c8f66a1f
Commit
c8f66a1f
authored
Nov 05, 2015
by
Adam Barth
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #31 from abarth/flutter_tools
Flutter tools
parents
a4d0b560
654faaf5
Changes
49
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
49 changed files
with
4719 additions
and
0 deletions
+4719
-0
README.md
packages/flutter_tools/README.md
+52
-0
build_sky_apk.dart
packages/flutter_tools/bin/build_sky_apk.dart
+126
-0
sky_server.dart
packages/flutter_tools/bin/sky_server.dart
+85
-0
sky_test.dart
packages/flutter_tools/bin/sky_test.dart
+11
-0
sky_tools.dart
packages/flutter_tools/bin/sky_tools.dart
+7
-0
executable.dart
packages/flutter_tools/lib/executable.dart
+77
-0
application_package.dart
packages/flutter_tools/lib/src/application_package.dart
+120
-0
artifacts.dart
packages/flutter_tools/lib/src/artifacts.dart
+236
-0
build_configuration.dart
packages/flutter_tools/lib/src/build_configuration.dart
+57
-0
build.dart
packages/flutter_tools/lib/src/commands/build.dart
+198
-0
cache.dart
packages/flutter_tools/lib/src/commands/cache.dart
+43
-0
daemon.dart
packages/flutter_tools/lib/src/commands/daemon.dart
+214
-0
flutter_command.dart
packages/flutter_tools/lib/src/commands/flutter_command.dart
+64
-0
flutter_command_runner.dart
...lutter_tools/lib/src/commands/flutter_command_runner.dart
+213
-0
init.dart
packages/flutter_tools/lib/src/commands/init.dart
+170
-0
install.dart
packages/flutter_tools/lib/src/commands/install.dart
+42
-0
list.dart
packages/flutter_tools/lib/src/commands/list.dart
+69
-0
listen.dart
packages/flutter_tools/lib/src/commands/listen.dart
+130
-0
logs.dart
packages/flutter_tools/lib/src/commands/logs.dart
+38
-0
run_mojo.dart
packages/flutter_tools/lib/src/commands/run_mojo.dart
+108
-0
start.dart
packages/flutter_tools/lib/src/commands/start.dart
+112
-0
stop.dart
packages/flutter_tools/lib/src/commands/stop.dart
+38
-0
trace.dart
packages/flutter_tools/lib/src/commands/trace.dart
+65
-0
device.dart
packages/flutter_tools/lib/src/device.dart
+995
-0
os_utils.dart
packages/flutter_tools/lib/src/os_utils.dart
+91
-0
process.dart
packages/flutter_tools/lib/src/process.dart
+96
-0
json_socket.dart
packages/flutter_tools/lib/src/test/json_socket.dart
+20
-0
loader.dart
packages/flutter_tools/lib/src/test/loader.dart
+189
-0
remote_listener.dart
packages/flutter_tools/lib/src/test/remote_listener.dart
+164
-0
remote_test.dart
packages/flutter_tools/lib/src/test/remote_test.dart
+95
-0
toolchain.dart
packages/flutter_tools/lib/src/toolchain.dart
+49
-0
pubspec.yaml
packages/flutter_tools/pubspec.yaml
+38
-0
all.dart
packages/flutter_tools/test/all.dart
+29
-0
android_device_test.dart
packages/flutter_tools/test/android_device_test.dart
+30
-0
daemon_test.dart
packages/flutter_tools/test/daemon_test.dart
+80
-0
init_test.dart
packages/flutter_tools/test/init_test.dart
+53
-0
install_test.dart
packages/flutter_tools/test/install_test.dart
+61
-0
list_test.dart
packages/flutter_tools/test/list_test.dart
+44
-0
listen_test.dart
packages/flutter_tools/test/listen_test.dart
+30
-0
logs_test.dart
packages/flutter_tools/test/logs_test.dart
+30
-0
os_utils_test.dart
packages/flutter_tools/test/os_utils_test.dart
+66
-0
mocks.dart
packages/flutter_tools/test/src/mocks.dart
+61
-0
start_test.dart
packages/flutter_tools/test/start_test.dart
+72
-0
stop_test.dart
packages/flutter_tools/test/stop_test.dart
+54
-0
trace_test.dart
packages/flutter_tools/test/trace_test.dart
+28
-0
daemon_client.dart
packages/flutter_tools/tool/daemon_client.dart
+49
-0
travis.sh
packages/flutter_tools/tool/travis.sh
+18
-0
setup.sh
travis/setup.sh
+1
-0
test.sh
travis/test.sh
+1
-0
No files found.
packages/flutter_tools/README.md
0 → 100644
View file @
c8f66a1f
# tools
[

](https://travis-ci.org/flutter/tools)
[

](https://ci.appveyor.com/project/devoncarew/tools/branch/master)
[

](https://pub.dartlang.org/packages/sky_tools)
Tools for building Flutter applications.
## Installing
To install, run:
pub global activate sky_tools
or, depend on this package in your pubspec:
```
yaml
dev_dependencies
:
sky_tools
:
any
```
## Running sky_tools
Run
`sky_tools`
(or
`pub global run sky_tools`
) to see a list of available
commands:
-
`init`
to create a new project
Then, run a
`sky_tools`
command:
sky_tools init --out my_sky_project
## Running sky_tools:sky_server
To serve the current directory using
`sky_server`
:
pub run sky_tools:sky_server [-v] PORT
## Running sky_tools:build_sky_apk
```
usage: pub run sky_tools:build_sky_apk <options>
-h, --help
--android-sdk
--skyx
```
## Filing Issues
Please file reports on the
[
GitHub Issue Tracker
](
https://github.com/flutter/tools/issues
)
.
packages/flutter_tools/bin/build_sky_apk.dart
0 → 100644
View file @
c8f66a1f
// 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
'dart:io'
;
import
'package:args/args.dart'
;
const
String
kBuildToolsVersion
=
'22.0.1'
;
const
String
kAndroidPlatformVersion
=
'22'
;
const
String
kKeystoreKeyName
=
"chromiumdebugkey"
;
const
String
kKeystorePassword
=
"chromium"
;
class
AssetBuilder
{
final
Directory
outDir
;
Directory
_assetDir
;
AssetBuilder
(
this
.
outDir
)
{
_assetDir
=
new
Directory
(
'
${outDir.path}
/assets'
);
_assetDir
.
createSync
(
recursive:
true
);
}
void
add
(
File
asset
,
String
assetName
)
{
asset
.
copySync
(
'
${_assetDir.path}
/
$assetName
'
);
}
Directory
get
directory
=>
_assetDir
;
}
class
ApkBuilder
{
final
String
androidSDK
;
File
_androidJar
;
File
_aapt
;
File
_zipalign
;
String
_jarsigner
;
ApkBuilder
(
this
.
androidSDK
)
{
_androidJar
=
new
File
(
'
$androidSDK
/platforms/android-
$kAndroidPlatformVersion
/android.jar'
);
String
buildTools
=
'
$androidSDK
/build-tools/
$kBuildToolsVersion
'
;
_aapt
=
new
File
(
'
$buildTools
/aapt'
);
_zipalign
=
new
File
(
'
$buildTools
/zipalign'
);
_jarsigner
=
'jarsigner'
;
}
void
package
(
File
androidManifest
,
Directory
assets
,
File
outputApk
)
{
_run
(
_aapt
.
path
,
[
'package'
,
'-M'
,
androidManifest
.
path
,
'-A'
,
assets
.
path
,
'-I'
,
_androidJar
.
path
,
'-F'
,
outputApk
.
path
,
]);
}
void
add
(
Directory
base
,
String
resource
,
File
outputApk
)
{
_run
(
_aapt
.
path
,
[
'add'
,
'-f'
,
outputApk
.
absolute
.
path
,
resource
,
],
workingDirectory:
base
.
path
);
}
void
sign
(
File
keystore
,
String
keystorePassword
,
String
keyName
,
File
outputApk
)
{
_run
(
_jarsigner
,
[
'-keystore'
,
keystore
.
path
,
'-storepass'
,
keystorePassword
,
outputApk
.
path
,
keyName
,
]);
}
void
align
(
File
unalignedApk
,
File
outputApk
)
{
_run
(
_zipalign
.
path
,
[
'4'
,
unalignedApk
.
path
,
outputApk
.
path
]);
}
void
_run
(
String
command
,
List
<
String
>
args
,
{
String
workingDirectory
})
{
ProcessResult
result
=
Process
.
runSync
(
command
,
args
,
workingDirectory:
workingDirectory
);
if
(
result
.
exitCode
==
0
)
return
;
stdout
.
write
(
result
.
stdout
);
stderr
.
write
(
result
.
stderr
);
}
}
main
(
List
<
String
>
argv
)
async
{
ArgParser
parser
=
new
ArgParser
();
parser
.
addFlag
(
'help'
,
abbr:
'h'
,
negatable:
false
);
parser
.
addOption
(
'android-sdk'
);
parser
.
addOption
(
'skyx'
);
ArgResults
args
=
parser
.
parse
(
argv
);
if
(
args
[
'help'
])
{
print
(
'usage: pub run sky_tools:build_sky_apk <options>'
);
print
(
''
);
print
(
parser
.
usage
);
return
;
}
Directory
artifacts
=
new
Directory
(
'artifacts'
);
File
keystore
=
new
File
(
'
${artifacts.path}
/chromium-debug.keystore'
);
File
androidManifest
=
new
File
(
'
${artifacts.path}
/AndroidManifest.xml'
);
File
icuData
=
new
File
(
'
${artifacts.path}
/assets/icudtl.dat'
);
File
appSkyx
=
new
File
(
args
[
'skyx'
]);
Directory
outDir
=
new
Directory
(
'out'
);
outDir
.
createSync
(
recursive:
true
);
AssetBuilder
assetBuilder
=
new
AssetBuilder
(
outDir
);
assetBuilder
.
add
(
icuData
,
'icudtl.dat'
);
assetBuilder
.
add
(
appSkyx
,
'app.skyx'
);
ApkBuilder
builder
=
new
ApkBuilder
(
args
[
'android-sdk'
]);
File
unalignedApk
=
new
File
(
'
${outDir.path}
/Example.apk.unaligned'
);
File
finalApk
=
new
File
(
'
${outDir.path}
/Example.apk'
);
builder
.
package
(
androidManifest
,
assetBuilder
.
directory
,
unalignedApk
);
builder
.
add
(
artifacts
,
'classes.dex'
,
unalignedApk
);
builder
.
add
(
artifacts
,
'lib/armeabi-v7a/libsky_shell.so'
,
unalignedApk
);
builder
.
sign
(
keystore
,
kKeystorePassword
,
kKeystoreKeyName
,
unalignedApk
);
builder
.
align
(
unalignedApk
,
finalApk
);
}
packages/flutter_tools/bin/sky_server.dart
0 → 100644
View file @
c8f66a1f
// 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
'dart:io'
;
import
'package:args/args.dart'
;
import
'package:shelf/shelf.dart'
;
import
'package:shelf/shelf_io.dart'
as
io
;
import
'package:shelf_route/shelf_route.dart'
as
shelf_route
;
import
'package:shelf_static/shelf_static.dart'
;
void
printUsage
(
parser
)
{
print
(
'Usage: sky_server [-v] PORT'
);
print
(
parser
.
usage
);
}
void
addRoute
(
var
router
,
String
route
,
String
path
)
{
router
.
add
(
route
,
[
'GET'
,
'HEAD'
],
createStaticHandler
(
path
,
serveFilesOutsidePath:
true
,
listDirectories:
true
),
exactMatch:
false
);
}
main
(
List
<
String
>
argv
)
async
{
ArgParser
parser
=
new
ArgParser
();
parser
.
addFlag
(
'help'
,
abbr:
'h'
,
negatable:
false
,
help:
'Display this help message.'
);
parser
.
addFlag
(
'verbose'
,
abbr:
'v'
,
negatable:
false
,
help:
'Log requests to stdout.'
);
parser
.
addOption
(
'route'
,
allowMultiple:
true
,
splitCommas:
false
,
help:
'Adds a virtual directory to the root.'
);
ArgResults
args
=
parser
.
parse
(
argv
);
if
(
args
[
'help'
]
||
args
.
rest
.
length
!=
1
)
{
printUsage
(
parser
);
return
;
}
int
port
;
try
{
port
=
int
.
parse
(
args
.
rest
[
0
]);
}
catch
(
e
)
{
printUsage
(
parser
);
return
;
}
var
router
=
shelf_route
.
router
();
if
(
args
[
'route'
]
!=
null
)
{
for
(
String
arg
in
args
[
'route'
])
{
List
<
String
>
parsedArgs
=
arg
.
split
(
','
);
addRoute
(
router
,
parsedArgs
[
0
],
parsedArgs
[
1
]);
}
}
addRoute
(
router
,
'/'
,
Directory
.
current
.
path
);
var
handler
=
router
.
handler
;
if
(
args
[
'verbose'
])
handler
=
const
Pipeline
().
addMiddleware
(
logRequests
()).
addHandler
(
handler
);
HttpServer
server
;
try
{
server
=
await
io
.
serve
(
handler
,
InternetAddress
.
LOOPBACK_IP_V4
,
port
);
print
(
'Serving
${Directory.current.absolute.path}
from '
'http://
${server.address.address}
:
${server.port}
.'
);
}
catch
(
e
)
{
print
(
e
);
exit
(
1
);
}
server
.
defaultResponseHeaders
..
removeAll
(
'x-content-type-options'
)
..
removeAll
(
'x-frame-options'
)
..
removeAll
(
'x-xss-protection'
)
..
add
(
'cache-control'
,
'no-store'
);
}
packages/flutter_tools/bin/sky_test.dart
0 → 100644
View file @
c8f66a1f
// 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:sky_tools/src/test/loader.dart'
as
loader
;
import
'package:test/src/executable.dart'
as
executable
;
main
(
List
<
String
>
args
)
{
loader
.
installHook
();
return
executable
.
main
(
args
);
}
packages/flutter_tools/bin/sky_tools.dart
0 → 100644
View file @
c8f66a1f
// 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:sky_tools/executable.dart'
as
executable
;
main
(
List
<
String
>
args
)
=>
executable
.
main
(
args
);
packages/flutter_tools/lib/executable.dart
0 → 100644
View file @
c8f66a1f
// 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
'dart:async'
;
import
'dart:io'
;
import
'package:args/command_runner.dart'
;
import
'package:logging/logging.dart'
;
import
'package:stack_trace/stack_trace.dart'
;
import
'src/commands/build.dart'
;
import
'src/commands/cache.dart'
;
import
'src/commands/daemon.dart'
;
import
'src/commands/flutter_command_runner.dart'
;
import
'src/commands/init.dart'
;
import
'src/commands/install.dart'
;
import
'src/commands/list.dart'
;
import
'src/commands/listen.dart'
;
import
'src/commands/logs.dart'
;
import
'src/commands/run_mojo.dart'
;
import
'src/commands/start.dart'
;
import
'src/commands/stop.dart'
;
import
'src/commands/trace.dart'
;
import
'src/process.dart'
;
/// Main entry point for commands.
///
/// This function is intended to be used from the [flutter] command line tool.
Future
main
(
List
<
String
>
args
)
async
{
// This level can be adjusted by users through the `--verbose` option.
Logger
.
root
.
level
=
Level
.
WARNING
;
Logger
.
root
.
onRecord
.
listen
((
LogRecord
record
)
{
if
(
record
.
level
>=
Level
.
WARNING
)
{
stderr
.
writeln
(
record
.
message
);
}
else
{
print
(
record
.
message
);
}
if
(
record
.
error
!=
null
)
stderr
.
writeln
(
record
.
error
);
if
(
record
.
stackTrace
!=
null
)
stderr
.
writeln
(
record
.
stackTrace
);
});
FlutterCommandRunner
runner
=
new
FlutterCommandRunner
()
..
addCommand
(
new
BuildCommand
())
..
addCommand
(
new
CacheCommand
())
..
addCommand
(
new
DaemonCommand
())
..
addCommand
(
new
InitCommand
())
..
addCommand
(
new
InstallCommand
())
..
addCommand
(
new
ListCommand
())
..
addCommand
(
new
ListenCommand
())
..
addCommand
(
new
LogsCommand
())
..
addCommand
(
new
RunMojoCommand
())
..
addCommand
(
new
StartCommand
())
..
addCommand
(
new
StopCommand
())
..
addCommand
(
new
TraceCommand
());
return
Chain
.
capture
(()
async
{
dynamic
result
=
await
runner
.
run
(
args
);
if
(
result
is
int
)
exit
(
result
);
},
onError:
(
error
,
Chain
chain
)
{
if
(
error
is
UsageException
)
{
stderr
.
writeln
(
error
);
// Argument error exit code.
exit
(
64
);
}
else
if
(
error
is
ProcessExit
)
{
// We've caught an exit code.
exit
(
error
.
exitCode
);
}
else
{
stderr
.
writeln
(
error
);
Logger
.
root
.
log
(
Level
.
SEVERE
,
'
\n
Exception:'
,
null
,
chain
.
terse
.
toTrace
());
exit
(
1
);
}
});
}
packages/flutter_tools/lib/src/application_package.dart
0 → 100644
View file @
c8f66a1f
// 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
'dart:async'
;
import
'package:logging/logging.dart'
;
import
'package:path/path.dart'
as
path
;
import
'artifacts.dart'
;
import
'build_configuration.dart'
;
final
Logger
_logging
=
new
Logger
(
'sky_tools.application_package'
);
abstract
class
ApplicationPackage
{
/// Path to the actual apk or bundle.
final
String
localPath
;
/// Package ID from the Android Manifest or equivalent.
final
String
id
;
/// File name of the apk or bundle.
final
String
name
;
ApplicationPackage
({
String
localPath
,
this
.
id
})
:
localPath
=
localPath
,
name
=
path
.
basename
(
localPath
)
{
assert
(
localPath
!=
null
);
assert
(
id
!=
null
);
}
}
class
AndroidApk
extends
ApplicationPackage
{
static
const
String
_defaultName
=
'SkyShell.apk'
;
static
const
String
_defaultId
=
'org.domokit.sky.shell'
;
static
const
String
_defaultLaunchActivity
=
'
$_defaultId
/
$_defaultId
.SkyActivity'
;
/// The path to the activity that should be launched.
/// Defaults to 'org.domokit.sky.shell/org.domokit.sky.shell.SkyActivity'
final
String
launchActivity
;
AndroidApk
({
String
localPath
,
String
id:
_defaultId
,
this
.
launchActivity
:
_defaultLaunchActivity
})
:
super
(
localPath:
localPath
,
id:
id
)
{
assert
(
launchActivity
!=
null
);
}
}
class
IOSApp
extends
ApplicationPackage
{
static
const
String
_defaultName
=
'SkyShell.app'
;
static
const
String
_defaultId
=
'com.google.SkyShell'
;
IOSApp
({
String
localPath
,
String
id:
_defaultId
})
:
super
(
localPath:
localPath
,
id:
id
);
}
class
ApplicationPackageStore
{
final
AndroidApk
android
;
final
IOSApp
iOS
;
final
IOSApp
iOSSimulator
;
ApplicationPackageStore
({
this
.
android
,
this
.
iOS
,
this
.
iOSSimulator
});
ApplicationPackage
getPackageForPlatform
(
TargetPlatform
platform
)
{
switch
(
platform
)
{
case
TargetPlatform
.
android
:
return
android
;
case
TargetPlatform
.
iOS
:
return
iOS
;
case
TargetPlatform
.
iOSSimulator
:
return
iOSSimulator
;
case
TargetPlatform
.
linux
:
return
null
;
}
}
static
Future
<
ApplicationPackageStore
>
forConfigs
(
List
<
BuildConfiguration
>
configs
)
async
{
AndroidApk
android
;
IOSApp
iOS
;
IOSApp
iOSSimulator
;
for
(
BuildConfiguration
config
in
configs
)
{
switch
(
config
.
targetPlatform
)
{
case
TargetPlatform
.
android
:
assert
(
android
==
null
);
if
(
config
.
type
!=
BuildType
.
prebuilt
)
{
String
localPath
=
path
.
join
(
config
.
buildDir
,
'apks'
,
AndroidApk
.
_defaultName
);
android
=
new
AndroidApk
(
localPath:
localPath
);
}
else
{
Artifact
artifact
=
ArtifactStore
.
getArtifact
(
type:
ArtifactType
.
shell
,
targetPlatform:
TargetPlatform
.
android
);
android
=
new
AndroidApk
(
localPath:
await
ArtifactStore
.
getPath
(
artifact
));
}
break
;
case
TargetPlatform
.
iOS
:
assert
(
iOS
==
null
);
assert
(
config
.
type
!=
BuildType
.
prebuilt
);
iOS
=
new
IOSApp
(
localPath:
path
.
join
(
config
.
buildDir
,
IOSApp
.
_defaultName
));
break
;
case
TargetPlatform
.
iOSSimulator
:
assert
(
iOSSimulator
==
null
);
assert
(
config
.
type
!=
BuildType
.
prebuilt
);
iOSSimulator
=
new
IOSApp
(
localPath:
path
.
join
(
config
.
buildDir
,
IOSApp
.
_defaultName
));
break
;
case
TargetPlatform
.
linux
:
break
;
}
}
return
new
ApplicationPackageStore
(
android:
android
,
iOS:
iOS
,
iOSSimulator:
iOSSimulator
);
}
}
packages/flutter_tools/lib/src/artifacts.dart
0 → 100644
View file @
c8f66a1f
// 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
'dart:async'
;
import
'dart:io'
;
import
'package:logging/logging.dart'
;
import
'package:path/path.dart'
as
path
;
import
'build_configuration.dart'
;
import
'os_utils.dart'
;
final
Logger
_logging
=
new
Logger
(
'sky_tools.artifacts'
);
const
String
_kShellCategory
=
'shell'
;
const
String
_kViewerCategory
=
'viewer'
;
String
_getNameForHostPlatform
(
HostPlatform
platform
)
{
switch
(
platform
)
{
case
HostPlatform
.
linux
:
return
'linux-x64'
;
case
HostPlatform
.
mac
:
return
'darwin-x64'
;
}
}
String
_getNameForTargetPlatform
(
TargetPlatform
platform
)
{
switch
(
platform
)
{
case
TargetPlatform
.
android
:
return
'android-arm'
;
case
TargetPlatform
.
iOS
:
return
'ios-arm'
;
case
TargetPlatform
.
iOSSimulator
:
return
'ios-x64'
;
case
TargetPlatform
.
linux
:
return
'linux-x64'
;
}
}
// Keep in sync with https://github.com/flutter/engine/blob/master/sky/tools/release_engine.py
// and https://github.com/flutter/buildbot/blob/master/travis/build.sh
String
_getCloudStorageBaseUrl
(
{
String
category
,
String
platform
,
String
revision
})
{
if
(
platform
==
'darwin-x64'
)
{
// In the fullness of time, we'll have a consistent URL pattern for all of
// our artifacts, but, for the time being, Mac OS X artifacts are stored in a
// different cloud storage bucket.
return
'https://storage.googleapis.com/mojo_infra/flutter/
${platform}
/
${revision}
/'
;
}
return
'https://storage.googleapis.com/mojo/sky/
${category}
/
${platform}
/
${revision}
/'
;
}
enum
ArtifactType
{
snapshot
,
shell
,
viewer
,
}
class
Artifact
{
const
Artifact
.
_
({
this
.
name
,
this
.
fileName
,
this
.
category
,
this
.
type
,
this
.
hostPlatform
,
this
.
targetPlatform
});
final
String
name
;
final
String
fileName
;
final
String
category
;
// TODO(abarth): Remove categories.
final
ArtifactType
type
;
final
HostPlatform
hostPlatform
;
final
TargetPlatform
targetPlatform
;
String
get
platform
{
if
(
targetPlatform
!=
null
)
return
_getNameForTargetPlatform
(
targetPlatform
);
if
(
hostPlatform
!=
null
)
return
_getNameForHostPlatform
(
hostPlatform
);
assert
(
false
);
return
null
;
}
String
getUrl
(
String
revision
)
{
return
_getCloudStorageBaseUrl
(
category:
category
,
platform:
platform
,
revision:
revision
)
+
fileName
;
}
// Whether the artifact needs to be marked as executable on disk.
bool
get
executable
=>
type
==
ArtifactType
.
snapshot
;
}
class
ArtifactStore
{
static
const
List
<
Artifact
>
knownArtifacts
=
const
<
Artifact
>[
const
Artifact
.
_
(
name:
'Sky Shell'
,
fileName:
'SkyShell.apk'
,
category:
_kShellCategory
,
type:
ArtifactType
.
shell
,
targetPlatform:
TargetPlatform
.
android
),
const
Artifact
.
_
(
name:
'Sky Snapshot'
,
fileName:
'sky_snapshot'
,
category:
_kShellCategory
,
type:
ArtifactType
.
snapshot
,
hostPlatform:
HostPlatform
.
linux
),
const
Artifact
.
_
(
name:
'Sky Snapshot'
,
fileName:
'sky_snapshot'
,
category:
_kShellCategory
,
type:
ArtifactType
.
snapshot
,
hostPlatform:
HostPlatform
.
mac
),
const
Artifact
.
_
(
name:
'Sky Viewer'
,
fileName:
'sky_viewer.mojo'
,
category:
_kViewerCategory
,
type:
ArtifactType
.
viewer
,
targetPlatform:
TargetPlatform
.
android
),
const
Artifact
.
_
(
name:
'Sky Viewer'
,
fileName:
'sky_viewer.mojo'
,
category:
_kViewerCategory
,
type:
ArtifactType
.
viewer
,
targetPlatform:
TargetPlatform
.
linux
),
];
static
Artifact
getArtifact
({
ArtifactType
type
,
HostPlatform
hostPlatform
,
TargetPlatform
targetPlatform
})
{
for
(
Artifact
artifact
in
ArtifactStore
.
knownArtifacts
)
{
if
(
type
!=
null
&&
type
!=
artifact
.
type
)
continue
;
if
(
hostPlatform
!=
null
&&
artifact
.
hostPlatform
!=
null
&&
hostPlatform
!=
artifact
.
hostPlatform
)
continue
;
if
(
targetPlatform
!=
null
&&
artifact
.
targetPlatform
!=
null
&&
targetPlatform
!=
artifact
.
targetPlatform
)
continue
;
return
artifact
;
}
return
null
;
}
static
String
packageRoot
;
static
String
_engineRevision
;
static
String
get
engineRevision
{
if
(
_engineRevision
==
null
)
{
File
revisionFile
=
new
File
(
path
.
join
(
packageRoot
,
'sky_engine'
,
'REVISION'
));
if
(
revisionFile
.
existsSync
())
_engineRevision
=
revisionFile
.
readAsStringSync
();
}
return
_engineRevision
;
}
static
String
getCloudStorageBaseUrl
(
String
category
,
String
platform
)
{
return
_getCloudStorageBaseUrl
(
category:
category
,
platform:
platform
,
revision:
engineRevision
);
}
static
Future
_downloadFile
(
String
url
,
File
file
)
async
{
_logging
.
info
(
'Downloading
$url
to
${file.path}
.'
);
HttpClient
httpClient
=
new
HttpClient
();
HttpClientRequest
request
=
await
httpClient
.
getUrl
(
Uri
.
parse
(
url
));
HttpClientResponse
response
=
await
request
.
close
();
_logging
.
fine
(
'Received response statusCode=
${response.statusCode}
'
);
if
(
response
.
statusCode
!=
200
)
throw
new
Exception
(
response
.
reasonPhrase
);
IOSink
sink
=
file
.
openWrite
();
await
sink
.
addStream
(
response
);
await
sink
.
close
();
_logging
.
fine
(
'Wrote file'
);
}
static
Directory
_getBaseCacheDir
()
{
Directory
cacheDir
=
new
Directory
(
path
.
join
(
packageRoot
,
'sky_tools'
,
'cache'
));
if
(!
cacheDir
.
existsSync
())
cacheDir
.
createSync
(
recursive:
true
);
return
cacheDir
;
}
static
Directory
_getCacheDirForArtifact
(
Artifact
artifact
)
{
Directory
baseDir
=
_getBaseCacheDir
();
// For now, all downloaded artifacts are release mode host binaries so use
// a path that mirrors a local release build.
// TODO(jamesr): Add support for more configurations.
String
config
=
'Release'
;
Directory
artifactSpecificDir
=
new
Directory
(
path
.
join
(
baseDir
.
path
,
'sky_engine'
,
engineRevision
,
config
,
artifact
.
platform
));
if
(!
artifactSpecificDir
.
existsSync
())
artifactSpecificDir
.
createSync
(
recursive:
true
);
return
artifactSpecificDir
;
}
static
Future
<
String
>
getPath
(
Artifact
artifact
)
async
{
Directory
cacheDir
=
_getCacheDirForArtifact
(
artifact
);
File
cachedFile
=
new
File
(
path
.
join
(
cacheDir
.
path
,
artifact
.
fileName
));
if
(!
cachedFile
.
existsSync
())
{
print
(
'Downloading
${artifact.name}
from the cloud, one moment please...'
);
await
_downloadFile
(
artifact
.
getUrl
(
engineRevision
),
cachedFile
);
if
(
artifact
.
executable
)
{
ProcessResult
result
=
osUtils
.
makeExecutable
(
cachedFile
);
if
(
result
.
exitCode
!=
0
)
throw
new
Exception
(
result
.
stderr
);
}
}
return
cachedFile
.
path
;
}
static
void
clear
()
{
Directory
cacheDir
=
_getBaseCacheDir
();
_logging
.
fine
(
'Clearing cache directory
${cacheDir.path}
'
);
cacheDir
.
deleteSync
(
recursive:
true
);
}
static
Future
populate
()
{
return
Future
.
wait
(
knownArtifacts
.
map
((
artifact
)
=>
getPath
(
artifact
)));
}
}
packages/flutter_tools/lib/src/build_configuration.dart
0 → 100644
View file @
c8f66a1f
// 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
'dart:io'
;
import
'package:logging/logging.dart'
;
import
'package:path/path.dart'
as
path
;
final
Logger
_logging
=
new
Logger
(
'sky_tools.build_configuration'
);
enum
BuildType
{
prebuilt
,
release
,
debug
,
}
enum
HostPlatform
{
mac
,
linux
,
}
enum
TargetPlatform
{
android
,
iOS
,
iOSSimulator
,
linux
,
}
HostPlatform
getCurrentHostPlatform
(
)
{
if
(
Platform
.
isMacOS
)
return
HostPlatform
.
mac
;
if
(
Platform
.
isLinux
)
return
HostPlatform
.
linux
;
_logging
.
warning
(
'Unsupported host platform, defaulting to Linux'
);
return
HostPlatform
.
linux
;
}
class
BuildConfiguration
{
BuildConfiguration
.
prebuilt
({
this
.
hostPlatform
,
this
.
targetPlatform
})
:
type
=
BuildType
.
prebuilt
,
buildDir
=
null
;
BuildConfiguration
.
local
({
this
.
type
,
this
.
hostPlatform
,
this
.
targetPlatform
,
String
enginePath
,
String
buildPath
})
:
buildDir
=
path
.
normalize
(
path
.
join
(
enginePath
,
buildPath
))
{
assert
(
type
==
BuildType
.
debug
||
type
==
BuildType
.
release
);
}
final
BuildType
type
;
final
HostPlatform
hostPlatform
;
final
TargetPlatform
targetPlatform
;
final
String
buildDir
;
}
packages/flutter_tools/lib/src/commands/build.dart
0 → 100644
View file @
c8f66a1f
// 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
'dart:async'
;
import
'dart:io'
;
import
'dart:typed_data'
;
import
'package:archive/archive.dart'
;
import
'package:flx/bundle.dart'
;
import
'package:flx/signing.dart'
;
import
'package:yaml/yaml.dart'
;
import
'../toolchain.dart'
;
import
'flutter_command.dart'
;
const
String
_kSnapshotKey
=
'snapshot_blob.bin'
;
const
List
<
String
>
_kDensities
=
const
[
'drawable-xxhdpi'
];
const
List
<
String
>
_kThemes
=
const
[
'white'
,
'black'
];
const
List
<
int
>
_kSizes
=
const
[
24
];
class
_Asset
{
final
String
base
;
final
String
key
;
_Asset
({
this
.
base
,
this
.
key
});
}
Iterable
<
_Asset
>
_parseAssets
(
Map
manifestDescriptor
,
String
manifestPath
)
sync
*
{
if
(
manifestDescriptor
==
null
||
!
manifestDescriptor
.
containsKey
(
'assets'
))
return
;
String
basePath
=
new
File
(
manifestPath
).
parent
.
path
;
for
(
String
asset
in
manifestDescriptor
[
'assets'
])
yield
new
_Asset
(
base:
basePath
,
key:
asset
);
}
class
_MaterialAsset
{
final
String
name
;
final
String
density
;
final
String
theme
;
final
int
size
;
_MaterialAsset
(
Map
descriptor
)
:
name
=
descriptor
[
'name'
],
density
=
descriptor
[
'density'
],
theme
=
descriptor
[
'theme'
],
size
=
descriptor
[
'size'
];
String
get
key
{
List
<
String
>
parts
=
name
.
split
(
'/'
);
String
category
=
parts
[
0
];
String
subtype
=
parts
[
1
];
return
'
$category
/
$density
/ic_
${subtype}
_
${theme}
_
${size}
dp.png'
;
}
}
List
_generateValues
(
Map
assetDescriptor
,
String
key
,
List
defaults
)
{
if
(
assetDescriptor
.
containsKey
(
key
))
return
[
assetDescriptor
[
key
]];
return
defaults
;
}
Iterable
<
_MaterialAsset
>
_generateMaterialAssets
(
Map
assetDescriptor
)
sync
*
{
Map
currentAssetDescriptor
=
new
Map
.
from
(
assetDescriptor
);
for
(
String
density
in
_generateValues
(
assetDescriptor
,
'density'
,
_kDensities
))
{
currentAssetDescriptor
[
'density'
]
=
density
;
for
(
String
theme
in
_generateValues
(
assetDescriptor
,
'theme'
,
_kThemes
))
{
currentAssetDescriptor
[
'theme'
]
=
theme
;
for
(
int
size
in
_generateValues
(
assetDescriptor
,
'size'
,
_kSizes
))
{
currentAssetDescriptor
[
'size'
]
=
size
;
yield
new
_MaterialAsset
(
currentAssetDescriptor
);
}
}
}
}
Iterable
<
_MaterialAsset
>
_parseMaterialAssets
(
Map
manifestDescriptor
)
sync
*
{
if
(
manifestDescriptor
==
null
||
!
manifestDescriptor
.
containsKey
(
'material-design-icons'
))
return
;
for
(
Map
assetDescriptor
in
manifestDescriptor
[
'material-design-icons'
])
{
for
(
_MaterialAsset
asset
in
_generateMaterialAssets
(
assetDescriptor
))
{
yield
asset
;
}
}
}
dynamic
_loadManifest
(
String
manifestPath
)
{
if
(
manifestPath
==
null
||
!
FileSystemEntity
.
isFileSync
(
manifestPath
))
return
null
;
String
manifestDescriptor
=
new
File
(
manifestPath
).
readAsStringSync
();
return
loadYaml
(
manifestDescriptor
);
}
ArchiveFile
_createFile
(
String
key
,
String
assetBase
)
{
File
file
=
new
File
(
'
${assetBase}
/
${key}
'
);
if
(!
file
.
existsSync
())
return
null
;
List
<
int
>
content
=
file
.
readAsBytesSync
();
return
new
ArchiveFile
.
noCompress
(
key
,
content
.
length
,
content
);
}
ArchiveFile
_createSnapshotFile
(
String
snapshotPath
)
{
File
file
=
new
File
(
snapshotPath
);
List
<
int
>
content
=
file
.
readAsBytesSync
();
return
new
ArchiveFile
(
_kSnapshotKey
,
content
.
length
,
content
);
}
const
String
_kDefaultAssetBase
=
'packages/material_design_icons/icons'
;
const
String
_kDefaultMainPath
=
'lib/main.dart'
;
const
String
_kDefaultManifestPath
=
'flutter.yaml'
;
const
String
_kDefaultOutputPath
=
'app.flx'
;
const
String
_kDefaultSnapshotPath
=
'snapshot_blob.bin'
;
const
String
_kDefaultPrivateKeyPath
=
'privatekey.der'
;
class
BuildCommand
extends
FlutterCommand
{
final
String
name
=
'build'
;
final
String
description
=
'Create a Flutter app.'
;
BuildCommand
()
{
argParser
.
addFlag
(
'precompiled'
,
negatable:
false
);
argParser
.
addOption
(
'asset-base'
,
defaultsTo:
_kDefaultAssetBase
);
argParser
.
addOption
(
'compiler'
);
argParser
.
addOption
(
'main'
,
defaultsTo:
_kDefaultMainPath
);
argParser
.
addOption
(
'manifest'
,
defaultsTo:
_kDefaultManifestPath
);
argParser
.
addOption
(
'private-key'
,
defaultsTo:
_kDefaultPrivateKeyPath
);
argParser
.
addOption
(
'output-file'
,
abbr:
'o'
,
defaultsTo:
_kDefaultOutputPath
);
argParser
.
addOption
(
'snapshot'
,
defaultsTo:
_kDefaultSnapshotPath
);
}
@override
Future
<
int
>
runInProject
()
async
{
String
compilerPath
=
argResults
[
'compiler'
];
if
(
compilerPath
==
null
)
await
downloadToolchain
();
else
toolchain
=
new
Toolchain
(
compiler:
new
Compiler
(
compilerPath
));
return
await
build
(
assetBase:
argResults
[
'asset-base'
],
mainPath:
argResults
[
'main'
],
manifestPath:
argResults
[
'manifest'
],
outputPath:
argResults
[
'output-file'
],
snapshotPath:
argResults
[
'snapshot'
],
privateKeyPath:
argResults
[
'private-key'
],
precompiledSnapshot:
argResults
[
'precompiled'
]
);
}
Future
<
int
>
build
({
String
assetBase:
_kDefaultAssetBase
,
String
mainPath:
_kDefaultMainPath
,
String
manifestPath:
_kDefaultManifestPath
,
String
outputPath:
_kDefaultOutputPath
,
String
snapshotPath:
_kDefaultSnapshotPath
,
String
privateKeyPath:
_kDefaultPrivateKeyPath
,
bool
precompiledSnapshot:
false
})
async
{
Map
manifestDescriptor
=
_loadManifest
(
manifestPath
);
Iterable
<
_Asset
>
assets
=
_parseAssets
(
manifestDescriptor
,
manifestPath
);
Iterable
<
_MaterialAsset
>
materialAssets
=
_parseMaterialAssets
(
manifestDescriptor
);
Archive
archive
=
new
Archive
();
if
(!
precompiledSnapshot
)
{
// In a precompiled snapshot, the instruction buffer contains script
// content equivalents
int
result
=
await
toolchain
.
compiler
.
compile
(
mainPath:
mainPath
,
snapshotPath:
snapshotPath
);
if
(
result
!=
0
)
return
result
;
archive
.
addFile
(
_createSnapshotFile
(
snapshotPath
));
}
for
(
_Asset
asset
in
assets
)
archive
.
addFile
(
_createFile
(
asset
.
key
,
asset
.
base
));
for
(
_MaterialAsset
asset
in
materialAssets
)
{
ArchiveFile
file
=
_createFile
(
asset
.
key
,
assetBase
);
if
(
file
!=
null
)
archive
.
addFile
(
file
);
}
await
CipherParameters
.
get
().
seedRandom
();
AsymmetricKeyPair
keyPair
=
keyPairFromPrivateKeyFileSync
(
privateKeyPath
);
Uint8List
zipBytes
=
new
Uint8List
.
fromList
(
new
ZipEncoder
().
encode
(
archive
));
Bundle
bundle
=
new
Bundle
.
fromContent
(
path:
outputPath
,
manifest:
manifestDescriptor
,
contentBytes:
zipBytes
,
keyPair:
keyPair
);
bundle
.
writeSync
();
return
0
;
}
}
packages/flutter_tools/lib/src/commands/cache.dart
0 → 100644
View file @
c8f66a1f
// 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
'dart:async'
;
import
'package:args/command_runner.dart'
;
import
'package:logging/logging.dart'
;
import
'../artifacts.dart'
;
final
Logger
_logging
=
new
Logger
(
'sky_tools.cache'
);
class
CacheCommand
extends
Command
{
final
String
name
=
'cache'
;
final
String
description
=
'Manages sky_tools
\'
cache of binary artifacts.'
;
CacheCommand
()
{
addSubcommand
(
new
_ClearCommand
());
addSubcommand
(
new
_PopulateCommand
());
}
}
class
_ClearCommand
extends
Command
{
final
String
name
=
'clear'
;
final
String
description
=
'Clears all artifacts from the cache.'
;
@override
Future
<
int
>
run
()
async
{
await
ArtifactStore
.
clear
();
return
0
;
}
}
class
_PopulateCommand
extends
Command
{
final
String
name
=
'populate'
;
final
String
description
=
'Populates the cache with all known artifacts.'
;
@override
Future
<
int
>
run
()
async
{
await
ArtifactStore
.
populate
();
return
0
;
}
}
packages/flutter_tools/lib/src/commands/daemon.dart
0 → 100644
View file @
c8f66a1f
// 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
'dart:async'
;
import
'dart:convert'
;
import
'dart:io'
;
import
'package:logging/logging.dart'
;
import
'flutter_command.dart'
;
import
'start.dart'
;
import
'stop.dart'
;
const
String
protocolVersion
=
'0.0.1'
;
/// A @domain annotation.
const
String
domain
=
'domain'
;
/// A domain @command annotation.
const
String
command
=
'command'
;
final
Logger
_logging
=
new
Logger
(
'sky_tools.daemon'
);
// TODO: Create a `device` domain in order to list devices and fire events when
// devices are added or removed.
// TODO: Is this the best name? Server? Daemon?
/// A server process command. This command will start up a long-lived server.
/// It reads JSON-RPC based commands from stdin, executes them, and returns
/// JSON-RPC based responses and events to stdout.
///
/// It can be shutdown with a `daemon.shutdown` command (or by killing the
/// process).
class
DaemonCommand
extends
FlutterCommand
{
final
String
name
=
'daemon'
;
final
String
description
=
'Run a persistent, JSON-RPC based server to communicate with devices.'
;
final
String
usageFooter
=
'
\n
This command is intended to be used by tooling environments that need '
'a programatic interface into launching Flutter applications.'
;
@override
Future
<
int
>
runInProject
()
async
{
print
(
'Starting device daemon...'
);
Stream
<
Map
>
commandStream
=
stdin
.
transform
(
UTF8
.
decoder
)
.
transform
(
const
LineSplitter
())
.
where
((
String
line
)
=>
line
.
startsWith
(
'[{'
)
&&
line
.
endsWith
(
'}]'
))
.
map
((
String
line
)
{
line
=
line
.
substring
(
1
,
line
.
length
-
1
);
return
JSON
.
decode
(
line
);
});
await
downloadApplicationPackagesAndConnectToDevices
();
Daemon
daemon
=
new
Daemon
(
commandStream
,
(
Map
command
)
{
stdout
.
writeln
(
'[
${JSON.encode(command)}
]'
);
},
daemonCommand:
this
);
return
daemon
.
onExit
;
}
}
typedef
void
DispatchComand
(
Map
command
);
typedef
Future
<
dynamic
>
CommandHandler
(
dynamic
args
);
class
Daemon
{
final
DispatchComand
sendCommand
;
final
DaemonCommand
daemonCommand
;
final
Completer
<
int
>
_onExitCompleter
=
new
Completer
();
final
Map
<
String
,
Domain
>
_domains
=
{};
Daemon
(
Stream
<
Map
>
commandStream
,
this
.
sendCommand
,
{
this
.
daemonCommand
})
{
// Set up domains.
_registerDomain
(
new
DaemonDomain
(
this
));
_registerDomain
(
new
AppDomain
(
this
));
// Start listening.
commandStream
.
listen
(
(
Map
command
)
=>
_handleCommand
(
command
),
onDone:
()
=>
_onExitCompleter
.
complete
(
0
)
);
}
void
_registerDomain
(
Domain
domain
)
{
_domains
[
domain
.
name
]
=
domain
;
}
Future
<
int
>
get
onExit
=>
_onExitCompleter
.
future
;
void
_handleCommand
(
Map
command
)
{
// {id, event, params}
var
id
=
command
[
'id'
];
if
(
id
==
null
)
{
_logging
.
severe
(
'no id for command:
${command}
'
);
return
;
}
try
{
String
event
=
command
[
'event'
];
if
(
event
.
indexOf
(
'.'
)
==
-
1
)
throw
'command not understood:
${event}
'
;
String
prefix
=
event
.
substring
(
0
,
event
.
indexOf
(
'.'
));
String
name
=
event
.
substring
(
event
.
indexOf
(
'.'
)
+
1
);
if
(
_domains
[
prefix
]
==
null
)
throw
'no domain for command:
${command}
'
;
_domains
[
prefix
].
handleEvent
(
name
,
id
,
command
[
'params'
]);
}
catch
(
error
,
trace
)
{
_send
({
'id'
:
id
,
'error'
:
_toJsonable
(
error
)});
_logging
.
warning
(
'error handling
${command['event']}
'
,
error
,
trace
);
}
}
void
_send
(
Map
map
)
=>
sendCommand
(
map
);
void
shutdown
()
{
if
(!
_onExitCompleter
.
isCompleted
)
_onExitCompleter
.
complete
(
0
);
}
}
abstract
class
Domain
{
final
Daemon
daemon
;
final
String
name
;
final
Map
<
String
,
CommandHandler
>
_handlers
=
{};
Domain
(
this
.
daemon
,
this
.
name
);
void
registerHandler
(
String
name
,
CommandHandler
handler
)
{
_handlers
[
name
]
=
handler
;
}
String
toString
()
=>
name
;
void
handleEvent
(
String
name
,
dynamic
id
,
dynamic
args
)
{
new
Future
.
sync
(()
{
if
(
_handlers
.
containsKey
(
name
))
return
_handlers
[
name
](
args
);
throw
'command not understood:
${name}
'
;
}).
then
((
result
)
{
if
(
result
==
null
)
{
_send
({
'id'
:
id
});
}
else
{
_send
({
'id'
:
id
,
'result'
:
_toJsonable
(
result
)});
}
}).
catchError
((
error
,
trace
)
{
_send
({
'id'
:
id
,
'error'
:
_toJsonable
(
error
)});
_logging
.
warning
(
'error handling
${name}
'
,
error
,
trace
);
});
}
void
_send
(
Map
map
)
=>
daemon
.
_send
(
map
);
}
/// This domain responds to methods like [version] and [shutdown].
@domain
class
DaemonDomain
extends
Domain
{
DaemonDomain
(
Daemon
daemon
)
:
super
(
daemon
,
'daemon'
)
{
registerHandler
(
'version'
,
version
);
registerHandler
(
'shutdown'
,
shutdown
);
}
@command
Future
<
dynamic
>
version
(
dynamic
args
)
{
return
new
Future
.
value
(
protocolVersion
);
}
@command
Future
<
dynamic
>
shutdown
(
dynamic
args
)
{
Timer
.
run
(()
=>
daemon
.
shutdown
());
return
new
Future
.
value
();
}
}
/// This domain responds to methods like [start] and [stopAll].
///
/// It'll be extended to fire events for when applications start, stop, and
/// log data.
@domain
class
AppDomain
extends
Domain
{
AppDomain
(
Daemon
daemon
)
:
super
(
daemon
,
'app'
)
{
registerHandler
(
'start'
,
start
);
registerHandler
(
'stopAll'
,
stopAll
);
}
@command
Future
<
dynamic
>
start
(
dynamic
args
)
{
// TODO: Add the ability to pass args: target, http, checked
StartCommand
startComand
=
new
StartCommand
();
startComand
.
inheritFromParent
(
daemon
.
daemonCommand
);
return
startComand
.
runInProject
().
then
((
_
)
=>
null
);
}
@command
Future
<
bool
>
stopAll
(
dynamic
args
)
{
StopCommand
stopCommand
=
new
StopCommand
();
stopCommand
.
inheritFromParent
(
daemon
.
daemonCommand
);
return
stopCommand
.
stop
();
}
}
dynamic
_toJsonable
(
dynamic
obj
)
{
if
(
obj
is
String
||
obj
is
int
||
obj
is
bool
||
obj
is
Map
||
obj
is
List
||
obj
==
null
)
return
obj
;
return
'
${obj}
'
;
}
packages/flutter_tools/lib/src/commands/flutter_command.dart
0 → 100644
View file @
c8f66a1f
// 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
'dart:async'
;
import
'dart:io'
;
import
'package:args/command_runner.dart'
;
import
'../application_package.dart'
;
import
'../device.dart'
;
import
'../toolchain.dart'
;
import
'flutter_command_runner.dart'
;
abstract
class
FlutterCommand
extends
Command
{
FlutterCommandRunner
get
runner
=>
super
.
runner
;
/// Whether this command needs to be run from the root of a project.
bool
get
requiresProjectRoot
=>
true
;
Future
downloadApplicationPackages
()
async
{
if
(
applicationPackages
==
null
)
applicationPackages
=
await
ApplicationPackageStore
.
forConfigs
(
runner
.
buildConfigurations
);
}
Future
downloadToolchain
()
async
{
if
(
toolchain
==
null
)
toolchain
=
await
Toolchain
.
forConfigs
(
runner
.
buildConfigurations
);
}
void
connectToDevices
()
{
if
(
devices
==
null
)
devices
=
new
DeviceStore
.
forConfigs
(
runner
.
buildConfigurations
);
}
Future
downloadApplicationPackagesAndConnectToDevices
()
async
{
await
downloadApplicationPackages
();
connectToDevices
();
}
void
inheritFromParent
(
FlutterCommand
other
)
{
applicationPackages
=
other
.
applicationPackages
;
toolchain
=
other
.
toolchain
;
devices
=
other
.
devices
;
}
Future
<
int
>
run
()
async
{
if
(
requiresProjectRoot
)
{
if
(!
FileSystemEntity
.
isFileSync
(
'pubspec.yaml'
))
{
stderr
.
writeln
(
'No pubspec.yaml file found. '
'This command should be run from the root of a project.'
);
return
1
;
}
}
return
runInProject
();
}
Future
<
int
>
runInProject
();
ApplicationPackageStore
applicationPackages
;
Toolchain
toolchain
;
DeviceStore
devices
;
}
packages/flutter_tools/lib/src/commands/flutter_command_runner.dart
0 → 100644
View file @
c8f66a1f
// 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
'dart:async'
;
import
'dart:io'
;
import
'package:args/args.dart'
;
import
'package:args/command_runner.dart'
;
import
'package:logging/logging.dart'
;
import
'package:path/path.dart'
as
path
;
import
'../artifacts.dart'
;
import
'../build_configuration.dart'
;
import
'../process.dart'
;
final
Logger
_logging
=
new
Logger
(
'sky_tools.flutter_command_runner'
);
class
FlutterCommandRunner
extends
CommandRunner
{
FlutterCommandRunner
()
:
super
(
'flutter'
,
'Manage your Flutter app development.'
)
{
argParser
.
addFlag
(
'verbose'
,
abbr:
'v'
,
negatable:
false
,
help:
'Noisy logging, including all shell commands executed.'
);
argParser
.
addFlag
(
'very-verbose'
,
negatable:
false
,
help:
'Very noisy logging, including the output of all '
'shell commands executed.'
);
argParser
.
addOption
(
'package-root'
,
help:
'Path to your packages directory.'
,
defaultsTo:
'packages'
);
argParser
.
addSeparator
(
'Local build selection options:'
);
argParser
.
addFlag
(
'debug'
,
negatable:
false
,
help:
'Set this if you are building Flutter locally and want to use the debug build products. '
'When set, attempts to automaticaly determine engine-src-path if engine-src-path is '
'not set. Not normally required.'
);
argParser
.
addFlag
(
'release'
,
negatable:
false
,
help:
'Set this if you are building Flutter locally and want to use the release build products. '
'When set, attempts to automaticaly determine engine-src-path if engine-src-path is '
'not set. Note that release is not compatible with the listen command '
'on iOS devices and simulators. Not normally required.'
);
argParser
.
addFlag
(
'local-build'
,
negatable:
false
,
help:
'Automatically detect your engine src directory from an overridden Flutter package.'
'Useful if you are building Flutter locally and are using a dependency_override for'
'the Flutter package that points to your engine src directory.'
);
argParser
.
addOption
(
'engine-src-path'
,
hide:
true
,
help:
'Path to your engine src directory, if you are building Flutter locally. '
'Ignored if neither debug nor release is set. Not normally required.'
);
argParser
.
addOption
(
'android-debug-build-path'
,
hide:
true
,
help:
'Path to your Android Debug out directory, if you are building Flutter locally. '
'This path is relative to engine-src-path. Not normally required.'
,
defaultsTo:
'out/android_Debug/'
);
argParser
.
addOption
(
'android-release-build-path'
,
hide:
true
,
help:
'Path to your Android Release out directory, if you are building Flutter locally. '
'This path is relative to engine-src-path. Not normally required.'
,
defaultsTo:
'out/android_Release/'
);
argParser
.
addOption
(
'ios-debug-build-path'
,
hide:
true
,
help:
'Path to your iOS Debug out directory, if you are building Flutter locally. '
'This path is relative to engine-src-path. Not normally required.'
,
defaultsTo:
'out/ios_Debug/'
);
argParser
.
addOption
(
'ios-release-build-path'
,
hide:
true
,
help:
'Path to your iOS Release out directory, if you are building Flutter locally. '
'This path is relative to engine-src-path. Not normally required.'
,
defaultsTo:
'out/ios_Release/'
);
argParser
.
addOption
(
'ios-sim-debug-build-path'
,
hide:
true
,
help:
'Path to your iOS Simulator Debug out directory, if you are building Sky locally. '
'This path is relative to engine-src-path. Not normally required.'
,
defaultsTo:
'out/ios_sim_Debug/'
);
argParser
.
addOption
(
'ios-sim-release-build-path'
,
hide:
true
,
help:
'Path to your iOS Simulator Release out directory, if you are building Sky locally. '
'This path is relative to engine-src-path. Not normally required.'
,
defaultsTo:
'out/ios_sim_Release/'
);
}
List
<
BuildConfiguration
>
get
buildConfigurations
{
if
(
_buildConfigurations
==
null
)
_buildConfigurations
=
_createBuildConfigurations
(
_globalResults
);
return
_buildConfigurations
;
}
List
<
BuildConfiguration
>
_buildConfigurations
;
ArgResults
_globalResults
;
Future
<
int
>
runCommand
(
ArgResults
globalResults
)
{
if
(
globalResults
[
'verbose'
])
Logger
.
root
.
level
=
Level
.
INFO
;
if
(
globalResults
[
'very-verbose'
])
Logger
.
root
.
level
=
Level
.
FINE
;
_globalResults
=
globalResults
;
ArtifactStore
.
packageRoot
=
globalResults
[
'package-root'
];
return
super
.
runCommand
(
globalResults
);
}
List
<
BuildConfiguration
>
_createBuildConfigurations
(
ArgResults
globalResults
)
{
if
(!
FileSystemEntity
.
isDirectorySync
(
ArtifactStore
.
packageRoot
))
{
String
message
=
'
${ArtifactStore.packageRoot}
is not a valid directory.'
;
if
(
ArtifactStore
.
packageRoot
==
'packages'
)
{
if
(
FileSystemEntity
.
isFileSync
(
'pubspec.yaml'
))
message
+=
'
\n
Did you run `pub get` in this directory?'
;
else
message
+=
'
\n
Did you run this command from the same directory as your pubspec.yaml file?'
;
}
stderr
.
writeln
(
message
);
throw
new
ProcessExit
(
2
);
}
String
enginePath
=
globalResults
[
'engine-src-path'
];
bool
isDebug
=
globalResults
[
'debug'
];
bool
isRelease
=
globalResults
[
'release'
];
HostPlatform
hostPlatform
=
getCurrentHostPlatform
();
if
(
enginePath
==
null
&&
globalResults
[
'local-build'
])
{
Directory
flutterDir
=
new
Directory
(
path
.
join
(
globalResults
[
'package-root'
],
'flutter'
));
String
realFlutterPath
=
flutterDir
.
resolveSymbolicLinksSync
();
enginePath
=
path
.
dirname
(
path
.
dirname
(
path
.
dirname
(
path
.
dirname
(
realFlutterPath
))));
bool
dirExists
=
FileSystemEntity
.
isDirectorySync
(
path
.
join
(
enginePath
,
'out'
));
if
(
enginePath
==
'/'
||
enginePath
.
isEmpty
||
!
dirExists
)
{
stderr
.
writeln
(
'Unable to detect local build in
$enginePath
.
\n
'
'Do you have a dependency override for the flutter package?'
);
throw
new
ProcessExit
(
2
);
}
}
List
<
BuildConfiguration
>
configs
=
<
BuildConfiguration
>[];
if
(
enginePath
==
null
)
{
configs
.
add
(
new
BuildConfiguration
.
prebuilt
(
hostPlatform:
hostPlatform
,
targetPlatform:
TargetPlatform
.
android
));
}
else
{
if
(!
FileSystemEntity
.
isDirectorySync
(
enginePath
))
_logging
.
warning
(
'
$enginePath
is not a valid directory'
);
if
(!
isDebug
&&
!
isRelease
)
isDebug
=
true
;
if
(
isDebug
)
{
configs
.
add
(
new
BuildConfiguration
.
local
(
type:
BuildType
.
debug
,
hostPlatform:
hostPlatform
,
targetPlatform:
TargetPlatform
.
android
,
enginePath:
enginePath
,
buildPath:
globalResults
[
'android-debug-build-path'
]
));
if
(
Platform
.
isMacOS
)
{
configs
.
add
(
new
BuildConfiguration
.
local
(
type:
BuildType
.
debug
,
hostPlatform:
hostPlatform
,
targetPlatform:
TargetPlatform
.
iOS
,
enginePath:
enginePath
,
buildPath:
globalResults
[
'ios-debug-build-path'
]
));
configs
.
add
(
new
BuildConfiguration
.
local
(
type:
BuildType
.
debug
,
hostPlatform:
hostPlatform
,
targetPlatform:
TargetPlatform
.
iOSSimulator
,
enginePath:
enginePath
,
buildPath:
globalResults
[
'ios-sim-debug-build-path'
]
));
}
}
if
(
isRelease
)
{
configs
.
add
(
new
BuildConfiguration
.
local
(
type:
BuildType
.
release
,
hostPlatform:
hostPlatform
,
targetPlatform:
TargetPlatform
.
android
,
enginePath:
enginePath
,
buildPath:
globalResults
[
'android-release-build-path'
]
));
if
(
Platform
.
isMacOS
)
{
configs
.
add
(
new
BuildConfiguration
.
local
(
type:
BuildType
.
release
,
hostPlatform:
hostPlatform
,
targetPlatform:
TargetPlatform
.
iOS
,
enginePath:
enginePath
,
buildPath:
globalResults
[
'ios-release-build-path'
]
));
configs
.
add
(
new
BuildConfiguration
.
local
(
type:
BuildType
.
release
,
hostPlatform:
hostPlatform
,
targetPlatform:
TargetPlatform
.
iOSSimulator
,
enginePath:
enginePath
,
buildPath:
globalResults
[
'ios-sim-release-build-path'
]
));
}
}
}
return
configs
;
}
}
packages/flutter_tools/lib/src/commands/init.dart
0 → 100644
View file @
c8f66a1f
// 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
'dart:async'
;
import
'dart:io'
;
import
'package:args/command_runner.dart'
;
import
'package:mustache4dart/mustache4dart.dart'
as
mustache
;
import
'package:path/path.dart'
as
p
;
import
'../process.dart'
;
class
InitCommand
extends
Command
{
final
String
name
=
'init'
;
final
String
description
=
'Create a new Flutter project.'
;
InitCommand
()
{
argParser
.
addOption
(
'out'
,
abbr:
'o'
,
help:
'The output directory.'
);
argParser
.
addFlag
(
'pub'
,
defaultsTo:
true
,
help:
'Whether to run pub after the project has been created.'
);
}
@override
Future
<
int
>
run
()
async
{
if
(!
argResults
.
wasParsed
(
'out'
))
{
print
(
'No option specified for the output directory.'
);
print
(
argParser
.
usage
);
return
2
;
}
// TODO: Confirm overwrite of an existing directory with the user.
Directory
out
=
new
Directory
(
argResults
[
'out'
]);
new
FlutterSimpleTemplate
().
generateInto
(
out
);
print
(
''
);
String
message
=
'''All done! To run your application:
\$
cd
${out.path}
\$
flutter start --checked
'''
;
if
(
argResults
[
'pub'
])
{
print
(
"Running pub get..."
);
Process
process
=
await
Process
.
start
(
sdkBinaryName
(
'pub'
),
[
'get'
],
workingDirectory:
out
.
path
);
stdout
.
addStream
(
process
.
stdout
);
stderr
.
addStream
(
process
.
stderr
);
int
code
=
await
process
.
exitCode
;
if
(
code
!=
0
)
return
code
;
}
print
(
message
);
return
0
;
}
}
abstract
class
Template
{
final
String
name
;
final
String
description
;
Map
<
String
,
String
>
files
=
{};
Template
(
this
.
name
,
this
.
description
);
void
generateInto
(
Directory
dir
)
{
String
dirPath
=
p
.
normalize
(
dir
.
absolute
.
path
);
String
projectName
=
_normalizeProjectName
(
p
.
basename
(
dirPath
));
print
(
'Creating
${p.basename(projectName)}
...'
);
dir
.
createSync
(
recursive:
true
);
files
.
forEach
((
String
path
,
String
contents
)
{
Map
m
=
{
'projectName'
:
projectName
,
'description'
:
description
};
contents
=
mustache
.
render
(
contents
,
m
);
path
=
path
.
replaceAll
(
'/'
,
Platform
.
pathSeparator
);
File
file
=
new
File
(
p
.
join
(
dir
.
path
,
path
));
file
.
parent
.
createSync
();
file
.
writeAsStringSync
(
contents
);
print
(
file
.
path
);
});
}
String
toString
()
=>
name
;
}
class
FlutterSimpleTemplate
extends
Template
{
FlutterSimpleTemplate
()
:
super
(
'flutter-simple'
,
'A minimal Flutter project.'
)
{
files
[
'.gitignore'
]
=
_gitignore
;
files
[
'pubspec.yaml'
]
=
_pubspec
;
files
[
'README.md'
]
=
_readme
;
files
[
'lib/main.dart'
]
=
_libMain
;
}
}
String
_normalizeProjectName
(
String
name
)
{
name
=
name
.
replaceAll
(
'-'
,
'_'
).
replaceAll
(
' '
,
'_'
);
// Strip any extension (like .dart).
if
(
name
.
contains
(
'.'
))
{
name
=
name
.
substring
(
0
,
name
.
indexOf
(
'.'
));
}
return
name
;
}
const
String
_gitignore
=
r''
'
.DS_Store
.idea
.packages
.pub/
build/
packages
pubspec.lock
'''
;
const
String
_readme
=
r''
'
# {{projectName}}
{{description}}
## Getting Started
For help getting started with Flutter, view our online
[documentation](http://flutter.io/).
'''
;
const
String
_pubspec
=
r''
'
name: {{projectName}}
description: {{description}}
dependencies:
flutter: ">=0.0.2 <0.1.0"
dev_dependencies:
sky_tools: any
'''
;
const
String
_libMain
=
r''
'
import '
package:
flutter
/
material
.
dart
';
void main() {
runApp(
new MaterialApp(
title: "Flutter Demo",
routes: {
'
/
': (RouteArguments args) => new FlutterDemo()
}
)
);
}
class FlutterDemo extends StatelessComponent {
Widget build(BuildContext context) {
return new Scaffold(
toolBar: new ToolBar(
center: new Text("Flutter Demo")
),
body: new Material(
child: new Center(
child: new Text("Hello world!")
)
),
floatingActionButton: new FloatingActionButton(
child: new Icon(
icon: '
content
/
add
'
)
)
);
}
}
'''
;
packages/flutter_tools/lib/src/commands/install.dart
0 → 100644
View file @
c8f66a1f
// 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
'dart:async'
;
import
'../application_package.dart'
;
import
'../device.dart'
;
import
'flutter_command.dart'
;
class
InstallCommand
extends
FlutterCommand
{
final
String
name
=
'install'
;
final
String
description
=
'Install Flutter apps on attached devices.'
;
InstallCommand
()
{
argParser
.
addFlag
(
'boot'
,
help:
'Boot the iOS Simulator if it isn
\'
t already running.'
);
}
@override
Future
<
int
>
runInProject
()
async
{
await
downloadApplicationPackagesAndConnectToDevices
();
return
install
(
boot:
argResults
[
'boot'
])
?
0
:
2
;
}
bool
install
({
bool
boot:
false
})
{
if
(
boot
)
devices
.
iOSSimulator
?.
boot
();
bool
installedSomewhere
=
false
;
for
(
Device
device
in
devices
.
all
)
{
ApplicationPackage
package
=
applicationPackages
.
getPackageForPlatform
(
device
.
platform
);
if
(
package
==
null
||
!
device
.
isConnected
()
||
device
.
isAppInstalled
(
package
))
continue
;
if
(
device
.
installApp
(
package
))
installedSomewhere
=
true
;
}
return
installedSomewhere
;
}
}
packages/flutter_tools/lib/src/commands/list.dart
0 → 100644
View file @
c8f66a1f
// 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
'dart:async'
;
import
'package:logging/logging.dart'
;
import
'../device.dart'
;
import
'flutter_command.dart'
;
final
Logger
_logging
=
new
Logger
(
'sky_tools.list'
);
class
ListCommand
extends
FlutterCommand
{
final
String
name
=
'list'
;
final
String
description
=
'List all connected devices.'
;
ListCommand
()
{
argParser
.
addFlag
(
'details'
,
abbr:
'd'
,
negatable:
false
,
help:
'Log additional details about attached devices.'
);
}
@override
Future
<
int
>
runInProject
()
async
{
connectToDevices
();
bool
details
=
argResults
[
'details'
];
if
(
details
)
print
(
'Android Devices:'
);
for
(
AndroidDevice
device
in
AndroidDevice
.
getAttachedDevices
(
devices
.
android
))
{
if
(
details
)
{
print
(
'
${device.id}
\t
'
'
${device.modelID}
\t
'
'
${device.productID}
\t
'
'
${device.deviceCodeName}
'
);
}
else
{
print
(
device
.
id
);
}
}
if
(
details
)
print
(
'iOS Devices:'
);
for
(
IOSDevice
device
in
IOSDevice
.
getAttachedDevices
(
devices
.
iOS
))
{
if
(
details
)
{
print
(
'
${device.id}
\t
${device.name}
'
);
}
else
{
print
(
device
.
id
);
}
}
if
(
details
)
{
print
(
'iOS Simulators:'
);
}
for
(
IOSSimulator
device
in
IOSSimulator
.
getAttachedDevices
(
devices
.
iOSSimulator
))
{
if
(
details
)
{
print
(
'
${device.id}
\t
${device.name}
'
);
}
else
{
print
(
device
.
id
);
}
}
return
0
;
}
}
packages/flutter_tools/lib/src/commands/listen.dart
0 → 100644
View file @
c8f66a1f
// 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
'dart:async'
;
import
'dart:io'
;
import
'package:logging/logging.dart'
;
import
'../application_package.dart'
;
import
'../device.dart'
;
import
'../process.dart'
;
import
'build.dart'
;
import
'flutter_command.dart'
;
final
Logger
_logging
=
new
Logger
(
'sky_tools.listen'
);
class
ListenCommand
extends
FlutterCommand
{
final
String
name
=
'listen'
;
final
String
description
=
'Listen for changes to files and reload the running app on all connected devices.'
;
List
<
String
>
watchCommand
;
/// Only run once. Used for testing.
bool
singleRun
;
ListenCommand
({
this
.
singleRun
:
false
})
{
argParser
.
addFlag
(
'checked'
,
negatable:
true
,
defaultsTo:
true
,
help:
'Toggle Dart
\'
s checked mode.'
);
argParser
.
addOption
(
'target'
,
defaultsTo:
'.'
,
abbr:
't'
,
help:
'Target app path or filename to start.'
);
}
static
const
String
_localFlutterBundle
=
'app.flx'
;
static
const
String
_remoteFlutterBundle
=
'Documents/app.flx'
;
@override
Future
<
int
>
runInProject
()
async
{
await
downloadApplicationPackagesAndConnectToDevices
();
await
downloadToolchain
();
if
(
argResults
.
rest
.
length
>
0
)
{
watchCommand
=
_initWatchCommand
(
argResults
.
rest
);
}
else
{
watchCommand
=
_initWatchCommand
([
'.'
]);
}
while
(
true
)
{
_logging
.
info
(
'Updating running Flutter apps...'
);
BuildCommand
builder
=
new
BuildCommand
();
builder
.
inheritFromParent
(
this
);
builder
.
build
(
outputPath:
_localFlutterBundle
);
for
(
Device
device
in
devices
.
all
)
{
ApplicationPackage
package
=
applicationPackages
.
getPackageForPlatform
(
device
.
platform
);
if
(
package
==
null
||
!
device
.
isConnected
())
continue
;
if
(
device
is
AndroidDevice
)
{
await
devices
.
android
.
startServer
(
argResults
[
'target'
],
true
,
argResults
[
'checked'
],
package
);
}
else
if
(
device
is
IOSDevice
)
{
device
.
pushFile
(
package
,
_localFlutterBundle
,
_remoteFlutterBundle
);
}
else
if
(
device
is
IOSSimulator
)
{
// TODO(abarth): Move pushFile up to Device once Android supports
// pushing new bundles.
device
.
pushFile
(
package
,
_localFlutterBundle
,
_remoteFlutterBundle
);
}
else
{
assert
(
false
);
}
}
if
(
singleRun
||
!
watchDirectory
())
break
;
}
return
0
;
}
List
<
String
>
_initWatchCommand
(
List
<
String
>
directories
)
{
if
(
Platform
.
isMacOS
)
{
try
{
runCheckedSync
([
'which'
,
'fswatch'
]);
}
catch
(
e
)
{
_logging
.
severe
(
'"listen" command is only useful if you have installed '
'fswatch on Mac. Run "brew install fswatch" to install it with '
'homebrew.'
);
return
null
;
}
return
[
'fswatch'
,
'-r'
,
'-v'
,
'-1'
]..
addAll
(
directories
);
}
else
if
(
Platform
.
isLinux
)
{
try
{
runCheckedSync
([
'which'
,
'inotifywait'
]);
}
catch
(
e
)
{
_logging
.
severe
(
'"listen" command is only useful if you have installed '
'inotifywait on Linux. Run "apt-get install inotify-tools" or '
'equivalent to install it.'
);
return
null
;
}
return
[
'inotifywait'
,
'-r'
,
'-e'
,
// Only listen for events that matter, to avoid triggering constantly
// from the editor watching files
'modify,close_write,move,create,delete'
,
]..
addAll
(
directories
);
}
else
{
_logging
.
severe
(
'"listen" command is only available on Mac and Linux.'
);
}
return
null
;
}
bool
watchDirectory
()
{
if
(
watchCommand
==
null
)
return
false
;
try
{
runCheckedSync
(
watchCommand
);
}
catch
(
e
)
{
_logging
.
warning
(
'Watching directories failed.'
,
e
);
return
false
;
}
return
true
;
}
}
packages/flutter_tools/lib/src/commands/logs.dart
0 → 100644
View file @
c8f66a1f
// 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
'dart:async'
;
import
'package:logging/logging.dart'
;
import
'../device.dart'
;
import
'flutter_command.dart'
;
final
Logger
_logging
=
new
Logger
(
'sky_tools.logs'
);
class
LogsCommand
extends
FlutterCommand
{
final
String
name
=
'logs'
;
final
String
description
=
'Show logs for running Sky apps.'
;
LogsCommand
()
{
argParser
.
addFlag
(
'clear'
,
negatable:
false
,
help:
'Clear log history before reading from logs (Android only).'
);
}
@override
Future
<
int
>
runInProject
()
async
{
connectToDevices
();
bool
clear
=
argResults
[
'clear'
];
Iterable
<
Future
<
int
>>
results
=
devices
.
all
.
map
(
(
Device
device
)
=>
device
.
logs
(
clear:
clear
));
for
(
Future
<
int
>
result
in
results
)
await
result
;
return
0
;
}
}
packages/flutter_tools/lib/src/commands/run_mojo.dart
0 → 100644
View file @
c8f66a1f
// 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
'dart:async'
;
import
'dart:io'
;
import
'package:args/command_runner.dart'
;
import
'package:logging/logging.dart'
;
import
'package:path/path.dart'
as
path
;
import
'../artifacts.dart'
;
import
'../build_configuration.dart'
;
import
'../process.dart'
;
final
Logger
_logging
=
new
Logger
(
'sky_tools.run_mojo'
);
enum
_MojoConfig
{
Debug
,
Release
}
class
RunMojoCommand
extends
Command
{
final
String
name
=
'run_mojo'
;
final
String
description
=
'Run a Flutter app in mojo.'
;
RunMojoCommand
()
{
argParser
.
addFlag
(
'android'
,
negatable:
false
,
help:
'Run on an Android device'
);
argParser
.
addFlag
(
'checked'
,
negatable:
false
,
help:
'Run Flutter in checked mode'
);
argParser
.
addFlag
(
'mojo-debug'
,
negatable:
false
,
help:
'Use Debug build of mojo'
);
argParser
.
addFlag
(
'mojo-release'
,
negatable:
false
,
help:
'Use Release build of mojo (default)'
);
argParser
.
addOption
(
'app'
,
defaultsTo:
'app.flx'
);
argParser
.
addOption
(
'mojo-path'
,
help:
'Path to directory containing mojo_shell and services for Linux and to mojo devtools from Android.'
);
}
// TODO(abarth): Why not use path.absolute?
String
_makePathAbsolute
(
String
relativePath
)
{
File
file
=
new
File
(
relativePath
);
if
(!
file
.
existsSync
())
{
throw
new
Exception
(
"Path
\"
${relativePath}
\"
does not exist"
);
}
return
file
.
absolute
.
path
;
}
Future
<
int
>
_runAndroid
(
String
devtoolsPath
,
_MojoConfig
mojoConfig
,
String
appPath
,
List
<
String
>
additionalArgs
)
{
String
skyViewerUrl
=
ArtifactStore
.
getCloudStorageBaseUrl
(
'viewer'
,
'android-arm'
);
String
command
=
_makePathAbsolute
(
devtoolsPath
);
String
appName
=
path
.
basename
(
appPath
);
String
appDir
=
path
.
dirname
(
appPath
);
String
buildFlag
=
mojoConfig
==
_MojoConfig
.
Debug
?
'--debug'
:
'--release'
;
List
<
String
>
cmd
=
[
command
,
'--android'
,
buildFlag
,
'http://app/
$appName
'
,
'--map-origin=http://app/=
$appDir
'
,
'--map-origin=http://sky_viewer/=
$skyViewerUrl
'
,
'--url-mappings=mojo:sky_viewer=http://sky_viewer/sky_viewer.mojo'
,
];
if
(
_logging
.
level
<=
Level
.
INFO
)
{
cmd
.
add
(
'--verbose'
);
if
(
_logging
.
level
<=
Level
.
FINE
)
{
cmd
.
add
(
'--verbose'
);
}
}
cmd
.
addAll
(
additionalArgs
);
return
runCommandAndStreamOutput
(
cmd
);
}
Future
<
int
>
_runLinux
(
String
mojoPath
,
_MojoConfig
mojoConfig
,
String
appPath
,
List
<
String
>
additionalArgs
)
async
{
Artifact
artifact
=
ArtifactStore
.
getArtifact
(
type:
ArtifactType
.
viewer
,
targetPlatform:
TargetPlatform
.
linux
);
String
viewerPath
=
_makePathAbsolute
(
await
ArtifactStore
.
getPath
(
artifact
));
String
mojoBuildType
=
mojoConfig
==
_MojoConfig
.
Debug
?
'Debug'
:
'Release'
;
String
mojoShellPath
=
_makePathAbsolute
(
path
.
join
(
mojoPath
,
'out'
,
mojoBuildType
,
'mojo_shell'
));
List
<
String
>
cmd
=
[
mojoShellPath
,
'file://
${appPath}
'
,
'--url-mappings=mojo:sky_viewer=file://
${viewerPath}
'
];
cmd
.
addAll
(
additionalArgs
);
return
runCommandAndStreamOutput
(
cmd
);
}
@override
Future
<
int
>
run
()
async
{
if
(
argResults
[
'mojo-path'
]
==
null
)
{
_logging
.
severe
(
'Must specify --mojo-path.'
);
return
1
;
}
if
(
argResults
[
'mojo-debug'
]
&&
argResults
[
'mojo-release'
])
{
_logging
.
severe
(
'Cannot specify both --mojo-debug and --mojo-release'
);
return
1
;
}
List
<
String
>
args
=
[];
if
(
argResults
[
'checked'
])
{
args
.
add
(
'--args-for=mojo:sky_viewer --enable-checked-mode'
);
}
String
mojoPath
=
argResults
[
'mojo-path'
];
_MojoConfig
mojoConfig
=
argResults
[
'mojo-debug'
]
?
_MojoConfig
.
Debug
:
_MojoConfig
.
Release
;
String
appPath
=
_makePathAbsolute
(
argResults
[
'app'
]);
args
.
addAll
(
argResults
.
rest
);
if
(
argResults
[
'android'
])
{
return
_runAndroid
(
mojoPath
,
mojoConfig
,
appPath
,
args
);
}
else
{
return
_runLinux
(
mojoPath
,
mojoConfig
,
appPath
,
args
);
}
}
}
packages/flutter_tools/lib/src/commands/start.dart
0 → 100644
View file @
c8f66a1f
// 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
'dart:async'
;
import
'dart:io'
;
import
'package:logging/logging.dart'
;
import
'package:path/path.dart'
as
path
;
import
'../application_package.dart'
;
import
'../device.dart'
;
import
'build.dart'
;
import
'flutter_command.dart'
;
import
'install.dart'
;
import
'stop.dart'
;
final
Logger
_logging
=
new
Logger
(
'sky_tools.start'
);
const
String
_localBundleName
=
'app.flx'
;
const
String
_localSnapshotName
=
'snapshot_blob.bin'
;
class
StartCommand
extends
FlutterCommand
{
final
String
name
=
'start'
;
final
String
description
=
'Start your Flutter app on attached devices.'
;
StartCommand
()
{
argParser
.
addFlag
(
'poke'
,
negatable:
false
,
help:
'Restart the connection to the server (Android only).'
);
argParser
.
addFlag
(
'checked'
,
negatable:
true
,
defaultsTo:
true
,
help:
'Toggle Dart
\'
s checked mode.'
);
argParser
.
addOption
(
'target'
,
defaultsTo:
'.'
,
abbr:
't'
,
help:
'Target app path or filename to start.'
);
argParser
.
addFlag
(
'http'
,
negatable:
true
,
help:
'Use a local HTTP server to serve your app to your device.'
);
argParser
.
addFlag
(
'boot'
,
help:
'Boot the iOS Simulator if it isn
\'
t already running.'
);
}
@override
Future
<
int
>
runInProject
()
async
{
await
Future
.
wait
([
downloadToolchain
(),
downloadApplicationPackagesAndConnectToDevices
(),
]);
bool
poke
=
argResults
[
'poke'
];
if
(!
poke
)
{
StopCommand
stopper
=
new
StopCommand
();
stopper
.
inheritFromParent
(
this
);
stopper
.
stop
();
// Only install if the user did not specify a poke
InstallCommand
installer
=
new
InstallCommand
();
installer
.
inheritFromParent
(
this
);
installer
.
install
(
boot:
argResults
[
'boot'
]);
}
bool
startedSomething
=
false
;
for
(
Device
device
in
devices
.
all
)
{
ApplicationPackage
package
=
applicationPackages
.
getPackageForPlatform
(
device
.
platform
);
if
(
package
==
null
||
!
device
.
isConnected
())
continue
;
if
(
device
is
AndroidDevice
)
{
String
target
=
path
.
absolute
(
argResults
[
'target'
]);
if
(
argResults
[
'http'
])
{
if
(
await
device
.
startServer
(
target
,
poke
,
argResults
[
'checked'
],
package
))
startedSomething
=
true
;
}
else
{
String
mainPath
=
target
;
if
(
FileSystemEntity
.
isDirectorySync
(
target
))
mainPath
=
path
.
join
(
target
,
'lib'
,
'main.dart'
);
BuildCommand
builder
=
new
BuildCommand
();
builder
.
inheritFromParent
(
this
);
Directory
tempDir
=
await
Directory
.
systemTemp
.
createTemp
(
'flutter_tools'
);
try
{
String
localBundlePath
=
path
.
join
(
tempDir
.
path
,
_localBundleName
);
String
localSnapshotPath
=
path
.
join
(
tempDir
.
path
,
_localSnapshotName
);
await
builder
.
build
(
snapshotPath:
localSnapshotPath
,
outputPath:
localBundlePath
,
mainPath:
mainPath
);
if
(
device
.
startBundle
(
package
,
localBundlePath
,
poke
,
argResults
[
'checked'
]))
startedSomething
=
true
;
}
finally
{
tempDir
.
deleteSync
(
recursive:
true
);
}
}
}
else
{
if
(
await
device
.
startApp
(
package
))
startedSomething
=
true
;
}
}
if
(!
startedSomething
)
{
if
(!
devices
.
all
.
any
((
device
)
=>
device
.
isConnected
()))
{
_logging
.
severe
(
'Unable to run application - no connected devices.'
);
}
else
{
_logging
.
severe
(
'Unable to run application.'
);
}
}
return
startedSomething
?
0
:
2
;
}
}
packages/flutter_tools/lib/src/commands/stop.dart
0 → 100644
View file @
c8f66a1f
// 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
'dart:async'
;
import
'package:logging/logging.dart'
;
import
'../application_package.dart'
;
import
'../device.dart'
;
import
'flutter_command.dart'
;
final
Logger
_logging
=
new
Logger
(
'sky_tools.stop'
);
class
StopCommand
extends
FlutterCommand
{
final
String
name
=
'stop'
;
final
String
description
=
'Stop your Flutter app on all attached devices.'
;
@override
Future
<
int
>
runInProject
()
async
{
await
downloadApplicationPackagesAndConnectToDevices
();
return
await
stop
()
?
0
:
2
;
}
Future
<
bool
>
stop
()
async
{
bool
stoppedSomething
=
false
;
for
(
Device
device
in
devices
.
all
)
{
ApplicationPackage
package
=
applicationPackages
.
getPackageForPlatform
(
device
.
platform
);
if
(
package
==
null
||
!
device
.
isConnected
())
continue
;
if
(
await
device
.
stopApp
(
package
))
stoppedSomething
=
true
;
}
return
stoppedSomething
;
}
}
packages/flutter_tools/lib/src/commands/trace.dart
0 → 100644
View file @
c8f66a1f
// 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
'dart:async'
;
import
'package:logging/logging.dart'
;
import
'../application_package.dart'
;
import
'../device.dart'
;
import
'flutter_command.dart'
;
final
Logger
_logging
=
new
Logger
(
'sky_tools.trace'
);
class
TraceCommand
extends
FlutterCommand
{
final
String
name
=
'trace'
;
final
String
description
=
'Start and stop tracing a running Flutter app '
'(Android only, requires root).
\n
'
'To start a trace, wait, and then stop the trace, don
\'
t set any flags '
'except (optionally) duration.
\n
'
'Otherwise, specify either start or stop to manually control the trace.'
;
TraceCommand
()
{
argParser
.
addFlag
(
'start'
,
negatable:
false
,
help:
'Start tracing.'
);
argParser
.
addFlag
(
'stop'
,
negatable:
false
,
help:
'Stop tracing.'
);
argParser
.
addOption
(
'duration'
,
defaultsTo:
'10'
,
abbr:
'd'
,
help:
'Duration in seconds to trace.'
);
}
@override
Future
<
int
>
runInProject
()
async
{
await
downloadApplicationPackagesAndConnectToDevices
();
if
(!
devices
.
android
.
isConnected
())
{
_logging
.
warning
(
'No device connected, so no trace was completed.'
);
return
1
;
}
ApplicationPackage
androidApp
=
applicationPackages
.
android
;
if
((!
argResults
[
'start'
]
&&
!
argResults
[
'stop'
])
||
(
argResults
[
'start'
]
&&
argResults
[
'stop'
]))
{
// Setting neither flags or both flags means do both commands and wait
// duration seconds in between.
devices
.
android
.
startTracing
(
androidApp
);
await
new
Future
.
delayed
(
new
Duration
(
seconds:
int
.
parse
(
argResults
[
'duration'
])),
()
=>
_stopTracing
(
devices
.
android
,
androidApp
));
}
else
if
(
argResults
[
'stop'
])
{
_stopTracing
(
devices
.
android
,
androidApp
);
}
else
{
devices
.
android
.
startTracing
(
androidApp
);
}
return
0
;
}
void
_stopTracing
(
AndroidDevice
android
,
AndroidApk
androidApp
)
{
String
tracePath
=
android
.
stopTracing
(
androidApp
);
if
(
tracePath
==
null
)
{
_logging
.
warning
(
'No trace file saved.'
);
}
else
{
print
(
'Trace file saved to
$tracePath
'
);
}
}
}
packages/flutter_tools/lib/src/device.dart
0 → 100644
View file @
c8f66a1f
This diff is collapsed.
Click to expand it.
packages/flutter_tools/lib/src/os_utils.dart
0 → 100644
View file @
c8f66a1f
// 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
'dart:io'
;
import
'package:logging/logging.dart'
;
import
'process.dart'
;
final
OperatingSystemUtils
osUtils
=
new
OperatingSystemUtils
.
_
();
final
Logger
_logging
=
new
Logger
(
'sky_tools.os'
);
abstract
class
OperatingSystemUtils
{
factory
OperatingSystemUtils
.
_
()
{
if
(
Platform
.
isWindows
)
{
return
new
_WindowsUtils
();
}
else
if
(
Platform
.
isMacOS
)
{
return
new
_MacUtils
();
}
else
{
return
new
_LinuxUtils
();
}
}
/// Make the given file executable. This may be a no-op on some platforms.
ProcessResult
makeExecutable
(
File
file
);
/// A best-effort attempt to kill all listeners on the given TCP port.
void
killTcpPortListeners
(
int
tcpPort
);
}
abstract
class
_PosixUtils
implements
OperatingSystemUtils
{
ProcessResult
makeExecutable
(
File
file
)
{
return
Process
.
runSync
(
'chmod'
,
[
'u+x'
,
file
.
path
]);
}
}
class
_WindowsUtils
implements
OperatingSystemUtils
{
// This is a no-op.
ProcessResult
makeExecutable
(
File
file
)
{
return
new
ProcessResult
(
0
,
0
,
null
,
null
);
}
void
killTcpPortListeners
(
int
tcpPort
)
{
// Get list of network processes and split on newline
List
<
String
>
processes
=
runSync
([
'netstat.exe'
,
'-ano'
]).
split
(
"
\r
"
);
// List entries from netstat is formatted like so:
// TCP 192.168.2.11:50945 192.30.252.90:443 LISTENING 1304
// This regexp is to find process where the the port exactly matches
RegExp
pattern
=
new
RegExp
(
':
$tcpPort
[ ]+'
);
// Split the columns by 1 or more spaces
RegExp
columnPattern
=
new
RegExp
(
'[ ]+'
);
processes
.
forEach
((
String
process
)
{
if
(
process
.
contains
(
pattern
))
{
// The last column is the Process ID
String
processId
=
process
.
split
(
columnPattern
).
last
;
// Force and Tree kill the process
_logging
.
info
(
'kill
$processId
'
);
runSync
([
'TaskKill.exe'
,
'/F'
,
'/T'
,
'/PID'
,
processId
]);
}
});
}
}
class
_MacUtils
extends
_PosixUtils
{
void
killTcpPortListeners
(
int
tcpPort
)
{
String
pids
=
runSync
([
'lsof'
,
'-i'
,
':
$tcpPort
'
,
'-t'
]).
trim
();
if
(
pids
.
isNotEmpty
)
{
// Handle multiple returned pids.
for
(
String
pidString
in
pids
.
split
(
'
\n
'
))
{
// Killing a pid with a shell command from within dart is hard, so use a
// library command, but it's still nice to give the equivalent command
// when doing verbose logging.
_logging
.
info
(
'kill
$pidString
'
);
int
pid
=
int
.
parse
(
pidString
,
onError:
(
_
)
=>
null
);
if
(
pid
!=
null
)
Process
.
killPid
(
pid
);
}
}
}
}
class
_LinuxUtils
extends
_PosixUtils
{
void
killTcpPortListeners
(
int
tcpPort
)
{
runSync
([
'fuser'
,
'-k'
,
'
$tcpPort
/tcp'
]);
}
}
packages/flutter_tools/lib/src/process.dart
0 → 100644
View file @
c8f66a1f
// 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
'dart:async'
;
import
'dart:convert'
;
import
'dart:io'
;
import
'package:logging/logging.dart'
;
final
Logger
_logging
=
new
Logger
(
'sky_tools.process'
);
/// This runs the command and streams stdout/stderr from the child process to
/// this process' stdout/stderr.
Future
<
int
>
runCommandAndStreamOutput
(
List
<
String
>
cmd
,
{
String
prefix:
''
,
RegExp
filter
})
async
{
_logging
.
info
(
cmd
.
join
(
' '
));
Process
proc
=
await
Process
.
start
(
cmd
[
0
],
cmd
.
getRange
(
1
,
cmd
.
length
).
toList
());
proc
.
stdout
.
transform
(
UTF8
.
decoder
).
listen
((
String
data
)
{
List
<
String
>
dataLines
=
data
.
trimRight
().
split
(
'
\n
'
);
if
(
filter
!=
null
)
{
dataLines
=
dataLines
.
where
((
String
s
)
=>
filter
.
hasMatch
(
s
)).
toList
();
}
if
(
dataLines
.
length
>
0
)
{
stdout
.
write
(
'
$prefix${dataLines.join('\n$prefix')}
\n
'
);
}
});
proc
.
stderr
.
transform
(
UTF8
.
decoder
).
listen
((
String
data
)
{
List
<
String
>
dataLines
=
data
.
trimRight
().
split
(
'
\n
'
);
if
(
filter
!=
null
)
{
dataLines
=
dataLines
.
where
((
String
s
)
=>
filter
.
hasMatch
(
s
));
}
if
(
dataLines
.
length
>
0
)
{
stderr
.
write
(
'
$prefix${dataLines.join('\n$prefix')}
\n
'
);
}
});
return
proc
.
exitCode
;
}
Future
runAndKill
(
List
<
String
>
cmd
,
Duration
timeout
)
async
{
Future
<
Process
>
proc
=
runDetached
(
cmd
);
return
new
Future
.
delayed
(
timeout
,
()
async
{
_logging
.
info
(
'Intentionally killing
${cmd[0]}
'
);
Process
.
killPid
((
await
proc
).
pid
);
});
}
Future
<
Process
>
runDetached
(
List
<
String
>
cmd
)
async
{
_logging
.
info
(
cmd
.
join
(
' '
));
Future
<
Process
>
proc
=
Process
.
start
(
cmd
[
0
],
cmd
.
getRange
(
1
,
cmd
.
length
).
toList
(),
mode:
ProcessStartMode
.
DETACHED
);
return
proc
;
}
/// Run cmd and return stdout.
/// Throws an error if cmd exits with a non-zero value.
String
runCheckedSync
(
List
<
String
>
cmd
)
=>
_runWithLoggingSync
(
cmd
,
checked:
true
);
/// Run cmd and return stdout.
String
runSync
(
List
<
String
>
cmd
)
=>
_runWithLoggingSync
(
cmd
);
/// Return the platform specific name for the given Dart SDK binary. So, `pub`
/// ==> `pub.bat`.
String
sdkBinaryName
(
String
name
)
{
return
Platform
.
isWindows
?
'
${name}
.bat'
:
name
;
}
String
_runWithLoggingSync
(
List
<
String
>
cmd
,
{
bool
checked:
false
})
{
_logging
.
info
(
cmd
.
join
(
' '
));
ProcessResult
results
=
Process
.
runSync
(
cmd
[
0
],
cmd
.
getRange
(
1
,
cmd
.
length
).
toList
());
if
(
results
.
exitCode
!=
0
)
{
String
errorDescription
=
'Error code
${results.exitCode}
'
'returned when attempting to run command:
${cmd.join(' ')}
'
;
_logging
.
fine
(
errorDescription
);
if
(
results
.
stderr
.
length
>
0
)
{
_logging
.
info
(
'Errors logged:
${results.stderr.trim()}
'
);
}
if
(
checked
)
{
throw
errorDescription
;
}
}
_logging
.
fine
(
results
.
stdout
.
trim
());
return
results
.
stdout
;
}
class
ProcessExit
implements
Exception
{
final
int
exitCode
;
ProcessExit
(
this
.
exitCode
);
String
get
message
=>
'ProcessExit:
${exitCode}
'
;
String
toString
()
=>
message
;
}
packages/flutter_tools/lib/src/test/json_socket.dart
0 → 100644
View file @
c8f66a1f
// 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
'dart:async'
;
import
'dart:convert'
;
import
'dart:io'
;
class
JSONSocket
{
JSONSocket
(
WebSocket
socket
,
this
.
unusualTermination
)
:
_socket
=
socket
,
stream
=
socket
.
map
(
JSON
.
decode
).
asBroadcastStream
();
final
WebSocket
_socket
;
final
Stream
stream
;
final
Future
<
String
>
unusualTermination
;
void
send
(
dynamic
data
)
{
_socket
.
add
(
JSON
.
encode
(
data
));
}
}
packages/flutter_tools/lib/src/test/loader.dart
0 → 100644
View file @
c8f66a1f
// 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
'dart:async'
;
import
'dart:convert'
;
import
'dart:io'
;
import
'package:path/path.dart'
as
p
;
import
'package:sky_tools/src/test/json_socket.dart'
;
import
'package:sky_tools/src/test/remote_test.dart'
;
import
'package:stack_trace/stack_trace.dart'
;
import
'package:test/src/backend/group.dart'
;
import
'package:test/src/backend/metadata.dart'
;
import
'package:test/src/backend/test_platform.dart'
;
import
'package:test/src/runner/configuration.dart'
;
import
'package:test/src/runner/hack_load_vm_file_hook.dart'
as
hack
;
import
'package:test/src/runner/load_exception.dart'
;
import
'package:test/src/runner/runner_suite.dart'
;
import
'package:test/src/runner/vm/environment.dart'
;
import
'package:test/src/util/io.dart'
;
import
'package:test/src/util/remote_exception.dart'
;
void
installHook
(
)
{
hack
.
loadVMFileHook
=
_loadVMFile
;
}
final
String
_kSkyShell
=
Platform
.
environment
[
'SKY_SHELL'
];
const
String
_kHost
=
'127.0.0.1'
;
const
String
_kPath
=
'/runner'
;
// Right now a bunch of our tests crash or assert after the tests have finished running.
// Mostly this is just because the test puts the framework in an inconsistent state with
// a scheduled microtask that verifies that state. Eventually we should fix all these
// problems but for now we'll just paper over them.
const
bool
kExpectAllTestsToCloseCleanly
=
false
;
class
_ServerInfo
{
final
String
url
;
final
Future
<
WebSocket
>
socket
;
final
HttpServer
server
;
_ServerInfo
(
this
.
server
,
this
.
url
,
this
.
socket
);
}
Future
<
_ServerInfo
>
_createServer
()
async
{
HttpServer
server
=
await
HttpServer
.
bind
(
_kHost
,
0
);
Completer
<
WebSocket
>
socket
=
new
Completer
<
WebSocket
>();
server
.
listen
((
HttpRequest
request
)
{
if
(
request
.
uri
.
path
==
_kPath
)
socket
.
complete
(
WebSocketTransformer
.
upgrade
(
request
));
});
return
new
_ServerInfo
(
server
,
'ws://
$_kHost
:
${server.port}$_kPath
'
,
socket
.
future
);
}
Future
<
Process
>
_startProcess
(
String
path
,
{
String
packageRoot
})
{
assert
(
_kSkyShell
!=
null
);
// Please provide the path to the shell in the SKY_SHELL environment variable.
return
Process
.
start
(
_kSkyShell
,
[
'--enable-checked-mode'
,
'--non-interactive'
,
'--package-root=
$packageRoot
'
,
path
,
]);
}
Future
<
RunnerSuite
>
_loadVMFile
(
String
path
,
Metadata
metadata
,
Configuration
config
)
async
{
String
encodedMetadata
=
Uri
.
encodeComponent
(
JSON
.
encode
(
metadata
.
serialize
()));
_ServerInfo
info
=
await
_createServer
();
Directory
tempDir
=
await
Directory
.
systemTemp
.
createTemp
(
'dart_test_listener'
);
File
listenerFile
=
new
File
(
'
${tempDir.path}
/listener.dart'
);
await
listenerFile
.
create
();
await
listenerFile
.
writeAsString
(
'''
import '
dart:
convert
';
import '
package:
test
/
src
/
backend
/
metadata
.
dart
';
import '
package:
sky_tools
/
src
/
test
/
remote_listener
.
dart
';
import '
$
{
p
.
toUri
(
p
.
absolute
(
path
))}
' as test;
void main() {
String server = Uri.decodeComponent('
$
{
Uri
.
encodeComponent
(
info
.
url
)}
');
Metadata metadata = new Metadata.deserialize(
JSON.decode(Uri.decodeComponent('
$encodedMetadata
')));
RemoteListener.start(server, metadata, () => test.main);
}
'''
);
Completer
<
Iterable
<
RemoteTest
>>
completer
=
new
Completer
<
Iterable
<
RemoteTest
>>();
Completer
<
String
>
deathCompleter
=
new
Completer
();
Process
process
=
await
_startProcess
(
listenerFile
.
path
,
packageRoot:
p
.
absolute
(
config
.
packageRoot
)
);
Future
cleanupTempDirectory
()
async
{
if
(
tempDir
==
null
)
return
;
Directory
dirToDelete
=
tempDir
;
tempDir
=
null
;
await
dirToDelete
.
delete
(
recursive:
true
);
}
process
.
exitCode
.
then
((
int
exitCode
)
async
{
try
{
info
.
server
.
close
(
force:
true
);
await
cleanupTempDirectory
();
String
output
=
''
;
if
(
exitCode
<
0
)
{
// Abnormal termination (high bit of signed 8-bit exitCode is set)
switch
(
exitCode
)
{
case
-
0x0f
:
// ProcessSignal.SIGTERM
break
;
// we probably killed it ourselves
case
-
0x0b
:
// ProcessSignal.SIGSEGV
output
+=
'Segmentation fault in subprocess for:
$path
\n
'
;
break
;
default
:
output
+=
'Unexpected exit code
$exitCode
from subprocess for:
$path
\n
'
;
}
}
String
stdout
=
await
process
.
stdout
.
transform
(
UTF8
.
decoder
).
join
(
'
\n
'
);
String
stderr
=
await
process
.
stderr
.
transform
(
UTF8
.
decoder
).
join
(
'
\n
'
);
if
(
stdout
!=
''
)
output
+=
'
\n
stdout:
\n
$stdout
'
;
if
(
stderr
!=
''
)
output
+=
'
\n
stderr:
\n
$stderr
'
;
if
(!
completer
.
isCompleted
)
{
if
(
output
==
''
)
output
=
'No output.'
;
completer
.
completeError
(
new
LoadException
(
path
,
output
),
new
Trace
.
current
()
);
}
else
{
if
(
kExpectAllTestsToCloseCleanly
&&
output
!=
''
)
print
(
'Unexpected failure after test claimed to pass:
\n
$output
'
);
}
deathCompleter
.
complete
(
output
);
}
catch
(
e
)
{
// Throwing inside this block causes all kinds of hard-to-debug issues
// like stack overflows and hangs. So catch everything just in case.
print
(
"exception while handling subprocess termination:
$e
"
);
}
});
JSONSocket
socket
=
new
JSONSocket
(
await
info
.
socket
,
deathCompleter
.
future
);
await
cleanupTempDirectory
();
StreamSubscription
subscription
;
subscription
=
socket
.
stream
.
listen
((
response
)
{
if
(
response
[
"type"
]
==
"print"
)
{
print
(
response
[
"line"
]);
}
else
if
(
response
[
"type"
]
==
"loadException"
)
{
process
.
kill
(
ProcessSignal
.
SIGTERM
);
completer
.
completeError
(
new
LoadException
(
path
,
response
[
"message"
]),
new
Trace
.
current
());
}
else
if
(
response
[
"type"
]
==
"error"
)
{
process
.
kill
(
ProcessSignal
.
SIGTERM
);
AsyncError
asyncError
=
RemoteException
.
deserialize
(
response
[
"error"
]);
completer
.
completeError
(
new
LoadException
(
path
,
asyncError
.
error
),
asyncError
.
stackTrace
);
}
else
{
assert
(
response
[
"type"
]
==
"success"
);
subscription
.
cancel
();
completer
.
complete
(
response
[
"tests"
].
map
((
test
)
{
var
testMetadata
=
new
Metadata
.
deserialize
(
test
[
'metadata'
]);
return
new
RemoteTest
(
test
[
'name'
],
testMetadata
,
socket
,
test
[
'index'
]);
}));
}
});
Iterable
<
RemoteTest
>
entries
=
await
completer
.
future
;
return
new
RunnerSuite
(
const
VMEnvironment
(),
new
Group
.
root
(
entries
,
metadata:
metadata
),
path:
path
,
platform:
TestPlatform
.
vm
,
os:
currentOS
,
onClose:
()
{
process
.
kill
(
ProcessSignal
.
SIGTERM
);
}
);
}
packages/flutter_tools/lib/src/test/remote_listener.dart
0 → 100644
View file @
c8f66a1f
// 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
'dart:async'
;
import
'dart:convert'
;
import
'dart:io'
;
import
'dart:isolate'
;
import
'package:stack_trace/stack_trace.dart'
;
import
'package:test/src/backend/declarer.dart'
;
import
'package:test/src/backend/live_test.dart'
;
import
'package:test/src/backend/metadata.dart'
;
import
'package:test/src/backend/operating_system.dart'
;
import
'package:test/src/backend/suite.dart'
;
import
'package:test/src/backend/test_platform.dart'
;
import
'package:test/src/backend/test.dart'
;
import
'package:test/src/util/remote_exception.dart'
;
final
OperatingSystem
currentOS
=
(()
{
var
name
=
Platform
.
operatingSystem
;
var
os
=
OperatingSystem
.
findByIoName
(
name
);
if
(
os
!=
null
)
return
os
;
throw
new
UnsupportedError
(
'Unsupported operating system "
$name
".'
);
})();
typedef
AsyncFunction
(
);
class
RemoteListener
{
RemoteListener
.
_
(
this
.
_suite
,
this
.
_socket
);
final
Suite
_suite
;
final
WebSocket
_socket
;
final
Set
<
LiveTest
>
_liveTests
=
new
Set
<
LiveTest
>();
static
Future
start
(
String
server
,
Metadata
metadata
,
Function
getMain
())
async
{
WebSocket
socket
=
await
WebSocket
.
connect
(
server
);
// Capture any top-level errors (mostly lazy syntax errors, since other are
// caught below) and report them to the parent isolate. We set errors
// non-fatal because otherwise they'll be double-printed.
var
errorPort
=
new
ReceivePort
();
Isolate
.
current
.
setErrorsFatal
(
false
);
Isolate
.
current
.
addErrorListener
(
errorPort
.
sendPort
);
errorPort
.
listen
((
message
)
{
// Masquerade as an IsolateSpawnException because that's what this would
// be if the error had been detected statically.
var
error
=
new
IsolateSpawnException
(
message
[
0
]);
var
stackTrace
=
message
[
1
]
==
null
?
new
Trace
([])
:
new
Trace
.
parse
(
message
[
1
]);
socket
.
add
(
JSON
.
encode
({
"type"
:
"error"
,
"error"
:
RemoteException
.
serialize
(
error
,
stackTrace
)
}));
});
var
main
;
try
{
main
=
getMain
();
}
on
NoSuchMethodError
catch
(
_
)
{
_sendLoadException
(
socket
,
"No top-level main() function defined."
);
return
;
}
if
(
main
is
!
Function
)
{
_sendLoadException
(
socket
,
"Top-level main getter is not a function."
);
return
;
}
else
if
(
main
is
!
AsyncFunction
)
{
_sendLoadException
(
socket
,
"Top-level main() function takes arguments."
);
return
;
}
Declarer
declarer
=
new
Declarer
(
metadata
);
try
{
await
runZoned
(()
=>
new
Future
.
sync
(
main
),
zoneValues:
{
#test
.
declarer
:
declarer
},
zoneSpecification:
new
ZoneSpecification
(
print:
(
_
,
__
,
___
,
line
)
{
socket
.
add
(
JSON
.
encode
({
"type"
:
"print"
,
"line"
:
line
}));
}));
}
catch
(
error
,
stackTrace
)
{
socket
.
add
(
JSON
.
encode
({
"type"
:
"error"
,
"error"
:
RemoteException
.
serialize
(
error
,
stackTrace
)
}));
return
;
}
Suite
suite
=
new
Suite
(
declarer
.
build
(),
platform:
TestPlatform
.
vm
,
os:
currentOS
);
new
RemoteListener
.
_
(
suite
,
socket
).
_listen
();
}
static
void
_sendLoadException
(
WebSocket
socket
,
String
message
)
{
socket
.
add
(
JSON
.
encode
({
"type"
:
"loadException"
,
"message"
:
message
}));
}
void
_send
(
data
)
{
_socket
.
add
(
JSON
.
encode
(
data
));
}
void
_listen
()
{
List
tests
=
[];
for
(
var
i
=
0
;
i
<
_suite
.
group
.
entries
.
length
;
i
++)
{
// TODO(ianh): entries[] might return a Group instead of a Test. We don't
// currently support nested groups.
Test
test
=
_suite
.
group
.
entries
[
i
];
tests
.
add
({
"name"
:
test
.
name
,
"metadata"
:
test
.
metadata
.
serialize
(),
"index"
:
i
,
});
}
_send
({
"type"
:
"success"
,
"tests"
:
tests
});
_socket
.
listen
(
_handleCommand
);
}
void
_handleCommand
(
String
data
)
{
var
message
=
JSON
.
decode
(
data
);
if
(
message
[
'command'
]
==
'run'
)
{
// TODO(ianh): entries[] might return a Group instead of a Test. We don't
// currently support nested groups.
Test
test
=
_suite
.
group
.
entries
[
message
[
'index'
]];
LiveTest
liveTest
=
test
.
load
(
_suite
);
_liveTests
.
add
(
liveTest
);
liveTest
.
onStateChange
.
listen
((
state
)
{
_send
({
"type"
:
"state-change"
,
"status"
:
state
.
status
.
name
,
"result"
:
state
.
result
.
name
});
});
liveTest
.
onError
.
listen
((
asyncError
)
{
_send
({
"type"
:
"error"
,
"error"
:
RemoteException
.
serialize
(
asyncError
.
error
,
asyncError
.
stackTrace
)
});
});
liveTest
.
onPrint
.
listen
((
line
)
{
_send
({
"type"
:
"print"
,
"line"
:
line
});
});
liveTest
.
run
().
then
((
_
)
{
_send
({
"type"
:
"complete"
});
_liveTests
.
remove
(
liveTest
);
});
}
else
if
(
message
[
'command'
]
==
'close'
)
{
if
(
_liveTests
.
isNotEmpty
)
print
(
'closing with
${_liveTests.length}
live tests'
);
for
(
LiveTest
liveTest
in
_liveTests
)
liveTest
.
close
();
_liveTests
.
clear
();
}
else
{
print
(
'remote_listener.dart: ignoring command "
${message["command"]}
" from test harness'
);
}
}
}
packages/flutter_tools/lib/src/test/remote_test.dart
0 → 100644
View file @
c8f66a1f
// 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
'dart:async'
;
import
'package:stack_trace/stack_trace.dart'
;
import
'package:test/src/backend/live_test.dart'
;
import
'package:test/src/backend/live_test_controller.dart'
;
import
'package:test/src/backend/metadata.dart'
;
import
'package:test/src/backend/operating_system.dart'
;
import
'package:test/src/backend/state.dart'
;
import
'package:test/src/backend/suite.dart'
;
import
'package:test/src/backend/test.dart'
;
import
'package:test/src/backend/test_platform.dart'
;
import
'package:test/src/util/remote_exception.dart'
;
import
'package:sky_tools/src/test/json_socket.dart'
;
class
RemoteTest
extends
Test
{
RemoteTest
(
this
.
name
,
this
.
metadata
,
this
.
_socket
,
this
.
_index
);
final
String
name
;
final
Metadata
metadata
;
final
JSONSocket
_socket
;
final
int
_index
;
LiveTest
load
(
Suite
suite
)
{
LiveTestController
controller
;
StreamSubscription
subscription
;
controller
=
new
LiveTestController
(
suite
,
this
,
()
async
{
controller
.
setState
(
const
State
(
Status
.
running
,
Result
.
success
));
_socket
.
send
({
'command'
:
'run'
,
'index'
:
_index
});
subscription
=
_socket
.
stream
.
listen
((
message
)
{
if
(
message
[
'type'
]
==
'error'
)
{
AsyncError
asyncError
=
RemoteException
.
deserialize
(
message
[
'error'
]);
controller
.
addError
(
asyncError
.
error
,
asyncError
.
stackTrace
);
}
else
if
(
message
[
'type'
]
==
'state-change'
)
{
controller
.
setState
(
new
State
(
new
Status
.
parse
(
message
[
'status'
]),
new
Result
.
parse
(
message
[
'result'
])));
}
else
if
(
message
[
'type'
]
==
'print'
)
{
controller
.
print
(
message
[
'line'
]);
}
else
{
assert
(
message
[
'type'
]
==
'complete'
);
subscription
.
cancel
();
subscription
=
null
;
controller
.
completer
.
complete
();
}
});
_socket
.
unusualTermination
.
then
((
String
message
)
{
if
(
subscription
!=
null
)
{
controller
.
print
(
'Unexpected subprocess termination:
$message
'
);
controller
.
addError
(
new
Exception
(
'Unexpected subprocess termination.'
),
new
Trace
.
current
());
controller
.
setState
(
new
State
(
Status
.
complete
,
Result
.
error
));
subscription
.
cancel
();
subscription
=
null
;
controller
.
completer
.
complete
();
}
});
},
()
async
{
_socket
.
send
({
'command'
:
'close'
});
if
(
subscription
!=
null
)
{
subscription
.
cancel
();
subscription
=
null
;
}
});
return
controller
.
liveTest
;
}
Test
change
({
String
name
,
Metadata
metadata
})
{
if
(
name
==
name
&&
metadata
==
this
.
metadata
)
return
this
;
if
(
name
==
null
)
name
=
this
.
name
;
if
(
metadata
==
null
)
metadata
=
this
.
metadata
;
return
new
RemoteTest
(
name
,
metadata
,
_socket
,
_index
);
}
// TODO(ianh): Implement this if we need it.
Test
forPlatform
(
TestPlatform
platform
,
{
OperatingSystem
os
})
{
if
(!
metadata
.
testOn
.
evaluate
(
platform
,
os:
os
))
return
null
;
return
new
RemoteTest
(
name
,
metadata
.
forPlatform
(
platform
,
os:
os
),
_socket
,
_index
);
}
}
packages/flutter_tools/lib/src/toolchain.dart
0 → 100644
View file @
c8f66a1f
// 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
'dart:async'
;
import
'package:path/path.dart'
as
path
;
import
'artifacts.dart'
;
import
'build_configuration.dart'
;
import
'process.dart'
;
class
Compiler
{
Compiler
(
this
.
_path
);
String
_path
;
Future
<
int
>
compile
({
String
mainPath
,
String
snapshotPath
})
{
return
runCommandAndStreamOutput
([
_path
,
mainPath
,
'--package-root=
${ArtifactStore.packageRoot}
'
,
'--snapshot=
$snapshotPath
'
]);
}
}
Future
<
String
>
_getCompilerPath
(
BuildConfiguration
config
)
async
{
if
(
config
.
type
!=
BuildType
.
prebuilt
)
return
path
.
join
(
config
.
buildDir
,
'clang_x64'
,
'sky_snapshot'
);
Artifact
artifact
=
ArtifactStore
.
getArtifact
(
type:
ArtifactType
.
snapshot
,
hostPlatform:
config
.
hostPlatform
);
return
await
ArtifactStore
.
getPath
(
artifact
);
}
class
Toolchain
{
Toolchain
({
this
.
compiler
});
final
Compiler
compiler
;
static
Future
<
Toolchain
>
forConfigs
(
List
<
BuildConfiguration
>
configs
)
async
{
// TODO(abarth): Shouldn't we consider all the configs?
String
compilerPath
=
await
_getCompilerPath
(
configs
.
first
);
return
new
Toolchain
(
compiler:
new
Compiler
(
compilerPath
));
}
}
packages/flutter_tools/pubspec.yaml
0 → 100644
View file @
c8f66a1f
name
:
sky_tools
version
:
0.0.37
description
:
Tools for building Flutter applications
homepage
:
http://flutter.io
author
:
Flutter Authors <flutter-dev@googlegroups.com>
environment
:
sdk
:
'
>=1.12.0
<2.0.0'
dependencies
:
analyzer
:
"
>=0.26.1+17"
# see note below
archive
:
^1.0.20
args
:
^0.13.0
flx
:
"
>=0.0.7
<0.1.0"
crypto
:
^0.9.1
mustache4dart
:
^1.0.0
path
:
^1.3.0
shelf_route
:
^0.13.4
shelf_static
:
^0.2.3
shelf
:
^0.6.2
stack_trace
:
^1.4.0
test
:
^0.12.5
yaml
:
^2.1.3
# A note about 'analyzer':
# We don't actually depend on 'analyzer', but 'test' does. We aren't
# compatible with some older versions of 'analyzer'. We lie here,
# saying we do depend on it, so that we constrain the version that
# 'test' will get to a version that we'll probably be ok with. (This
# is why there's no upper bound on our dependency.)
# See also https://github.com/dart-lang/pub/issues/1356
dev_dependencies
:
mockito
:
"
^0.10.1"
# Add the bin/sky_tools.dart script to the scripts pub installs.
executables
:
sky_tools
:
packages/flutter_tools/test/all.dart
0 → 100644
View file @
c8f66a1f
// 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
'android_device_test.dart'
as
android_device_test
;
import
'daemon_test.dart'
as
daemon_test
;
import
'init_test.dart'
as
init_test
;
import
'install_test.dart'
as
install_test
;
import
'listen_test.dart'
as
listen_test
;
import
'list_test.dart'
as
list_test
;
import
'logs_test.dart'
as
logs_test
;
import
'os_utils_test.dart'
as
os_utils_test
;
import
'start_test.dart'
as
start_test
;
import
'stop_test.dart'
as
stop_test
;
import
'trace_test.dart'
as
trace_test
;
main
()
{
android_device_test
.
defineTests
();
daemon_test
.
defineTests
();
init_test
.
defineTests
();
install_test
.
defineTests
();
listen_test
.
defineTests
();
list_test
.
defineTests
();
logs_test
.
defineTests
();
os_utils_test
.
defineTests
();
start_test
.
defineTests
();
stop_test
.
defineTests
();
trace_test
.
defineTests
();
}
packages/flutter_tools/test/android_device_test.dart
0 → 100644
View file @
c8f66a1f
// 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:sky_tools/src/device.dart'
;
import
'package:test/test.dart'
;
main
()
=>
defineTests
();
defineTests
()
{
group
(
'android_device'
,
()
{
test
(
'uses the correct default ID'
,
()
{
AndroidDevice
android
=
new
AndroidDevice
();
expect
(
android
.
id
,
equals
(
AndroidDevice
.
defaultDeviceID
));
});
test
(
'stores the requested id'
,
()
{
String
deviceId
=
'1234'
;
AndroidDevice
android
=
new
AndroidDevice
(
id:
deviceId
);
expect
(
android
.
id
,
equals
(
deviceId
));
});
test
(
'correctly creates only one of each requested device id'
,
()
{
String
deviceID
=
'1234'
;
AndroidDevice
a1
=
new
AndroidDevice
(
id:
deviceID
);
AndroidDevice
a2
=
new
AndroidDevice
(
id:
deviceID
);
expect
(
a1
,
equals
(
a2
));
});
});
}
packages/flutter_tools/test/daemon_test.dart
0 → 100644
View file @
c8f66a1f
// 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
'dart:async'
;
import
'package:mockito/mockito.dart'
;
import
'package:sky_tools/src/commands/daemon.dart'
;
import
'package:test/test.dart'
;
import
'src/mocks.dart'
;
main
()
=>
defineTests
();
defineTests
()
{
group
(
'daemon'
,
()
{
Daemon
daemon
;
tearDown
(()
{
if
(
daemon
!=
null
)
return
daemon
.
shutdown
();
});
test
(
'daemon.version'
,
()
async
{
StreamController
<
Map
>
commands
=
new
StreamController
();
StreamController
<
Map
>
responses
=
new
StreamController
();
daemon
=
new
Daemon
(
commands
.
stream
,
(
Map
result
)
=>
responses
.
add
(
result
)
);
commands
.
add
({
'id'
:
0
,
'event'
:
'daemon.version'
});
Map
response
=
await
responses
.
stream
.
first
;
expect
(
response
[
'id'
],
0
);
expect
(
response
[
'result'
],
isNotEmpty
);
expect
(
response
[
'result'
]
is
String
,
true
);
});
test
(
'daemon.shutdown'
,
()
async
{
StreamController
<
Map
>
commands
=
new
StreamController
();
StreamController
<
Map
>
responses
=
new
StreamController
();
daemon
=
new
Daemon
(
commands
.
stream
,
(
Map
result
)
=>
responses
.
add
(
result
)
);
commands
.
add
({
'id'
:
0
,
'event'
:
'daemon.shutdown'
});
return
daemon
.
onExit
.
then
((
int
code
)
{
expect
(
code
,
0
);
});
});
test
(
'daemon.stopAll'
,
()
async
{
DaemonCommand
command
=
new
DaemonCommand
();
applyMocksToCommand
(
command
);
StreamController
<
Map
>
commands
=
new
StreamController
();
StreamController
<
Map
>
responses
=
new
StreamController
();
daemon
=
new
Daemon
(
commands
.
stream
,
(
Map
result
)
=>
responses
.
add
(
result
),
daemonCommand:
command
);
MockDeviceStore
mockDevices
=
command
.
devices
;
when
(
mockDevices
.
android
.
isConnected
()).
thenReturn
(
true
);
when
(
mockDevices
.
android
.
stopApp
(
any
)).
thenReturn
(
true
);
when
(
mockDevices
.
iOS
.
isConnected
()).
thenReturn
(
false
);
when
(
mockDevices
.
iOS
.
stopApp
(
any
)).
thenReturn
(
false
);
when
(
mockDevices
.
iOSSimulator
.
isConnected
()).
thenReturn
(
false
);
when
(
mockDevices
.
iOSSimulator
.
stopApp
(
any
)).
thenReturn
(
false
);
commands
.
add
({
'id'
:
0
,
'event'
:
'app.stopAll'
});
Map
response
=
await
responses
.
stream
.
first
;
expect
(
response
[
'id'
],
0
);
expect
(
response
[
'result'
],
true
);
});
});
}
packages/flutter_tools/test/init_test.dart
0 → 100644
View file @
c8f66a1f
// 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
'dart:io'
;
import
'package:args/command_runner.dart'
;
import
'package:path/path.dart'
as
p
;
import
'package:sky_tools/src/commands/init.dart'
;
import
'package:sky_tools/src/process.dart'
;
import
'package:test/test.dart'
;
main
()
=>
defineTests
();
defineTests
()
{
group
(
'init'
,
()
{
Directory
temp
;
setUp
(()
{
temp
=
Directory
.
systemTemp
.
createTempSync
(
'sky_tools'
);
});
tearDown
(()
{
temp
.
deleteSync
(
recursive:
true
);
});
// This test consistently times out on our windows bot. The code is already
// covered on the linux one.
if
(!
Platform
.
isWindows
)
{
// Verify that we create a project that is well-formed.
test
(
'flutter-simple'
,
()
async
{
InitCommand
command
=
new
InitCommand
();
CommandRunner
runner
=
new
CommandRunner
(
'test_flutter'
,
''
)
..
addCommand
(
command
);
await
runner
.
run
([
'init'
,
'--out'
,
temp
.
path
])
.
then
((
int
code
)
=>
expect
(
code
,
equals
(
0
)));
String
path
=
p
.
join
(
temp
.
path
,
'lib'
,
'main.dart'
);
expect
(
new
File
(
path
).
existsSync
(),
true
);
ProcessResult
exec
=
Process
.
runSync
(
sdkBinaryName
(
'dartanalyzer'
),
[
'--fatal-warnings'
,
path
],
workingDirectory:
temp
.
path
);
if
(
exec
.
exitCode
!=
0
)
{
print
(
exec
.
stdout
);
print
(
exec
.
stderr
);
}
expect
(
exec
.
exitCode
,
0
);
},
// This test can take a while due to network requests.
timeout:
new
Timeout
(
new
Duration
(
minutes:
2
)));
}
});
}
packages/flutter_tools/test/install_test.dart
0 → 100644
View file @
c8f66a1f
// 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:args/command_runner.dart'
;
import
'package:mockito/mockito.dart'
;
import
'package:sky_tools/src/commands/install.dart'
;
import
'package:test/test.dart'
;
import
'src/mocks.dart'
;
main
()
=>
defineTests
();
defineTests
()
{
group
(
'install'
,
()
{
test
(
'returns 0 when Android is connected and ready for an install'
,
()
{
InstallCommand
command
=
new
InstallCommand
();
applyMocksToCommand
(
command
);
MockDeviceStore
mockDevices
=
command
.
devices
;
when
(
mockDevices
.
android
.
isConnected
()).
thenReturn
(
true
);
when
(
mockDevices
.
android
.
isAppInstalled
(
any
)).
thenReturn
(
false
);
when
(
mockDevices
.
android
.
installApp
(
any
)).
thenReturn
(
true
);
when
(
mockDevices
.
iOS
.
isConnected
()).
thenReturn
(
false
);
when
(
mockDevices
.
iOS
.
isAppInstalled
(
any
)).
thenReturn
(
false
);
when
(
mockDevices
.
iOS
.
installApp
(
any
)).
thenReturn
(
false
);
when
(
mockDevices
.
iOSSimulator
.
isConnected
()).
thenReturn
(
false
);
when
(
mockDevices
.
iOSSimulator
.
isAppInstalled
(
any
)).
thenReturn
(
false
);
when
(
mockDevices
.
iOSSimulator
.
installApp
(
any
)).
thenReturn
(
false
);
CommandRunner
runner
=
new
CommandRunner
(
'test_flutter'
,
''
)
..
addCommand
(
command
);
runner
.
run
([
'install'
]).
then
((
int
code
)
=>
expect
(
code
,
equals
(
0
)));
});
test
(
'returns 0 when iOS is connected and ready for an install'
,
()
{
InstallCommand
command
=
new
InstallCommand
();
applyMocksToCommand
(
command
);
MockDeviceStore
mockDevices
=
command
.
devices
;
when
(
mockDevices
.
android
.
isConnected
()).
thenReturn
(
false
);
when
(
mockDevices
.
android
.
isAppInstalled
(
any
)).
thenReturn
(
false
);
when
(
mockDevices
.
android
.
installApp
(
any
)).
thenReturn
(
false
);
when
(
mockDevices
.
iOS
.
isConnected
()).
thenReturn
(
true
);
when
(
mockDevices
.
iOS
.
isAppInstalled
(
any
)).
thenReturn
(
false
);
when
(
mockDevices
.
iOS
.
installApp
(
any
)).
thenReturn
(
true
);
when
(
mockDevices
.
iOSSimulator
.
isConnected
()).
thenReturn
(
false
);
when
(
mockDevices
.
iOSSimulator
.
isAppInstalled
(
any
)).
thenReturn
(
false
);
when
(
mockDevices
.
iOSSimulator
.
installApp
(
any
)).
thenReturn
(
false
);
CommandRunner
runner
=
new
CommandRunner
(
'test_flutter'
,
''
)
..
addCommand
(
command
);
runner
.
run
([
'install'
]).
then
((
int
code
)
=>
expect
(
code
,
equals
(
0
)));
});
});
}
packages/flutter_tools/test/list_test.dart
0 → 100644
View file @
c8f66a1f
// 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
'dart:io'
;
import
'package:args/command_runner.dart'
;
import
'package:mockito/mockito.dart'
;
import
'package:sky_tools/src/commands/list.dart'
;
import
'package:test/test.dart'
;
import
'src/mocks.dart'
;
main
()
=>
defineTests
();
defineTests
()
{
group
(
'list'
,
()
{
test
(
'returns 0 when called'
,
()
{
final
String
mockCommand
=
Platform
.
isWindows
?
'cmd /c echo'
:
'echo'
;
ListCommand
command
=
new
ListCommand
();
applyMocksToCommand
(
command
);
MockDeviceStore
mockDevices
=
command
.
devices
;
// Avoid relying on adb being installed on the test system.
// Instead, cause the test to run the echo command.
when
(
mockDevices
.
android
.
adbPath
).
thenReturn
(
mockCommand
);
// Avoid relying on idevice* being installed on the test system.
// Instead, cause the test to run the echo command.
when
(
mockDevices
.
iOS
.
informerPath
).
thenReturn
(
mockCommand
);
when
(
mockDevices
.
iOS
.
installerPath
).
thenReturn
(
mockCommand
);
when
(
mockDevices
.
iOS
.
listerPath
).
thenReturn
(
mockCommand
);
// Avoid relying on xcrun being installed on the test system.
// Instead, cause the test to run the echo command.
when
(
mockDevices
.
iOSSimulator
.
xcrunPath
).
thenReturn
(
mockCommand
);
CommandRunner
runner
=
new
CommandRunner
(
'test_flutter'
,
''
)
..
addCommand
(
command
);
runner
.
run
([
'list'
]).
then
((
int
code
)
=>
expect
(
code
,
equals
(
0
)));
});
});
}
packages/flutter_tools/test/listen_test.dart
0 → 100644
View file @
c8f66a1f
// 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:args/command_runner.dart'
;
import
'package:mockito/mockito.dart'
;
import
'package:sky_tools/src/commands/listen.dart'
;
import
'package:test/test.dart'
;
import
'src/mocks.dart'
;
main
()
=>
defineTests
();
defineTests
()
{
group
(
'listen'
,
()
{
test
(
'returns 0 when no device is connected'
,
()
{
ListenCommand
command
=
new
ListenCommand
(
singleRun:
true
);
applyMocksToCommand
(
command
);
MockDeviceStore
mockDevices
=
command
.
devices
;
when
(
mockDevices
.
android
.
isConnected
()).
thenReturn
(
false
);
when
(
mockDevices
.
iOS
.
isConnected
()).
thenReturn
(
false
);
when
(
mockDevices
.
iOSSimulator
.
isConnected
()).
thenReturn
(
false
);
CommandRunner
runner
=
new
CommandRunner
(
'test_flutter'
,
''
)
..
addCommand
(
command
);
runner
.
run
([
'listen'
]).
then
((
int
code
)
=>
expect
(
code
,
equals
(
0
)));
});
});
}
packages/flutter_tools/test/logs_test.dart
0 → 100644
View file @
c8f66a1f
// 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:args/command_runner.dart'
;
import
'package:mockito/mockito.dart'
;
import
'package:sky_tools/src/commands/logs.dart'
;
import
'package:test/test.dart'
;
import
'src/mocks.dart'
;
main
()
=>
defineTests
();
defineTests
()
{
group
(
'logs'
,
()
{
test
(
'returns 0 when no device is connected'
,
()
{
LogsCommand
command
=
new
LogsCommand
();
applyMocksToCommand
(
command
);
MockDeviceStore
mockDevices
=
command
.
devices
;
when
(
mockDevices
.
android
.
isConnected
()).
thenReturn
(
false
);
when
(
mockDevices
.
iOS
.
isConnected
()).
thenReturn
(
false
);
when
(
mockDevices
.
iOSSimulator
.
isConnected
()).
thenReturn
(
false
);
CommandRunner
runner
=
new
CommandRunner
(
'test_flutter'
,
''
)
..
addCommand
(
command
);
runner
.
run
([
'logs'
]).
then
((
int
code
)
=>
expect
(
code
,
equals
(
0
)));
});
});
}
packages/flutter_tools/test/os_utils_test.dart
0 → 100644
View file @
c8f66a1f
// 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
'dart:io'
;
import
'package:sky_tools/src/os_utils.dart'
;
import
'package:test/test.dart'
;
import
'package:path/path.dart'
as
p
;
main
()
=>
defineTests
();
defineTests
()
{
group
(
'OperatingSystemUtils'
,
()
{
Directory
temp
;
setUp
(()
{
temp
=
Directory
.
systemTemp
.
createTempSync
(
'sky_tools'
);
});
tearDown
(()
{
temp
.
deleteSync
(
recursive:
true
);
});
test
(
'makeExecutable'
,
()
{
File
file
=
new
File
(
p
.
join
(
temp
.
path
,
'foo.script'
));
file
.
writeAsStringSync
(
'hello world'
);
osUtils
.
makeExecutable
(
file
);
// Skip this test on windows.
if
(!
Platform
.
isWindows
)
{
String
mode
=
file
.
statSync
().
modeString
();
// rwxr--r--
expect
(
mode
.
substring
(
0
,
3
),
endsWith
(
'x'
));
}
});
/// Start a script listening on a port, try and kill that process.
test
(
'killTcpPortListeners'
,
()
async
{
final
int
port
=
40170
;
File
file
=
new
File
(
p
.
join
(
temp
.
path
,
'script.dart'
));
file
.
writeAsStringSync
(
'''
import '
dart:
io
';
void main() async {
ServerSocket serverSocket = await ServerSocket.bind(
InternetAddress.LOOPBACK_IP_V4,
${port}
);
// wait...
print('
listening
on
port
$
{
port
}...
');
}
'''
);
Process
process
=
await
Process
.
start
(
'dart'
,
[
file
.
path
]);
await
process
.
stdout
.
first
;
osUtils
.
killTcpPortListeners
(
40170
);
int
exitCode
=
await
process
.
exitCode
;
expect
(
exitCode
,
isNot
(
equals
(
0
)));
});
/// Try and kill with a port that no process is listening to.
test
(
'killTcpPortListeners none'
,
()
{
osUtils
.
killTcpPortListeners
(
40171
);
});
});
}
packages/flutter_tools/test/src/mocks.dart
0 → 100644
View file @
c8f66a1f
// 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:mockito/mockito.dart'
;
import
'package:sky_tools/src/application_package.dart'
;
import
'package:sky_tools/src/build_configuration.dart'
;
import
'package:sky_tools/src/commands/flutter_command.dart'
;
import
'package:sky_tools/src/device.dart'
;
import
'package:sky_tools/src/toolchain.dart'
;
class
MockApplicationPackageStore
extends
ApplicationPackageStore
{
MockApplicationPackageStore
()
:
super
(
android:
new
AndroidApk
(
localPath:
'/mock/path/to/android/SkyShell.apk'
),
iOS:
new
IOSApp
(
localPath:
'/mock/path/to/iOS/SkyShell.app'
),
iOSSimulator:
new
IOSApp
(
localPath:
'/mock/path/to/iOSSimulator/SkyShell.app'
));
}
class
MockCompiler
extends
Mock
implements
Compiler
{
@override
dynamic
noSuchMethod
(
Invocation
invocation
)
=>
super
.
noSuchMethod
(
invocation
);
}
class
MockToolchain
extends
Toolchain
{
MockToolchain
()
:
super
(
compiler:
new
MockCompiler
());
}
class
MockAndroidDevice
extends
Mock
implements
AndroidDevice
{
TargetPlatform
get
platform
=>
TargetPlatform
.
android
;
@override
dynamic
noSuchMethod
(
Invocation
invocation
)
=>
super
.
noSuchMethod
(
invocation
);
}
class
MockIOSDevice
extends
Mock
implements
IOSDevice
{
TargetPlatform
get
platform
=>
TargetPlatform
.
iOS
;
@override
dynamic
noSuchMethod
(
Invocation
invocation
)
=>
super
.
noSuchMethod
(
invocation
);
}
class
MockIOSSimulator
extends
Mock
implements
IOSSimulator
{
TargetPlatform
get
platform
=>
TargetPlatform
.
iOSSimulator
;
@override
dynamic
noSuchMethod
(
Invocation
invocation
)
=>
super
.
noSuchMethod
(
invocation
);
}
class
MockDeviceStore
extends
DeviceStore
{
MockDeviceStore
()
:
super
(
android:
new
MockAndroidDevice
(),
iOS:
new
MockIOSDevice
(),
iOSSimulator:
new
MockIOSSimulator
());
}
void
applyMocksToCommand
(
FlutterCommand
command
)
{
command
..
applicationPackages
=
new
MockApplicationPackageStore
()
..
toolchain
=
new
MockToolchain
()
..
devices
=
new
MockDeviceStore
();
}
packages/flutter_tools/test/start_test.dart
0 → 100644
View file @
c8f66a1f
// 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:args/command_runner.dart'
;
import
'package:mockito/mockito.dart'
;
import
'package:sky_tools/src/commands/start.dart'
;
import
'package:test/test.dart'
;
import
'src/mocks.dart'
;
main
()
=>
defineTests
();
defineTests
()
{
group
(
'start'
,
()
{
test
(
'returns 0 when Android is connected and ready to be started'
,
()
{
StartCommand
command
=
new
StartCommand
();
applyMocksToCommand
(
command
);
MockDeviceStore
mockDevices
=
command
.
devices
;
when
(
mockDevices
.
android
.
isConnected
()).
thenReturn
(
true
);
when
(
mockDevices
.
android
.
isAppInstalled
(
any
)).
thenReturn
(
false
);
when
(
mockDevices
.
android
.
installApp
(
any
)).
thenReturn
(
true
);
when
(
mockDevices
.
android
.
startBundle
(
any
,
any
,
any
,
any
)).
thenReturn
(
true
);
when
(
mockDevices
.
android
.
stopApp
(
any
)).
thenReturn
(
true
);
when
(
mockDevices
.
iOS
.
isConnected
()).
thenReturn
(
false
);
when
(
mockDevices
.
iOS
.
isAppInstalled
(
any
)).
thenReturn
(
false
);
when
(
mockDevices
.
iOS
.
installApp
(
any
)).
thenReturn
(
false
);
when
(
mockDevices
.
iOS
.
startApp
(
any
)).
thenReturn
(
false
);
when
(
mockDevices
.
iOS
.
stopApp
(
any
)).
thenReturn
(
false
);
when
(
mockDevices
.
iOSSimulator
.
isConnected
()).
thenReturn
(
false
);
when
(
mockDevices
.
iOSSimulator
.
isAppInstalled
(
any
)).
thenReturn
(
false
);
when
(
mockDevices
.
iOSSimulator
.
installApp
(
any
)).
thenReturn
(
false
);
when
(
mockDevices
.
iOSSimulator
.
startApp
(
any
)).
thenReturn
(
false
);
when
(
mockDevices
.
iOSSimulator
.
stopApp
(
any
)).
thenReturn
(
false
);
CommandRunner
runner
=
new
CommandRunner
(
'test_flutter'
,
''
)
..
addCommand
(
command
);
runner
.
run
([
'start'
]).
then
((
int
code
)
=>
expect
(
code
,
equals
(
0
)));
});
test
(
'returns 0 when iOS is connected and ready to be started'
,
()
{
StartCommand
command
=
new
StartCommand
();
applyMocksToCommand
(
command
);
MockDeviceStore
mockDevices
=
command
.
devices
;
when
(
mockDevices
.
android
.
isConnected
()).
thenReturn
(
false
);
when
(
mockDevices
.
android
.
isAppInstalled
(
any
)).
thenReturn
(
false
);
when
(
mockDevices
.
android
.
installApp
(
any
)).
thenReturn
(
false
);
when
(
mockDevices
.
android
.
startBundle
(
any
,
any
,
any
,
any
)).
thenReturn
(
false
);
when
(
mockDevices
.
android
.
stopApp
(
any
)).
thenReturn
(
false
);
when
(
mockDevices
.
iOS
.
isConnected
()).
thenReturn
(
true
);
when
(
mockDevices
.
iOS
.
isAppInstalled
(
any
)).
thenReturn
(
false
);
when
(
mockDevices
.
iOS
.
installApp
(
any
)).
thenReturn
(
true
);
when
(
mockDevices
.
iOS
.
startApp
(
any
)).
thenReturn
(
true
);
when
(
mockDevices
.
iOS
.
stopApp
(
any
)).
thenReturn
(
false
);
when
(
mockDevices
.
iOSSimulator
.
isConnected
()).
thenReturn
(
false
);
when
(
mockDevices
.
iOSSimulator
.
isAppInstalled
(
any
)).
thenReturn
(
false
);
when
(
mockDevices
.
iOSSimulator
.
installApp
(
any
)).
thenReturn
(
false
);
when
(
mockDevices
.
iOSSimulator
.
startApp
(
any
)).
thenReturn
(
false
);
when
(
mockDevices
.
iOSSimulator
.
stopApp
(
any
)).
thenReturn
(
false
);
CommandRunner
runner
=
new
CommandRunner
(
'test_flutter'
,
''
)
..
addCommand
(
command
);
runner
.
run
([
'start'
]).
then
((
int
code
)
=>
expect
(
code
,
equals
(
0
)));
});
});
}
packages/flutter_tools/test/stop_test.dart
0 → 100644
View file @
c8f66a1f
// 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:args/command_runner.dart'
;
import
'package:mockito/mockito.dart'
;
import
'package:sky_tools/src/commands/stop.dart'
;
import
'package:test/test.dart'
;
import
'src/mocks.dart'
;
main
()
=>
defineTests
();
defineTests
()
{
group
(
'stop'
,
()
{
test
(
'returns 0 when Android is connected and ready to be stopped'
,
()
{
StopCommand
command
=
new
StopCommand
();
applyMocksToCommand
(
command
);
MockDeviceStore
mockDevices
=
command
.
devices
;
when
(
mockDevices
.
android
.
isConnected
()).
thenReturn
(
true
);
when
(
mockDevices
.
android
.
stopApp
(
any
)).
thenReturn
(
true
);
when
(
mockDevices
.
iOS
.
isConnected
()).
thenReturn
(
false
);
when
(
mockDevices
.
iOS
.
stopApp
(
any
)).
thenReturn
(
false
);
when
(
mockDevices
.
iOSSimulator
.
isConnected
()).
thenReturn
(
false
);
when
(
mockDevices
.
iOSSimulator
.
stopApp
(
any
)).
thenReturn
(
false
);
CommandRunner
runner
=
new
CommandRunner
(
'test_flutter'
,
''
)
..
addCommand
(
command
);
runner
.
run
([
'stop'
]).
then
((
int
code
)
=>
expect
(
code
,
equals
(
0
)));
});
test
(
'returns 0 when iOS is connected and ready to be stopped'
,
()
{
StopCommand
command
=
new
StopCommand
();
applyMocksToCommand
(
command
);
MockDeviceStore
mockDevices
=
command
.
devices
;
when
(
mockDevices
.
android
.
isConnected
()).
thenReturn
(
false
);
when
(
mockDevices
.
android
.
stopApp
(
any
)).
thenReturn
(
false
);
when
(
mockDevices
.
iOS
.
isConnected
()).
thenReturn
(
true
);
when
(
mockDevices
.
iOS
.
stopApp
(
any
)).
thenReturn
(
true
);
when
(
mockDevices
.
iOSSimulator
.
isConnected
()).
thenReturn
(
false
);
when
(
mockDevices
.
iOSSimulator
.
stopApp
(
any
)).
thenReturn
(
false
);
CommandRunner
runner
=
new
CommandRunner
(
'test_flutter'
,
''
)
..
addCommand
(
command
);
runner
.
run
([
'stop'
]).
then
((
int
code
)
=>
expect
(
code
,
equals
(
0
)));
});
});
}
packages/flutter_tools/test/trace_test.dart
0 → 100644
View file @
c8f66a1f
// 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:args/command_runner.dart'
;
import
'package:mockito/mockito.dart'
;
import
'package:sky_tools/src/commands/trace.dart'
;
import
'package:test/test.dart'
;
import
'src/mocks.dart'
;
main
()
=>
defineTests
();
defineTests
()
{
group
(
'trace'
,
()
{
test
(
'returns 1 when no Android device is connected'
,
()
{
TraceCommand
command
=
new
TraceCommand
();
applyMocksToCommand
(
command
);
MockDeviceStore
mockDevices
=
command
.
devices
;
when
(
mockDevices
.
android
.
isConnected
()).
thenReturn
(
false
);
CommandRunner
runner
=
new
CommandRunner
(
'test_flutter'
,
''
)
..
addCommand
(
command
);
runner
.
run
([
'trace'
]).
then
((
int
code
)
=>
expect
(
code
,
equals
(
1
)));
});
});
}
packages/flutter_tools/tool/daemon_client.dart
0 → 100644
View file @
c8f66a1f
// 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
'dart:convert'
;
import
'dart:io'
;
Process
daemon
;
main
()
async
{
daemon
=
await
Process
.
start
(
'dart'
,
[
'bin/sky_tools.dart'
,
'daemon'
]);
print
(
'daemon process started, pid:
${daemon.pid}
'
);
daemon
.
stdout
.
transform
(
UTF8
.
decoder
)
.
transform
(
const
LineSplitter
())
.
listen
((
String
line
)
=>
print
(
'<==
${line}
'
));
daemon
.
stderr
.
listen
((
data
)
=>
stderr
.
add
(
data
));
stdout
.
write
(
'> '
);
stdin
.
transform
(
UTF8
.
decoder
).
transform
(
const
LineSplitter
()).
listen
((
String
line
)
{
if
(
line
==
'version'
||
line
==
'v'
)
{
_send
({
'event'
:
'daemon.version'
});
}
else
if
(
line
==
'shutdown'
||
line
==
'q'
)
{
_send
({
'event'
:
'daemon.shutdown'
});
}
else
if
(
line
==
'start'
)
{
_send
({
'event'
:
'app.start'
});
}
else
if
(
line
==
'stopAll'
)
{
_send
({
'event'
:
'app.stopAll'
});
}
else
{
print
(
'command not understood:
${line}
'
);
}
stdout
.
write
(
'> '
);
});
daemon
.
exitCode
.
then
((
int
code
)
{
print
(
'daemon exiting (
${code}
)'
);
exit
(
code
);
});
}
int
id
=
0
;
void
_send
(
Map
map
)
{
map
[
'id'
]
=
id
++;
String
str
=
'[
${JSON.encode(map)}
]'
;
daemon
.
stdin
.
writeln
(
str
);
print
(
'==>
${str}
'
);
}
packages/flutter_tools/tool/travis.sh
0 → 100755
View file @
c8f66a1f
#!/bin/bash
# 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.
# Fast fail the script on failures.
set
-e
# Fetch all our dependencies
pub get
# Verify that the libraries are error free.
pub global activate tuneup
pub global run tuneup check
# And run our tests.
pub run
test
-j1
travis/setup.sh
View file @
c8f66a1f
...
@@ -3,5 +3,6 @@ set -ex
...
@@ -3,5 +3,6 @@ set -ex
(
cd
packages/cassowary
;
pub get
)
(
cd
packages/cassowary
;
pub get
)
(
cd
packages/newton
;
pub get
)
(
cd
packages/newton
;
pub get
)
(
cd
packages/flutter_tools
;
pub get
)
pub global activate tuneup
pub global activate tuneup
travis/test.sh
View file @
c8f66a1f
...
@@ -3,3 +3,4 @@ set -ex
...
@@ -3,3 +3,4 @@ set -ex
(
cd
packages/cassowary
;
pub global run tuneup check
;
pub run
test
-j1
)
(
cd
packages/cassowary
;
pub global run tuneup check
;
pub run
test
-j1
)
(
cd
packages/newton
;
pub global run tuneup check
;
pub run
test
-j1
)
(
cd
packages/newton
;
pub global run tuneup check
;
pub run
test
-j1
)
(
cd
packages/flutter_tools
;
pub global run tuneup check
;
pub run
test
-j1
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment