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
5a21ef24
Commit
5a21ef24
authored
Feb 01, 2016
by
Devon Carew
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1504 from devoncarew/flutter_logs
refactor flutter logs
parents
3abb8c4e
78e05884
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
275 additions
and
97 deletions
+275
-97
device_android.dart
packages/flutter_tools/lib/src/android/device_android.dart
+41
-21
process.dart
packages/flutter_tools/lib/src/base/process.dart
+21
-6
ios.dart
packages/flutter_tools/lib/src/commands/ios.dart
+0
-2
logs.dart
packages/flutter_tools/lib/src/commands/logs.dart
+38
-10
start.dart
packages/flutter_tools/lib/src/commands/start.dart
+1
-2
device.dart
packages/flutter_tools/lib/src/device.dart
+30
-1
device_ios.dart
packages/flutter_tools/lib/src/ios/device_ios.dart
+128
-39
flutter_command_runner.dart
.../flutter_tools/lib/src/runner/flutter_command_runner.dart
+10
-5
logs_test.dart
packages/flutter_tools/test/logs_test.dart
+6
-11
No files found.
packages/flutter_tools/lib/src/android/device_android.dart
View file @
5a21ef24
...
@@ -294,6 +294,7 @@ class AndroidDevice extends Device {
...
@@ -294,6 +294,7 @@ class AndroidDevice extends Device {
String
mainPath
,
String
mainPath
,
String
route
,
String
route
,
bool
checked:
true
,
bool
checked:
true
,
bool
clearLogs:
false
,
Map
<
String
,
dynamic
>
platformArgs
Map
<
String
,
dynamic
>
platformArgs
})
{
})
{
return
flx
.
buildInTempDir
(
return
flx
.
buildInTempDir
(
...
@@ -309,7 +310,7 @@ class AndroidDevice extends Device {
...
@@ -309,7 +310,7 @@ class AndroidDevice extends Device {
checked:
checked
,
checked:
checked
,
traceStartup:
platformArgs
[
'trace-startup'
],
traceStartup:
platformArgs
[
'trace-startup'
],
route:
route
,
route:
route
,
clearLogs:
platformArgs
[
'clear-logs'
]
clearLogs:
clearLogs
))
{
))
{
return
true
;
return
true
;
}
else
{
}
else
{
...
@@ -334,26 +335,7 @@ class AndroidDevice extends Device {
...
@@ -334,26 +335,7 @@ class AndroidDevice extends Device {
runSync
(
adbCommandForDevice
([
'logcat'
,
'-c'
]));
runSync
(
adbCommandForDevice
([
'logcat'
,
'-c'
]));
}
}
Future
<
int
>
logs
({
bool
clear:
false
})
async
{
DeviceLogReader
createLogReader
()
=>
new
_AdbLogReader
(
this
);
if
(!
isConnected
())
{
return
2
;
}
if
(
clear
)
{
clearLogs
();
}
return
await
runCommandAndStreamOutput
(
adbCommandForDevice
([
'logcat'
,
'-v'
,
'tag'
,
// Only log the tag and the message
'-s'
,
'flutter:V'
,
'ActivityManager:W'
,
'System.err:W'
,
'*:F'
,
]),
prefix:
'android: '
);
}
void
startTracing
(
AndroidApk
apk
)
{
void
startTracing
(
AndroidApk
apk
)
{
runCheckedSync
(
adbCommandForDevice
([
runCheckedSync
(
adbCommandForDevice
([
...
@@ -529,3 +511,41 @@ String getAdbPath() {
...
@@ -529,3 +511,41 @@ String getAdbPath() {
return
_defaultAdbPath
;
return
_defaultAdbPath
;
}
}
}
}
/// A log reader that logs from `adb logcat`. This will have the same output as
/// another copy of [_AdbLogReader], and the two instances will be equivalent.
class
_AdbLogReader
extends
DeviceLogReader
{
_AdbLogReader
(
this
.
device
);
final
AndroidDevice
device
;
String
get
name
=>
'Android'
;
Future
<
int
>
logs
({
bool
clear:
false
})
async
{
if
(!
device
.
isConnected
())
return
2
;
if
(
clear
)
device
.
clearLogs
();
return
await
runCommandAndStreamOutput
(
device
.
adbCommandForDevice
(<
String
>[
'logcat'
,
'-v'
,
'tag'
,
// Only log the tag and the message
'-s'
,
'flutter:V'
,
'ActivityManager:W'
,
'System.err:W'
,
'*:F'
,
]),
prefix:
'[Android] '
);
}
// Intentionally constant; overridden because we've overridden the `operator ==` method below.
int
get
hashCode
=>
name
.
hashCode
;
bool
operator
==(
dynamic
other
)
{
if
(
identical
(
this
,
other
))
return
true
;
return
other
is
_AdbLogReader
;
}
}
packages/flutter_tools/lib/src/base/process.dart
View file @
5a21ef24
...
@@ -8,12 +8,15 @@ import 'dart:io';
...
@@ -8,12 +8,15 @@ import 'dart:io';
import
'context.dart'
;
import
'context.dart'
;
typedef
String
StringConverter
(
String
string
);
/// This runs the command and streams stdout/stderr from the child process to
/// This runs the command and streams stdout/stderr from the child process to
/// this process' stdout/stderr.
/// this process' stdout/stderr.
Future
<
int
>
runCommandAndStreamOutput
(
List
<
String
>
cmd
,
{
Future
<
int
>
runCommandAndStreamOutput
(
List
<
String
>
cmd
,
{
String
workingDirectory
,
String
prefix:
''
,
String
prefix:
''
,
RegExp
filter
,
RegExp
filter
,
String
workingDirectory
String
Converter
mapFunction
})
async
{
})
async
{
printTrace
(
cmd
.
join
(
' '
));
printTrace
(
cmd
.
join
(
' '
));
Process
process
=
await
Process
.
start
(
Process
process
=
await
Process
.
start
(
...
@@ -26,14 +29,20 @@ Future<int> runCommandAndStreamOutput(List<String> cmd, {
...
@@ -26,14 +29,20 @@ Future<int> runCommandAndStreamOutput(List<String> cmd, {
.
transform
(
const
LineSplitter
())
.
transform
(
const
LineSplitter
())
.
where
((
String
line
)
=>
filter
==
null
?
true
:
filter
.
hasMatch
(
line
))
.
where
((
String
line
)
=>
filter
==
null
?
true
:
filter
.
hasMatch
(
line
))
.
listen
((
String
line
)
{
.
listen
((
String
line
)
{
printStatus
(
'
$prefix$line
'
);
if
(
mapFunction
!=
null
)
line
=
mapFunction
(
line
);
if
(
line
!=
null
)
printStatus
(
'
$prefix$line
'
);
});
});
process
.
stderr
process
.
stderr
.
transform
(
UTF8
.
decoder
)
.
transform
(
UTF8
.
decoder
)
.
transform
(
const
LineSplitter
())
.
transform
(
const
LineSplitter
())
.
where
((
String
line
)
=>
filter
==
null
?
true
:
filter
.
hasMatch
(
line
))
.
where
((
String
line
)
=>
filter
==
null
?
true
:
filter
.
hasMatch
(
line
))
.
listen
((
String
line
)
{
.
listen
((
String
line
)
{
printError
(
'
$prefix$line
'
);
if
(
mapFunction
!=
null
)
line
=
mapFunction
(
line
);
if
(
line
!=
null
)
printError
(
'
$prefix$line
'
);
});
});
return
await
process
.
exitCode
;
return
await
process
.
exitCode
;
}
}
...
@@ -57,7 +66,7 @@ Future<Process> runDetached(List<String> cmd) {
...
@@ -57,7 +66,7 @@ Future<Process> runDetached(List<String> cmd) {
/// Run cmd and return stdout.
/// Run cmd and return stdout.
/// Throws an error if cmd exits with a non-zero value.
/// Throws an error if cmd exits with a non-zero value.
String
runCheckedSync
(
List
<
String
>
cmd
,
{
String
workingDirectory
})
{
String
runCheckedSync
(
List
<
String
>
cmd
,
{
String
workingDirectory
})
{
return
_runWithLoggingSync
(
cmd
,
workingDirectory:
workingDirectory
,
checked:
true
);
return
_runWithLoggingSync
(
cmd
,
workingDirectory:
workingDirectory
,
checked:
true
,
noisyErrors:
true
);
}
}
/// Run cmd and return stdout.
/// Run cmd and return stdout.
...
@@ -73,6 +82,7 @@ String sdkBinaryName(String name) {
...
@@ -73,6 +82,7 @@ String sdkBinaryName(String name) {
String
_runWithLoggingSync
(
List
<
String
>
cmd
,
{
String
_runWithLoggingSync
(
List
<
String
>
cmd
,
{
bool
checked:
false
,
bool
checked:
false
,
bool
noisyErrors:
false
,
String
workingDirectory
String
workingDirectory
})
{
})
{
printTrace
(
cmd
.
join
(
' '
));
printTrace
(
cmd
.
join
(
' '
));
...
@@ -82,8 +92,13 @@ String _runWithLoggingSync(List<String> cmd, {
...
@@ -82,8 +92,13 @@ String _runWithLoggingSync(List<String> cmd, {
String
errorDescription
=
'Error code
${results.exitCode}
'
String
errorDescription
=
'Error code
${results.exitCode}
'
'returned when attempting to run command:
${cmd.join(' ')}
'
;
'returned when attempting to run command:
${cmd.join(' ')}
'
;
printTrace
(
errorDescription
);
printTrace
(
errorDescription
);
if
(
results
.
stderr
.
length
>
0
)
if
(
results
.
stderr
.
length
>
0
)
{
printTrace
(
'Errors logged:
${results.stderr.trim()}
'
);
if
(
noisyErrors
)
{
printError
(
results
.
stderr
.
trim
());
}
else
{
printTrace
(
'Errors logged:
${results.stderr.trim()}
'
);
}
}
if
(
checked
)
if
(
checked
)
throw
errorDescription
;
throw
errorDescription
;
}
}
...
...
packages/flutter_tools/lib/src/commands/ios.dart
View file @
5a21ef24
...
@@ -17,8 +17,6 @@ class IOSCommand extends FlutterCommand {
...
@@ -17,8 +17,6 @@ class IOSCommand extends FlutterCommand {
final
String
name
=
"ios"
;
final
String
name
=
"ios"
;
final
String
description
=
"Commands for creating and updating Flutter iOS projects."
;
final
String
description
=
"Commands for creating and updating Flutter iOS projects."
;
final
bool
requiresProjectRoot
=
true
;
IOSCommand
()
{
IOSCommand
()
{
argParser
.
addFlag
(
'init'
,
help:
'Initialize the Xcode project for building the iOS application'
);
argParser
.
addFlag
(
'init'
,
help:
'Initialize the Xcode project for building the iOS application'
);
}
}
...
...
packages/flutter_tools/lib/src/commands/logs.dart
View file @
5a21ef24
...
@@ -4,6 +4,7 @@
...
@@ -4,6 +4,7 @@
import
'dart:async'
;
import
'dart:async'
;
import
'../base/context.dart'
;
import
'../device.dart'
;
import
'../device.dart'
;
import
'../runner/flutter_command.dart'
;
import
'../runner/flutter_command.dart'
;
...
@@ -13,25 +14,52 @@ class LogsCommand extends FlutterCommand {
...
@@ -13,25 +14,52 @@ class LogsCommand extends FlutterCommand {
LogsCommand
()
{
LogsCommand
()
{
argParser
.
addFlag
(
'clear'
,
argParser
.
addFlag
(
'clear'
,
negatable:
false
,
negatable:
false
,
abbr:
'c'
,
abbr:
'c'
,
help:
'Clear log history before reading from logs (Android only).'
);
help:
'Clear log history before reading from logs.'
);
}
}
bool
get
requiresProjectRoot
=>
false
;
bool
get
requiresProjectRoot
=>
false
;
@override
Future
<
int
>
runInProject
()
async
{
Future
<
int
>
runInProject
()
async
{
connectToDevices
();
DeviceManager
deviceManager
=
new
DeviceManager
();
List
<
Device
>
devices
;
String
deviceId
=
globalResults
[
'device-id'
];
if
(
deviceId
!=
null
)
{
Device
device
=
await
deviceManager
.
getDeviceById
(
deviceId
);
if
(
device
==
null
)
{
printError
(
"No device found with id '
$deviceId
'."
);
return
1
;
}
devices
=
<
Device
>[
device
];
}
else
{
devices
=
await
deviceManager
.
getDevices
();
}
if
(
devices
.
isEmpty
)
{
printStatus
(
'No connected devices.'
);
return
0
;
}
bool
clear
=
argResults
[
'clear'
];
bool
clear
=
argResults
[
'clear'
];
Iterable
<
Future
<
int
>>
results
=
devices
.
all
.
map
(
Set
<
DeviceLogReader
>
readers
=
new
Set
<
DeviceLogReader
>();
(
Device
device
)
=>
device
.
logs
(
clear:
clear
));
for
(
Device
device
in
devices
)
{
readers
.
add
(
device
.
createLogReader
());
}
printStatus
(
'Logging for
${readers.join(', ')}
...'
);
for
(
Future
<
int
>
result
in
results
)
List
<
int
>
results
=
await
Future
.
wait
(
readers
.
map
((
DeviceLogReader
reader
)
async
{
await
result
;
int
result
=
await
reader
.
logs
(
clear:
clear
);
if
(
result
!=
0
)
printError
(
'Error listening to
$reader
logs.'
);
return
result
;
}));
return
0
;
// If all readers failed, return an error.
return
results
.
every
((
int
result
)
=>
result
!=
0
)
?
1
:
0
;
}
}
}
}
packages/flutter_tools/lib/src/commands/start.dart
View file @
5a21ef24
...
@@ -134,8 +134,6 @@ Future<int> startApp(
...
@@ -134,8 +134,6 @@ Future<int> startApp(
if
(
traceStartup
!=
null
)
if
(
traceStartup
!=
null
)
platformArgs
[
'trace-startup'
]
=
traceStartup
;
platformArgs
[
'trace-startup'
]
=
traceStartup
;
if
(
clearLogs
!=
null
)
platformArgs
[
'clear-logs'
]
=
clearLogs
;
printStatus
(
'Starting
${_getDisplayPath(mainPath)}
on
${device.name}
...'
);
printStatus
(
'Starting
${_getDisplayPath(mainPath)}
on
${device.name}
...'
);
...
@@ -145,6 +143,7 @@ Future<int> startApp(
...
@@ -145,6 +143,7 @@ Future<int> startApp(
mainPath:
mainPath
,
mainPath:
mainPath
,
route:
route
,
route:
route
,
checked:
checked
,
checked:
checked
,
clearLogs:
clearLogs
,
platformArgs:
platformArgs
platformArgs:
platformArgs
);
);
...
...
packages/flutter_tools/lib/src/device.dart
View file @
5a21ef24
...
@@ -34,6 +34,19 @@ class DeviceManager {
...
@@ -34,6 +34,19 @@ class DeviceManager {
Completer
_initedCompleter
=
new
Completer
();
Completer
_initedCompleter
=
new
Completer
();
/// Return the device with the matching ID; else, complete the Future with
/// `null`.
///
/// This does a case insentitive compare with `deviceId`.
Future
<
Device
>
getDeviceById
(
String
deviceId
)
async
{
deviceId
=
deviceId
.
toLowerCase
();
List
<
Device
>
devices
=
await
getDevices
();
return
devices
.
firstWhere
(
(
Device
device
)
=>
device
.
id
.
toLowerCase
()
==
deviceId
,
orElse:
()
=>
null
);
}
Future
<
List
<
Device
>>
getDevices
()
async
{
Future
<
List
<
Device
>>
getDevices
()
async
{
await
_initedCompleter
.
future
;
await
_initedCompleter
.
future
;
...
@@ -78,7 +91,7 @@ abstract class Device {
...
@@ -78,7 +91,7 @@ abstract class Device {
TargetPlatform
get
platform
;
TargetPlatform
get
platform
;
Future
<
int
>
logs
({
bool
clear:
false
}
);
DeviceLogReader
createLogReader
(
);
/// Start an app package on the current device.
/// Start an app package on the current device.
///
///
...
@@ -90,6 +103,7 @@ abstract class Device {
...
@@ -90,6 +103,7 @@ abstract class Device {
String
mainPath
,
String
mainPath
,
String
route
,
String
route
,
bool
checked:
true
,
bool
checked:
true
,
bool
clearLogs:
false
,
Map
<
String
,
dynamic
>
platformArgs
Map
<
String
,
dynamic
>
platformArgs
});
});
...
@@ -99,6 +113,21 @@ abstract class Device {
...
@@ -99,6 +113,21 @@ abstract class Device {
String
toString
()
=>
'
$runtimeType
$id
'
;
String
toString
()
=>
'
$runtimeType
$id
'
;
}
}
/// Read the log for a particular device. Subclasses must implement `hashCode`
/// and `operator ==` so that log readers that read from the same location can be
/// de-duped. For example, two Android devices will both try and log using
/// `adb logcat`; we don't want to display two identical log streams.
abstract
class
DeviceLogReader
{
String
get
name
;
Future
<
int
>
logs
({
bool
clear:
false
});
int
get
hashCode
;
bool
operator
==(
dynamic
other
);
String
toString
()
=>
name
;
}
// TODO(devoncarew): Unify this with [DeviceManager].
// TODO(devoncarew): Unify this with [DeviceManager].
class
DeviceStore
{
class
DeviceStore
{
final
AndroidDevice
android
;
final
AndroidDevice
android
;
...
...
packages/flutter_tools/lib/src/ios/device_ios.dart
View file @
5a21ef24
...
@@ -184,9 +184,10 @@ class IOSDevice extends Device {
...
@@ -184,9 +184,10 @@ class IOSDevice extends Device {
String
mainPath
,
String
mainPath
,
String
route
,
String
route
,
bool
checked:
true
,
bool
checked:
true
,
bool
clearLogs:
false
,
Map
<
String
,
dynamic
>
platformArgs
Map
<
String
,
dynamic
>
platformArgs
})
async
{
})
async
{
// TODO
: Use checked, mainPath, route
// TODO
(chinmaygarde): Use checked, mainPath, route, clearLogs.
printTrace
(
'Building
${app.name}
for
$id
'
);
printTrace
(
'Building
${app.name}
for
$id
'
);
// Step 1: Install the precompiled application if necessary
// Step 1: Install the precompiled application if necessary
...
@@ -231,8 +232,7 @@ class IOSDevice extends Device {
...
@@ -231,8 +232,7 @@ class IOSDevice extends Device {
return
false
;
return
false
;
}
}
Future
<
bool
>
pushFile
(
Future
<
bool
>
pushFile
(
ApplicationPackage
app
,
String
localFile
,
String
targetFile
)
async
{
ApplicationPackage
app
,
String
localFile
,
String
targetFile
)
async
{
if
(
Platform
.
isMacOS
)
{
if
(
Platform
.
isMacOS
)
{
runSync
([
runSync
([
pusherPath
,
pusherPath
,
...
@@ -255,14 +255,7 @@ class IOSDevice extends Device {
...
@@ -255,14 +255,7 @@ class IOSDevice extends Device {
@override
@override
TargetPlatform
get
platform
=>
TargetPlatform
.
iOS
;
TargetPlatform
get
platform
=>
TargetPlatform
.
iOS
;
/// Note that clear is not supported on iOS at this time.
DeviceLogReader
createLogReader
()
=>
new
_IOSDeviceLogReader
(
this
);
Future
<
int
>
logs
({
bool
clear:
false
})
async
{
if
(!
isConnected
())
{
return
2
;
}
return
await
runCommandAndStreamOutput
([
loggerPath
],
prefix:
'iOS: '
,
filter:
new
RegExp
(
r'(FlutterRunner|flutter.runner.Runner)'
));
}
}
}
class
IOSSimulator
extends
Device
{
class
IOSSimulator
extends
Device
{
...
@@ -335,10 +328,9 @@ class IOSSimulator extends Device {
...
@@ -335,10 +328,9 @@ class IOSSimulator extends Device {
String
_getSimulatorPath
()
{
String
_getSimulatorPath
()
{
String
deviceID
=
id
==
defaultDeviceID
?
_getRunningSimulatorInfo
()?.
id
:
id
;
String
deviceID
=
id
==
defaultDeviceID
?
_getRunningSimulatorInfo
()?.
id
:
id
;
String
homeDirectory
=
path
.
absolute
(
Platform
.
environment
[
'HOME'
]);
if
(
deviceID
==
null
)
if
(
deviceID
==
null
)
return
null
;
return
null
;
return
path
.
join
(
homeDirectory
,
'Library'
,
'Developer'
,
'CoreSimulator'
,
'Devices'
,
deviceID
);
return
path
.
join
(
_
homeDirectory
,
'Library'
,
'Developer'
,
'CoreSimulator'
,
'Devices'
,
deviceID
);
}
}
String
_getSimulatorAppHomeDirectory
(
ApplicationPackage
app
)
{
String
_getSimulatorAppHomeDirectory
(
ApplicationPackage
app
)
{
...
@@ -438,11 +430,15 @@ class IOSSimulator extends Device {
...
@@ -438,11 +430,15 @@ class IOSSimulator extends Device {
String
mainPath
,
String
mainPath
,
String
route
,
String
route
,
bool
checked:
true
,
bool
checked:
true
,
bool
clearLogs:
false
,
Map
<
String
,
dynamic
>
platformArgs
Map
<
String
,
dynamic
>
platformArgs
})
async
{
})
async
{
// TODO
: Use checked, mainPath, route
// TODO
(chinmaygarde): Use checked, mainPath, route.
printTrace
(
'Building
${app.name}
for
$id
'
);
printTrace
(
'Building
${app.name}
for
$id
'
);
if
(
clearLogs
)
this
.
clearLogs
();
// Step 1: Build the Xcode project
// Step 1: Build the Xcode project
bool
buildResult
=
await
_buildIOSXcodeProject
(
app
,
false
);
bool
buildResult
=
await
_buildIOSXcodeProject
(
app
,
false
);
if
(!
buildResult
)
{
if
(!
buildResult
)
{
...
@@ -506,34 +502,122 @@ class IOSSimulator extends Device {
...
@@ -506,34 +502,122 @@ class IOSSimulator extends Device {
return
false
;
return
false
;
}
}
String
get
logFilePath
{
return
path
.
join
(
_homeDirectory
,
'Library'
,
'Logs'
,
'CoreSimulator'
,
id
,
'system.log'
);
}
@override
@override
TargetPlatform
get
platform
=>
TargetPlatform
.
iOSSimulator
;
TargetPlatform
get
platform
=>
TargetPlatform
.
iOSSimulator
;
Future
<
int
>
logs
({
bool
clear:
false
})
async
{
DeviceLogReader
createLogReader
()
=>
new
_IOSSimulatorLogReader
(
this
);
if
(!
isConnected
())
void
clearLogs
()
{
File
logFile
=
new
File
(
logFilePath
);
if
(
logFile
.
existsSync
())
logFile
.
delete
();
}
}
class
_IOSDeviceLogReader
extends
DeviceLogReader
{
_IOSDeviceLogReader
(
this
.
device
);
final
IOSDevice
device
;
String
get
name
=>
device
.
name
;
// TODO(devoncarew): Support [clear].
Future
<
int
>
logs
({
bool
clear:
false
})
async
{
if
(!
device
.
isConnected
())
return
2
;
return
2
;
String
homeDirectory
=
path
.
absolute
(
Platform
.
environment
[
'HOME'
]);
return
await
runCommandAndStreamOutput
(
String
simulatorDeviceID
=
_getRunningSimulatorInfo
().
id
;
[
device
.
loggerPath
],
String
logFilePath
=
path
.
join
(
prefix:
'[
$name
] '
,
homeDirectory
,
'Library'
,
'Logs'
,
'CoreSimulator'
,
simulatorDeviceID
,
'system.log'
filter:
new
RegExp
(
r'(FlutterRunner|flutter.runner.Runner)'
)
);
);
}
int
get
hashCode
=>
name
.
hashCode
;
bool
operator
==(
dynamic
other
)
{
if
(
identical
(
this
,
other
))
return
true
;
if
(
other
is
!
_IOSDeviceLogReader
)
return
false
;
return
other
.
name
==
name
;
}
}
class
_IOSSimulatorLogReader
extends
DeviceLogReader
{
_IOSSimulatorLogReader
(
this
.
device
);
final
IOSSimulator
device
;
String
get
name
=>
device
.
name
;
Future
<
int
>
logs
({
bool
clear:
false
})
async
{
if
(!
device
.
isConnected
())
return
2
;
if
(
clear
)
if
(
clear
)
runSync
([
'rm'
,
logFilePath
]);
device
.
clearLogs
();
// TODO(devoncarew): The log message prefix could be shortened or removed.
// Match the log prefix (in order to shorten it):
// Jan 29 01:31:44 devoncarew-macbookpro3 SpringBoard[96648]:
// 'Jan 29 01:31:44 devoncarew-macbookpro3 SpringBoard[96648]: ...'
// TODO(devoncarew): This truncates multi-line messages like:
RegExp
mapRegex
=
new
RegExp
(
r'\S+ +\S+ +\S+ \S+ (.+)\[\d+\]\)?: (.*)$'
);
// Jan 29 01:31:43 devoncarew-macbookpro3 CoreSimulatorBridge[96656]: Requesting... {
// Jan 31 19:23:28 --- last message repeated 1 time ---
// environment = {
RegExp
lastMessageRegex
=
new
RegExp
(
r'\S+ +\S+ +\S+ (--- .* ---)$'
);
// };
// }
// This filter matches many Flutter lines in the log:
return
await
runCommandAndStreamOutput
(
// new RegExp(r'(FlutterRunner|flutter.runner.Runner|$id)'), but it misses
[
'tail'
,
'-f'
,
logFilePath
],
// a fair number, including ones that would be useful in diagnosing crashes.
prefix:
'iOS: '
,
// For now, we're not filtering the log file (but do clear it with each run).
filter:
new
RegExp
(
r'(FlutterRunner|flutter.runner.Runner)'
)
Future
<
int
>
result
=
runCommandAndStreamOutput
(
<
String
>[
'tail'
,
'-n'
,
'+0'
,
'-F'
,
device
.
logFilePath
],
prefix:
'[
$name
] '
,
mapFunction:
(
String
string
)
{
Match
match
=
mapRegex
.
matchAsPrefix
(
string
);
if
(
match
!=
null
)
{
// Filter out some messages that clearly aren't related to Flutter.
if
(
string
.
contains
(
': could not find icon for representation -> com.apple.'
))
return
null
;
String
category
=
match
.
group
(
1
);
String
content
=
match
.
group
(
2
);
if
(
category
==
'Game Center'
||
category
==
'itunesstored'
||
category
==
'nanoregistrylaunchd'
)
return
null
;
return
'
$category
:
$content
'
;
}
match
=
lastMessageRegex
.
matchAsPrefix
(
string
);
if
(
match
!=
null
)
return
match
.
group
(
1
);
return
string
;
}
);
);
// Track system.log crashes.
// ReportCrash[37965]: Saved crash report for FlutterRunner[37941]...
runCommandAndStreamOutput
(
<
String
>[
'tail'
,
'-F'
,
'/private/var/log/system.log'
],
prefix:
'[
$name
] '
,
filter:
new
RegExp
(
r' FlutterRunner\[\d+\] '
),
mapFunction:
(
String
string
)
{
Match
match
=
mapRegex
.
matchAsPrefix
(
string
);
return
match
==
null
?
string
:
'
${match.group(1)}
:
${match.group(2)}
'
;
}
);
return
result
;
}
int
get
hashCode
=>
device
.
logFilePath
.
hashCode
;
bool
operator
==(
dynamic
other
)
{
if
(
identical
(
this
,
other
))
return
true
;
if
(
other
is
!
_IOSSimulatorLogReader
)
return
false
;
return
other
.
device
.
logFilePath
==
device
.
logFilePath
;
}
}
}
}
...
@@ -547,6 +631,8 @@ class _IOSSimulatorInfo {
...
@@ -547,6 +631,8 @@ class _IOSSimulatorInfo {
final
RegExp
_xcodeVersionRegExp
=
new
RegExp
(
r'Xcode (\d+)\..*'
);
final
RegExp
_xcodeVersionRegExp
=
new
RegExp
(
r'Xcode (\d+)\..*'
);
final
String
_xcodeRequirement
=
'Xcode 7.0 or greater is required to develop for iOS.'
;
final
String
_xcodeRequirement
=
'Xcode 7.0 or greater is required to develop for iOS.'
;
String
get
_homeDirectory
=>
path
.
absolute
(
Platform
.
environment
[
'HOME'
]);
bool
_checkXcodeVersion
(
)
{
bool
_checkXcodeVersion
(
)
{
if
(!
Platform
.
isMacOS
)
if
(!
Platform
.
isMacOS
)
return
false
;
return
false
;
...
@@ -573,15 +659,18 @@ Future<bool> _buildIOSXcodeProject(ApplicationPackage app, bool isDevice) async
...
@@ -573,15 +659,18 @@ Future<bool> _buildIOSXcodeProject(ApplicationPackage app, bool isDevice) async
if
(!
_checkXcodeVersion
())
if
(!
_checkXcodeVersion
())
return
false
;
return
false
;
List
<
String
>
command
=
[
List
<
String
>
command
s
=
[
'xcrun'
,
'xcodebuild'
,
'-target'
,
'Runner'
,
'-configuration'
,
'Release'
'
/usr/bin/env'
,
'
xcrun'
,
'xcodebuild'
,
'-target'
,
'Runner'
,
'-configuration'
,
'Release'
];
];
if
(!
isDevice
)
{
if
(!
isDevice
)
{
command
.
addAll
([
'-sdk'
,
'iphonesimulator'
]);
command
s
.
addAll
([
'-sdk'
,
'iphonesimulator'
]);
}
}
ProcessResult
result
=
Process
.
runSync
(
'/usr/bin/env'
,
command
,
try
{
workingDirectory:
app
.
localPath
);
runCheckedSync
(
commands
,
workingDirectory:
app
.
localPath
);
return
result
.
exitCode
==
0
;
return
true
;
}
catch
(
error
)
{
return
false
;
}
}
}
packages/flutter_tools/lib/src/runner/flutter_command_runner.dart
View file @
5a21ef24
...
@@ -142,11 +142,16 @@ class FlutterCommandRunner extends CommandRunner {
...
@@ -142,11 +142,16 @@ class FlutterCommandRunner extends CommandRunner {
String
get
_defaultFlutterRoot
{
String
get
_defaultFlutterRoot
{
if
(
Platform
.
environment
.
containsKey
(
kFlutterRootEnvironmentVariableName
))
if
(
Platform
.
environment
.
containsKey
(
kFlutterRootEnvironmentVariableName
))
return
Platform
.
environment
[
kFlutterRootEnvironmentVariableName
];
return
Platform
.
environment
[
kFlutterRootEnvironmentVariableName
];
String
script
=
Platform
.
script
.
toFilePath
();
if
(
path
.
basename
(
script
)
==
kSnapshotFileName
)
try
{
return
path
.
dirname
(
path
.
dirname
(
path
.
dirname
(
script
)));
String
script
=
Platform
.
script
.
toFilePath
();
if
(
path
.
basename
(
script
)
==
kFlutterToolsScriptFileName
)
if
(
path
.
basename
(
script
)
==
kSnapshotFileName
)
return
path
.
dirname
(
path
.
dirname
(
path
.
dirname
(
path
.
dirname
(
script
))));
return
path
.
dirname
(
path
.
dirname
(
path
.
dirname
(
script
)));
if
(
path
.
basename
(
script
)
==
kFlutterToolsScriptFileName
)
return
path
.
dirname
(
path
.
dirname
(
path
.
dirname
(
path
.
dirname
(
script
))));
}
catch
(
error
)
{
printTrace
(
'Unable to locate fluter root:
$error
'
);
}
return
'.'
;
return
'.'
;
}
}
...
...
packages/flutter_tools/test/logs_test.dart
View file @
5a21ef24
...
@@ -4,7 +4,7 @@
...
@@ -4,7 +4,7 @@
import
'package:args/command_runner.dart'
;
import
'package:args/command_runner.dart'
;
import
'package:flutter_tools/src/commands/logs.dart'
;
import
'package:flutter_tools/src/commands/logs.dart'
;
import
'package:
mockito/mockito
.dart'
;
import
'package:
flutter_tools/src/runner/flutter_command_runner
.dart'
;
import
'package:test/test.dart'
;
import
'package:test/test.dart'
;
import
'src/mocks.dart'
;
import
'src/mocks.dart'
;
...
@@ -13,18 +13,13 @@ main() => defineTests();
...
@@ -13,18 +13,13 @@ main() => defineTests();
defineTests
()
{
defineTests
()
{
group
(
'logs'
,
()
{
group
(
'logs'
,
()
{
test
(
'
returns 0 when no device is connecte
d'
,
()
{
test
(
'
fail with a bad device i
d'
,
()
{
LogsCommand
command
=
new
LogsCommand
();
LogsCommand
command
=
new
LogsCommand
();
applyMocksToCommand
(
command
);
applyMocksToCommand
(
command
);
MockDeviceStore
mockDevices
=
command
.
devices
;
CommandRunner
runner
=
new
FlutterCommandRunner
()..
addCommand
(
command
);
runner
.
run
(<
String
>[
'-d'
,
'abc123'
,
'logs'
]).
then
((
int
code
)
{
when
(
mockDevices
.
android
.
isConnected
()).
thenReturn
(
false
);
expect
(
code
,
equals
(
1
));
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
)));
});
});
});
});
}
}
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