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
94ce956f
Unverified
Commit
94ce956f
authored
May 21, 2019
by
Zachary Anderson
Committed by
GitHub
May 21, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[flutter_tool] Adds support for 'run' for Fuchsia devices (#32849)
parent
3265e159
Changes
15
Show whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
1167 additions
and
197 deletions
+1167
-197
application_package.dart
packages/flutter_tools/lib/src/application_package.dart
+4
-1
os.dart
packages/flutter_tools/lib/src/base/os.dart
+33
-0
context_runner.dart
packages/flutter_tools/lib/src/context_runner.dart
+4
-6
amber_ctl.dart
packages/flutter_tools/lib/src/fuchsia/amber_ctl.dart
+76
-0
application_package.dart
...es/flutter_tools/lib/src/fuchsia/application_package.dart
+71
-0
fuchsia_build.dart
packages/flutter_tools/lib/src/fuchsia/fuchsia_build.dart
+3
-2
fuchsia_dev_finder.dart
...ges/flutter_tools/lib/src/fuchsia/fuchsia_dev_finder.dart
+56
-0
fuchsia_device.dart
packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart
+159
-43
fuchsia_kernel_compiler.dart
...lutter_tools/lib/src/fuchsia/fuchsia_kernel_compiler.dart
+7
-8
fuchsia_pm.dart
packages/flutter_tools/lib/src/fuchsia/fuchsia_pm.dart
+161
-54
fuchsia_sdk.dart
packages/flutter_tools/lib/src/fuchsia/fuchsia_sdk.dart
+38
-18
tiles_ctl.dart
packages/flutter_tools/lib/src/fuchsia/tiles_ctl.dart
+113
-0
resident_runner.dart
packages/flutter_tools/lib/src/resident_runner.dart
+8
-2
build_fuchsia_test.dart
packages/flutter_tools/test/commands/build_fuchsia_test.dart
+96
-53
fuchsa_device_test.dart
packages/flutter_tools/test/fuchsia/fuchsa_device_test.dart
+338
-10
No files found.
packages/flutter_tools/lib/src/application_package.dart
View file @
94ce956f
...
...
@@ -17,6 +17,7 @@ import 'base/os.dart' show os;
import
'base/process.dart'
;
import
'base/user_messages.dart'
;
import
'build_info.dart'
;
import
'fuchsia/application_package.dart'
;
import
'globals.dart'
;
import
'ios/ios_workflow.dart'
;
import
'ios/plist_utils.dart'
as
plist
;
...
...
@@ -66,7 +67,9 @@ class ApplicationPackageFactory {
?
WindowsApp
.
fromWindowsProject
(
FlutterProject
.
current
().
windows
)
:
WindowsApp
.
fromPrebuiltApp
(
applicationBinary
);
case
TargetPlatform
.
fuchsia
:
return
null
;
return
applicationBinary
==
null
?
FuchsiaApp
.
fromFuchsiaProject
(
FlutterProject
.
current
().
fuchsia
)
:
FuchsiaApp
.
fromPrebuiltApp
(
applicationBinary
);
}
assert
(
platform
!=
null
);
return
null
;
...
...
packages/flutter_tools/lib/src/base/os.dart
View file @
94ce956f
...
...
@@ -3,6 +3,8 @@
// found in the LICENSE file.
import
'package:archive/archive.dart'
;
import
'../globals.dart'
;
import
'context.dart'
;
import
'file_system.dart'
;
import
'io.dart'
;
...
...
@@ -72,6 +74,37 @@ abstract class OperatingSystemUtils {
/// Returns the separator between items in the PATH environment variable.
String
get
pathVarSeparator
;
/// Returns an unused network port.
///
/// Returns 0 if an unused port cannot be found.
///
/// The port returned by this function may become used before it is bound by
/// its intended user.
Future
<
int
>
findFreePort
({
bool
ipv6
=
false
})
async
{
int
port
=
0
;
ServerSocket
serverSocket
;
final
InternetAddress
loopback
=
ipv6
?
InternetAddress
.
loopbackIPv6
:
InternetAddress
.
loopbackIPv4
;
try
{
serverSocket
=
await
ServerSocket
.
bind
(
loopback
,
0
);
port
=
serverSocket
.
port
;
}
on
SocketException
catch
(
e
)
{
// If ipv4 loopback bind fails, try ipv6.
if
(!
ipv6
)
{
return
findFreePort
(
ipv6:
true
);
}
printTrace
(
'findFreePort failed:
$e
'
);
}
catch
(
e
)
{
// Failures are signaled by a return value of 0 from this function.
printTrace
(
'findFreePort failed:
$e
'
);
}
finally
{
if
(
serverSocket
!=
null
)
{
await
serverSocket
.
close
();
}
}
return
port
;
}
}
class
_PosixUtils
extends
OperatingSystemUtils
{
...
...
packages/flutter_tools/lib/src/context_runner.dart
View file @
94ce956f
...
...
@@ -27,10 +27,9 @@ import 'devfs.dart';
import
'device.dart'
;
import
'doctor.dart'
;
import
'emulator.dart'
;
import
'fuchsia/fuchsia_kernel_compiler.dart'
;
import
'fuchsia/fuchsia_pm.dart'
;
import
'fuchsia/fuchsia_sdk.dart'
;
import
'fuchsia/fuchsia_workflow.dart'
;
import
'fuchsia/fuchsia_device.dart'
show
FuchsiaDeviceTools
;
import
'fuchsia/fuchsia_sdk.dart'
show
FuchsiaSdk
,
FuchsiaArtifacts
;
import
'fuchsia/fuchsia_workflow.dart'
show
FuchsiaWorkflow
;
import
'ios/cocoapods.dart'
;
import
'ios/ios_workflow.dart'
;
import
'ios/mac.dart'
;
...
...
@@ -76,8 +75,7 @@ Future<T> runInContext<T>(
Flags:
()
=>
const
EmptyFlags
(),
FlutterVersion:
()
=>
FlutterVersion
(
const
SystemClock
()),
FuchsiaArtifacts:
()
=>
FuchsiaArtifacts
.
find
(),
FuchsiaKernelCompiler:
()
=>
FuchsiaKernelCompiler
(),
FuchsiaPM:
()
=>
FuchsiaPM
(),
FuchsiaDeviceTools:
()
=>
FuchsiaDeviceTools
(),
FuchsiaSdk:
()
=>
FuchsiaSdk
(),
FuchsiaWorkflow:
()
=>
FuchsiaWorkflow
(),
GenSnapshot:
()
=>
const
GenSnapshot
(),
...
...
packages/flutter_tools/lib/src/fuchsia/amber_ctl.dart
0 → 100644
View file @
94ce956f
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'../base/process.dart'
;
import
'fuchsia_device.dart'
;
import
'fuchsia_pm.dart'
;
// usage: amber_ctl <command> [opts]
// Commands
// get_up - get an update for a package
// Options
// -n: name of the package
// -v: version of the package to retrieve, if none is supplied any
// package instance could match
// -m: merkle root of the package to retrieve, if none is supplied
// any package instance could match
//
// get_blob - get the specified content blob
// -i: content ID of the blob
//
// add_src - add a source to the list we can use
// -n: name of the update source (optional, with URL)
// -f: file path or url to a source config file
// -h: SHA256 hash of source config file (optional, with URL)
// -x: do not disable other active sources (if the provided source is
// enabled)
//
// rm_src - remove a source, if it exists
// -n: name of the update source
//
// list_srcs - list the set of sources we can use
//
// enable_src
// -n: name of the update source
// -x: do not disable other active sources
//
// disable_src
// -n: name of the update source
//
// system_update - check for, download, and apply any available system
// update
//
// gc - trigger a garbage collection
//
// print_state - print go routine state of amber process
/// Simple wrapper for interacting with the 'amber_ctl' tool running on the
/// Fuchsia device.
class
FuchsiaAmberCtl
{
/// Teaches the amber instance running on [device] about the Fuchsia package
/// server accessible via [configUrl].
Future
<
bool
>
addSrc
(
FuchsiaDevice
device
,
FuchsiaPackageServer
server
)
async
{
final
String
configUrl
=
'
${server.url}
/config.json'
;
final
RunResult
result
=
await
device
.
shell
(
'amber_ctl add_src -x -f
$configUrl
'
);
return
result
.
exitCode
==
0
;
}
/// Instructs the amber instance running on [device] to forget about the
/// Fuchsia package server that it was accessing via [serverUrl].
Future
<
bool
>
rmSrc
(
FuchsiaDevice
device
,
FuchsiaPackageServer
server
)
async
{
final
RunResult
result
=
await
device
.
shell
(
'amber_ctl rm_src -n
${server.url}
'
);
return
result
.
exitCode
==
0
;
}
/// Instructs the amber instance running on [device] to prefetch the package
/// [packageName].
Future
<
bool
>
getUp
(
FuchsiaDevice
device
,
String
packageName
)
async
{
final
RunResult
result
=
await
device
.
shell
(
'amber_ctl get_up -n
$packageName
'
);
return
result
.
exitCode
==
0
;
}
}
packages/flutter_tools/lib/src/fuchsia/application_package.dart
0 → 100644
View file @
94ce956f
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'package:meta/meta.dart'
;
import
'../application_package.dart'
;
import
'../base/file_system.dart'
;
import
'../build_info.dart'
;
import
'../project.dart'
;
abstract
class
FuchsiaApp
extends
ApplicationPackage
{
FuchsiaApp
({
@required
String
projectBundleId
})
:
super
(
id:
projectBundleId
);
/// Creates a new [FuchsiaApp] from a fuchsia sub project.
factory
FuchsiaApp
.
fromFuchsiaProject
(
FuchsiaProject
project
)
{
return
BuildableFuchsiaApp
(
project:
project
,
);
}
/// Creates a new [FuchsiaApp] from an existing .far archive.
///
/// [applicationBinary] is the path to the .far archive.
factory
FuchsiaApp
.
fromPrebuiltApp
(
FileSystemEntity
applicationBinary
)
{
return
PrebuiltFuchsiaApp
(
farArchive:
applicationBinary
.
path
,
);
}
@override
String
get
displayName
=>
id
;
/// The location of the 'far' archive containing the built app.
File
farArchive
(
BuildMode
buildMode
);
}
class
PrebuiltFuchsiaApp
extends
FuchsiaApp
{
PrebuiltFuchsiaApp
({
@required
String
farArchive
,
})
:
_farArchive
=
farArchive
,
// TODO(zra): Extract the archive and extract the id from meta/package.
super
(
projectBundleId:
farArchive
);
final
String
_farArchive
;
@override
File
farArchive
(
BuildMode
buildMode
)
=>
fs
.
file
(
_farArchive
);
@override
String
get
name
=>
_farArchive
;
}
class
BuildableFuchsiaApp
extends
FuchsiaApp
{
BuildableFuchsiaApp
({
this
.
project
})
:
super
(
projectBundleId:
project
.
project
.
manifest
.
appName
);
final
FuchsiaProject
project
;
@override
File
farArchive
(
BuildMode
buildMode
)
{
// TODO(zra): Distinguish among build modes.
final
String
outDir
=
getFuchsiaBuildDirectory
();
final
String
pkgDir
=
fs
.
path
.
join
(
outDir
,
'pkg'
);
final
String
appName
=
project
.
project
.
manifest
.
appName
;
return
fs
.
file
(
fs
.
path
.
join
(
pkgDir
,
'
$appName
-0.far'
));
}
@override
String
get
name
=>
project
.
project
.
manifest
.
appName
;
}
packages/flutter_tools/lib/src/fuchsia/fuchsia_build.dart
View file @
94ce956f
...
...
@@ -12,8 +12,8 @@ import '../bundle.dart';
import
'../devfs.dart'
;
import
'../project.dart'
;
import
'fuchsia_kernel_compiler.dart'
;
import
'fuchsia_pm.dart'
;
import
'fuchsia_sdk.dart'
;
// Building a Fuchsia package has a few steps:
// 1. Do the custom kernel compile using the kernel compiler from the Fuchsia
...
...
@@ -30,7 +30,7 @@ Future<void> buildFuchsia(
outDir
.
createSync
(
recursive:
true
);
}
await
fuchsiaKernelCompiler
.
build
(
await
fuchsia
Sdk
.
fuchsia
KernelCompiler
.
build
(
fuchsiaProject:
fuchsiaProject
,
target:
target
,
buildInfo:
buildInfo
);
await
_buildAssets
(
fuchsiaProject
,
target
,
buildInfo
);
await
_buildPackage
(
fuchsiaProject
,
target
,
buildInfo
);
...
...
@@ -96,6 +96,7 @@ Future<void> _buildPackage(
manifestFile
.
writeAsStringSync
(
'meta/package=
$pkgDir
/meta/package
\n
'
,
mode:
FileMode
.
append
);
final
FuchsiaPM
fuchsiaPM
=
fuchsiaSdk
.
fuchsiaPM
;
if
(!
await
fuchsiaPM
.
init
(
pkgDir
,
appName
))
{
return
;
}
...
...
packages/flutter_tools/lib/src/fuchsia/fuchsia_dev_finder.dart
0 → 100644
View file @
94ce956f
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'../base/common.dart'
;
import
'../base/process.dart'
;
import
'fuchsia_sdk.dart'
;
// Usage: dev_finder <flags> <subcommand> <subcommand args>
//
// Subcommands:
// commands list all command names
// flags describe all known top-level flags
// help describe subcommands and their syntax
// list lists all Fuchsia devices on the network
// resolve attempts to resolve all passed Fuchsia domain names on the
// network
/// A simple wrapper for the Fuchsia SDK's 'dev_finder' tool.
class
FuchsiaDevFinder
{
/// Returns a list of attached devices as a list of strings with entries
/// formatted as follows:
/// 192.168.42.172 scare-cable-skip-joy
Future
<
List
<
String
>>
list
()
async
{
if
(
fuchsiaArtifacts
.
devFinder
==
null
)
{
throwToolExit
(
'Fuchsia dev_finder tool not found.'
);
}
final
List
<
String
>
command
=
<
String
>[
fuchsiaArtifacts
.
devFinder
.
path
,
'list'
,
'-full'
];
final
RunResult
result
=
await
runAsync
(
command
);
return
(
result
.
exitCode
==
0
)
?
result
.
stdout
.
split
(
'
\n
'
)
:
null
;
}
/// Returns the host address by which the device [deviceName] should use for
/// the host.
///
/// The string [deviceName] should be the name of the device from the
/// 'list' command, e.g. 'scare-cable-skip-joy'.
Future
<
String
>
resolve
(
String
deviceName
)
async
{
if
(
fuchsiaArtifacts
.
devFinder
==
null
)
{
throwToolExit
(
'Fuchsia dev_finder tool not found.'
);
}
final
List
<
String
>
command
=
<
String
>[
fuchsiaArtifacts
.
devFinder
.
path
,
'resolve'
,
'-local'
,
'-device-limit'
,
'1'
,
deviceName
];
final
RunResult
result
=
await
runAsync
(
command
);
return
(
result
.
exitCode
==
0
)
?
result
.
stdout
.
trim
()
:
null
;
}
}
packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart
View file @
94ce956f
...
...
@@ -9,8 +9,11 @@ import 'package:meta/meta.dart';
import
'../application_package.dart'
;
import
'../artifacts.dart'
;
import
'../base/common.dart'
;
import
'../base/context.dart'
;
import
'../base/file_system.dart'
;
import
'../base/io.dart'
;
import
'../base/logger.dart'
;
import
'../base/os.dart'
;
import
'../base/platform.dart'
;
import
'../base/process.dart'
;
import
'../base/process_manager.dart'
;
...
...
@@ -21,8 +24,28 @@ import '../globals.dart';
import
'../project.dart'
;
import
'../vmservice.dart'
;
import
'amber_ctl.dart'
;
import
'application_package.dart'
;
import
'fuchsia_build.dart'
;
import
'fuchsia_pm.dart'
;
import
'fuchsia_sdk.dart'
;
import
'fuchsia_workflow.dart'
;
import
'tiles_ctl.dart'
;
/// The [FuchsiaDeviceTools] instance.
FuchsiaDeviceTools
get
fuchsiaDeviceTools
=>
context
.
get
<
FuchsiaDeviceTools
>();
/// Fuchsia device-side tools.
class
FuchsiaDeviceTools
{
FuchsiaAmberCtl
_amberCtl
;
FuchsiaAmberCtl
get
amberCtl
=>
_amberCtl
??=
FuchsiaAmberCtl
();
FuchsiaTilesCtl
_tilesCtl
;
FuchsiaTilesCtl
get
tilesCtl
=>
_tilesCtl
??=
FuchsiaTilesCtl
();
}
final
FuchsiaAmberCtl
_amberCtl
=
fuchsiaDeviceTools
.
amberCtl
;
final
FuchsiaTilesCtl
_tilesCtl
=
fuchsiaDeviceTools
.
tilesCtl
;
final
String
_ipv4Loopback
=
InternetAddress
.
loopbackIPv4
.
address
;
final
String
_ipv6Loopback
=
InternetAddress
.
loopbackIPv6
.
address
;
...
...
@@ -48,11 +71,15 @@ class _FuchsiaLogReader extends DeviceLogReader {
Stream
<
String
>
_logLines
;
@override
Stream
<
String
>
get
logLines
{
_logLines
??=
_processLogs
(
fuchsiaSdk
.
syslogs
(
_device
.
id
));
final
Stream
<
String
>
logStream
=
fuchsiaSdk
.
syslogs
(
_device
.
id
);
_logLines
??=
_processLogs
(
logStream
);
return
_logLines
;
}
Stream
<
String
>
_processLogs
(
Stream
<
String
>
lines
)
{
if
(
lines
==
null
)
{
return
null
;
}
// Get the starting time of the log processor to filter logs from before
// the process attached.
final
DateTime
startTime
=
systemClock
.
now
();
...
...
@@ -60,7 +87,7 @@ class _FuchsiaLogReader extends DeviceLogReader {
// the correct fuchsia module.
final
RegExp
matchRegExp
=
_app
==
null
?
_flutterLogOutput
:
RegExp
(
'INFO:
${_app.name}
\\
(flutter
\\
): '
);
:
RegExp
(
'INFO:
${_app.name}
(
\
.cmx)?
\\
(flutter
\\
): '
);
return
Stream
<
String
>.
eventTransformed
(
lines
,
(
Sink
<
String
>
outout
)
=>
_FuchsiaLogSink
(
outout
,
matchRegExp
,
startTime
),
...
...
@@ -188,7 +215,7 @@ class FuchsiaDevice extends Device {
@override
Future
<
LaunchResult
>
startApp
(
ApplicationPackage
package
,
{
covariant
FuchsiaApp
package
,
{
String
mainPath
,
String
route
,
DebuggingOptions
debuggingOptions
,
...
...
@@ -196,14 +223,111 @@ class FuchsiaDevice extends Device {
bool
prebuiltApplication
=
false
,
bool
usesTerminalUi
=
true
,
bool
ipv6
=
false
,
})
=>
Future
<
void
>.
error
(
'unimplemented'
);
})
async
{
if
(!
prebuiltApplication
)
{
await
buildFuchsia
(
fuchsiaProject:
FlutterProject
.
current
().
fuchsia
,
target:
mainPath
,
buildInfo:
debuggingOptions
.
buildInfo
);
}
// Stop the app if it's currently running.
await
stopApp
(
package
);
// Find out who the device thinks we are.
final
String
host
=
await
fuchsiaSdk
.
fuchsiaDevFinder
.
resolve
(
name
);
final
int
port
=
await
os
.
findFreePort
();
if
(
port
==
0
)
{
printError
(
'Failed to find a free port'
);
return
LaunchResult
.
failed
();
}
final
Directory
packageRepo
=
fs
.
directory
(
fs
.
path
.
join
(
getFuchsiaBuildDirectory
(),
'.pkg-repo'
));
packageRepo
.
createSync
(
recursive:
true
);
final
String
appName
=
FlutterProject
.
current
().
manifest
.
appName
;
final
Status
status
=
logger
.
startProgress
(
'Starting Fuchsia application...'
,
timeout:
null
,
);
FuchsiaPackageServer
fuchsiaPackageServer
;
bool
serverRegistered
=
false
;
try
{
// Start up a package server.
fuchsiaPackageServer
=
FuchsiaPackageServer
(
packageRepo
.
path
,
host
,
port
);
if
(!
await
fuchsiaPackageServer
.
start
())
{
printError
(
'Failed to start the Fuchsia package server'
);
return
LaunchResult
.
failed
();
}
final
File
farArchive
=
package
.
farArchive
(
debuggingOptions
.
buildInfo
.
mode
);
if
(!
await
fuchsiaPackageServer
.
addPackage
(
farArchive
))
{
printError
(
'Failed to add package to the package server'
);
return
LaunchResult
.
failed
();
}
// Teach amber about the package server.
if
(!
await
_amberCtl
.
addSrc
(
this
,
fuchsiaPackageServer
))
{
printError
(
'Failed to teach amber about the package server'
);
return
LaunchResult
.
failed
();
}
serverRegistered
=
true
;
// Tell amber to prefetch the app.
if
(!
await
_amberCtl
.
getUp
(
this
,
appName
))
{
printError
(
'Failed to get amber to prefetch the package'
);
return
LaunchResult
.
failed
();
}
// Ensure tiles_ctl is started, and start the app.
if
(!
await
FuchsiaTilesCtl
.
ensureStarted
(
this
))
{
printError
(
'Failed to ensure that tiles is started on the device'
);
return
LaunchResult
.
failed
();
}
// Instruct tiles_ctl to start the app.
final
String
fuchsiaUrl
=
'fuchsia-pkg://fuchsia.com/
$appName
#meta/
$appName
.cmx'
;
if
(!
await
_tilesCtl
.
add
(
this
,
fuchsiaUrl
,
<
String
>[]))
{
printError
(
'Failed to add the app to tiles'
);
return
LaunchResult
.
failed
();
}
}
finally
{
// Try to un-teach amber about the package server if needed.
if
(
serverRegistered
)
{
await
_amberCtl
.
rmSrc
(
this
,
fuchsiaPackageServer
);
}
// Shutdown the package server and delete the package repo;
fuchsiaPackageServer
.
stop
();
packageRepo
.
deleteSync
(
recursive:
true
);
status
.
cancel
();
}
if
(!
debuggingOptions
.
buildInfo
.
isDebug
&&
!
debuggingOptions
.
buildInfo
.
isProfile
)
{
return
LaunchResult
.
succeeded
();
}
// In a debug or profile build, try to find the observatory uri.
final
FuchsiaIsolateDiscoveryProtocol
discovery
=
FuchsiaIsolateDiscoveryProtocol
(
this
,
appName
);
try
{
final
Uri
observatoryUri
=
await
discovery
.
uri
;
return
LaunchResult
.
succeeded
(
observatoryUri:
observatoryUri
);
}
finally
{
discovery
.
dispose
();
}
}
@override
Future
<
bool
>
stopApp
(
ApplicationPackage
app
)
async
{
// Currently we don't have a way to stop an app running on Fuchsia.
Future
<
bool
>
stopApp
(
covariant
FuchsiaApp
app
)
async
{
final
int
appKey
=
await
FuchsiaTilesCtl
.
findAppKey
(
this
,
app
.
id
);
if
(
appKey
!=
-
1
)
{
if
(!
await
_tilesCtl
.
remove
(
this
,
appKey
))
{
printError
(
'tiles_ctl remove on
${app.id}
failed.'
);
return
false
;
}
}
return
true
;
}
@override
Future
<
TargetPlatform
>
get
targetPlatform
async
=>
TargetPlatform
.
fuchsia
;
...
...
@@ -250,7 +374,13 @@ class FuchsiaDevice extends Device {
/// List the ports currently running a dart observatory.
Future
<
List
<
int
>>
servicePorts
()
async
{
final
String
findOutput
=
await
shell
(
'find /hub -name vmservice-port'
);
const
String
findCommand
=
'find /hub -name vmservice-port'
;
final
RunResult
findResult
=
await
shell
(
findCommand
);
if
(
findResult
.
exitCode
!=
0
)
{
throwToolExit
(
"'
$findCommand
' on device
$id
failed"
);
return
null
;
}
final
String
findOutput
=
findResult
.
stdout
;
if
(
findOutput
.
trim
()
==
''
)
{
throwToolExit
(
'No Dart Observatories found. Are you running a debug build?'
);
...
...
@@ -261,7 +391,13 @@ class FuchsiaDevice extends Device {
if
(
path
==
''
)
{
continue
;
}
final
String
lsOutput
=
await
shell
(
'ls
$path
'
);
final
String
lsCommand
=
'ls
$path
'
;
final
RunResult
lsResult
=
await
shell
(
lsCommand
);
if
(
lsResult
.
exitCode
!=
0
)
{
throwToolExit
(
"'
$lsCommand
' on device
$id
failed"
);
return
null
;
}
final
String
lsOutput
=
lsResult
.
stdout
;
for
(
String
line
in
lsOutput
.
split
(
'
\n
'
))
{
if
(
line
==
''
)
{
continue
;
...
...
@@ -276,20 +412,18 @@ class FuchsiaDevice extends Device {
}
/// Run `command` on the Fuchsia device shell.
Future
<
String
>
shell
(
String
command
)
async
{
final
RunResult
result
=
await
runAsync
(<
String
>[
Future
<
RunResult
>
shell
(
String
command
)
async
{
if
(
fuchsiaArtifacts
.
sshConfig
==
null
)
{
throwToolExit
(
'Cannot interact with device. No ssh config.
\n
'
'Try setting FUCHSIA_SSH_CONFIG or FUCHSIA_BUILD_DIR.'
);
}
return
await
runAsync
(<
String
>[
'ssh'
,
'-F'
,
fuchsiaArtifacts
.
sshConfig
.
absolute
.
path
,
id
,
command
]);
if
(
result
.
exitCode
!=
0
)
{
throwToolExit
(
'Command failed:
$command
\n
stdout:
${result.stdout}
\n
stderr:
${result.stderr}
'
);
return
null
;
}
return
result
.
stdout
;
}
/// Finds the first port running a VM matching `isolateName` from the
...
...
@@ -332,7 +466,9 @@ class FuchsiaDevice extends Device {
FuchsiaIsolateDiscoveryProtocol
(
this
,
isolateName
);
@override
bool
isSupportedForProject
(
FlutterProject
flutterProject
)
=>
true
;
bool
isSupportedForProject
(
FlutterProject
flutterProject
)
{
return
flutterProject
.
fuchsia
.
existsSync
();
}
}
class
FuchsiaIsolateDiscoveryProtocol
{
...
...
@@ -431,7 +567,10 @@ class _FuchsiaPortForwarder extends DevicePortForwarder {
@override
Future
<
int
>
forward
(
int
devicePort
,
{
int
hostPort
})
async
{
hostPort
??=
await
_findPort
();
hostPort
??=
await
os
.
findFreePort
();
if
(
hostPort
==
0
)
{
throwToolExit
(
'Failed to forward port
$devicePort
. No free host-side ports'
);
}
// Note: the provided command works around a bug in -N, see US-515
// for more explanation.
final
List
<
String
>
command
=
<
String
>[
...
...
@@ -483,27 +622,4 @@ class _FuchsiaPortForwarder extends DevicePortForwarder {
throwToolExit
(
result
.
stderr
);
}
}
static
Future
<
int
>
_findPort
()
async
{
int
port
=
0
;
ServerSocket
serverSocket
;
try
{
serverSocket
=
await
ServerSocket
.
bind
(
_ipv4Loopback
,
0
);
port
=
serverSocket
.
port
;
}
catch
(
e
)
{
// Failures are signaled by a return value of 0 from this function.
printTrace
(
'_findPort failed:
$e
'
);
}
if
(
serverSocket
!=
null
)
{
await
serverSocket
.
close
();
}
return
port
;
}
}
class
FuchsiaModulePackage
extends
ApplicationPackage
{
FuchsiaModulePackage
({
@required
this
.
name
})
:
super
(
id:
name
);
@override
final
String
name
;
}
packages/flutter_tools/lib/src/fuchsia/fuchsia_kernel_compiler.dart
View file @
94ce956f
...
...
@@ -6,11 +6,10 @@ import 'package:meta/meta.dart';
import
'../artifacts.dart'
;
import
'../base/common.dart'
;
import
'../base/context.dart'
;
import
'../base/file_system.dart'
;
import
'../base/io.dart'
;
import
'../base/logger.dart'
;
import
'../base/process
_manager
.dart'
;
import
'../base/process.dart'
;
import
'../build_info.dart'
;
import
'../convert.dart'
;
import
'../globals.dart'
;
...
...
@@ -18,10 +17,8 @@ import '../project.dart';
import
'fuchsia_sdk.dart'
;
/// The [FuchsiaKernelCompiler] instance.
FuchsiaKernelCompiler
get
fuchsiaKernelCompiler
=>
context
.
get
<
FuchsiaKernelCompiler
>();
/// This is a simple wrapper around the custom kernel compiler from the Fuchsia
/// SDK.
class
FuchsiaKernelCompiler
{
/// Compiles the [fuchsiaProject] with entrypoint [target] to a collection of
/// .dilp files (consisting of the app split along package: boundaries, but
...
...
@@ -33,6 +30,9 @@ class FuchsiaKernelCompiler {
BuildInfo
buildInfo
=
BuildInfo
.
debug
,
})
async
{
// TODO(zra): Use filesystem root and scheme information from buildInfo.
if
(
fuchsiaArtifacts
.
kernelCompiler
==
null
)
{
throwToolExit
(
'Fuchisa kernel compiler not found'
);
}
const
String
multiRootScheme
=
'main-root'
;
final
String
packagesFile
=
fuchsiaProject
.
project
.
packagesFile
.
path
;
final
String
outDir
=
getFuchsiaBuildDirectory
();
...
...
@@ -87,8 +87,7 @@ class FuchsiaKernelCompiler {
artifacts
.
getArtifactPath
(
Artifact
.
engineDartBinary
),
fuchsiaArtifacts
.
kernelCompiler
.
path
,
]..
addAll
(
flags
);
printTrace
(
"Running: '
${command.join(' ')}
'"
);
final
Process
process
=
await
processManager
.
start
(
command
);
final
Process
process
=
await
runCommand
(
command
);
final
Status
status
=
logger
.
startProgress
(
'Building Fuchsia application...'
,
timeout:
null
,
...
...
packages/flutter_tools/lib/src/fuchsia/fuchsia_pm.dart
View file @
94ce956f
...
...
@@ -2,16 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'../base/context.dart'
;
import
'../base/common.dart'
;
import
'../base/file_system.dart'
;
import
'../base/io.dart'
;
import
'../base/process_manager.dart'
;
import
'../base/process.dart'
;
import
'../convert.dart'
;
import
'../globals.dart'
;
import
'fuchsia_sdk.dart'
;
/// The [FuchsiaPM] instance.
FuchsiaPM
get
fuchsiaPM
=>
context
.
get
<
FuchsiaPM
>();
/// This is a basic wrapper class for the Fuchsia SDK's `pm` tool.
class
FuchsiaPM
{
/// Initializes the staging area at [buildPath] for creating the Fuchsia
...
...
@@ -21,47 +20,27 @@ class FuchsiaPM {
///
/// NB: The [buildPath] should probably be e.g. `build/fuchsia/pkg`, and the
/// [appName] should probably be the name of the app from the pubspec file.
Future
<
bool
>
init
(
String
buildPath
,
String
appName
)
async
{
final
List
<
String
>
command
=
<
String
>[
fuchsiaArtifacts
.
pm
.
path
,
Future
<
bool
>
init
(
String
buildPath
,
String
appName
)
{
return
_runPMCommand
(<
String
>[
'-o'
,
buildPath
,
'-n'
,
appName
,
'init'
,
];
printTrace
(
"Running: '
${command.join(' ')}
'"
);
final
ProcessResult
result
=
await
processManager
.
run
(
command
);
if
(
result
.
exitCode
!=
0
)
{
printError
(
'Error initializing Fuchsia package for
$appName
: '
);
printError
(
result
.
stdout
);
printError
(
result
.
stderr
);
return
false
;
}
return
true
;
]);
}
/// Generates a new private key to be used to sign a Fuchsia package.
///
/// [buildPath] should be the same [buildPath] passed to [init].
Future
<
bool
>
genkey
(
String
buildPath
,
String
outKeyPath
)
async
{
final
List
<
String
>
command
=
<
String
>[
fuchsiaArtifacts
.
pm
.
path
,
Future
<
bool
>
genkey
(
String
buildPath
,
String
outKeyPath
)
{
return
_runPMCommand
(<
String
>[
'-o'
,
buildPath
,
'-k'
,
outKeyPath
,
'genkey'
,
];
printTrace
(
"Running: '
${command.join(' ')}
'"
);
final
ProcessResult
result
=
await
processManager
.
run
(
command
);
if
(
result
.
exitCode
!=
0
)
{
printError
(
'Error generating key for Fuchsia package: '
);
printError
(
result
.
stdout
);
printError
(
result
.
stderr
);
return
false
;
}
return
true
;
]);
}
/// Updates, signs, and seals a Fuchsia package.
...
...
@@ -80,9 +59,8 @@ class FuchsiaPM {
/// where $APPNAME is the same [appName] passed to [init], and meta/package
/// is set up to be the file `meta/package` created by [init].
Future
<
bool
>
build
(
String
buildPath
,
String
keyPath
,
String
manifestPath
)
async
{
final
List
<
String
>
command
=
<
String
>[
fuchsiaArtifacts
.
pm
.
path
,
String
buildPath
,
String
keyPath
,
String
manifestPath
)
{
return
_runPMCommand
(<
String
>[
'-o'
,
buildPath
,
'-k'
,
...
...
@@ -90,16 +68,7 @@ class FuchsiaPM {
'-m'
,
manifestPath
,
'build'
,
];
printTrace
(
"Running: '
${command.join(' ')}
'"
);
final
ProcessResult
result
=
await
processManager
.
run
(
command
);
if
(
result
.
exitCode
!=
0
)
{
printError
(
'Error building Fuchsia package: '
);
printError
(
result
.
stdout
);
printError
(
result
.
stderr
);
return
false
;
}
return
true
;
]);
}
/// Constructs a .far representation of the Fuchsia package.
...
...
@@ -109,10 +78,8 @@ class FuchsiaPM {
///
/// [buildPath] should be the same path passed to [init], and [manfiestPath]
/// should be the same manifest passed to [build].
Future
<
bool
>
archive
(
String
buildPath
,
String
keyPath
,
String
manifestPath
)
async
{
final
List
<
String
>
command
=
<
String
>[
fuchsiaArtifacts
.
pm
.
path
,
Future
<
bool
>
archive
(
String
buildPath
,
String
keyPath
,
String
manifestPath
)
{
return
_runPMCommand
(<
String
>[
'-o'
,
buildPath
,
'-k'
,
...
...
@@ -120,15 +87,155 @@ class FuchsiaPM {
'-m'
,
manifestPath
,
'archive'
,
]);
}
/// Initializes a new package repository at [repoPath] to be later served by
/// the 'serve' command.
Future
<
bool
>
newrepo
(
String
repoPath
)
{
return
_runPMCommand
(<
String
>[
'newrepo'
,
'-repo'
,
repoPath
,
]);
}
/// Spawns an http server in a new process for serving Fuchisa packages.
///
/// The arguemnt [repoPath] should have previously been an arguemnt to
/// [newrepo]. The [host] should be the host reported by
/// [FuchsiaDevFinder.resolve], and [port] should be an unused port for the
/// http server to bind.
Future
<
Process
>
serve
(
String
repoPath
,
String
host
,
int
port
)
async
{
if
(
fuchsiaArtifacts
.
pm
==
null
)
{
throwToolExit
(
'Fuchsia pm tool not found'
);
}
final
List
<
String
>
command
=
<
String
>[
fuchsiaArtifacts
.
pm
.
path
,
'serve'
,
'-repo'
,
repoPath
,
'-l'
,
'
$host
:
$port
'
,
];
printTrace
(
"Running: '
${command.join(' ')}
'"
);
final
ProcessResult
result
=
await
processManager
.
run
(
command
);
if
(
result
.
exitCode
!=
0
)
{
printError
(
'Error archiving Fuchsia package: '
);
printError
(
result
.
stdout
);
printError
(
result
.
stderr
);
final
Process
process
=
await
runCommand
(
command
);
process
.
stdout
.
transform
(
utf8
.
decoder
)
.
transform
(
const
LineSplitter
())
.
listen
(
printTrace
);
process
.
stderr
.
transform
(
utf8
.
decoder
)
.
transform
(
const
LineSplitter
())
.
listen
(
printError
);
return
process
;
}
/// Publishes a Fuchsia package to a served package repository.
///
/// For a package repo initialized with [newrepo] at [repoPath] and served
/// by [serve], this call publishes the `far` package at [packagePath] to
/// the repo such that it will be visible to devices connecting to the
/// package server.
Future
<
bool
>
publish
(
String
repoPath
,
String
packagePath
)
{
return
_runPMCommand
(<
String
>[
'publish'
,
'-a'
,
'-r'
,
repoPath
,
'-f'
,
packagePath
,
]);
}
Future
<
bool
>
_runPMCommand
(
List
<
String
>
args
)
async
{
if
(
fuchsiaArtifacts
.
pm
==
null
)
{
throwToolExit
(
'Fuchsia pm tool not found'
);
}
final
List
<
String
>
command
=
<
String
>[
fuchsiaArtifacts
.
pm
.
path
]
+
args
;
final
RunResult
result
=
await
runAsync
(
command
);
return
result
.
exitCode
==
0
;
}
}
/// A class for running and retaining state for a Fuchsia package server.
///
/// [FuchsiaPackageServer] takes care of initializing the package repository,
/// spinning up the package server, publishing packages, and shutting down the
/// the server.
///
/// Example usage:
/// var server = FuchsiaPackageServer(
/// '/path/to/repo',
/// await FuchsiaDevFinder.resolve(deviceName),
/// await freshPort());
/// try {
/// await server.start();
/// await server.addPackage(farArchivePath);
/// ...
/// } finally {
/// server.stop();
/// }
class
FuchsiaPackageServer
{
FuchsiaPackageServer
(
this
.
_repo
,
this
.
_host
,
this
.
_port
);
final
String
_repo
;
final
String
_host
;
final
int
_port
;
Process
_process
;
/// The url that can be used by the device to access this package server.
String
get
url
=>
'http://
$_host
:
$_port
'
;
/// Usees [FuchiaPM.newrepo] and [FuchsiaPM.serve] to spin up a new Fuchsia
/// package server.
///
/// Returns false if ther repo could not be created or the server could not
/// be spawned, and true otherwise.
Future
<
bool
>
start
()
async
{
if
(
_process
!=
null
)
{
printError
(
'
$this
already started!'
);
return
false
;
}
// initialize a new repo.
if
(!
await
fuchsiaSdk
.
fuchsiaPM
.
newrepo
(
_repo
))
{
printError
(
'Failed to create a new package server repo'
);
return
false
;
}
_process
=
await
fuchsiaSdk
.
fuchsiaPM
.
serve
(
_repo
,
_host
,
_port
);
// Put a completer on _process.exitCode to watch for error.
unawaited
(
_process
.
exitCode
.
whenComplete
(()
{
// If _process is null, then the server was stopped deliberately.
if
(
_process
!=
null
)
{
printError
(
'Error running Fuchsia pm tool "serve" command'
);
}
}));
return
true
;
}
/// Forcefully stops the package server process by sending it SIGTERM.
void
stop
()
{
if
(
_process
!=
null
)
{
_process
.
kill
();
_process
=
null
;
}
}
/// Uses [FuchsiaPM.publish] to add the Fuchsia 'far' package at
/// [packagePath] to the package server.
///
/// Returns true on success and false if the server wasn't started or the
/// publish command failed.
Future
<
bool
>
addPackage
(
File
package
)
async
{
if
(
_process
==
null
)
{
return
false
;
}
return
await
fuchsiaSdk
.
fuchsiaPM
.
publish
(
_repo
,
package
.
path
);
}
@override
String
toString
()
{
final
String
p
=
(
_process
==
null
)
?
'stopped'
:
'running
${_process.pid}
'
;
return
'FuchsiaPackageServer at
$_host
:
$_port
(
$p
)'
;
}
}
packages/flutter_tools/lib/src/fuchsia/fuchsia_sdk.dart
View file @
94ce956f
...
...
@@ -8,12 +8,15 @@ import '../base/context.dart';
import
'../base/file_system.dart'
;
import
'../base/io.dart'
;
import
'../base/platform.dart'
;
import
'../base/process.dart'
;
import
'../base/process_manager.dart'
;
import
'../cache.dart'
;
import
'../convert.dart'
;
import
'../globals.dart'
;
import
'fuchsia_dev_finder.dart'
;
import
'fuchsia_kernel_compiler.dart'
;
import
'fuchsia_pm.dart'
;
/// The [FuchsiaSdk] instance.
FuchsiaSdk
get
fuchsiaSdk
=>
context
.
get
<
FuchsiaSdk
>();
...
...
@@ -25,23 +28,32 @@ FuchsiaArtifacts get fuchsiaArtifacts => context.get<FuchsiaArtifacts>();
/// This workflow assumes development within the fuchsia source tree,
/// including a working fx command-line tool in the user's PATH.
class
FuchsiaSdk
{
/// Interface to the 'pm' tool.
FuchsiaPM
get
fuchsiaPM
=>
_fuchsiaPM
??=
FuchsiaPM
();
FuchsiaPM
_fuchsiaPM
;
/// Interface to the 'dev_finder' tool.
FuchsiaDevFinder
_fuchsiaDevFinder
;
FuchsiaDevFinder
get
fuchsiaDevFinder
=>
_fuchsiaDevFinder
??=
FuchsiaDevFinder
();
/// Interface to the 'kernel_compiler' tool.
FuchsiaKernelCompiler
_fuchsiaKernelCompiler
;
FuchsiaKernelCompiler
get
fuchsiaKernelCompiler
=>
_fuchsiaKernelCompiler
??=
FuchsiaKernelCompiler
();
/// Example output:
/// $ dev_finder list -full
/// > 192.168.42.56 paper-pulp-bush-angel
Future
<
String
>
listDevices
()
async
{
try
{
final
String
path
=
fuchsiaArtifacts
.
devFinder
.
absolute
.
path
;
final
RunResult
process
=
await
runAsync
(<
String
>[
path
,
'list'
,
'-full'
]);
return
process
.
stdout
.
trim
();
}
catch
(
exception
)
{
printTrace
(
'
$exception
'
);
}
if
(
fuchsiaArtifacts
.
devFinder
==
null
)
{
return
null
;
}
final
List
<
String
>
devices
=
await
fuchsiaDevFinder
.
list
();
return
devices
.
isNotEmpty
?
devices
[
0
]
:
null
;
}
/// Returns the fuchsia system logs for an attached device.
///
/// Does not currently support multiple attached devices.
Stream
<
String
>
syslogs
(
String
id
)
{
Process
process
;
try
{
...
...
@@ -50,6 +62,8 @@ class FuchsiaSdk {
process
.
kill
();
});
if
(
fuchsiaArtifacts
.
sshConfig
==
null
)
{
printError
(
'Cannot read device logs: No ssh config.'
);
printError
(
'Have you set FUCHSIA_SSH_CONFIG or FUCHSIA_BUILD_DIR?'
);
return
null
;
}
const
String
remoteCommand
=
'log_listener --clock Local'
;
...
...
@@ -101,6 +115,15 @@ class FuchsiaArtifacts {
final
String
tools
=
fs
.
path
.
join
(
fuchsia
,
'tools'
);
final
String
dartPrebuilts
=
fs
.
path
.
join
(
tools
,
'dart_prebuilts'
);
final
File
devFinder
=
fs
.
file
(
fs
.
path
.
join
(
tools
,
'dev_finder'
));
final
File
platformDill
=
fs
.
file
(
fs
.
path
.
join
(
dartPrebuilts
,
'flutter_runner'
,
'platform_strong.dill'
));
final
File
patchedSdk
=
fs
.
file
(
fs
.
path
.
join
(
dartPrebuilts
,
'flutter_runner'
));
final
File
kernelCompiler
=
fs
.
file
(
fs
.
path
.
join
(
dartPrebuilts
,
'kernel_compiler.snapshot'
));
final
File
pm
=
fs
.
file
(
fs
.
path
.
join
(
tools
,
'pm'
));
// If FUCHSIA_BUILD_DIR is defined, then look for the ssh_config dir
// relative to it. Next, if FUCHSIA_SSH_CONFIG is defined, then use it.
// TODO(zra): Consider passing the ssh config path in with a flag.
...
...
@@ -113,14 +136,11 @@ class FuchsiaArtifacts {
}
return
FuchsiaArtifacts
(
sshConfig:
sshConfig
,
devFinder:
fs
.
file
(
fs
.
path
.
join
(
tools
,
'dev_finder'
)),
platformKernelDill:
fs
.
file
(
fs
.
path
.
join
(
dartPrebuilts
,
'flutter_runner'
,
'platform_strong.dill'
)),
flutterPatchedSdk:
fs
.
file
(
fs
.
path
.
join
(
dartPrebuilts
,
'flutter_runner'
)),
kernelCompiler:
fs
.
file
(
fs
.
path
.
join
(
dartPrebuilts
,
'kernel_compiler.snapshot'
)),
pm:
fs
.
file
(
fs
.
path
.
join
(
tools
,
'pm'
)),
devFinder:
devFinder
.
existsSync
()
?
devFinder
:
null
,
platformKernelDill:
platformDill
.
existsSync
()
?
platformDill
:
null
,
flutterPatchedSdk:
patchedSdk
.
existsSync
()
?
patchedSdk
:
null
,
kernelCompiler:
kernelCompiler
.
existsSync
()
?
kernelCompiler
:
null
,
pm:
pm
.
existsSync
()
?
pm
:
null
,
);
}
...
...
packages/flutter_tools/lib/src/fuchsia/tiles_ctl.dart
0 → 100644
View file @
94ce956f
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'../base/process.dart'
;
import
'../globals.dart'
;
import
'fuchsia_device.dart'
;
// Usage: tiles_ctl <command>
// Supported commands:
// start
// add [--disable-focus] <url> [<args>...]
// remove <key>
// list
// quit
/// A simple wrapper around the 'tiles_ctl' tool running on the Fuchsia device.
class
FuchsiaTilesCtl
{
/// Finds the key for the app called [appName], or returns -1 if it can't be
/// found.
static
Future
<
int
>
findAppKey
(
FuchsiaDevice
device
,
String
appName
)
async
{
final
FuchsiaTilesCtl
tilesCtl
=
fuchsiaDeviceTools
.
tilesCtl
;
final
Map
<
int
,
String
>
runningApps
=
await
tilesCtl
.
list
(
device
);
if
(
runningApps
==
null
)
{
printTrace
(
'tiles_ctl is not running'
);
return
-
1
;
}
for
(
MapEntry
<
int
,
String
>
entry
in
runningApps
.
entries
)
{
if
(
entry
.
value
.
contains
(
'
$appName
#meta'
))
{
return
entry
.
key
;
}
}
return
-
1
;
}
/// Ensures that tiles is running on the device.
static
Future
<
bool
>
ensureStarted
(
FuchsiaDevice
device
)
async
{
final
FuchsiaTilesCtl
tilesCtl
=
fuchsiaDeviceTools
.
tilesCtl
;
final
Map
<
int
,
String
>
runningApps
=
await
tilesCtl
.
list
(
device
);
if
(
runningApps
==
null
)
{
return
tilesCtl
.
start
(
device
);
}
return
true
;
}
/// Instructs 'tiles' to start on the device.
///
/// Returns true on success and false on failure.
Future
<
bool
>
start
(
FuchsiaDevice
device
)
async
{
final
RunResult
result
=
await
device
.
shell
(
'tiles_ctl start'
);
return
result
.
exitCode
==
0
;
}
/// Returns a mapping of tile keys to app urls.
///
/// Returns an empty mapping if tiles_ctl is running but no apps are running.
/// Returns null if tiles_ctl is not running.
Future
<
Map
<
int
,
String
>>
list
(
FuchsiaDevice
device
)
async
{
// Output of tiles_ctl list has the format:
// Found 1 tiles:
// Tile key 1 url fuchsia-pkg://fuchsia.com/stocks#meta/stocks.cmx ...
final
Map
<
int
,
String
>
tiles
=
<
int
,
String
>{};
final
RunResult
result
=
await
device
.
shell
(
'tiles_ctl list'
);
if
(
result
.
exitCode
!=
0
)
{
return
null
;
}
// Look for evidence that tiles_ctl is not running.
if
(
result
.
stdout
.
contains
(
"Couldn't find tiles component in realm"
))
{
return
null
;
}
// Find lines beginning with 'Tile'
for
(
String
line
in
result
.
stdout
.
split
(
'
\n
'
))
{
final
List
<
String
>
words
=
line
.
split
(
' '
);
if
(
words
.
isNotEmpty
&&
words
[
0
]
==
'Tile'
)
{
final
int
key
=
int
.
tryParse
(
words
[
2
]);
final
String
url
=
words
[
4
];
tiles
[
key
]
=
url
;
}
}
return
tiles
;
}
/// Instructs tiles on the device to begin running the app at [url] in a new
/// tile.
///
/// The app is passed the arguemnts in [args]. Flutter apps receive these
/// arguments as arguments to `main()`. [url] should be formatted as a
/// Fuchsia-style package url, e.g.:
/// fuchsia-pkg://fuchsia.com/flutter_gallery#meta/flutter_gallery.cmx
/// Returns true on success and false on failure.
Future
<
bool
>
add
(
FuchsiaDevice
device
,
String
url
,
List
<
String
>
args
)
async
{
final
RunResult
result
=
await
device
.
shell
(
'tiles_ctl add
$url
${args.join(" ")}
'
);
return
result
.
exitCode
==
0
;
}
/// Instructs tiles on the device to remove the app with key [key].
///
/// Returns true on success and false on failure.
Future
<
bool
>
remove
(
FuchsiaDevice
device
,
int
key
)
async
{
final
RunResult
result
=
await
device
.
shell
(
'tiles_ctl remove
$key
'
);
return
result
.
exitCode
==
0
;
}
/// Instructs tiles on the device to quit.
///
/// Returns true on success and false on failure.
Future
<
bool
>
quit
(
FuchsiaDevice
device
)
async
{
final
RunResult
result
=
await
device
.
shell
(
'tiles_ctl quit'
);
return
result
.
exitCode
==
0
;
}
}
packages/flutter_tools/lib/src/resident_runner.dart
View file @
94ce956f
...
...
@@ -313,9 +313,15 @@ class FlutterDevice {
}
void
startEchoingDeviceLog
()
{
if
(
_loggingSubscription
!=
null
)
if
(
_loggingSubscription
!=
null
)
{
return
;
_loggingSubscription
=
device
.
getLogReader
(
app:
package
).
logLines
.
listen
((
String
line
)
{
}
final
Stream
<
String
>
logStream
=
device
.
getLogReader
(
app:
package
).
logLines
;
if
(
logStream
==
null
)
{
printError
(
'Failed to read device log stream'
);
return
;
}
_loggingSubscription
=
logStream
.
listen
((
String
line
)
{
if
(!
line
.
contains
(
'Observatory listening on http'
))
printStatus
(
line
,
wrap:
false
);
});
...
...
packages/flutter_tools/test/commands/build_fuchsia_test.dart
View file @
94ce956f
...
...
@@ -11,6 +11,7 @@ import 'package:flutter_tools/src/cache.dart';
import
'package:flutter_tools/src/commands/build.dart'
;
import
'package:flutter_tools/src/fuchsia/fuchsia_kernel_compiler.dart'
;
import
'package:flutter_tools/src/fuchsia/fuchsia_pm.dart'
;
import
'package:flutter_tools/src/fuchsia/fuchsia_sdk.dart'
;
import
'package:flutter_tools/src/project.dart'
;
import
'package:meta/meta.dart'
;
import
'package:mockito/mockito.dart'
;
...
...
@@ -25,23 +26,28 @@ void main() {
MemoryFileSystem
memoryFileSystem
;
MockPlatform
linuxPlatform
;
MockPlatform
windowsPlatform
;
MockFuchsiaPM
fuchsiaPM
;
MockFuchsiaKernelCompiler
fuchsiaKernelCompiler
;
MockFuchsiaSdk
fuchsiaSdk
;
MockFuchsiaArtifacts
fuchsiaArtifacts
;
MockFuchsiaArtifacts
fuchsiaArtifactsNoCompiler
;
setUp
(()
{
memoryFileSystem
=
MemoryFileSystem
();
linuxPlatform
=
MockPlatform
();
windowsPlatform
=
MockPlatform
();
fuchsiaPM
=
MockFuchsiaPM
();
fuchsiaKernelCompiler
=
MockFuchsiaKernelCompiler
();
fuchsiaSdk
=
MockFuchsiaSdk
();
fuchsiaArtifacts
=
MockFuchsiaArtifacts
();
fuchsiaArtifactsNoCompiler
=
MockFuchsiaArtifacts
();
when
(
linuxPlatform
.
isLinux
).
thenReturn
(
true
);
when
(
windowsPlatform
.
isWindows
).
thenReturn
(
true
);
when
(
windowsPlatform
.
isLinux
).
thenReturn
(
false
);
when
(
windowsPlatform
.
isMacOS
).
thenReturn
(
false
);
when
(
fuchsiaArtifacts
.
kernelCompiler
).
thenReturn
(
MockFile
());
when
(
fuchsiaArtifactsNoCompiler
.
kernelCompiler
).
thenReturn
(
null
);
});
testUsingContext
(
'Fuchsia build fails when there is no fuchsia project'
,
group
(
'Fuchsia build fails gracefully when'
,
()
{
testUsingContext
(
'there is no Fuchsia project'
,
()
async
{
final
BuildCommand
command
=
BuildCommand
();
applyMocksToCommand
(
command
);
...
...
@@ -52,9 +58,10 @@ void main() {
},
overrides:
<
Type
,
Generator
>{
Platform:
()
=>
linuxPlatform
,
FileSystem:
()
=>
memoryFileSystem
,
FuchsiaArtifacts:
()
=>
fuchsiaArtifacts
,
});
testUsingContext
(
'Fuchsia build fails when
there is no cmx file'
,
()
async
{
testUsingContext
(
'
there is no cmx file'
,
()
async
{
final
BuildCommand
command
=
BuildCommand
();
applyMocksToCommand
(
command
);
fs
.
directory
(
'fuchsia'
).
createSync
(
recursive:
true
);
...
...
@@ -68,9 +75,10 @@ void main() {
},
overrides:
<
Type
,
Generator
>{
Platform:
()
=>
linuxPlatform
,
FileSystem:
()
=>
memoryFileSystem
,
FuchsiaArtifacts:
()
=>
fuchsiaArtifacts
,
});
testUsingContext
(
'Fuchsia build fails
on Windows platform'
,
()
async
{
testUsingContext
(
'
on Windows platform'
,
()
async
{
final
BuildCommand
command
=
BuildCommand
();
applyMocksToCommand
(
command
);
const
String
appName
=
'app_name'
;
...
...
@@ -88,6 +96,29 @@ void main() {
},
overrides:
<
Type
,
Generator
>{
Platform:
()
=>
windowsPlatform
,
FileSystem:
()
=>
memoryFileSystem
,
FuchsiaArtifacts:
()
=>
fuchsiaArtifacts
,
});
testUsingContext
(
'there is no Fuchsia kernel compiler'
,
()
async
{
final
BuildCommand
command
=
BuildCommand
();
applyMocksToCommand
(
command
);
const
String
appName
=
'app_name'
;
fs
.
file
(
fs
.
path
.
join
(
'fuchsia'
,
'meta'
,
'
$appName
.cmx'
))
.
createSync
(
recursive:
true
);
fs
.
file
(
'.packages'
).
createSync
();
fs
.
file
(
fs
.
path
.
join
(
'lib'
,
'main.dart'
)).
createSync
(
recursive:
true
);
final
File
pubspecFile
=
fs
.
file
(
'pubspec.yaml'
)..
createSync
();
pubspecFile
.
writeAsStringSync
(
'name:
$appName
'
);
expect
(
createTestCommandRunner
(
command
)
.
run
(
const
<
String
>[
'build'
,
'fuchsia'
]),
throwsA
(
isInstanceOf
<
ToolExit
>()));
},
overrides:
<
Type
,
Generator
>{
Platform:
()
=>
linuxPlatform
,
FileSystem:
()
=>
memoryFileSystem
,
FuchsiaArtifacts:
()
=>
fuchsiaArtifactsNoCompiler
,
});
});
testUsingContext
(
'Fuchsia build parts fit together right'
,
()
async
{
...
...
@@ -110,8 +141,7 @@ void main() {
},
overrides:
<
Type
,
Generator
>{
Platform:
()
=>
linuxPlatform
,
FileSystem:
()
=>
memoryFileSystem
,
FuchsiaPM:
()
=>
fuchsiaPM
,
FuchsiaKernelCompiler:
()
=>
fuchsiaKernelCompiler
,
FuchsiaSdk:
()
=>
fuchsiaSdk
,
});
}
...
...
@@ -189,3 +219,16 @@ class MockFuchsiaKernelCompiler extends Mock implements FuchsiaKernelCompiler {
fs
.
file
(
manifestPath
).
createSync
(
recursive:
true
);
}
}
class
MockFuchsiaSdk
extends
Mock
implements
FuchsiaSdk
{
@override
final
FuchsiaPM
fuchsiaPM
=
MockFuchsiaPM
();
@override
final
FuchsiaKernelCompiler
fuchsiaKernelCompiler
=
MockFuchsiaKernelCompiler
();
}
class
MockFile
extends
Mock
implements
File
{}
class
MockFuchsiaArtifacts
extends
Mock
implements
FuchsiaArtifacts
{}
packages/flutter_tools/test/fuchsia/fuchsa_device_test.dart
View file @
94ce956f
...
...
@@ -5,26 +5,42 @@
import
'dart:async'
;
import
'dart:convert'
;
import
'package:flutter_tools/src/base/logger.dart'
;
import
'package:flutter_tools/src/vmservice.dart'
;
import
'package:mockito/mockito.dart'
;
import
'package:process/process.dart'
;
import
'package:file/memory.dart'
;
import
'package:flutter_tools/src/application_package.dart'
;
import
'package:flutter_tools/src/artifacts.dart'
;
import
'package:flutter_tools/src/base/common.dart'
;
import
'package:flutter_tools/src/base/context.dart'
;
import
'package:flutter_tools/src/base/file_system.dart'
;
import
'package:flutter_tools/src/base/io.dart'
;
import
'package:flutter_tools/src/base/logger.dart'
;
import
'package:flutter_tools/src/base/os.dart'
;
import
'package:flutter_tools/src/base/time.dart'
;
import
'package:flutter_tools/src/build_info.dart'
;
import
'package:flutter_tools/src/device.dart'
;
import
'package:flutter_tools/src/fuchsia/application_package.dart'
;
import
'package:flutter_tools/src/fuchsia/amber_ctl.dart'
;
import
'package:flutter_tools/src/fuchsia/fuchsia_device.dart'
;
import
'package:flutter_tools/src/fuchsia/fuchsia_dev_finder.dart'
;
import
'package:flutter_tools/src/fuchsia/fuchsia_kernel_compiler.dart'
;
import
'package:flutter_tools/src/fuchsia/fuchsia_pm.dart'
;
import
'package:flutter_tools/src/fuchsia/fuchsia_sdk.dart'
;
import
'package:flutter_tools/src/fuchsia/tiles_ctl.dart'
;
import
'package:flutter_tools/src/project.dart'
;
import
'package:flutter_tools/src/vmservice.dart'
;
import
'package:meta/meta.dart'
;
import
'package:mockito/mockito.dart'
;
import
'package:process/process.dart'
;
import
'../src/common.dart'
;
import
'../src/context.dart'
;
void
main
(
)
{
group
(
'fuchsia device'
,
()
{
MemoryFileSystem
memoryFileSystem
;
setUp
(()
{
memoryFileSystem
=
MemoryFileSystem
();
});
testUsingContext
(
'stores the requested id and name'
,
()
{
const
String
deviceId
=
'e80::0000:a00a:f00f:2002/3'
;
const
String
name
=
'halfbaked'
;
...
...
@@ -49,14 +65,34 @@ void main() {
expect
(
names
.
length
,
0
);
});
test
(
'default capabilities'
,
()
async
{
test
UsingContext
(
'default capabilities'
,
()
async
{
final
FuchsiaDevice
device
=
FuchsiaDevice
(
'123'
);
fs
.
directory
(
'fuchsia'
).
createSync
(
recursive:
true
);
fs
.
file
(
'pubspec.yaml'
).
createSync
();
expect
(
device
.
supportsHotReload
,
true
);
expect
(
device
.
supportsHotRestart
,
false
);
expect
(
device
.
supportsStopApp
,
false
);
expect
(
device
.
isSupportedForProject
(
null
),
true
);
expect
(
await
device
.
stopApp
(
null
),
false
);
expect
(
device
.
isSupportedForProject
(
FlutterProject
.
current
()),
true
);
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
memoryFileSystem
,
});
testUsingContext
(
'supported for project'
,
()
async
{
final
FuchsiaDevice
device
=
FuchsiaDevice
(
'123'
);
fs
.
directory
(
'fuchsia'
).
createSync
(
recursive:
true
);
fs
.
file
(
'pubspec.yaml'
).
createSync
();
expect
(
device
.
isSupportedForProject
(
FlutterProject
.
current
()),
true
);
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
memoryFileSystem
,
});
testUsingContext
(
'not supported for project'
,
()
async
{
final
FuchsiaDevice
device
=
FuchsiaDevice
(
'123'
);
fs
.
file
(
'pubspec.yaml'
).
createSync
();
expect
(
device
.
isSupportedForProject
(
FlutterProject
.
current
()),
false
);
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
memoryFileSystem
,
});
});
...
...
@@ -215,7 +251,7 @@ void main() {
testUsingContext
(
'can be parsed for an app'
,
()
async
{
final
FuchsiaDevice
device
=
FuchsiaDevice
(
'id'
,
name:
'tester'
);
final
DeviceLogReader
reader
=
device
.
getLogReader
(
app:
FuchsiaModulePackage
(
name:
'example_app
.cmx
'
));
app:
FuchsiaModulePackage
(
name:
'example_app'
));
final
List
<
String
>
logLines
=
<
String
>[];
final
Completer
<
void
>
lock
=
Completer
<
void
>();
reader
.
logLines
.
listen
((
String
line
)
{
...
...
@@ -244,7 +280,7 @@ void main() {
testUsingContext
(
'cuts off prior logs'
,
()
async
{
final
FuchsiaDevice
device
=
FuchsiaDevice
(
'id'
,
name:
'tester'
);
final
DeviceLogReader
reader
=
device
.
getLogReader
(
app:
FuchsiaModulePackage
(
name:
'example_app
.cmx
'
));
app:
FuchsiaModulePackage
(
name:
'example_app'
));
final
List
<
String
>
logLines
=
<
String
>[];
final
Completer
<
void
>
lock
=
Completer
<
void
>();
reader
.
logLines
.
listen
((
String
line
)
{
...
...
@@ -367,16 +403,119 @@ void main() {
Logger:
()
=>
StdoutLogger
(),
});
});
group
(
'fuchsia app start and stop: '
,
()
{
MemoryFileSystem
memoryFileSystem
;
MockOperatingSystemUtils
osUtils
;
MockFuchsiaDeviceTools
fuchsiaDeviceTools
;
MockFuchsiaSdk
fuchsiaSdk
;
setUp
(()
{
memoryFileSystem
=
MemoryFileSystem
();
osUtils
=
MockOperatingSystemUtils
();
fuchsiaDeviceTools
=
MockFuchsiaDeviceTools
();
fuchsiaSdk
=
MockFuchsiaSdk
();
when
(
osUtils
.
findFreePort
()).
thenAnswer
((
_
)
=>
Future
<
int
>.
value
(
12345
));
});
testUsingContext
(
'start prebuilt app in release mode'
,
()
async
{
const
String
appName
=
'app_name'
;
final
FuchsiaDevice
device
=
FuchsiaDevice
(
'123'
);
fs
.
directory
(
'fuchsia'
).
createSync
(
recursive:
true
);
final
File
pubspecFile
=
fs
.
file
(
'pubspec.yaml'
)..
createSync
();
pubspecFile
.
writeAsStringSync
(
'name:
$appName
'
);
final
File
far
=
fs
.
file
(
'app_name-0.far'
)..
createSync
();
final
FuchsiaApp
app
=
FuchsiaApp
.
fromPrebuiltApp
(
far
);
final
DebuggingOptions
debuggingOptions
=
DebuggingOptions
.
disabled
(
const
BuildInfo
(
BuildMode
.
release
,
null
));
final
LaunchResult
launchResult
=
await
device
.
startApp
(
app
,
prebuiltApplication:
true
,
debuggingOptions:
debuggingOptions
);
expect
(
launchResult
.
started
,
isTrue
);
expect
(
launchResult
.
hasObservatory
,
isFalse
);
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
memoryFileSystem
,
FuchsiaDeviceTools:
()
=>
fuchsiaDeviceTools
,
FuchsiaSdk:
()
=>
fuchsiaSdk
,
OperatingSystemUtils:
()
=>
osUtils
,
});
testUsingContext
(
'start and stop prebuilt app in release mode'
,
()
async
{
const
String
appName
=
'app_name'
;
final
FuchsiaDevice
device
=
FuchsiaDevice
(
'123'
);
fs
.
directory
(
'fuchsia'
).
createSync
(
recursive:
true
);
final
File
pubspecFile
=
fs
.
file
(
'pubspec.yaml'
)..
createSync
();
pubspecFile
.
writeAsStringSync
(
'name:
$appName
'
);
final
File
far
=
fs
.
file
(
'app_name-0.far'
)..
createSync
();
final
FuchsiaApp
app
=
FuchsiaApp
.
fromPrebuiltApp
(
far
);
final
DebuggingOptions
debuggingOptions
=
DebuggingOptions
.
disabled
(
const
BuildInfo
(
BuildMode
.
release
,
null
));
final
LaunchResult
launchResult
=
await
device
.
startApp
(
app
,
prebuiltApplication:
true
,
debuggingOptions:
debuggingOptions
);
expect
(
launchResult
.
started
,
isTrue
);
expect
(
launchResult
.
hasObservatory
,
isFalse
);
expect
(
await
device
.
stopApp
(
app
),
isTrue
);
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
memoryFileSystem
,
FuchsiaDeviceTools:
()
=>
fuchsiaDeviceTools
,
FuchsiaSdk:
()
=>
fuchsiaSdk
,
OperatingSystemUtils:
()
=>
osUtils
,
});
});
}
class
FuchsiaModulePackage
extends
ApplicationPackage
{
FuchsiaModulePackage
({
@required
this
.
name
})
:
super
(
id:
name
);
@override
final
String
name
;
}
class
MockProcessManager
extends
Mock
implements
ProcessManager
{}
class
MockProcessResult
extends
Mock
implements
ProcessResult
{}
class
MockOperatingSystemUtils
extends
Mock
implements
OperatingSystemUtils
{}
class
MockFile
extends
Mock
implements
File
{}
class
MockProcess
extends
Mock
implements
Process
{}
Process
_createMockProcess
(
{
int
exitCode
=
0
,
String
stdout
=
''
,
String
stderr
=
''
,
bool
persistent
=
false
,
})
{
final
Stream
<
List
<
int
>>
stdoutStream
=
Stream
<
List
<
int
>>.
fromIterable
(<
List
<
int
>>[
utf8
.
encode
(
stdout
),
]);
final
Stream
<
List
<
int
>>
stderrStream
=
Stream
<
List
<
int
>>.
fromIterable
(<
List
<
int
>>[
utf8
.
encode
(
stderr
),
]);
final
Process
process
=
MockProcess
();
when
(
process
.
stdout
).
thenAnswer
((
_
)
=>
stdoutStream
);
when
(
process
.
stderr
).
thenAnswer
((
_
)
=>
stderrStream
);
if
(
persistent
)
{
final
Completer
<
int
>
exitCodeCompleter
=
Completer
<
int
>();
when
(
process
.
kill
()).
thenAnswer
((
_
)
{
exitCodeCompleter
.
complete
(-
11
);
return
true
;
});
when
(
process
.
exitCode
).
thenAnswer
((
_
)
=>
exitCodeCompleter
.
future
);
}
else
{
when
(
process
.
exitCode
).
thenAnswer
((
_
)
=>
Future
<
int
>.
value
(
exitCode
));
}
return
process
;
}
class
MockFuchsiaDevice
extends
Mock
implements
FuchsiaDevice
{
MockFuchsiaDevice
(
this
.
id
,
this
.
portForwarder
,
this
.
ipv6
);
...
...
@@ -419,3 +558,192 @@ class MockIsolate extends Mock implements Isolate {
@override
final
String
name
;
}
class
MockFuchsiaAmberCtl
extends
Mock
implements
FuchsiaAmberCtl
{
@override
Future
<
bool
>
addSrc
(
FuchsiaDevice
device
,
FuchsiaPackageServer
server
)
async
{
return
true
;
}
@override
Future
<
bool
>
rmSrc
(
FuchsiaDevice
device
,
FuchsiaPackageServer
server
)
async
{
return
true
;
}
@override
Future
<
bool
>
getUp
(
FuchsiaDevice
device
,
String
packageName
)
async
{
return
true
;
}
}
class
MockFuchsiaTilesCtl
extends
Mock
implements
FuchsiaTilesCtl
{
final
Map
<
int
,
String
>
_runningApps
=
<
int
,
String
>{};
bool
_started
=
false
;
int
_nextAppId
=
1
;
@override
Future
<
bool
>
start
(
FuchsiaDevice
device
)
async
{
_started
=
true
;
return
true
;
}
@override
Future
<
Map
<
int
,
String
>>
list
(
FuchsiaDevice
device
)
async
{
if
(!
_started
)
{
return
null
;
}
return
_runningApps
;
}
@override
Future
<
bool
>
add
(
FuchsiaDevice
device
,
String
url
,
List
<
String
>
args
)
async
{
if
(!
_started
)
{
return
false
;
}
_runningApps
[
_nextAppId
]
=
url
;
_nextAppId
++;
return
true
;
}
@override
Future
<
bool
>
remove
(
FuchsiaDevice
device
,
int
key
)
async
{
if
(!
_started
)
{
return
false
;
}
_runningApps
.
remove
(
key
);
return
true
;
}
@override
Future
<
bool
>
quit
(
FuchsiaDevice
device
)
async
{
if
(!
_started
)
{
return
false
;
}
_started
=
false
;
return
true
;
}
}
class
MockFuchsiaDeviceTools
extends
Mock
implements
FuchsiaDeviceTools
{
@override
final
FuchsiaAmberCtl
amberCtl
=
MockFuchsiaAmberCtl
();
@override
final
FuchsiaTilesCtl
tilesCtl
=
MockFuchsiaTilesCtl
();
}
class
MockFuchsiaPM
extends
Mock
implements
FuchsiaPM
{
String
_appName
;
@override
Future
<
bool
>
init
(
String
buildPath
,
String
appName
)
async
{
if
(!
fs
.
directory
(
buildPath
).
existsSync
())
{
return
false
;
}
fs
.
file
(
fs
.
path
.
join
(
buildPath
,
'meta'
,
'package'
))
.
createSync
(
recursive:
true
);
_appName
=
appName
;
return
true
;
}
@override
Future
<
bool
>
genkey
(
String
buildPath
,
String
outKeyPath
)
async
{
if
(!
fs
.
file
(
fs
.
path
.
join
(
buildPath
,
'meta'
,
'package'
)).
existsSync
())
{
return
false
;
}
fs
.
file
(
outKeyPath
).
createSync
(
recursive:
true
);
return
true
;
}
@override
Future
<
bool
>
build
(
String
buildPath
,
String
keyPath
,
String
manifestPath
)
async
{
if
(!
fs
.
file
(
fs
.
path
.
join
(
buildPath
,
'meta'
,
'package'
)).
existsSync
()
||
!
fs
.
file
(
keyPath
).
existsSync
()
||
!
fs
.
file
(
manifestPath
).
existsSync
())
{
return
false
;
}
fs
.
file
(
fs
.
path
.
join
(
buildPath
,
'meta.far'
)).
createSync
(
recursive:
true
);
return
true
;
}
@override
Future
<
bool
>
archive
(
String
buildPath
,
String
keyPath
,
String
manifestPath
)
async
{
if
(!
fs
.
file
(
fs
.
path
.
join
(
buildPath
,
'meta'
,
'package'
)).
existsSync
()
||
!
fs
.
file
(
keyPath
).
existsSync
()
||
!
fs
.
file
(
manifestPath
).
existsSync
())
{
return
false
;
}
if
(
_appName
==
null
)
{
return
false
;
}
fs
.
file
(
fs
.
path
.
join
(
buildPath
,
'
$_appName
-0.far'
))
.
createSync
(
recursive:
true
);
return
true
;
}
@override
Future
<
bool
>
newrepo
(
String
repoPath
)
async
{
if
(!
fs
.
directory
(
repoPath
).
existsSync
())
{
return
false
;
}
return
true
;
}
@override
Future
<
Process
>
serve
(
String
repoPath
,
String
host
,
int
port
)
async
{
return
_createMockProcess
(
persistent:
true
);
}
@override
Future
<
bool
>
publish
(
String
repoPath
,
String
packagePath
)
async
{
if
(!
fs
.
directory
(
repoPath
).
existsSync
())
{
return
false
;
}
if
(!
fs
.
file
(
packagePath
).
existsSync
())
{
return
false
;
}
return
true
;
}
}
class
MockFuchsiaKernelCompiler
extends
Mock
implements
FuchsiaKernelCompiler
{
@override
Future
<
void
>
build
({
@required
FuchsiaProject
fuchsiaProject
,
@required
String
target
,
// E.g., lib/main.dart
BuildInfo
buildInfo
=
BuildInfo
.
debug
,
})
async
{
final
String
outDir
=
getFuchsiaBuildDirectory
();
final
String
appName
=
fuchsiaProject
.
project
.
manifest
.
appName
;
final
String
manifestPath
=
fs
.
path
.
join
(
outDir
,
'
$appName
.dilpmanifest'
);
fs
.
file
(
manifestPath
).
createSync
(
recursive:
true
);
}
}
class
MockFuchsiaDevFinder
extends
Mock
implements
FuchsiaDevFinder
{
@override
Future
<
List
<
String
>>
list
()
async
{
return
<
String
>[
'192.168.42.172 scare-cable-skip-joy'
];
}
@override
Future
<
String
>
resolve
(
String
deviceName
)
async
{
return
'192.168.42.10'
;
}
}
class
MockFuchsiaSdk
extends
Mock
implements
FuchsiaSdk
{
@override
final
FuchsiaPM
fuchsiaPM
=
MockFuchsiaPM
();
@override
final
FuchsiaKernelCompiler
fuchsiaKernelCompiler
=
MockFuchsiaKernelCompiler
();
@override
final
FuchsiaDevFinder
fuchsiaDevFinder
=
MockFuchsiaDevFinder
();
}
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