enrich-pod-patcher 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +48 -0
- data/lib/cocoapods_patch.rb +3 -0
- data/lib/cocoapods_plugin.rb +2 -0
- data/lib/pod/command/patch/apply.rb +53 -0
- data/lib/pod/command/patch/create.rb +80 -0
- data/lib/pod/command/patch/migrate.rb +44 -0
- data/lib/pod/command/patch.rb +20 -0
- data/lib/pod/command.rb +4 -0
- data/lib/pod/hook.rb +54 -0
- metadata +108 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 310dd4c977748c88b926f757e3a345d7894359b7857021f20c0784496acc9dc5
|
4
|
+
data.tar.gz: 994ad2bdc661218e7bfe7ffc53a3d59a4c1878d61d1eb9ba0d0e71c7f98c7830
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8c9842268a7af22c4e60f073efbf1bbfd4650f6d6633f560fef351b811b165207920915c4ac7341a59a726c8d0810b2ba91bef3dff43f70c785912a37ad6e7c4
|
7
|
+
data.tar.gz: 3477da36f4bf3a89a1ed48e48e6004b79c86817ed64d06ebd998a9a209d18b785ef6fbddf11ee99584195aeb10b1ed54513bd585f571e03c66f4be151189bfea
|
data/README.md
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
|
2
|
+
# cocoapods-patch
|
3
|
+
|
4
|
+
cocoapods-patch is a Cocoapods plugin that solves the problem of forking and maintaining a separate version of a Pod when only a small (often a one-liner), long-lived change in the original Pod is needed.
|
5
|
+
|
6
|
+
The idea behind the plugin is that patches should live inside the repo (in the `patches` directory) and be distributed together with the rest of your source code. This way, you can more easily code review and test the changes to a Pod and keep it synced across your team.
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
First, install the plugin
|
11
|
+
|
12
|
+
$ gem install cocoapods-patch
|
13
|
+
|
14
|
+
Next, add a `plugin 'cocoapods-patch'` line to your Podfile to use the plugin. This will enable [automatic apply](#automatically-applying-all-patches-on-install) so you don't have to worry about it again.
|
15
|
+
|
16
|
+
That's it, you're done.
|
17
|
+
|
18
|
+
**NOTE:**
|
19
|
+
`cocoapods-patch` version 1.0.0 and above require you to use Cocoapods 1.11.0 or greater.
|
20
|
+
For anything below that please use version 0.0.9.
|
21
|
+
|
22
|
+
## Migrating to v1.0.1+
|
23
|
+
|
24
|
+
In v1.0.1 of the plugin we've changed the naming scheme of the generated patch files to also include the version of the pods used to generate the patches. This will allow us to do more automation safety and make sure patches are applied successfully.
|
25
|
+
|
26
|
+
We've added a new command to help with the migration. After updating before doing a `pod install` please first run `pod patch migrate` which will translate any existing patches into their new format. This will use the current version of the pods stated in your lockfile.
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
### Creating a patch
|
31
|
+
|
32
|
+
To create a patch, first, you need to modify the source code of the installed Pod. Do the desired changes to the Pod source code (under the `Pods/` directory). Once you're satisfied with the result, run:
|
33
|
+
|
34
|
+
pod patch create POD_NAME
|
35
|
+
|
36
|
+
This will create a `patches/POD_NAME.diff` file in your repository. The patch is a diff between the Pod version you have specified in your Podfile and your local changes to the Pod. You can now add and commit this patch.
|
37
|
+
|
38
|
+
### Automatically applying all patches on install
|
39
|
+
|
40
|
+
cocoapod-patch can be seamlessly integrated into the normal iOS development workflow. If you follow the installation instructions and add `plugin 'cocoapods-patch'` to your Podfile, every time you do a `pod install`, the plugin will go throught all the available patches and try to apply them. It will only warn you when the patch cannot be applied.
|
41
|
+
|
42
|
+
### Applying a patch manually
|
43
|
+
|
44
|
+
When you want to apply a patch to a pod, run
|
45
|
+
|
46
|
+
pod patch apply POD_NAME
|
47
|
+
|
48
|
+
This command will look for the appropriate patch in the `patches` directory and, if possibly, apply it to your local Pod. A patch can be applied only once.
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'cocoapods'
|
2
|
+
|
3
|
+
module Pod
|
4
|
+
class Command
|
5
|
+
class Patch < Command
|
6
|
+
class Apply < Patch
|
7
|
+
self.summary = 'Applies a patch to an installed Pod'
|
8
|
+
|
9
|
+
self.arguments = [
|
10
|
+
CLAide::Argument.new('NAME', true)
|
11
|
+
]
|
12
|
+
|
13
|
+
def initialize(argv)
|
14
|
+
@name = argv.shift_argument
|
15
|
+
super
|
16
|
+
end
|
17
|
+
|
18
|
+
def validate!
|
19
|
+
super
|
20
|
+
help! 'A Pod name is required.' unless @name
|
21
|
+
end
|
22
|
+
|
23
|
+
def run
|
24
|
+
apply_patch patch_file
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# also used from the post-install hook
|
32
|
+
def apply_patch(patch_file)
|
33
|
+
working_dir = Dir.pwd
|
34
|
+
repo_root = `git rev-parse --show-toplevel`.strip
|
35
|
+
ios_project_path = Pathname.new(working_dir).relative_path_from(Pathname.new(repo_root))
|
36
|
+
|
37
|
+
directory_arg = (ios_project_path.to_s.eql? ".") ? "Pods" : File.join(ios_project_path, 'Pods')
|
38
|
+
|
39
|
+
Dir.chdir(repo_root) {
|
40
|
+
check_cmd = "git apply --check '#{patch_file}' --directory='#{directory_arg}' -p2 2> /dev/null"
|
41
|
+
|
42
|
+
can_apply = system(check_cmd)
|
43
|
+
if can_apply
|
44
|
+
apply_cmd = check_cmd.gsub('--check ', '')
|
45
|
+
did_apply = system(apply_cmd)
|
46
|
+
if did_apply
|
47
|
+
Pod::UI.puts "Successfully applied #{patch_file} 🎉"
|
48
|
+
else
|
49
|
+
Pod::UI.warn "Error: failed to apply #{patch_file}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
}
|
53
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
module Pod
|
4
|
+
class Command
|
5
|
+
class Patch < Command
|
6
|
+
class Create < Patch
|
7
|
+
self.description = <<-DESC
|
8
|
+
Creates a patch file comparing your local Pod changes to the upstream
|
9
|
+
version specified in your Podfile. The patch is saved into the `patches`
|
10
|
+
directory.
|
11
|
+
DESC
|
12
|
+
|
13
|
+
self.arguments = [
|
14
|
+
CLAide::Argument.new('NAME', true)
|
15
|
+
]
|
16
|
+
|
17
|
+
def initialize(argv)
|
18
|
+
@name = argv.shift_argument
|
19
|
+
super
|
20
|
+
end
|
21
|
+
|
22
|
+
def validate!
|
23
|
+
super
|
24
|
+
help! 'A Pod name is required.' unless @name
|
25
|
+
end
|
26
|
+
|
27
|
+
def clear_patches_folder_if_empty
|
28
|
+
if Dir.empty?(patches_path)
|
29
|
+
FileUtils.remove_dir(patches_path)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def run
|
34
|
+
# create patches folder if it doesn't exist
|
35
|
+
FileUtils.mkdir_p(patches_path)
|
36
|
+
|
37
|
+
Dir.mktmpdir('cocoapods-patch-', config.project_root) do |work_dir|
|
38
|
+
sandbox = Pod::Sandbox.new(work_dir)
|
39
|
+
installer = Pod::Installer.new(sandbox, config.podfile, config.lockfile)
|
40
|
+
installer.clean_install = true
|
41
|
+
|
42
|
+
installer.prepare
|
43
|
+
installer.resolve_dependencies
|
44
|
+
|
45
|
+
UI.puts "Checking if pod exists in project..."
|
46
|
+
specs_by_platform = installer.send :specs_for_pod, @name
|
47
|
+
|
48
|
+
if specs_by_platform.empty?
|
49
|
+
clear_patches_folder_if_empty
|
50
|
+
help! "Given pod does not exist in project. Did you use incorrect pod name?"
|
51
|
+
|
52
|
+
return
|
53
|
+
end
|
54
|
+
|
55
|
+
pod_installer = installer.send :create_pod_installer, @name
|
56
|
+
pod_installer.install!
|
57
|
+
|
58
|
+
UI.puts "Creating patch"
|
59
|
+
theirs = Pathname.new(work_dir).join(@name).relative_path_from(config.project_root)
|
60
|
+
ours = config.project_pods_root.join(@name).relative_path_from(config.project_root)
|
61
|
+
gen_diff_cmd = "git diff --no-index '#{theirs}' '#{ours}' > '#{patch_file}'"
|
62
|
+
|
63
|
+
did_succeed = system(gen_diff_cmd)
|
64
|
+
if not did_succeed.nil?
|
65
|
+
if File.empty?(patch_file)
|
66
|
+
File.delete(patch_file)
|
67
|
+
clear_patches_folder_if_empty
|
68
|
+
UI.warn "Error: no changes detected between current pod and original"
|
69
|
+
else
|
70
|
+
UI.puts "Created patch #{patch_file} 🎉"
|
71
|
+
end
|
72
|
+
else
|
73
|
+
UI.warn "Error: failed to create patch for #{@name}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
module Pod
|
4
|
+
class Command
|
5
|
+
class Patch < Command
|
6
|
+
class Migrate < Patch
|
7
|
+
self.description = <<-DESC
|
8
|
+
Migrates previous patch files to the new format.
|
9
|
+
DESC
|
10
|
+
|
11
|
+
def clear_patches_folder_if_empty
|
12
|
+
if Dir.empty?(patches_path)
|
13
|
+
FileUtils.remove_dir(patches_path)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def run
|
18
|
+
UI.puts 'Migrating patches...'
|
19
|
+
patches_dir = Pathname.new(Dir.pwd) + 'patches'
|
20
|
+
if patches_dir.directory?
|
21
|
+
patches = patches_dir.each_child.select { |c| c.to_s.end_with?('.diff') }
|
22
|
+
patches.each do |p|
|
23
|
+
# check if patch file has new format
|
24
|
+
if p.to_s.include?('+')
|
25
|
+
# do nothing
|
26
|
+
else
|
27
|
+
# rename patch file
|
28
|
+
pod_name = p.basename('.diff').to_s
|
29
|
+
UI.puts "Renaming #{pod_name}"
|
30
|
+
|
31
|
+
pod_version = config.lockfile.version(pod_name)
|
32
|
+
new_patch_name = p.to_s.gsub('.diff', "+#{pod_version}.diff")
|
33
|
+
|
34
|
+
File.rename(p, new_patch_name)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require_relative 'patch/apply'
|
2
|
+
require_relative 'patch/create'
|
3
|
+
|
4
|
+
module Pod
|
5
|
+
class Command
|
6
|
+
class Patch < Command
|
7
|
+
self.abstract_command = true
|
8
|
+
self.summary = 'Create & apply patches to Pods.'
|
9
|
+
|
10
|
+
def patch_file
|
11
|
+
version = config.lockfile.version(@name)
|
12
|
+
return config.project_root + 'patches' + "#{@name}+#{version}.diff"
|
13
|
+
end
|
14
|
+
|
15
|
+
def patches_path
|
16
|
+
config.project_root + 'patches'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/pod/command.rb
ADDED
data/lib/pod/hook.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'cocoapods'
|
2
|
+
require 'pathname'
|
3
|
+
require_relative 'command/patch/apply'
|
4
|
+
|
5
|
+
module EnrichPodPatcher
|
6
|
+
module Hooks
|
7
|
+
Pod::HooksManager.register('enrich-pod-patcher', :pre_install) do |context|
|
8
|
+
Pod::UI.puts 'Preparing patchable pods for clean patching'
|
9
|
+
patches_dir = Pathname.new(Dir.pwd) + 'patches'
|
10
|
+
if patches_dir.directory?
|
11
|
+
patches = patches_dir.each_child.select { |c| c.to_s.end_with?('.diff') }
|
12
|
+
patches.each do |p|
|
13
|
+
pod_name = File.basename(p, ".diff")
|
14
|
+
pod_dir = context.sandbox.pod_dir(pod_name)
|
15
|
+
context.sandbox.clean_pod(pod_name, pod_dir)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class Pod::Installer
|
23
|
+
# Because our patches may also delete files, we need to apply them before the pod project is generated
|
24
|
+
# The project is generated in the `integrate` method, so we override it
|
25
|
+
# We first run our patch action and then the original implementation of the method
|
26
|
+
# Reference: https://github.com/CocoaPods/CocoaPods/blob/760828a07f8fcfbff03bce13f56a1789b6f5a95d/lib/cocoapods/installer.rb#L178
|
27
|
+
alias_method :integrate_old, :integrate
|
28
|
+
|
29
|
+
def integrate
|
30
|
+
# apply our patches
|
31
|
+
apply_patches
|
32
|
+
# run the original implementation
|
33
|
+
integrate_old
|
34
|
+
end
|
35
|
+
|
36
|
+
def apply_patches
|
37
|
+
Pod::UI.puts 'Applying patches if necessary'
|
38
|
+
patches_dir = Pathname.new(Dir.pwd) + 'patches'
|
39
|
+
if patches_dir.directory?
|
40
|
+
patches = patches_dir.each_child.select { |c| c.to_s.end_with?('.diff') }
|
41
|
+
patches.each do |p|
|
42
|
+
pod_name = File.basename(p, ".diff")
|
43
|
+
# check if patch is in new format otherwise warn user
|
44
|
+
unless p.to_s.include?('+')
|
45
|
+
Pod::UI.puts "WARNING: #{pod_name}.diff has an old naming format. Please run pod patch migration first before pod install. See the README for more information.".yellow
|
46
|
+
end
|
47
|
+
|
48
|
+
apply_patch(p)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
metadata
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: enrich-pod-patcher
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Enrich Software Corp
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-07-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: cocoapods
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.12.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.12.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '13.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '13.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.9'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.9'
|
69
|
+
description: Create & apply patches to Pods
|
70
|
+
email:
|
71
|
+
- doug.yuen@enrichsoftware.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- README.md
|
77
|
+
- lib/cocoapods_patch.rb
|
78
|
+
- lib/cocoapods_plugin.rb
|
79
|
+
- lib/pod/command.rb
|
80
|
+
- lib/pod/command/patch.rb
|
81
|
+
- lib/pod/command/patch/apply.rb
|
82
|
+
- lib/pod/command/patch/create.rb
|
83
|
+
- lib/pod/command/patch/migrate.rb
|
84
|
+
- lib/pod/hook.rb
|
85
|
+
homepage:
|
86
|
+
licenses:
|
87
|
+
- MIT
|
88
|
+
metadata: {}
|
89
|
+
post_install_message:
|
90
|
+
rdoc_options: []
|
91
|
+
require_paths:
|
92
|
+
- lib
|
93
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
requirements: []
|
104
|
+
rubygems_version: 3.0.9
|
105
|
+
signing_key:
|
106
|
+
specification_version: 4
|
107
|
+
summary: Create & apply patches to Pods
|
108
|
+
test_files: []
|