ann-flavor-cocoapods 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 203077b214e8b6dcbf87c8792ea6df6055d34b4b6ea36af00c1c28a94207aab9
4
- data.tar.gz: fcdbfba3ba5e54184fb3d05ace52259c10476947259d550cc4b134009d83e560
3
+ metadata.gz: 0b4a6fb9baad3561d14ffa73da2e419ebbaa0664edf12924875484973e5e5f21
4
+ data.tar.gz: a88e357ca0d0fdf957a3640229d7f98a852a058d3ea442f5333d8c6f02c1393c
5
5
  SHA512:
6
- metadata.gz: 1968396623737c7d68439d68cb2fb4d8b8ac6d1da7bba9c32722bc9a0408e3d73fc2b6a4087fbff63231d0d8bd1403949d62e46bf2382a7d9361bd33a7d9fbd1
7
- data.tar.gz: 5f6f3d65b87f5f8c41d52f6201c622fb379da14d81cf7d6338edf5a76bde7168213c2722f067495d0e8571f0ce35415f67e37538f47f4b5d266e297887672cee
6
+ metadata.gz: a156d31659cb317a3e114adda24d44048e0a8c28bf781f23b50f3821a8e0eb84e19aabf2ac57beec9da4d3e7cc192ab3182acf8a4f95c5177eb8ff3445298df0
7
+ data.tar.gz: 7c4b22bba78a36cb28338c38152e2126ea9b9d92007e633d1b6684bb40b2db1a30ca5f7ac74ad0855e31a3ae65bcca98210d3e6d8c2f98cac7664dbded19ee18
data/CHANGELOG.md CHANGED
@@ -1,5 +1,34 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.0
4
+
5
+ ### Added
6
+ - **New `[ann-flavor] Merge Entitlements` build phase composes the final
7
+ `.entitlements` file Xcode signs with at build time**, not sync time: copies
8
+ `ios/Runner/Runner.entitlements` (the generic/base layer, developer-owned —
9
+ if present; unlike `Runner/Info.plist`, most projects have no stock
10
+ entitlements file at all, so a missing base file here starts from an empty
11
+ plist rather than failing), then merges in every key from the current
12
+ flavor's `ann/Entitlements/<flavor>.entitlements` delta (see
13
+ `ann_flutter_flavor` 1.3.0 — that file now holds only the flavor's
14
+ `entitlements:` cascade, not a full copy of `Runner.entitlements`), with the
15
+ flavor's value winning on any key both define. Uses `PlistBuddy`, mirroring
16
+ `[ann-flavor] Merge Info.plist` (0.3.0) exactly — entitlements files and
17
+ Info.plist are both plain Apple XML property lists, so the same
18
+ type-preserving merge logic applies unchanged. Injected only when at least
19
+ one flavor actually needs entitlements (its own cascade, or a stock
20
+ `Runner.entitlements`); removed automatically once nothing needs it anymore.
21
+
22
+ ### Changed
23
+ - **`CODE_SIGN_ENTITLEMENTS` now points at
24
+ `$(DERIVED_FILE_DIR)/Entitlements-merged.entitlements`** (the Merge
25
+ Entitlements phase's output above) instead of directly at
26
+ `ann/Entitlements/<flavor>.entitlements`, whenever anything needs signing —
27
+ extends the same `INFOPLIST_FILE` rewiring from 0.3.0 to entitlements. See
28
+ [plan 039](../../docs/03-planning/features/039-entitlements-build-time-merge.md)
29
+ and the [Entitlements](../../docs/04-userguide/ios/overview.md#entitlements)
30
+ section of the iOS userguide for the full design.
31
+
3
32
  ## 0.3.0
4
33
 
5
34
  ### Added
@@ -155,6 +155,7 @@ module AnnFlavorCocoapods
155
155
  user_project.native_targets.each do |target|
156
156
  if target.symbol_type == :application
157
157
  find_or_create_icon_catalog(target, user_project)
158
+ target_has_entitlements = false
158
159
 
159
160
  ios.flavors.each_key do |flavor_key|
160
161
  flavor = ios.flavors[flavor_key]
@@ -178,16 +179,25 @@ module AnnFlavorCocoapods
178
179
 
179
180
  assert_icon_generated!(user_project, flavor_key, icon_name)
180
181
 
181
- # Unlike the icon catalog and Info.plist, entitlements: is
182
- # opt-in -- ios_generator.dart's _generateEntitlements skips
183
- # creating ios/ann/Entitlements/ entirely when no annspec.yaml
184
- # entitlements: block and no stock Runner.entitlements exist
185
- # anywhere. Only set CODE_SIGN_ENTITLEMENTS when the file
186
- # actually exists on disk; leaving it unset is correct (no
187
- # entitlements to sign with), not an error condition.
188
- entitlements_path = "ann/Entitlements/#{flavor_key}.entitlements"
189
- entitlements_file = File.join(user_project.project_dir.to_s, 'ann', 'Entitlements', "#{flavor_key}.entitlements")
190
- entitlements_path = nil unless File.exist?(entitlements_file)
182
+ # Extended opt-in check (plan 039): CODE_SIGN_ENTITLEMENTS is
183
+ # wired only when there is something to sign with at all --
184
+ # either this flavor's entitlements: cascade, or a stock
185
+ # Runner.entitlements to fall back to. Mirrors
186
+ # ios_generator.dart's _anyFlavorHasEntitlements OR-condition,
187
+ # but evaluated here instead of at sync time -- the actual
188
+ # merge now happens at this (pod install / build time) layer,
189
+ # not sync time, so this is where "is there anything to sign
190
+ # with" needs to be answered from. The Merge Entitlements
191
+ # phase itself is injected once per target below (like Merge
192
+ # Info.plist), not per flavor/build-type here -- it derives
193
+ # $FLAVOR_NAME from $CONFIGURATION at build time, so one
194
+ # shared phase correctly serves every flavor, whether or not
195
+ # that specific flavor has its own entitlements: cascade.
196
+ flavor_entitlements_file = File.join(user_project.project_dir.to_s, 'ann', 'Entitlements', "#{flavor_key}.entitlements")
197
+ stock_entitlements_file = File.join(user_project.project_dir.to_s, 'Runner', 'Runner.entitlements')
198
+ has_entitlements = File.exist?(flavor_entitlements_file) || File.exist?(stock_entitlements_file)
199
+ entitlements_path = has_entitlements ? '$(DERIVED_FILE_DIR)/Entitlements-merged.entitlements' : nil
200
+ target_has_entitlements ||= has_entitlements
191
201
 
192
202
  configure_build_configuration(
193
203
  target, user_project, xcode_config, xcconfig_path,
@@ -203,6 +213,17 @@ module AnnFlavorCocoapods
203
213
  end
204
214
 
205
215
  inject_merge_info_plist_phase(target)
216
+
217
+ # Unlike Merge Info.plist (unconditional -- every flavor always
218
+ # has an Info.plist), Merge Entitlements is only injected when at
219
+ # least one flavor actually needs it (its own cascade, or a
220
+ # stock Runner.entitlements) -- entitlements are opt-in overall,
221
+ # and a phase with nothing to sign would just be dead weight.
222
+ if target_has_entitlements
223
+ inject_merge_entitlements_phase(target)
224
+ else
225
+ remove_merge_entitlements_phase(target)
226
+ end
206
227
  end
207
228
 
208
229
  # Fixes a real pod-install failure: PBXNativeTarget#resolved_build_setting
@@ -894,5 +915,110 @@ module AnnFlavorCocoapods
894
915
 
895
916
  target.build_phases.unshift(phase) unless existing
896
917
  end
918
+
919
+ # Composes the final .entitlements file Xcode actually signs with, from
920
+ # two layers -- Runner.entitlements (generic/base, developer-owned, may
921
+ # not exist at all) and the flavor-specific ann/Entitlements/<flavor>
922
+ # .entitlements delta (annspec.yaml's entitlements: cascade, opt-in --
923
+ # may also not exist) -- with the flavor layer winning on any key
924
+ # collision. Plan 039: mirrors inject_merge_info_plist_phase (plan 038)
925
+ # exactly -- same PlistBuddy-based merge (entitlements files and Info.plist
926
+ # are both plain Apple XML property lists; PlistBuddy has no notion of
927
+ # file "kind" beyond that), same find-or-update idempotency, same
928
+ # collision-warning behavior. The one real difference: unlike
929
+ # Runner/Info.plist (every Xcode project has one), most projects have no
930
+ # Runner.entitlements at all -- a missing base file here is a normal,
931
+ # non-fatal case (starts from an empty plist dict), not the fatal error
932
+ # Merge Info.plist treats a missing Runner/Info.plist as.
933
+ def self.inject_merge_entitlements_phase(target)
934
+ script = <<~SHELL
935
+ # Injected by ann-flavor-cocoapods: compose the final .entitlements file
936
+ # from two layers -- Runner.entitlements (generic/base, may not exist)
937
+ # and the flavor-specific ann/Entitlements/<flavor>.entitlements delta
938
+ # (annspec.yaml's entitlements: cascade, may also not exist) -- with the
939
+ # flavor layer winning on any key collision. Mirrors [ann-flavor] Merge
940
+ # Info.plist (plan 038) -- see plan 039 for why entitlements needed the
941
+ # same redesign.
942
+ PLISTBUDDY=/usr/libexec/PlistBuddy
943
+ BASE="${SRCROOT}/Runner/Runner.entitlements"
944
+ FLAVOR_NAME="${CONFIGURATION#*-}"
945
+ FLAVOR_FILE="${SRCROOT}/ann/Entitlements/${FLAVOR_NAME}.entitlements"
946
+ OUT="${DERIVED_FILE_DIR}/Entitlements-merged.entitlements"
947
+
948
+ if [ -f "$BASE" ]; then
949
+ cp "$BASE" "$OUT"
950
+ else
951
+ # No stock Runner.entitlements -- start from an empty plist dict
952
+ # rather than failing; the flavor delta (if any) is still applied
953
+ # below.
954
+ cat > "$OUT" <<PLISTEOF
955
+ <?xml version="1.0" encoding="UTF-8"?>
956
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
957
+ <plist version="1.0">
958
+ <dict/>
959
+ </plist>
960
+ PLISTEOF
961
+ fi
962
+
963
+ if [ ! -f "$FLAVOR_FILE" ]; then
964
+ echo "[ann-flavor] Entitlements: no flavor delta found for '$FLAVOR_NAME' at $FLAVOR_FILE -- using Runner.entitlements unmerged."
965
+ exit 0
966
+ fi
967
+
968
+ FLAVOR_KEYS=$("$PLISTBUDDY" -c "Print" "$FLAVOR_FILE" | grep -E '^ [A-Za-z]' | sed 's/ =.*//' | sed 's/^ *//')
969
+
970
+ for KEY in $FLAVOR_KEYS; do
971
+ BASE_VALUE=$("$PLISTBUDDY" -c "Print :$KEY" "$OUT" 2>/dev/null)
972
+ BASE_HAD_KEY=$?
973
+ FLAVOR_VALUE=$("$PLISTBUDDY" -c "Print :$KEY" "$FLAVOR_FILE")
974
+
975
+ if [ "$BASE_HAD_KEY" -eq 0 ] && [ "$BASE_VALUE" != "$FLAVOR_VALUE" ]; then
976
+ echo "[ann-flavor] Entitlements: '$KEY' overridden by flavor value ($FLAVOR_NAME) -- Runner.entitlements' value ignored for this build."
977
+ fi
978
+
979
+ VALUE_XML=$("$PLISTBUDDY" -x -c "Print :$KEY" "$FLAVOR_FILE" | sed -n '/<plist version/,/<\\/plist>/p' | sed '1d;$d')
980
+
981
+ "$PLISTBUDDY" -c "Delete :$KEY" "$OUT" >/dev/null 2>&1
982
+ FRAGMENT=$(mktemp /tmp/ann-flavor-entitlements-fragment.XXXXXX)
983
+ cat > "$FRAGMENT" <<XMLEOF
984
+ <?xml version="1.0" encoding="UTF-8"?>
985
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
986
+ <plist version="1.0">
987
+ <dict>
988
+ <key>$KEY</key>
989
+ $VALUE_XML
990
+ </dict>
991
+ </plist>
992
+ XMLEOF
993
+ "$PLISTBUDDY" -c "Merge \\"$FRAGMENT\\"" "$OUT"
994
+ rm -f "$FRAGMENT"
995
+ done
996
+ SHELL
997
+
998
+ existing = target.build_phases.find { |p| p.respond_to?(:name) && p.name == '[ann-flavor] Merge Entitlements' }
999
+ phase = existing || target.project.new(Xcodeproj::Project::Object::PBXShellScriptBuildPhase)
1000
+ phase.name = '[ann-flavor] Merge Entitlements'
1001
+ phase.shell_path = '/bin/sh'
1002
+ phase.shell_script = script
1003
+ phase.show_env_vars_in_log = '0'
1004
+ phase.output_paths = ['$(DERIVED_FILE_DIR)/Entitlements-merged.entitlements']
1005
+
1006
+ target.build_phases.unshift(phase) unless existing
1007
+ end
1008
+
1009
+ # Removes a previously-injected Merge Entitlements phase when no flavor
1010
+ # needs entitlements anymore (annspec.yaml's entitlements: cascade was
1011
+ # removed, and no stock Runner.entitlements exists either) -- entitlements
1012
+ # are opt-in overall, so a stale phase with nothing to sign would be dead
1013
+ # weight left in project.pbxproj. Uses ObjectList#delete (not plain
1014
+ # Array#reject!/select), same rationale as the stale "[ann-flavor] Remove
1015
+ # Firebase plist" cleanup above -- plain array removal only drops the
1016
+ # phase from target.build_phases, leaving the object itself permanently
1017
+ # orphaned in the project's global objects table.
1018
+ def self.remove_merge_entitlements_phase(target)
1019
+ target.build_phases.select do |p|
1020
+ p.respond_to?(:name) && p.name == '[ann-flavor] Merge Entitlements'
1021
+ end.each { |p| target.build_phases.delete(p) }
1022
+ end
897
1023
  end
898
1024
  end
@@ -1,3 +1,3 @@
1
1
  module AnnFlavorCocoapods
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ann-flavor-cocoapods
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ANN Solutions