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
20004357
Unverified
Commit
20004357
authored
Feb 16, 2018
by
Mikkel Nygaard Ravn
Committed by
GitHub
Feb 16, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Move plugin injection to just after pub get (#14743)
parent
558c753f
Changes
20
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
761 additions
and
236 deletions
+761
-236
plugin_test.dart
dev/devicelab/bin/tasks/plugin_test.dart
+12
-0
plugin_test_ios.dart
dev/devicelab/bin/tasks/plugin_test_ios.dart
+12
-0
plugin_test_win.dart
dev/devicelab/bin/tasks/plugin_test_win.dart
+12
-0
plugin_tests.dart
dev/devicelab/lib/tasks/plugin_tests.dart
+77
-0
manifest.yaml
dev/devicelab/manifest.yaml
+21
-0
gradle.dart
packages/flutter_tools/lib/src/android/gradle.dart
+0
-2
application_package.dart
packages/flutter_tools/lib/src/application_package.dart
+2
-2
create.dart
packages/flutter_tools/lib/src/commands/create.dart
+1
-13
inject_plugins.dart
packages/flutter_tools/lib/src/commands/inject_plugins.dart
+2
-1
packages.dart
packages/flutter_tools/lib/src/commands/packages.dart
+3
-0
cocoapods.dart
packages/flutter_tools/lib/src/ios/cocoapods.dart
+62
-31
mac.dart
packages/flutter_tools/lib/src/ios/mac.dart
+8
-12
xcodeproj.dart
packages/flutter_tools/lib/src/ios/xcodeproj.dart
+53
-20
plugins.dart
packages/flutter_tools/lib/src/plugins.dart
+40
-23
project.dart
packages/flutter_tools/lib/src/project.dart
+21
-0
flutter_command.dart
packages/flutter_tools/lib/src/runner/flutter_command.dart
+4
-1
packages_test.dart
packages/flutter_tools/test/commands/packages_test.dart
+145
-18
cocoapods_test.dart
packages/flutter_tools/test/ios/cocoapods_test.dart
+218
-111
project_test.dart
packages/flutter_tools/test/project_test.dart
+47
-2
context.dart
packages/flutter_tools/test/src/context.dart
+21
-0
No files found.
dev/devicelab/bin/tasks/plugin_test.dart
0 → 100644
View file @
20004357
// Copyright (c) 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:async'
;
import
'package:flutter_devicelab/tasks/plugin_tests.dart'
;
import
'package:flutter_devicelab/framework/framework.dart'
;
Future
<
Null
>
main
()
async
{
await
task
(
new
PluginTest
(
'apk'
));
}
dev/devicelab/bin/tasks/plugin_test_ios.dart
0 → 100644
View file @
20004357
// Copyright (c) 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:async'
;
import
'package:flutter_devicelab/tasks/plugin_tests.dart'
;
import
'package:flutter_devicelab/framework/framework.dart'
;
Future
<
Null
>
main
()
async
{
await
task
(
new
PluginTest
(
'ios'
));
}
dev/devicelab/bin/tasks/plugin_test_win.dart
0 → 100644
View file @
20004357
// Copyright (c) 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:async'
;
import
'package:flutter_devicelab/tasks/plugin_tests.dart'
;
import
'package:flutter_devicelab/framework/framework.dart'
;
Future
<
Null
>
main
()
async
{
await
task
(
new
PluginTest
(
'apk'
));
}
dev/devicelab/lib/tasks/plugin_tests.dart
0 → 100644
View file @
20004357
// Copyright (c) 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:async'
;
import
'dart:io'
;
import
'package:path/path.dart'
as
path
;
import
'package:flutter_devicelab/framework/framework.dart'
;
import
'package:flutter_devicelab/framework/ios.dart'
;
import
'package:flutter_devicelab/framework/utils.dart'
;
/// Defines task that creates new Flutter project, adds a plugin, and then
/// builds the specified [buildTarget].
class
PluginTest
{
final
String
buildTarget
;
PluginTest
(
this
.
buildTarget
);
Future
<
TaskResult
>
call
()
async
{
section
(
'Create Flutter project'
);
final
Directory
tmp
=
await
Directory
.
systemTemp
.
createTemp
(
'plugin'
);
final
FlutterProject
project
=
await
FlutterProject
.
create
(
tmp
);
if
(
buildTarget
==
'ios'
)
{
await
prepareProvisioningCertificates
(
project
.
rootPath
);
}
try
{
section
(
'Add plugin'
);
await
project
.
addPlugin
(
'path_provider'
);
section
(
'Build'
);
await
project
.
build
(
buildTarget
);
return
new
TaskResult
.
success
(
null
);
}
catch
(
e
)
{
return
new
TaskResult
.
failure
(
e
.
toString
());
}
finally
{
await
project
.
delete
();
}
}
}
class
FlutterProject
{
FlutterProject
(
this
.
parent
,
this
.
name
);
final
Directory
parent
;
final
String
name
;
static
Future
<
FlutterProject
>
create
(
Directory
directory
)
async
{
await
inDirectory
(
directory
,
()
async
{
await
flutter
(
'create'
,
options:
<
String
>[
'--org'
,
'io.flutter.devicelab'
,
'plugintest'
]);
});
return
new
FlutterProject
(
directory
,
'plugintest'
);
}
String
get
rootPath
=>
path
.
join
(
parent
.
path
,
name
);
Future
<
Null
>
addPlugin
(
String
plugin
)
async
{
final
File
pubspec
=
new
File
(
path
.
join
(
rootPath
,
'pubspec.yaml'
));
String
content
=
await
pubspec
.
readAsString
();
content
=
content
.
replaceFirst
(
'
\n
dependencies:
\n
'
,
'
\n
dependencies:
\n
$plugin
:
\n
'
,
);
await
pubspec
.
writeAsString
(
content
,
flush:
true
);
}
Future
<
Null
>
build
(
String
target
)
async
{
await
inDirectory
(
new
Directory
(
rootPath
),
()
async
{
await
flutter
(
'build'
,
options:
<
String
>[
target
]);
});
}
Future
<
Null
>
delete
()
async
{
await
parent
.
delete
(
recursive:
true
);
}
}
dev/devicelab/manifest.yaml
View file @
20004357
...
@@ -237,6 +237,13 @@ tasks:
...
@@ -237,6 +237,13 @@ tasks:
stage
:
devicelab
stage
:
devicelab
required_agent_capabilities
:
[
"
linux/android"
]
required_agent_capabilities
:
[
"
linux/android"
]
plugin_test
:
description
:
>
Checks that the project template works and supports plugins.
stage
:
devicelab
required_agent_capabilities
:
[
"
linux/android"
]
flaky
:
true
flutter_gallery_instrumentation_test
:
flutter_gallery_instrumentation_test
:
description
:
>
description
:
>
Same as flutter_gallery__transition_perf but uses Android instrumentation
Same as flutter_gallery__transition_perf but uses Android instrumentation
...
@@ -253,6 +260,13 @@ tasks:
...
@@ -253,6 +260,13 @@ tasks:
stage
:
devicelab_ios
stage
:
devicelab_ios
required_agent_capabilities
:
[
"
mac/ios"
]
required_agent_capabilities
:
[
"
mac/ios"
]
plugin_test_ios
:
description
:
>
Checks that the project template works and supports plugins on iOS.
stage
:
devicelab_ios
required_agent_capabilities
:
[
"
mac/ios"
]
flaky
:
true
external_ui_integration_test_ios
:
external_ui_integration_test_ios
:
description
:
>
description
:
>
Checks that external UIs work on iOS.
Checks that external UIs work on iOS.
...
@@ -347,6 +361,13 @@ tasks:
...
@@ -347,6 +361,13 @@ tasks:
stage
:
devicelab_win
stage
:
devicelab_win
required_agent_capabilities
:
[
"
windows/android"
]
required_agent_capabilities
:
[
"
windows/android"
]
plugin_test_win
:
description
:
>
Checks that the project template works and supports plugins on Windows.
stage
:
devicelab_win
required_agent_capabilities
:
[
"
windows/android"
]
flaky
:
true
hot_mode_dev_cycle_win__benchmark
:
hot_mode_dev_cycle_win__benchmark
:
description
:
>
description
:
>
Measures the performance of Dart VM hot patching feature on Windows.
Measures the performance of Dart VM hot patching feature on Windows.
...
...
packages/flutter_tools/lib/src/android/gradle.dart
View file @
20004357
...
@@ -16,7 +16,6 @@ import '../base/utils.dart';
...
@@ -16,7 +16,6 @@ import '../base/utils.dart';
import
'../build_info.dart'
;
import
'../build_info.dart'
;
import
'../cache.dart'
;
import
'../cache.dart'
;
import
'../globals.dart'
;
import
'../globals.dart'
;
import
'../plugins.dart'
;
import
'android_sdk.dart'
;
import
'android_sdk.dart'
;
import
'android_studio.dart'
;
import
'android_studio.dart'
;
...
@@ -94,7 +93,6 @@ Future<GradleProject> _gradleProject() async {
...
@@ -94,7 +93,6 @@ Future<GradleProject> _gradleProject() async {
Future
<
GradleProject
>
_readGradleProject
()
async
{
Future
<
GradleProject
>
_readGradleProject
()
async
{
final
String
gradle
=
await
_ensureGradle
();
final
String
gradle
=
await
_ensureGradle
();
updateLocalProperties
();
updateLocalProperties
();
injectPlugins
();
try
{
try
{
final
Status
status
=
logger
.
startProgress
(
'Resolving dependencies...'
,
expectSlowOperation:
true
);
final
Status
status
=
logger
.
startProgress
(
'Resolving dependencies...'
,
expectSlowOperation:
true
);
final
RunResult
runResult
=
await
runCheckedAsync
(
final
RunResult
runResult
=
await
runCheckedAsync
(
...
...
packages/flutter_tools/lib/src/application_package.dart
View file @
20004357
...
@@ -181,11 +181,11 @@ abstract class IOSApp extends ApplicationPackage {
...
@@ -181,11 +181,11 @@ abstract class IOSApp extends ApplicationPackage {
if
(
id
==
null
)
if
(
id
==
null
)
return
null
;
return
null
;
final
String
projectPath
=
fs
.
path
.
join
(
'ios'
,
'Runner.xcodeproj'
);
final
String
projectPath
=
fs
.
path
.
join
(
'ios'
,
'Runner.xcodeproj'
);
final
Map
<
String
,
String
>
buildSettings
=
getXcode
BuildSettings
(
projectPath
,
'Runner'
);
final
Map
<
String
,
String
>
buildSettings
=
xcodeProjectInterpreter
.
get
BuildSettings
(
projectPath
,
'Runner'
);
id
=
substituteXcodeVariables
(
id
,
buildSettings
);
id
=
substituteXcodeVariables
(
id
,
buildSettings
);
return
new
BuildableIOSApp
(
return
new
BuildableIOSApp
(
appDirectory:
fs
.
path
.
join
(
'ios'
)
,
appDirectory:
'ios'
,
projectBundleId:
id
,
projectBundleId:
id
,
buildSettings:
buildSettings
,
buildSettings:
buildSettings
,
);
);
...
...
packages/flutter_tools/lib/src/commands/create.dart
View file @
20004357
...
@@ -14,14 +14,10 @@ import '../base/common.dart';
...
@@ -14,14 +14,10 @@ import '../base/common.dart';
import
'../base/file_system.dart'
;
import
'../base/file_system.dart'
;
import
'../base/os.dart'
;
import
'../base/os.dart'
;
import
'../base/utils.dart'
;
import
'../base/utils.dart'
;
import
'../build_info.dart'
;
import
'../cache.dart'
;
import
'../cache.dart'
;
import
'../dart/pub.dart'
;
import
'../dart/pub.dart'
;
import
'../doctor.dart'
;
import
'../doctor.dart'
;
import
'../flx.dart'
as
flx
;
import
'../globals.dart'
;
import
'../globals.dart'
;
import
'../ios/xcodeproj.dart'
;
import
'../plugins.dart'
;
import
'../project.dart'
;
import
'../project.dart'
;
import
'../runner/flutter_command.dart'
;
import
'../runner/flutter_command.dart'
;
import
'../template.dart'
;
import
'../template.dart'
;
...
@@ -232,17 +228,9 @@ class CreateCommand extends FlutterCommand {
...
@@ -232,17 +228,9 @@ class CreateCommand extends FlutterCommand {
printStatus
(
'Wrote
$generatedCount
files.'
);
printStatus
(
'Wrote
$generatedCount
files.'
);
printStatus
(
''
);
printStatus
(
''
);
updateXcodeGeneratedProperties
(
projectPath:
appPath
,
buildInfo:
BuildInfo
.
debug
,
target:
flx
.
defaultMainPath
,
hasPlugins:
generatePlugin
,
previewDart2:
false
,
);
if
(
argResults
[
'pub'
])
{
if
(
argResults
[
'pub'
])
{
await
pubGet
(
context:
PubContext
.
create
,
directory:
appPath
,
offline:
argResults
[
'offline'
]);
await
pubGet
(
context:
PubContext
.
create
,
directory:
appPath
,
offline:
argResults
[
'offline'
]);
injectPlugins
(
directory:
appPath
);
new
FlutterProject
(
fs
.
directory
(
appPath
)).
ensureReadyForPlatformSpecificTooling
(
);
}
}
if
(
android_sdk
.
androidSdk
!=
null
)
if
(
android_sdk
.
androidSdk
!=
null
)
...
...
packages/flutter_tools/lib/src/commands/inject_plugins.dart
View file @
20004357
...
@@ -24,7 +24,8 @@ class InjectPluginsCommand extends FlutterCommand {
...
@@ -24,7 +24,8 @@ class InjectPluginsCommand extends FlutterCommand {
@override
@override
Future
<
Null
>
runCommand
()
async
{
Future
<
Null
>
runCommand
()
async
{
final
bool
result
=
injectPlugins
().
hasPlugin
;
injectPlugins
();
final
bool
result
=
hasPlugins
();
if
(
result
)
{
if
(
result
)
{
printStatus
(
'GeneratedPluginRegistrants successfully written.'
);
printStatus
(
'GeneratedPluginRegistrants successfully written.'
);
}
else
{
}
else
{
...
...
packages/flutter_tools/lib/src/commands/packages.dart
View file @
20004357
...
@@ -5,8 +5,10 @@
...
@@ -5,8 +5,10 @@
import
'dart:async'
;
import
'dart:async'
;
import
'../base/common.dart'
;
import
'../base/common.dart'
;
import
'../base/file_system.dart'
;
import
'../base/os.dart'
;
import
'../base/os.dart'
;
import
'../dart/pub.dart'
;
import
'../dart/pub.dart'
;
import
'../project.dart'
;
import
'../runner/flutter_command.dart'
;
import
'../runner/flutter_command.dart'
;
class
PackagesCommand
extends
FlutterCommand
{
class
PackagesCommand
extends
FlutterCommand
{
...
@@ -75,6 +77,7 @@ class PackagesGetCommand extends FlutterCommand {
...
@@ -75,6 +77,7 @@ class PackagesGetCommand extends FlutterCommand {
offline:
argResults
[
'offline'
],
offline:
argResults
[
'offline'
],
checkLastModified:
false
,
checkLastModified:
false
,
);
);
new
FlutterProject
(
fs
.
directory
(
target
)).
ensureReadyForPlatformSpecificTooling
();
}
}
}
}
...
...
packages/flutter_tools/lib/src/ios/cocoapods.dart
View file @
20004357
...
@@ -16,6 +16,7 @@ import '../base/process_manager.dart';
...
@@ -16,6 +16,7 @@ import '../base/process_manager.dart';
import
'../base/version.dart'
;
import
'../base/version.dart'
;
import
'../cache.dart'
;
import
'../cache.dart'
;
import
'../globals.dart'
;
import
'../globals.dart'
;
import
'xcodeproj.dart'
;
const
String
noCocoaPodsConsequence
=
'''
const
String
noCocoaPodsConsequence
=
'''
CocoaPods is used to retrieve the iOS platform side'
s
plugin
code
that
responds
to
your
plugin
usage
on
the
Dart
side
.
CocoaPods is used to retrieve the iOS platform side'
s
plugin
code
that
responds
to
your
plugin
usage
on
the
Dart
side
.
...
@@ -60,13 +61,13 @@ class CocoaPods {
...
@@ -60,13 +61,13 @@ class CocoaPods {
// For backward compatibility with previously created Podfile only.
// For backward compatibility with previously created Podfile only.
@required
String
iosEngineDir
,
@required
String
iosEngineDir
,
bool
isSwift:
false
,
bool
isSwift:
false
,
bool
pluginOrF
lutterPodChanged:
true
,
bool
f
lutterPodChanged:
true
,
})
async
{
})
async
{
if
(!(
await
appIosDir
.
childFile
(
'Podfile'
).
exists
()))
{
throwToolExit
(
'Podfile missing'
);
}
if
(
await
_checkPodCondition
())
{
if
(
await
_checkPodCondition
())
{
if
(!
fs
.
file
(
fs
.
path
.
join
(
appIosDir
.
path
,
'Podfile'
)).
existsSync
())
{
if
(
_shouldRunPodInstall
(
appIosDir
.
path
,
flutterPodChanged
))
await
_createPodfile
(
appIosDir
,
isSwift
);
}
// TODO(xster): Add more logic for handling merge conflicts.
if
(
_shouldRunPodInstall
(
appIosDir
.
path
,
pluginOrFlutterPodChanged
))
await
_runPodInstall
(
appIosDir
,
iosEngineDir
);
await
_runPodInstall
(
appIosDir
,
iosEngineDir
);
}
}
}
}
...
@@ -99,39 +100,69 @@ class CocoaPods {
...
@@ -99,39 +100,69 @@ class CocoaPods {
return
true
;
return
true
;
}
}
Future
<
Null
>
_createPodfile
(
Directory
bundle
,
bool
isSwift
)
async
{
/// Ensures the `ios` sub-project of the Flutter project at [directory]
final
File
podfileTemplate
=
fs
.
file
(
fs
.
path
.
join
(
/// contains a suitable `Podfile` and that its `Flutter/Xxx.xcconfig` files
Cache
.
flutterRoot
,
/// include pods configuration.
'packages'
,
void
setupPodfile
(
String
directory
)
{
'flutter_tools'
,
if
(!
xcodeProjectInterpreter
.
canInterpretXcodeProjects
)
{
'templates'
,
// Don't do anything for iOS when host platform doesn't support it.
'cocoapods'
,
return
;
isSwift
?
'Podfile-swift'
:
'Podfile-objc'
,
}
));
final
String
podfilePath
=
fs
.
path
.
join
(
directory
,
'ios'
,
'Podfile'
);
podfileTemplate
.
copySync
(
fs
.
path
.
join
(
bundle
.
path
,
'Podfile'
));
if
(!
fs
.
file
(
podfilePath
).
existsSync
())
{
final
bool
isSwift
=
xcodeProjectInterpreter
.
getBuildSettings
(
fs
.
path
.
join
(
directory
,
'ios'
,
'Runner.xcodeproj'
),
'Runner'
,
).
containsKey
(
'SWIFT_VERSION'
);
final
File
podfileTemplate
=
fs
.
file
(
fs
.
path
.
join
(
Cache
.
flutterRoot
,
'packages'
,
'flutter_tools'
,
'templates'
,
'cocoapods'
,
isSwift
?
'Podfile-swift'
:
'Podfile-objc'
,
));
podfileTemplate
.
copySync
(
podfilePath
);
}
_addPodsDependencyToFlutterXcconfig
(
directory
,
'Debug'
);
_addPodsDependencyToFlutterXcconfig
(
directory
,
'Release'
);
}
void
_addPodsDependencyToFlutterXcconfig
(
String
directory
,
String
mode
)
{
final
File
file
=
fs
.
file
(
fs
.
path
.
join
(
directory
,
'ios'
,
'Flutter'
,
'
$mode
.xcconfig'
));
if
(
file
.
existsSync
())
{
final
String
content
=
file
.
readAsStringSync
();
final
String
include
=
'#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.
${mode
.toLowerCase()}
.xcconfig"'
;
if
(!
content
.
contains
(
include
))
file
.
writeAsStringSync
(
'
$include
\n
$content
'
,
flush:
true
);
}
}
/// Ensures that pod install is deemed needed on next check.
void
invalidatePodInstallOutput
(
String
directory
)
{
final
File
manifest
=
fs
.
file
(
fs
.
path
.
join
(
directory
,
'ios'
,
'Pods'
,
'Manifest.lock'
),
);
if
(
manifest
.
existsSync
())
manifest
.
deleteSync
();
}
}
// Check if you need to run pod install.
// Check if you need to run pod install.
// The pod install will run if any of below is true.
// The pod install will run if any of below is true.
// 1. Any plugins changed (add/update/delete)
// 1. The flutter.framework has changed (debug/release/profile)
// 2. The flutter.framework has changed (debug/release/profile)
// 2. The podfile.lock doesn't exist
// 3. The podfile.lock doesn't exists
// 3. The Pods/Manifest.lock doesn't exist (It is deleted when plugins change)
// 4. The Pods/manifest.lock doesn't exists
// 4. The podfile.lock doesn't match Pods/Manifest.lock.
// 5. The podfile.lock doesn't match Pods/manifest.lock.
bool
_shouldRunPodInstall
(
String
appDir
,
bool
flutterPodChanged
)
{
bool
_shouldRunPodInstall
(
String
appDir
,
bool
pluginOrFlutterPodChanged
)
{
if
(
flutterPodChanged
)
if
(
pluginOrFlutterPodChanged
)
return
true
;
return
true
;
// Check if podfile.lock and Pods/Manifest.lock exist
s and matches
.
// Check if podfile.lock and Pods/Manifest.lock exist
and match
.
final
File
podfileLockFile
=
fs
.
file
(
fs
.
path
.
join
(
appDir
,
'Podfile.lock'
));
final
File
podfileLockFile
=
fs
.
file
(
fs
.
path
.
join
(
appDir
,
'Podfile.lock'
));
final
File
manifestLockFile
=
final
File
manifestLockFile
=
fs
.
file
(
fs
.
path
.
join
(
appDir
,
'Pods'
,
'Manifest.lock'
));
fs
.
file
(
fs
.
path
.
join
(
appDir
,
'Pods'
,
'Manifest.lock'
));
return
!
podfileLockFile
.
existsSync
()
if
(!
podfileLockFile
.
existsSync
()
||
!
manifestLockFile
.
existsSync
()
||
!
manifestLockFile
.
existsSync
()
||
podfileLockFile
.
readAsStringSync
()
!=
||
podfileLockFile
.
readAsStringSync
()
!=
manifestLockFile
.
readAsStringSync
();
manifestLockFile
.
readAsStringSync
())
{
return
true
;
}
return
false
;
}
}
Future
<
Null
>
_runPodInstall
(
Directory
bundle
,
String
engineDirectory
)
async
{
Future
<
Null
>
_runPodInstall
(
Directory
bundle
,
String
engineDirectory
)
async
{
...
...
packages/flutter_tools/lib/src/ios/mac.dart
View file @
20004357
...
@@ -219,7 +219,7 @@ Future<XcodeBuildResult> buildXcodeProject({
...
@@ -219,7 +219,7 @@ Future<XcodeBuildResult> buildXcodeProject({
return
new
XcodeBuildResult
(
success:
false
);
return
new
XcodeBuildResult
(
success:
false
);
}
}
final
XcodeProjectInfo
projectInfo
=
new
XcodeProjectInfo
.
fromProjectSync
(
app
.
appDirectory
);
final
XcodeProjectInfo
projectInfo
=
xcodeProjectInterpreter
.
getInfo
(
app
.
appDirectory
);
if
(!
projectInfo
.
targets
.
contains
(
'Runner'
))
{
if
(!
projectInfo
.
targets
.
contains
(
'Runner'
))
{
printError
(
'The Xcode project does not define target "Runner" which is needed by Flutter tooling.'
);
printError
(
'The Xcode project does not define target "Runner" which is needed by Flutter tooling.'
);
printError
(
'Open Xcode to fix the problem:'
);
printError
(
'Open Xcode to fix the problem:'
);
...
@@ -256,26 +256,22 @@ Future<XcodeBuildResult> buildXcodeProject({
...
@@ -256,26 +256,22 @@ Future<XcodeBuildResult> buildXcodeProject({
// copied over to a location that is suitable for Xcodebuild to find them.
// copied over to a location that is suitable for Xcodebuild to find them.
final
Directory
appDirectory
=
fs
.
directory
(
app
.
appDirectory
);
final
Directory
appDirectory
=
fs
.
directory
(
app
.
appDirectory
);
await
_addServicesToBundle
(
appDirectory
);
await
_addServicesToBundle
(
appDirectory
);
final
InjectPluginsResult
injectPluginsResult
=
injectPlugins
();
final
bool
hasFlutterPlugins
=
injectPluginsResult
.
hasPlugin
;
final
String
previousGeneratedXcconfig
=
readGeneratedXcconfig
(
app
.
appDirectory
);
final
String
previousGeneratedXcconfig
=
readGeneratedXcconfig
(
app
.
appDirectory
);
update
XcodeGenerated
Properties
(
update
GeneratedXcode
Properties
(
projectPath:
fs
.
currentDirectory
.
path
,
projectPath:
fs
.
currentDirectory
.
path
,
buildInfo:
buildInfo
,
buildInfo:
buildInfo
,
target:
target
,
target:
target
,
hasPlugins:
hasFlutterPlugins
,
previewDart2:
buildInfo
.
previewDart2
,
previewDart2:
buildInfo
.
previewDart2
,
);
);
if
(
has
FlutterPlugins
)
{
if
(
has
Plugins
()
)
{
final
String
currentGeneratedXcconfig
=
readGeneratedXcconfig
(
app
.
appDirectory
);
final
String
currentGeneratedXcconfig
=
readGeneratedXcconfig
(
app
.
appDirectory
);
await
cocoaPods
.
processPods
(
await
cocoaPods
.
processPods
(
appIosDir:
appDirectory
,
appIosDir:
appDirectory
,
iosEngineDir:
flutterFrameworkDir
(
buildInfo
.
mode
),
iosEngineDir:
flutterFrameworkDir
(
buildInfo
.
mode
),
isSwift:
app
.
isSwift
,
isSwift:
app
.
isSwift
,
pluginOrFlutterPodChanged:
injectPluginsResult
.
hasChanged
flutterPodChanged:
(
previousGeneratedXcconfig
!=
currentGeneratedXcconfig
),
||
previousGeneratedXcconfig
!=
currentGeneratedXcconfig
,
);
);
}
}
...
@@ -465,7 +461,7 @@ Future<XcodeBuildResult> buildXcodeProject({
...
@@ -465,7 +461,7 @@ Future<XcodeBuildResult> buildXcodeProject({
String
readGeneratedXcconfig
(
String
appPath
)
{
String
readGeneratedXcconfig
(
String
appPath
)
{
final
String
generatedXcconfigPath
=
final
String
generatedXcconfigPath
=
fs
.
path
.
join
(
fs
.
currentDirectory
.
path
,
appPath
,
'Flutter'
,
'Generated.xcconfig'
);
fs
.
path
.
join
(
fs
.
currentDirectory
.
path
,
appPath
,
'Flutter'
,
'Generated.xcconfig'
);
final
File
generatedXcconfigFile
=
fs
.
file
(
generatedXcconfigPath
);
final
File
generatedXcconfigFile
=
fs
.
file
(
generatedXcconfigPath
);
if
(!
generatedXcconfigFile
.
existsSync
())
if
(!
generatedXcconfigFile
.
existsSync
())
return
null
;
return
null
;
...
...
packages/flutter_tools/lib/src/ios/xcodeproj.dart
View file @
20004357
...
@@ -5,11 +5,13 @@
...
@@ -5,11 +5,13 @@
import
'package:meta/meta.dart'
;
import
'package:meta/meta.dart'
;
import
'../artifacts.dart'
;
import
'../artifacts.dart'
;
import
'../base/context.dart'
;
import
'../base/file_system.dart'
;
import
'../base/file_system.dart'
;
import
'../base/process.dart'
;
import
'../base/process.dart'
;
import
'../base/utils.dart'
;
import
'../base/utils.dart'
;
import
'../build_info.dart'
;
import
'../build_info.dart'
;
import
'../cache.dart'
;
import
'../cache.dart'
;
import
'../flx.dart'
as
flx
;
import
'../globals.dart'
;
import
'../globals.dart'
;
final
RegExp
_settingExpr
=
new
RegExp
(
r'(\w+)\s*=\s*(.*)$'
);
final
RegExp
_settingExpr
=
new
RegExp
(
r'(\w+)\s*=\s*(.*)$'
);
...
@@ -19,11 +21,28 @@ String flutterFrameworkDir(BuildMode mode) {
...
@@ -19,11 +21,28 @@ String flutterFrameworkDir(BuildMode mode) {
return
fs
.
path
.
normalize
(
fs
.
path
.
dirname
(
artifacts
.
getArtifactPath
(
Artifact
.
flutterFramework
,
TargetPlatform
.
ios
,
mode
)));
return
fs
.
path
.
normalize
(
fs
.
path
.
dirname
(
artifacts
.
getArtifactPath
(
Artifact
.
flutterFramework
,
TargetPlatform
.
ios
,
mode
)));
}
}
void
updateXcodeGeneratedProperties
(
{
String
_generatedXcodePropertiesPath
(
String
projectPath
)
{
return
fs
.
path
.
join
(
projectPath
,
'ios'
,
'Flutter'
,
'Generated.xcconfig'
);
}
/// Writes default Xcode properties files in the Flutter project at
/// [projectPath], if such files do not already exist.
void
generateXcodeProperties
(
String
projectPath
)
{
if
(
fs
.
file
(
_generatedXcodePropertiesPath
(
projectPath
)).
existsSync
())
return
;
updateGeneratedXcodeProperties
(
projectPath:
projectPath
,
buildInfo:
BuildInfo
.
debug
,
target:
flx
.
defaultMainPath
,
previewDart2:
false
,
);
}
/// Writes or rewrites Xcode property files with the specified information.
void
updateGeneratedXcodeProperties
(
{
@required
String
projectPath
,
@required
String
projectPath
,
@required
BuildInfo
buildInfo
,
@required
BuildInfo
buildInfo
,
@required
String
target
,
@required
String
target
,
@required
bool
hasPlugins
,
@required
bool
previewDart2
,
@required
bool
previewDart2
,
})
{
})
{
final
StringBuffer
localsBuffer
=
new
StringBuffer
();
final
StringBuffer
localsBuffer
=
new
StringBuffer
();
...
@@ -58,21 +77,42 @@ void updateXcodeGeneratedProperties({
...
@@ -58,21 +77,42 @@ void updateXcodeGeneratedProperties({
localsBuffer
.
writeln
(
'PREVIEW_DART_2=true'
);
localsBuffer
.
writeln
(
'PREVIEW_DART_2=true'
);
}
}
// Add dependency to CocoaPods' generated project only if plugins are used.
final
File
localsFile
=
fs
.
file
(
_generatedXcodePropertiesPath
(
projectPath
));
if
(
hasPlugins
)
localsBuffer
.
writeln
(
'#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"'
);
final
File
localsFile
=
fs
.
file
(
fs
.
path
.
join
(
projectPath
,
'ios'
,
'Flutter'
,
'Generated.xcconfig'
));
localsFile
.
createSync
(
recursive:
true
);
localsFile
.
createSync
(
recursive:
true
);
localsFile
.
writeAsStringSync
(
localsBuffer
.
toString
());
localsFile
.
writeAsStringSync
(
localsBuffer
.
toString
());
}
}
Map
<
String
,
String
>
getXcodeBuildSettings
(
String
xcodeProjPath
,
String
target
)
{
XcodeProjectInterpreter
get
xcodeProjectInterpreter
=>
context
.
putIfAbsent
(
final
String
absProjPath
=
fs
.
path
.
absolute
(
xcodeProjPath
);
XcodeProjectInterpreter
,
final
String
out
=
runCheckedSync
(<
String
>[
()
=>
const
XcodeProjectInterpreter
(),
'/usr/bin/xcodebuild'
,
'-project'
,
absProjPath
,
'-target'
,
target
,
'-showBuildSettings'
);
]);
return
parseXcodeBuildSettings
(
out
);
/// Interpreter of Xcode projects settings.
class
XcodeProjectInterpreter
{
static
const
String
_executable
=
'/usr/bin/xcodebuild'
;
const
XcodeProjectInterpreter
();
bool
get
canInterpretXcodeProjects
=>
fs
.
isFileSync
(
_executable
);
Map
<
String
,
String
>
getBuildSettings
(
String
projectPath
,
String
target
)
{
final
String
out
=
runCheckedSync
(<
String
>[
_executable
,
'-project'
,
fs
.
path
.
absolute
(
projectPath
),
'-target'
,
target
,
'-showBuildSettings'
],
workingDirectory:
projectPath
);
return
parseXcodeBuildSettings
(
out
);
}
XcodeProjectInfo
getInfo
(
String
projectPath
)
{
final
String
out
=
runCheckedSync
(<
String
>[
_executable
,
'-list'
,
],
workingDirectory:
projectPath
);
return
new
XcodeProjectInfo
.
fromXcodeBuildOutput
(
out
);
}
}
}
Map
<
String
,
String
>
parseXcodeBuildSettings
(
String
showBuildSettingsOutput
)
{
Map
<
String
,
String
>
parseXcodeBuildSettings
(
String
showBuildSettingsOutput
)
{
...
@@ -101,13 +141,6 @@ String substituteXcodeVariables(String str, Map<String, String> xcodeBuildSettin
...
@@ -101,13 +141,6 @@ String substituteXcodeVariables(String str, Map<String, String> xcodeBuildSettin
class
XcodeProjectInfo
{
class
XcodeProjectInfo
{
XcodeProjectInfo
(
this
.
targets
,
this
.
buildConfigurations
,
this
.
schemes
);
XcodeProjectInfo
(
this
.
targets
,
this
.
buildConfigurations
,
this
.
schemes
);
factory
XcodeProjectInfo
.
fromProjectSync
(
String
projectPath
)
{
final
String
out
=
runCheckedSync
(<
String
>[
'/usr/bin/xcodebuild'
,
'-list'
,
],
workingDirectory:
projectPath
);
return
new
XcodeProjectInfo
.
fromXcodeBuildOutput
(
out
);
}
factory
XcodeProjectInfo
.
fromXcodeBuildOutput
(
String
output
)
{
factory
XcodeProjectInfo
.
fromXcodeBuildOutput
(
String
output
)
{
final
List
<
String
>
targets
=
<
String
>[];
final
List
<
String
>
targets
=
<
String
>[];
final
List
<
String
>
buildConfigurations
=
<
String
>[];
final
List
<
String
>
buildConfigurations
=
<
String
>[];
...
...
packages/flutter_tools/lib/src/plugins.dart
View file @
20004357
...
@@ -9,6 +9,7 @@ import 'package:yaml/yaml.dart';
...
@@ -9,6 +9,7 @@ import 'package:yaml/yaml.dart';
import
'base/file_system.dart'
;
import
'base/file_system.dart'
;
import
'dart/package_map.dart'
;
import
'dart/package_map.dart'
;
import
'globals.dart'
;
import
'globals.dart'
;
import
'ios/cocoapods.dart'
;
class
Plugin
{
class
Plugin
{
final
String
name
;
final
String
name
;
...
@@ -80,21 +81,25 @@ List<Plugin> _findPlugins(String directory) {
...
@@ -80,21 +81,25 @@ List<Plugin> _findPlugins(String directory) {
/// Returns true if .flutter-plugins has changed, otherwise returns false.
/// Returns true if .flutter-plugins has changed, otherwise returns false.
bool
_writeFlutterPluginsList
(
String
directory
,
List
<
Plugin
>
plugins
)
{
bool
_writeFlutterPluginsList
(
String
directory
,
List
<
Plugin
>
plugins
)
{
final
File
pluginsProperties
=
fs
.
file
(
fs
.
path
.
join
(
directory
,
'.flutter-plugins'
));
final
File
pluginsFile
=
fs
.
file
(
fs
.
path
.
join
(
directory
,
'.flutter-plugins'
));
final
String
previousFlutterPlugins
=
final
String
oldContents
=
_readFlutterPluginsList
(
directory
);
pluginsProperties
.
existsSync
()
?
pluginsProperties
.
readAsStringSync
()
:
null
;
final
String
pluginManifest
=
final
String
pluginManifest
=
plugins
.
map
((
Plugin
p
)
=>
'
${p.name}
=
${escapePath(p.path)}
'
).
join
(
'
\n
'
);
plugins
.
map
((
Plugin
p
)
=>
'
${p.name}
=
${escapePath(p.path)}
'
).
join
(
'
\n
'
);
if
(
pluginManifest
.
isNotEmpty
)
{
if
(
pluginManifest
.
isNotEmpty
)
{
plugins
Properties
.
writeAsStringSync
(
'
$pluginManifest
\n
'
);
plugins
File
.
writeAsStringSync
(
'
$pluginManifest
\n
'
,
flush:
true
);
}
else
{
}
else
{
if
(
pluginsProperties
.
existsSync
())
{
if
(
pluginsFile
.
existsSync
())
pluginsProperties
.
deleteSync
();
pluginsFile
.
deleteSync
();
}
}
}
final
String
currentFlutterPlugins
=
final
String
newContents
=
_readFlutterPluginsList
(
directory
);
pluginsProperties
.
existsSync
()
?
pluginsProperties
.
readAsStringSync
()
:
null
;
return
oldContents
!=
newContents
;
return
currentFlutterPlugins
!=
previousFlutterPlugins
;
}
/// Returns the contents of the `.flutter-plugins` file in [directory], or
/// null if that file does not exist.
String
_readFlutterPluginsList
(
String
directory
)
{
final
File
pluginsFile
=
fs
.
file
(
fs
.
path
.
join
(
directory
,
'.flutter-plugins'
));
return
pluginsFile
.
existsSync
()
?
pluginsFile
.
readAsStringSync
()
:
null
;
}
}
const
String
_androidPluginRegistryTemplate
=
'''package io.flutter.plugins;
const
String
_androidPluginRegistryTemplate
=
'''package io.flutter.plugins;
...
@@ -128,7 +133,7 @@ public final class GeneratedPluginRegistrant {
...
@@ -128,7 +133,7 @@ public final class GeneratedPluginRegistrant {
}
}
'''
;
'''
;
void
_writeAndroidPluginRegistr
y
(
String
directory
,
List
<
Plugin
>
plugins
)
{
void
_writeAndroidPluginRegistr
ant
(
String
directory
,
List
<
Plugin
>
plugins
)
{
final
List
<
Map
<
String
,
dynamic
>>
androidPlugins
=
plugins
final
List
<
Map
<
String
,
dynamic
>>
androidPlugins
=
plugins
.
where
((
Plugin
p
)
=>
p
.
androidPackage
!=
null
&&
p
.
pluginClass
!=
null
)
.
where
((
Plugin
p
)
=>
p
.
androidPackage
!=
null
&&
p
.
pluginClass
!=
null
)
.
map
((
Plugin
p
)
=>
<
String
,
dynamic
>{
.
map
((
Plugin
p
)
=>
<
String
,
dynamic
>{
...
@@ -187,7 +192,7 @@ const String _iosPluginRegistryImplementationTemplate = '''//
...
@@ -187,7 +192,7 @@ const String _iosPluginRegistryImplementationTemplate = '''//
@end
@end
'''
;
'''
;
void
_writeIOSPluginRegistr
y
(
String
directory
,
List
<
Plugin
>
plugins
)
{
void
_writeIOSPluginRegistr
ant
(
String
directory
,
List
<
Plugin
>
plugins
)
{
final
List
<
Map
<
String
,
dynamic
>>
iosPlugins
=
plugins
final
List
<
Map
<
String
,
dynamic
>>
iosPlugins
=
plugins
.
where
((
Plugin
p
)
=>
p
.
pluginClass
!=
null
)
.
where
((
Plugin
p
)
=>
p
.
pluginClass
!=
null
)
.
map
((
Plugin
p
)
=>
<
String
,
dynamic
>{
.
map
((
Plugin
p
)
=>
<
String
,
dynamic
>{
...
@@ -210,7 +215,6 @@ void _writeIOSPluginRegistry(String directory, List<Plugin> plugins) {
...
@@ -210,7 +215,6 @@ void _writeIOSPluginRegistry(String directory, List<Plugin> plugins) {
registryHeaderFile
.
writeAsStringSync
(
pluginRegistryHeader
);
registryHeaderFile
.
writeAsStringSync
(
pluginRegistryHeader
);
final
File
registryImplementationFile
=
registryDirectory
.
childFile
(
'GeneratedPluginRegistrant.m'
);
final
File
registryImplementationFile
=
registryDirectory
.
childFile
(
'GeneratedPluginRegistrant.m'
);
registryImplementationFile
.
writeAsStringSync
(
pluginRegistryImplementation
);
registryImplementationFile
.
writeAsStringSync
(
pluginRegistryImplementation
);
}
}
class
InjectPluginsResult
{
class
InjectPluginsResult
{
...
@@ -224,17 +228,30 @@ class InjectPluginsResult{
...
@@ -224,17 +228,30 @@ class InjectPluginsResult{
final
bool
hasChanged
;
final
bool
hasChanged
;
}
}
/// Finds Flutter plugins in the pubspec.yaml, creates platform injection
/// Injects plugins found in `pubspec.yaml` into the platform-specific projects.
/// registries classes and add them to the build dependencies.
void
injectPlugins
(
{
String
directory
})
{
///
/// Returns whether any Flutter plugins are added and whether they changed.
InjectPluginsResult
injectPlugins
(
{
String
directory
})
{
directory
??=
fs
.
currentDirectory
.
path
;
directory
??=
fs
.
currentDirectory
.
path
;
if
(
fs
.
file
(
fs
.
path
.
join
(
directory
,
'example'
,
'pubspec.yaml'
)).
existsSync
())
{
// Switch to example app if in plugin project template.
directory
=
fs
.
path
.
join
(
directory
,
'example'
);
}
final
List
<
Plugin
>
plugins
=
_findPlugins
(
directory
);
final
List
<
Plugin
>
plugins
=
_findPlugins
(
directory
);
final
bool
hasPluginsC
hanged
=
_writeFlutterPluginsList
(
directory
,
plugins
);
final
bool
c
hanged
=
_writeFlutterPluginsList
(
directory
,
plugins
);
if
(
fs
.
isDirectorySync
(
fs
.
path
.
join
(
directory
,
'android'
)))
if
(
fs
.
isDirectorySync
(
fs
.
path
.
join
(
directory
,
'android'
)))
_writeAndroidPluginRegistry
(
directory
,
plugins
);
_writeAndroidPluginRegistrant
(
directory
,
plugins
);
if
(
fs
.
isDirectorySync
(
fs
.
path
.
join
(
directory
,
'ios'
)))
if
(
fs
.
isDirectorySync
(
fs
.
path
.
join
(
directory
,
'ios'
)))
{
_writeIOSPluginRegistry
(
directory
,
plugins
);
_writeIOSPluginRegistrant
(
directory
,
plugins
);
return
new
InjectPluginsResult
(
hasPlugin:
plugins
.
isNotEmpty
,
hasChanged:
hasPluginsChanged
);
final
CocoaPods
cocoaPods
=
const
CocoaPods
();
if
(
plugins
.
isNotEmpty
)
cocoaPods
.
setupPodfile
(
directory
);
if
(
changed
)
cocoaPods
.
invalidatePodInstallOutput
(
directory
);
}
}
/// Returns whether the Flutter project at the specified [directory]
/// has any plugin dependencies.
bool
hasPlugins
(
{
String
directory
})
{
directory
??=
fs
.
currentDirectory
.
path
;
return
_readFlutterPluginsList
(
directory
)
!=
null
;
}
}
packages/flutter_tools/lib/src/project.dart
View file @
20004357
...
@@ -4,7 +4,11 @@
...
@@ -4,7 +4,11 @@
import
'dart:async'
;
import
'dart:async'
;
import
'dart:convert'
;
import
'dart:convert'
;
import
'base/file_system.dart'
;
import
'base/file_system.dart'
;
import
'ios/xcodeproj.dart'
;
import
'plugins.dart'
;
/// Represents the contents of a Flutter project at the specified [directory].
/// Represents the contents of a Flutter project at the specified [directory].
class
FlutterProject
{
class
FlutterProject
{
...
@@ -43,8 +47,25 @@ class FlutterProject {
...
@@ -43,8 +47,25 @@ class FlutterProject {
/// The Android sub project of this project.
/// The Android sub project of this project.
AndroidProject
get
android
=>
new
AndroidProject
(
directory
.
childDirectory
(
'android'
));
AndroidProject
get
android
=>
new
AndroidProject
(
directory
.
childDirectory
(
'android'
));
/// Returns true if this project is a plugin project.
bool
get
isPluginProject
=>
directory
.
childDirectory
(
'example'
).
childFile
(
'pubspec.yaml'
).
existsSync
();
/// The example sub project of this (plugin) project.
/// The example sub project of this (plugin) project.
FlutterProject
get
example
=>
new
FlutterProject
(
directory
.
childDirectory
(
'example'
));
FlutterProject
get
example
=>
new
FlutterProject
(
directory
.
childDirectory
(
'example'
));
/// Generates project files necessary to make Gradle builds work on Android
/// and CocoaPods+Xcode work on iOS.
void
ensureReadyForPlatformSpecificTooling
()
{
if
(!
directory
.
existsSync
())
{
return
;
}
if
(
isPluginProject
)
{
example
.
ensureReadyForPlatformSpecificTooling
();
}
else
{
injectPlugins
(
directory:
directory
.
path
);
generateXcodeProperties
(
directory
.
path
);
}
}
}
}
/// Represents the contents of the ios/ folder of a Flutter project.
/// Represents the contents of the ios/ folder of a Flutter project.
...
...
packages/flutter_tools/lib/src/runner/flutter_command.dart
View file @
20004357
...
@@ -21,6 +21,7 @@ import '../device.dart';
...
@@ -21,6 +21,7 @@ import '../device.dart';
import
'../doctor.dart'
;
import
'../doctor.dart'
;
import
'../flx.dart'
as
flx
;
import
'../flx.dart'
as
flx
;
import
'../globals.dart'
;
import
'../globals.dart'
;
import
'../project.dart'
;
import
'../usage.dart'
;
import
'../usage.dart'
;
import
'flutter_command_runner.dart'
;
import
'flutter_command_runner.dart'
;
...
@@ -272,8 +273,10 @@ abstract class FlutterCommand extends Command<Null> {
...
@@ -272,8 +273,10 @@ abstract class FlutterCommand extends Command<Null> {
if
(
shouldUpdateCache
)
if
(
shouldUpdateCache
)
await
cache
.
updateAll
();
await
cache
.
updateAll
();
if
(
shouldRunPub
)
if
(
shouldRunPub
)
{
await
pubGet
(
context:
PubContext
.
getVerifyContext
(
name
));
await
pubGet
(
context:
PubContext
.
getVerifyContext
(
name
));
new
FlutterProject
(
fs
.
currentDirectory
).
ensureReadyForPlatformSpecificTooling
();
}
setupApplicationPackages
();
setupApplicationPackages
();
...
...
packages/flutter_tools/test/commands/packages_test.dart
View file @
20004357
...
@@ -29,9 +29,19 @@ void main() {
...
@@ -29,9 +29,19 @@ void main() {
temp
.
deleteSync
(
recursive:
true
);
temp
.
deleteSync
(
recursive:
true
);
});
});
Future
<
String
>
runCommand
(
String
verb
,
{
List
<
String
>
args
}
)
async
{
Future
<
String
>
createProjectWithPlugin
(
String
plugin
)
async
{
final
String
projectPath
=
await
createProject
(
temp
);
final
String
projectPath
=
await
createProject
(
temp
);
final
File
pubspec
=
fs
.
file
(
fs
.
path
.
join
(
projectPath
,
'pubspec.yaml'
));
String
content
=
await
pubspec
.
readAsString
();
content
=
content
.
replaceFirst
(
'
\n
dependencies:
\n
'
,
'
\n
dependencies:
\n
$plugin
:
\n
'
,
);
await
pubspec
.
writeAsString
(
content
,
flush:
true
);
return
projectPath
;
}
Future
<
Null
>
runCommandIn
(
String
projectPath
,
String
verb
,
{
List
<
String
>
args
})
async
{
final
PackagesCommand
command
=
new
PackagesCommand
();
final
PackagesCommand
command
=
new
PackagesCommand
();
final
CommandRunner
<
Null
>
runner
=
createTestCommandRunner
(
command
);
final
CommandRunner
<
Null
>
runner
=
createTestCommandRunner
(
command
);
...
@@ -41,31 +51,148 @@ void main() {
...
@@ -41,31 +51,148 @@ void main() {
commandArgs
.
add
(
projectPath
);
commandArgs
.
add
(
projectPath
);
await
runner
.
run
(
commandArgs
);
await
runner
.
run
(
commandArgs
);
return
projectPath
;
}
}
void
expectExists
(
String
projectPath
,
String
relPath
)
{
void
expectExists
(
String
projectPath
,
String
relPath
)
{
expect
(
fs
.
isFileSync
(
fs
.
path
.
join
(
projectPath
,
relPath
)),
true
);
expect
(
fs
.
isFileSync
(
fs
.
path
.
join
(
projectPath
,
relPath
)),
true
,
reason:
'
$projectPath
/
$relPath
should exist, but does not'
,
);
}
void
expectContains
(
String
projectPath
,
String
relPath
,
String
substring
)
{
expectExists
(
projectPath
,
relPath
);
expect
(
fs
.
file
(
fs
.
path
.
join
(
projectPath
,
relPath
)).
readAsStringSync
(),
contains
(
substring
),
reason:
'
$projectPath
/
$relPath
has unexpected content'
);
}
void
expectNotExists
(
String
projectPath
,
String
relPath
)
{
expect
(
fs
.
isFileSync
(
fs
.
path
.
join
(
projectPath
,
relPath
)),
false
,
reason:
'
$projectPath
/
$relPath
should not exist, but does'
,
);
}
void
expectNotContains
(
String
projectPath
,
String
relPath
,
String
substring
)
{
expectExists
(
projectPath
,
relPath
);
expect
(
fs
.
file
(
fs
.
path
.
join
(
projectPath
,
relPath
)).
readAsStringSync
(),
isNot
(
contains
(
substring
)),
reason:
'
$projectPath
/
$relPath
has unexpected content'
,
);
}
const
List
<
String
>
pubOutput
=
const
<
String
>[
'.packages'
,
'pubspec.lock'
,
];
const
List
<
String
>
pluginRegistrants
=
const
<
String
>[
'ios/Runner/GeneratedPluginRegistrant.h'
,
'ios/Runner/GeneratedPluginRegistrant.m'
,
'android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java'
,
];
const
List
<
String
>
pluginWitnesses
=
const
<
String
>[
'.flutter-plugins'
,
'ios/Podfile'
,
];
const
Map
<
String
,
String
>
pluginContentWitnesses
=
const
<
String
,
String
>{
'ios/Flutter/Debug.xcconfig'
:
'#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"'
,
'ios/Flutter/Release.xcconfig'
:
'#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"'
,
};
void
expectDependenciesResolved
(
String
projectPath
)
{
for
(
String
output
in
pubOutput
)
{
expectExists
(
projectPath
,
output
);
}
}
void
expectZeroPluginsInjected
(
String
projectPath
)
{
for
(
final
String
registrant
in
pluginRegistrants
)
{
expectExists
(
projectPath
,
registrant
);
}
for
(
final
String
witness
in
pluginWitnesses
)
{
expectNotExists
(
projectPath
,
witness
);
}
pluginContentWitnesses
.
forEach
((
String
witness
,
String
content
)
{
expectNotContains
(
projectPath
,
witness
,
content
);
});
}
void
expectPluginInjected
(
String
projectPath
)
{
for
(
final
String
registrant
in
pluginRegistrants
)
{
expectExists
(
projectPath
,
registrant
);
}
for
(
final
String
witness
in
pluginWitnesses
)
{
expectExists
(
projectPath
,
witness
);
}
pluginContentWitnesses
.
forEach
((
String
witness
,
String
content
)
{
expectContains
(
projectPath
,
witness
,
content
);
});
}
void
removeGeneratedFiles
(
String
projectPath
)
{
final
Iterable
<
String
>
allFiles
=
<
List
<
String
>>[
pubOutput
,
pluginRegistrants
,
pluginWitnesses
,
].
expand
((
List
<
String
>
list
)
=>
list
);
for
(
String
path
in
allFiles
)
{
final
File
file
=
fs
.
file
(
fs
.
path
.
join
(
projectPath
,
path
));
if
(
file
.
existsSync
())
file
.
deleteSync
();
}
}
}
// Verify that we create a project that is well-formed.
testUsingContext
(
'get fetches packages'
,
()
async
{
testUsingContext
(
'get'
,
()
async
{
final
String
projectPath
=
await
createProject
(
temp
);
final
String
projectPath
=
await
runCommand
(
'get'
);
expectExists
(
projectPath
,
'lib/main.dart'
);
removeGeneratedFiles
(
projectPath
);
expectExists
(
projectPath
,
'.packages'
);
await
runCommandIn
(
projectPath
,
'get'
);
expectDependenciesResolved
(
projectPath
);
expectZeroPluginsInjected
(
projectPath
);
},
timeout:
allowForRemotePubInvocation
);
},
timeout:
allowForRemotePubInvocation
);
testUsingContext
(
'get --offline'
,
()
async
{
testUsingContext
(
'get --offline fetches packages'
,
()
async
{
final
String
projectPath
=
await
runCommand
(
'get'
,
args:
<
String
>[
'--offline'
]);
final
String
projectPath
=
await
createProject
(
temp
);
expectExists
(
projectPath
,
'lib/main.dart'
);
expectExists
(
projectPath
,
'.packages'
);
removeGeneratedFiles
(
projectPath
);
});
await
runCommandIn
(
projectPath
,
'get'
,
args:
<
String
>[
'--offline'
]);
expectDependenciesResolved
(
projectPath
);
expectZeroPluginsInjected
(
projectPath
);
},
timeout:
allowForCreateFlutterProject
);
testUsingContext
(
'upgrade fetches packages'
,
()
async
{
final
String
projectPath
=
await
createProject
(
temp
);
removeGeneratedFiles
(
projectPath
);
await
runCommandIn
(
projectPath
,
'upgrade'
);
expectDependenciesResolved
(
projectPath
);
expectZeroPluginsInjected
(
projectPath
);
},
timeout:
allowForRemotePubInvocation
);
testUsingContext
(
'get fetches packages and injects plugin'
,
()
async
{
final
String
projectPath
=
await
createProjectWithPlugin
(
'path_provider'
);
removeGeneratedFiles
(
projectPath
);
await
runCommandIn
(
projectPath
,
'get'
);
testUsingContext
(
'upgrade'
,
()
async
{
expectDependenciesResolved
(
projectPath
);
final
String
projectPath
=
await
runCommand
(
'upgrade'
);
expectPluginInjected
(
projectPath
);
expectExists
(
projectPath
,
'lib/main.dart'
);
expectExists
(
projectPath
,
'.packages'
);
},
timeout:
allowForRemotePubInvocation
);
},
timeout:
allowForRemotePubInvocation
);
});
});
...
...
packages/flutter_tools/test/ios/cocoapods_test.dart
View file @
20004357
This diff is collapsed.
Click to expand it.
packages/flutter_tools/test/project_test.dart
View file @
20004357
...
@@ -17,6 +17,29 @@ void main() {
...
@@ -17,6 +17,29 @@ void main() {
final
Directory
directory
=
fs
.
directory
(
'myproject'
);
final
Directory
directory
=
fs
.
directory
(
'myproject'
);
expect
(
new
FlutterProject
(
directory
).
directory
,
directory
);
expect
(
new
FlutterProject
(
directory
).
directory
,
directory
);
});
});
group
(
'ensure ready for platform-specific tooling'
,
()
{
testInMemory
(
'does nothing, if project is not created'
,
()
async
{
final
FlutterProject
project
=
someProject
();
project
.
ensureReadyForPlatformSpecificTooling
();
expect
(
project
.
directory
.
existsSync
(),
isFalse
);
});
testInMemory
(
'injects plugins'
,
()
async
{
final
FlutterProject
project
=
aProjectWithIos
();
project
.
ensureReadyForPlatformSpecificTooling
();
expect
(
project
.
ios
.
directory
.
childFile
(
'Runner/GeneratedPluginRegistrant.h'
).
existsSync
(),
isTrue
);
});
testInMemory
(
'generates Xcode configuration'
,
()
async
{
final
FlutterProject
project
=
aProjectWithIos
();
project
.
ensureReadyForPlatformSpecificTooling
();
expect
(
project
.
ios
.
directory
.
childFile
(
'Flutter/Generated.xcconfig'
).
existsSync
(),
isTrue
);
});
testInMemory
(
'generates files in plugin example project'
,
()
async
{
final
FlutterProject
project
=
aPluginProject
();
project
.
ensureReadyForPlatformSpecificTooling
();
expect
(
project
.
example
.
ios
.
directory
.
childFile
(
'Runner/GeneratedPluginRegistrant.h'
).
existsSync
(),
isTrue
);
expect
(
project
.
example
.
ios
.
directory
.
childFile
(
'Flutter/Generated.xcconfig'
).
existsSync
(),
isTrue
);
});
});
group
(
'organization names set'
,
()
{
group
(
'organization names set'
,
()
{
testInMemory
(
'is empty, if project not created'
,
()
async
{
testInMemory
(
'is empty, if project not created'
,
()
async
{
final
FlutterProject
project
=
someProject
();
final
FlutterProject
project
=
someProject
();
...
@@ -71,8 +94,23 @@ void main() {
...
@@ -71,8 +94,23 @@ void main() {
});
});
}
}
FlutterProject
someProject
(
)
=>
FlutterProject
someProject
(
)
=>
new
FlutterProject
(
fs
.
directory
(
'some_project'
));
new
FlutterProject
(
fs
.
directory
(
'some_project'
));
FlutterProject
aProjectWithIos
(
)
{
final
Directory
directory
=
fs
.
directory
(
'ios_project'
);
directory
.
childFile
(
'pubspec.yaml'
).
createSync
(
recursive:
true
);
directory
.
childFile
(
'.packages'
).
createSync
(
recursive:
true
);
directory
.
childDirectory
(
'ios'
).
createSync
(
recursive:
true
);
return
new
FlutterProject
(
directory
);
}
FlutterProject
aPluginProject
(
)
{
final
Directory
directory
=
fs
.
directory
(
'plugin_project/example'
);
directory
.
childFile
(
'pubspec.yaml'
).
createSync
(
recursive:
true
);
directory
.
childFile
(
'.packages'
).
createSync
(
recursive:
true
);
directory
.
childDirectory
(
'ios'
).
createSync
(
recursive:
true
);
return
new
FlutterProject
(
directory
.
parent
);
}
void
testInMemory
(
String
description
,
Future
<
Null
>
testMethod
())
{
void
testInMemory
(
String
description
,
Future
<
Null
>
testMethod
())
{
testUsingContext
(
testUsingContext
(
...
@@ -84,6 +122,13 @@ void testInMemory(String description, Future<Null> testMethod()) {
...
@@ -84,6 +122,13 @@ void testInMemory(String description, Future<Null> testMethod()) {
);
);
}
}
void
addPubPackages
(
Directory
directory
)
{
directory
.
childFile
(
'pubspec.yaml'
)
..
createSync
(
recursive:
true
);
directory
.
childFile
(
'.packages'
)
..
createSync
(
recursive:
true
);
}
void
addIosWithBundleId
(
Directory
directory
,
String
id
)
{
void
addIosWithBundleId
(
Directory
directory
,
String
id
)
{
directory
directory
.
childDirectory
(
'ios'
)
.
childDirectory
(
'ios'
)
...
...
packages/flutter_tools/test/src/context.dart
View file @
20004357
...
@@ -19,6 +19,7 @@ import 'package:flutter_tools/src/device.dart';
...
@@ -19,6 +19,7 @@ import 'package:flutter_tools/src/device.dart';
import
'package:flutter_tools/src/doctor.dart'
;
import
'package:flutter_tools/src/doctor.dart'
;
import
'package:flutter_tools/src/ios/mac.dart'
;
import
'package:flutter_tools/src/ios/mac.dart'
;
import
'package:flutter_tools/src/ios/simulators.dart'
;
import
'package:flutter_tools/src/ios/simulators.dart'
;
import
'package:flutter_tools/src/ios/xcodeproj.dart'
;
import
'package:flutter_tools/src/run_hot.dart'
;
import
'package:flutter_tools/src/run_hot.dart'
;
import
'package:flutter_tools/src/usage.dart'
;
import
'package:flutter_tools/src/usage.dart'
;
import
'package:flutter_tools/src/version.dart'
;
import
'package:flutter_tools/src/version.dart'
;
...
@@ -50,6 +51,7 @@ void _defaultInitializeContext(AppContext testContext) {
...
@@ -50,6 +51,7 @@ void _defaultInitializeContext(AppContext testContext) {
..
putIfAbsent
(
OperatingSystemUtils
,
()
=>
new
MockOperatingSystemUtils
())
..
putIfAbsent
(
OperatingSystemUtils
,
()
=>
new
MockOperatingSystemUtils
())
..
putIfAbsent
(
PortScanner
,
()
=>
new
MockPortScanner
())
..
putIfAbsent
(
PortScanner
,
()
=>
new
MockPortScanner
())
..
putIfAbsent
(
Xcode
,
()
=>
new
Xcode
())
..
putIfAbsent
(
Xcode
,
()
=>
new
Xcode
())
..
putIfAbsent
(
XcodeProjectInterpreter
,
()
=>
new
MockXcodeProjectInterpreter
())
..
putIfAbsent
(
IOSSimulatorUtils
,
()
{
..
putIfAbsent
(
IOSSimulatorUtils
,
()
{
final
MockIOSSimulatorUtils
mock
=
new
MockIOSSimulatorUtils
();
final
MockIOSSimulatorUtils
mock
=
new
MockIOSSimulatorUtils
();
when
(
mock
.
getAttachedDevices
()).
thenReturn
(<
IOSSimulator
>[]);
when
(
mock
.
getAttachedDevices
()).
thenReturn
(<
IOSSimulator
>[]);
...
@@ -262,6 +264,25 @@ class MockUsage implements Usage {
...
@@ -262,6 +264,25 @@ class MockUsage implements Usage {
void
printWelcome
()
{
}
void
printWelcome
()
{
}
}
}
class
MockXcodeProjectInterpreter
implements
XcodeProjectInterpreter
{
@override
bool
get
canInterpretXcodeProjects
=>
true
;
@override
Map
<
String
,
String
>
getBuildSettings
(
String
projectPath
,
String
target
)
{
return
<
String
,
String
>{};
}
@override
XcodeProjectInfo
getInfo
(
String
projectPath
)
{
return
new
XcodeProjectInfo
(
<
String
>[
'Runner'
],
<
String
>[
'Debug'
,
'Release'
],
<
String
>[
'Runner'
],
);
}
}
class
MockFlutterVersion
extends
Mock
implements
FlutterVersion
{}
class
MockFlutterVersion
extends
Mock
implements
FlutterVersion
{}
class
MockClock
extends
Mock
implements
Clock
{}
class
MockClock
extends
Mock
implements
Clock
{}
...
...
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