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
a6c3ffe1
Commit
a6c3ffe1
authored
Jan 02, 2020
by
Jenn Magder
Committed by
Flutter GitHub Bot
Jan 02, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Allow Xcode project Info.plist to be moved (#47993)
parent
c3406914
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
70 additions
and
26 deletions
+70
-26
project.dart
packages/flutter_tools/lib/src/project.dart
+41
-19
project_test.dart
packages/flutter_tools/test/general.shard/project_test.dart
+29
-7
No files found.
packages/flutter_tools/lib/src/project.dart
View file @
a6c3ffe1
...
...
@@ -354,8 +354,8 @@ class IosProject implements XcodeBasedProject {
@override
File get podManifestLock => hostAppRoot.childDirectory('
Pods
').childFile('
Manifest
.
lock
');
/// The
'
Info
.
plist
' file of the host app
.
File get
h
ostInfoPlist => hostAppRoot.childDirectory(_hostAppBundleName).childFile('
Info
.
plist
');
/// The
default '
Info
.
plist
' file of the host app. The developer can change this location in Xcode
.
File get
defaultH
ostInfoPlist => hostAppRoot.childDirectory(_hostAppBundleName).childFile('
Info
.
plist
');
@override
Directory get symlinks => _flutterLibRoot.childDirectory('
.
symlinks
');
...
...
@@ -384,27 +384,43 @@ class IosProject implements XcodeBasedProject {
/// iOS tooling needed to read it is not installed.
Future<String> get productBundleIdentifier async {
String fromPlist;
try {
fromPlist = PlistParser.instance.getValueFromFile(
hostInfoPlist.path,
PlistParser.kCFBundleIdentifierKey,
);
} on FileNotFoundException {
// iOS tooling not found; likely not running OSX; let [fromPlist] be null
final File defaultInfoPlist = defaultHostInfoPlist;
// Users can change the location of the Info.plist.
// Try parsing the default, first.
if (defaultInfoPlist.existsSync()) {
try {
fromPlist = PlistParser.instance.getValueFromFile(
defaultHostInfoPlist.path,
PlistParser.kCFBundleIdentifierKey,
);
} on FileNotFoundException {
// iOS tooling not found; likely not running OSX; let [fromPlist] be null
}
if (fromPlist != null && !fromPlist.contains('
\$
')) {
// Info.plist has no build variables in product bundle ID.
return fromPlist;
}
}
if (fromPlist != null && !fromPlist.contains('
\$
')) {
// Info.plist has no build variables in product bundle ID.
return fromPlist;
final Map<String, String> allBuildSettings = await buildSettings;
if (allBuildSettings != null) {
if (fromPlist != null) {
// Perform variable substitution using build settings.
return xcode.substituteXcodeVariables(fromPlist, allBuildSettings);
}
return allBuildSettings['
PRODUCT_BUNDLE_IDENTIFIER
'];
}
// On non-macOS platforms, parse the first PRODUCT_BUNDLE_IDENTIFIER from
// the project file. This can return the wrong bundle identifier if additional
// bundles have been added to the project and are found first, like frameworks
// or companion watchOS projects. However, on non-macOS platforms this is
// only used for display purposes and to regenerate organization names, so
// best-effort is probably fine.
final String fromPbxproj = _firstMatchInFile(xcodeProjectInfoFile, _productBundleIdPattern)?.group(2);
if (fromPbxproj != null && (fromPlist == null || fromPlist == _productBundleIdVariable)) {
// Common case. Avoids parsing build settings.
return fromPbxproj;
}
if (fromPlist != null && xcode.xcodeProjectInterpreter.isInstalled) {
// General case: perform variable substitution using build settings.
return xcode.substituteXcodeVariables(fromPlist, await buildSettings);
}
return null;
}
...
...
@@ -415,11 +431,17 @@ class IosProject implements XcodeBasedProject {
if (!xcode.xcodeProjectInterpreter.isInstalled) {
return null;
}
_buildSettings ??= await xcode.xcodeProjectInterpreter.getBuildSettings(
Map<String, String> buildSettings = _buildSettings;
buildSettings ??= await xcode.xcodeProjectInterpreter.getBuildSettings(
xcodeProject.path,
_hostAppBundleName,
);
return _buildSettings;
if (buildSettings != null && buildSettings.isNotEmpty) {
// No timeouts, flakes, or errors.
_buildSettings = buildSettings;
return buildSettings;
}
return null;
}
Map<String, String> _buildSettings;
...
...
packages/flutter_tools/test/general.shard/project_test.dart
View file @
a6c3ffe1
...
...
@@ -348,32 +348,54 @@ apply plugin: 'kotlin-android'
});
}
testWithMocks
(
'null, if no
pbxproj
or plist entries'
,
()
async
{
testWithMocks
(
'null, if no
build settings
or plist entries'
,
()
async
{
final
FlutterProject
project
=
await
someProject
();
expect
(
await
project
.
ios
.
productBundleIdentifier
,
isNull
);
});
testWithMocks
(
'from pbxproj file, if no plist'
,
()
async
{
testWithMocks
(
'from build settings, if no plist'
,
()
async
{
final
FlutterProject
project
=
await
someProject
();
when
(
mockXcodeProjectInterpreter
.
getBuildSettings
(
any
,
any
)).
thenAnswer
(
(
_
)
{
return
Future
<
Map
<
String
,
String
>>.
value
(<
String
,
String
>{
'PRODUCT_BUNDLE_IDENTIFIER'
:
'io.flutter.someProject'
,
});
}
);
expect
(
await
project
.
ios
.
productBundleIdentifier
,
'io.flutter.someProject'
);
});
testWithMocks
(
'from project file, if no plist or build settings'
,
()
async
{
final
FlutterProject
project
=
await
someProject
();
addIosProjectFile
(
project
.
directory
,
projectFileContent:
()
{
return
projectFileWithBundleId
(
'io.flutter.someProject'
);
});
expect
(
await
project
.
ios
.
productBundleIdentifier
,
'io.flutter.someProject'
);
});
testWithMocks
(
'from plist, if no variables'
,
()
async
{
final
FlutterProject
project
=
await
someProject
();
project
.
ios
.
defaultHostInfoPlist
.
createSync
(
recursive:
true
);
when
(
mockPlistUtils
.
getValueFromFile
(
any
,
any
)).
thenReturn
(
'io.flutter.someProject'
);
expect
(
await
project
.
ios
.
productBundleIdentifier
,
'io.flutter.someProject'
);
});
testWithMocks
(
'from pbxproj and plist, if default variable'
,
()
async
{
testWithMocks
(
'from build settings and plist, if default variable'
,
()
async
{
final
FlutterProject
project
=
await
someProject
();
addIosProjectFile
(
project
.
directory
,
projectFileContent:
()
{
return
projectFileWithBundleId
(
'io.flutter.someProject'
);
});
when
(
mockXcodeProjectInterpreter
.
getBuildSettings
(
any
,
any
)).
thenAnswer
(
(
_
)
{
return
Future
<
Map
<
String
,
String
>>.
value
(<
String
,
String
>{
'PRODUCT_BUNDLE_IDENTIFIER'
:
'io.flutter.someProject'
,
});
}
);
when
(
mockPlistUtils
.
getValueFromFile
(
any
,
any
)).
thenReturn
(
'
\$
(PRODUCT_BUNDLE_IDENTIFIER)'
);
expect
(
await
project
.
ios
.
productBundleIdentifier
,
'io.flutter.someProject'
);
});
testWithMocks
(
'from pbxproj and plist, by substitution'
,
()
async
{
testWithMocks
(
'from build settings and plist, by substitution'
,
()
async
{
final
FlutterProject
project
=
await
someProject
();
project
.
ios
.
defaultHostInfoPlist
.
createSync
(
recursive:
true
);
when
(
mockXcodeProjectInterpreter
.
getBuildSettings
(
any
,
any
)).
thenAnswer
(
(
_
)
{
return
Future
<
Map
<
String
,
String
>>.
value
(<
String
,
String
>{
...
...
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