fastlane-plugin-plist_surgeon 0.1.2 → 0.3.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: 8a4c842111d0642840d28e07781a460e50c2391ece4591051efea52033861617
4
- data.tar.gz: f6065508091457bee57180beb14181b688771f0f16c6198fa9723226c001b3d2
3
+ metadata.gz: 82054adab900dcfce44257cf14ca8424b4b67d88aa91d199b0a4dc9fea582b54
4
+ data.tar.gz: ac5dc48534e943bbbd5e904ae0d11d391bb11a912cd21126d727e5209dd02606
5
5
  SHA512:
6
- metadata.gz: d94f7e8ac67bfa10333845e5dc07694dd741c1f22f5d8729218d52517a3e4cee8cd9a00a2c7fb106f760db685f350fbc0418958ff8a802ca6397c02b21548f17
7
- data.tar.gz: 3e14d8221bf389634e6352d5be9a257eeeabf8d9aa7b318f901844840eb3f1f60899fc90d7e3e138818c930763b57593e958ac8cdcf223839324c6a38b802d32
6
+ metadata.gz: be055a5d05b355171d0e8957e4d3ecfdeb1d643478acba8eed57576d3c85dad31463a12bae4621a4c6fd1b03af2c0f9428d17fe035c50c868b7e8149170f0a3b
7
+ data.tar.gz: d721daa745390daff18e8a40329c18f2014c05b9f3b4dd7372b86c5309f28dd76e65ff63019222e2df1bd9b6509266ae410eeb4d1497109d8356fd7c166bf297
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # plist_surgeon plugin
2
2
  _The all-in-one tool to edit iOS configuration files from one plugin._
3
3
 
4
- [![fastlane Plugin Badge](https://rawcdn.githack.com/fastlane/fastlane/master/fastlane/assets/plugin-badge.svg)](https://rubygems.org/gems/fastlane-plugin-plist_surgeon)
4
+ [![Gem Version](https://badge.fury.io/rb/fastlane-plugin-plist_surgeon.svg)](https://badge.fury.io/rb/fastlane-plugin-plist_surgeon)
5
5
 
6
6
  ## Getting Started
7
7
 
@@ -71,6 +71,22 @@ privacy_surgeon(
71
71
  | `key` | The key to update (supports dot notation for nested keys) | Yes | |
72
72
  | `value` | The value to set | Yes | |
73
73
 
74
+ ### plist_surgeon_delete
75
+
76
+ Delete a key from a `.plist` file.
77
+
78
+ ```rb
79
+ plist_surgeon_delete(
80
+ path: "./Info.plist",
81
+ key: "CFBundleAlternateIcons"
82
+ )
83
+ ```
84
+
85
+ | Parameter | Description | Required | Default |
86
+ |-----------|-----------------------------------------------------------|----------|---------|
87
+ | `path` | The path to the plist file | Yes | |
88
+ | `key` | The key to delete (supports dot notation for nested keys) | Yes | |
89
+
74
90
  ### Complex Values
75
91
 
76
92
  You can set complex values (Arrays or Hashes) by passing a JSON string. This is especially useful when running from the command line.
@@ -82,6 +98,40 @@ fastlane run plist_surgeon \
82
98
  value:'{"CFBundlePrimaryIcon":{"CFBundleIconFiles":["AppIcon"]}}'
83
99
  ```
84
100
 
101
+ ### Array Search Syntax
102
+
103
+ When dealing with arrays of dictionaries, you can use the `(key=value)` syntax to find the correct element instead of relying on a fixed index.
104
+
105
+ For example, given an `Info.plist` with:
106
+
107
+ ```xml
108
+ <key>service_api_key</key>
109
+ <array>
110
+ <dict>
111
+ <key>test</key>
112
+ <string>other_app</string>
113
+ <key>live</key>
114
+ <string>old_key_1</string>
115
+ </dict>
116
+ <dict>
117
+ <key>test</key>
118
+ <string>my_app</string>
119
+ <key>live</key>
120
+ <string>old_key_2</string>
121
+ </dict>
122
+ </array>
123
+ ```
124
+
125
+ You can update the `live` key for the dictionary where `test` is `my_app`:
126
+
127
+ ```rb
128
+ plist_surgeon(
129
+ path: "Info.plist",
130
+ key: "service_api_key.(test=my_app).live",
131
+ value: "new_live_key"
132
+ )
133
+ ```
134
+
85
135
  ### Run tests for this plugin
86
136
 
87
137
  To run both the tests, and code style validation, run
@@ -36,11 +36,7 @@ module Fastlane
36
36
  end
37
37
 
38
38
  def self.is_supported?(platform)
39
- # Adjust this if your plugin only works for a particular platform (iOS vs. Android, for example)
40
- # See: https://docs.fastlane.tools/advanced/#control-configuration-by-lane-and-by-platform
41
- #
42
- # [:ios, :mac, :android].include?(platform)
43
- true
39
+ [:ios, :mac].include?(platform)
44
40
  end
45
41
  end
46
42
  end
@@ -0,0 +1,39 @@
1
+ require 'fastlane/action'
2
+ require_relative '../helper/plist_surgeon_helper'
3
+
4
+ module Fastlane
5
+ module Actions
6
+ class PlistSurgeonDeleteAction < Action
7
+ def self.run(params)
8
+ Helper::PlistSurgeonHelper.delete(params[:path], params[:key])
9
+ end
10
+
11
+ def self.description
12
+ "Delete a key from a .plist file."
13
+ end
14
+
15
+ def self.authors
16
+ ["Connor Tumbleson"]
17
+ end
18
+
19
+ def self.available_options
20
+ [
21
+ FastlaneCore::ConfigItem.new(key: :path,
22
+ env_name: "PLIST_SURGEON_PLIST_PATH",
23
+ description: "The path to the plist file",
24
+ optional: false,
25
+ type: String),
26
+ FastlaneCore::ConfigItem.new(key: :key,
27
+ env_name: "PLIST_SURGEON_PLIST_KEY",
28
+ description: "The key to delete (supports dot notation for nested keys)",
29
+ optional: false,
30
+ type: String)
31
+ ]
32
+ end
33
+
34
+ def self.is_supported?(platform)
35
+ [:ios, :mac].include?(platform)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -20,6 +20,22 @@ module Fastlane
20
20
  "#{File.basename(path)} saved with #{key} change."
21
21
  end
22
22
 
23
+ def self.delete(path, key)
24
+ unless File.exist?(path)
25
+ FastlaneCore::UI.user_error!("File not found at path: #{path}")
26
+ end
27
+
28
+ plist = Plist.parse_xml(path)
29
+ if plist.nil?
30
+ FastlaneCore::UI.user_error!("Failed to parse plist at path: #{path}")
31
+ end
32
+
33
+ delete_key(plist, key)
34
+ plist_content = plist.to_plist
35
+ File.write(path, plist_content)
36
+ "#{File.basename(path)} saved after deleting #{key}."
37
+ end
38
+
23
39
  def self.set_value(plist, key, value)
24
40
  value = parse_json_if_needed(value)
25
41
 
@@ -34,12 +50,25 @@ module Fastlane
34
50
 
35
51
  def self.set_direct_value(plist, key, value)
36
52
  if plist.kind_of?(Array)
37
- plist[key.to_i] = value
53
+ index = find_index_for_key(plist, key)
54
+ plist[index] = value
38
55
  else
39
56
  plist[key] = value
40
57
  end
41
58
  end
42
59
 
60
+ def self.find_index_for_key(array, key)
61
+ if key.start_with?('(') && key.end_with?(')')
62
+ search_term = key[1...-1]
63
+ search_key, search_value = search_term.split('=', 2)
64
+ if search_key && search_value
65
+ index = array.index { |item| item.kind_of?(Hash) && item[search_key].to_s == search_value }
66
+ return index if index
67
+ end
68
+ end
69
+ key.to_i
70
+ end
71
+
43
72
  def self.parse_json_if_needed(value)
44
73
  if value.kind_of?(String) && value.start_with?('{', '[')
45
74
  begin
@@ -82,7 +111,8 @@ module Fastlane
82
111
  current = plist
83
112
  keys.each do |k|
84
113
  if current.kind_of?(Array)
85
- current = current[k.to_i]
114
+ index = find_index_for_key(current, k)
115
+ current = current[index]
86
116
  else
87
117
  current[k] ||= {}
88
118
  current = current[k]
@@ -90,11 +120,71 @@ module Fastlane
90
120
  end
91
121
 
92
122
  if current.kind_of?(Array)
93
- current[last_key.to_i] = value
123
+ index = find_index_for_key(current, last_key)
124
+ current[index] = value
94
125
  else
95
126
  current[last_key] = value
96
127
  end
97
128
  end
129
+
130
+ def self.delete_key(plist, key)
131
+ if plist.kind_of?(Hash) && plist.key?(key)
132
+ plist.delete(key)
133
+ elsif key.include?('.')
134
+ delete_nested_value(plist, key)
135
+ else
136
+ delete_direct_value(plist, key)
137
+ end
138
+ end
139
+
140
+ def self.delete_direct_value(plist, key)
141
+ if plist.kind_of?(Array)
142
+ index = find_index_for_key(plist, key)
143
+ plist.delete_at(index) if index
144
+ else
145
+ plist.delete(key)
146
+ end
147
+ end
148
+
149
+ def self.delete_nested_value(plist, key)
150
+ parts = key.split('.')
151
+ prefix_key = find_prefix_key(plist, parts)
152
+
153
+ if prefix_key
154
+ prefix, remainder = prefix_key
155
+ delete_key(plist[prefix], remainder)
156
+ else
157
+ delete_deep_nested_value(plist, parts)
158
+ end
159
+ end
160
+
161
+ def self.delete_deep_nested_value(plist, keys)
162
+ last_key = keys.pop
163
+ current = navigate_to_container(plist, keys)
164
+
165
+ return unless current
166
+
167
+ if current.kind_of?(Array)
168
+ index = find_index_for_key(current, last_key)
169
+ current.delete_at(index) if index
170
+ elsif current.kind_of?(Hash)
171
+ current.delete(last_key)
172
+ end
173
+ end
174
+
175
+ def self.navigate_to_container(plist, keys)
176
+ current = plist
177
+ keys.each do |k|
178
+ current = if current.kind_of?(Array)
179
+ index = find_index_for_key(current, k)
180
+ current[index]
181
+ else
182
+ current[k]
183
+ end
184
+ break unless current
185
+ end
186
+ current
187
+ end
98
188
  end
99
189
  end
100
190
  end
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
2
  module PlistSurgeon
3
- VERSION = "0.1.2"
3
+ VERSION = "0.3.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastlane-plugin-plist_surgeon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sourcetoad
@@ -33,6 +33,7 @@ files:
33
33
  - lib/fastlane/plugin/plist_surgeon.rb
34
34
  - lib/fastlane/plugin/plist_surgeon/actions/entitlements_surgeon_action.rb
35
35
  - lib/fastlane/plugin/plist_surgeon/actions/plist_surgeon_action.rb
36
+ - lib/fastlane/plugin/plist_surgeon/actions/plist_surgeon_delete_action.rb
36
37
  - lib/fastlane/plugin/plist_surgeon/actions/privacy_surgeon_action.rb
37
38
  - lib/fastlane/plugin/plist_surgeon/helper/plist_surgeon_helper.rb
38
39
  - lib/fastlane/plugin/plist_surgeon/version.rb