cocoapods-project-gen 0.1.0 → 0.2.3

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: 8224b3941957448267846730698368b63e05c21813a8785cef0077ffb5ea56b2
4
- data.tar.gz: 525e97837422369163770a4e56fd3baadc67edeea2c5b156505e91c6325b78df
3
+ metadata.gz: ea8031db47261426a1e1ac999b16ffdcaff6e404fa9ebe8ea790f654720b04b9
4
+ data.tar.gz: b9de39c0d6fb2944bcb5be0bab8e175d14ba65a0d5eb865c491e4fd1fcd8bc5d
5
5
  SHA512:
6
- metadata.gz: 2e62a1df71643dcc9f824c2a330e6d30d4c8854011e5d1b6b6bdcb696349d1766e288bde42d1e36730a0a988cf7bfd60e5d2c59cfbc7b0215bbce51536cde705
7
- data.tar.gz: 9b0e65439b421036a9ef85bc2983edb34f16c3592cdbce370865387c57e47efc04e71b50dcbed185ceb873a651f17e8e4058baf2cf9599ccebbd8c9deea2e4cd
6
+ metadata.gz: b2576574c992dd78e94f3a69a3ed17419c4e09dcf2cfa314190c22b73c7a0227dc22a0b161e0943e62dd21f56e329e05f1e11883a183674e840543a8568124af
7
+ data.tar.gz: 23b165ff2623b80e727c0f9d630ebb3321b0d75b261ed7d36115bff4ff60b249e74097b53d61f421125f2c5191d75c8eb088de79f9b674ddca9edce7b3e919c2
data/README.md CHANGED
@@ -25,55 +25,94 @@ Or install it yourself as:
25
25
  # gem install
26
26
  $ gem install cocoapods-project-gen
27
27
  ```
28
+
28
29
  ### Quickstart
29
30
 
31
+ To begin gen an cocoapods project by opening an podpsec dir, and to your command line with:
32
+
33
+ ```shell
34
+ xcframework gen
35
+ ```
36
+
37
+ or
38
+
39
+ ```shell
40
+ xcframework gen --output-dir=<xcframework output dir>
41
+ ```
42
+
43
+ ```shell
44
+ xcframework gen --output-dir=<xcframework output dir> **.podspec
45
+ ```
46
+
30
47
  To begin gen an cocoapods project start by create an `ProjectGenerator`:
31
48
 
32
49
  ```ruby
33
- require 'cocoapods-project-gen'
34
- podspecs = Pathname.glob(File.expand_path("./Resources/AFNetworking-master", __dir__) + '/*.podspec{.json,}')
35
- out_put = File.expand_path("./Resources/output", __dir__)
36
- gen = ProjectGen::ProjectGenerator.new_from_local(podspecs, [])
37
- gen.generate!(out_put) do |platforms, pod_targets, validated|
38
- p platforms, pod_targets, validated
39
- end
50
+ podspecs = [**.podspec]
51
+ ProjectGen::Command.run(['gen', "--output-dir=#{File.expand_path('./Resources/output', __dir__)}", *podspecs])
40
52
  ```
41
53
 
42
- or use this way:
54
+ or to build for xcframework use this way:
43
55
 
44
56
  ```ruby
45
57
  require 'cocoapods-project-gen'
46
58
 
47
59
  product_type = :dynamic_framework
48
60
  use_module = true
49
- include_podspecs = []
61
+ external_podspecs = []
50
62
  swift_version = '4.2'
51
63
  configuration = :release
64
+ output_dir = <output dir>
52
65
  generator = ProjectGen::ProjectGenerator.new(include_podspecs.first, @sources, @platforms)
53
66
  generator.local = false
54
67
  generator.no_clean = false
55
68
  generator.allow_warnings = true
56
- generator.no_subspecs = true
57
- generator.only_subspec = false
69
+ generator.only_subspec = %w[AFNetworking/UIKit AFNetworking/Reachability]
58
70
  generator.use_frameworks = product_type == :dynamic_framework
59
71
  generator.use_static_frameworks = product_type == :framework
60
72
  generator.use_modular_headers = use_module
61
- generator.skip_import_validation = true
62
- generator.external_podspecs = include_podspecs.drop(1)
73
+ generator.external_podspecs = external_podspecs.drop(1)
63
74
  generator.swift_version = swift_version
64
75
  generator.configuration = configuration
65
- generator.skip_tests = true
66
- begin
67
- generator.generate!(spec_root) do |platform, pod_targets, validated|
68
- raise 'Could not generator App.xcodeproj' unless validated
69
-
70
- end
71
- rescue StandardError => e
72
- raise Pod::Informative, "The `#{@include_podspecs.join(' ')}` specification does not validate." \
73
- "\n\n#{e.message}"
74
- end
76
+ # xcframework gen
77
+ xc_gen = ProjectGen::XcframeworkGen.new(generator)
78
+ xc_gen.generate_xcframework(output_dir, build_library_for_distribution: true)
79
+ ```
80
+
81
+ other options:
82
+
83
+ ```ruby
84
+ ['--no-build', 'Is or is not to build xcframework'],
85
+ ['--build-library-for-distribution', ' Enables BUILD_LIBRARY_FOR_DISTRIBUTION'],
86
+ ['--use-latest', 'When multiple dependencies with different sources, use latest.'],
87
+ ['--local', 'podpsecs is local or not'],
88
+ ['--output-dir=/project/dir/', 'Gen output dir'],
89
+ ['--allow-warnings', 'Gen even if warnings are present'],
90
+ ['--subspecs=NAME/NAME', 'Gen only the given subspecs'],
91
+ ['--no-clean', 'Gen leaves the build directory intact for inspection'],
92
+ ['--use-libraries', 'Gen uses static libraries to install the spec'],
93
+ ['--use-modular-headers', 'Gen uses modular headers during installation'],
94
+ ['--use-static-frameworks', 'Gen uses static frameworks during installation'],
95
+ ["--sources=#{Pod::TrunkSource::TRUNK_REPO_URL}", 'The sources from which to pull dependent pods ' \
96
+ "(defaults to #{Pod::TrunkSource::TRUNK_REPO_URL}). Multiple sources must be comma-delimited"],
97
+ ['--platforms=ios,macos', 'Gen against specific platforms (defaults to all platforms supported by the ' \
98
+ 'podspec). Multiple platforms must be comma-delimited'],
99
+ ['--swift-version=VERSION', 'The `SWIFT_VERSION` that should be used to gen the spec. ' \
100
+ 'This takes precedence over the Swift versions specified by the spec or a `.swift-version` file'],
101
+ ['--include-podspecs=**/*.podspec', 'Additional ancillary podspecs which are used for gening via :path'],
102
+ ['--external-podspecs=**/*.podspec', 'Additional ancillary podspecs which are used for gening '\
103
+ 'via :podspec. If there are --include-podspecs, then these are removed from them'],
104
+ ['--configuration=CONFIGURATION', 'Build using the given configuration (defaults to Release)']
75
105
  ```
76
106
 
107
+ ## Command Line Tool
108
+
109
+ Installing the `cocoapods-project-gen` gem will also install one command-line tool `xcframework gen` which you can use to generate xcframework from podspec.
110
+
111
+ For more information consult
112
+
113
+ - `xcframework --help`
114
+ - `xcframework gen --help`
115
+
77
116
  ## Contributing
78
117
 
79
118
  Bug reports and pull requests are welcome on GitHub at [cocoapods-project-gen](https://github.com/Cat1237/cocoapods-project-gen). This project is intended to be a safe, welcoming space for collaboration.
data/bin/xcframework ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ if $PROGRAM_NAME == __FILE__
5
+ ENV['BUNDLE_GEMFILE'] = File.expand_path('../Gemfile', __dir__)
6
+ require 'bundler/setup'
7
+ end
8
+
9
+ require 'cocoapods-project-gen'
10
+
11
+ ProjectGen::Command.run(ARGV)
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The primary namespace for Gen.
4
+ module ProjectGen
5
+ require 'colored2'
6
+ require 'claide'
7
+ # The primary Command for Gen.
8
+ class Command < CLAide::Command
9
+ require 'cocoapods-project-gen/command/gen'
10
+
11
+ self.abstract_command = false
12
+ self.command = 'xcframework'
13
+ self.version = VERSION
14
+ self.description = 'Creates Pods project and gen xcframework.'
15
+ self.plugin_prefixes = %w[claide gen]
16
+
17
+ def initialize(argv)
18
+ super
19
+ return if ansi_output?
20
+
21
+ Colored2.disable!
22
+ String.send(:define_method, :colorize) { |string, _| string }
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,120 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ProjectGen
4
+ class Command
5
+ # hmap file gen cmd
6
+ class Gen < Command
7
+ # summary
8
+ self.summary = 'Creates Pods project and gen xcframework.'
9
+
10
+ self.description = <<-DESC
11
+ Creates the target for the Pods libraries in the Pods project and the relative support files and gen xcframework.
12
+ DESC
13
+
14
+ self.arguments = [
15
+ CLAide::Argument.new('PODSPEC_PATHS', false, true)
16
+ ]
17
+
18
+ def initialize(argv)
19
+ super
20
+ @build = argv.flag?('build', true)
21
+ @local = argv.flag?('local')
22
+ @build_library_for_distribution = argv.flag?('build-library-for-distribution')
23
+ @use_latest = argv.flag?('use-latest', true)
24
+ output_dir = argv.option('output-dir', Pathname.pwd)
25
+ @output_dir = Pathname.new(output_dir).expand_path.join('project_gen/App')
26
+ @allow_warnings = argv.flag?('allow-warnings', true)
27
+ @clean = argv.flag?('clean', false)
28
+ @only_subspecs = argv.option('subspecs', '').split(',')
29
+ @use_frameworks = !argv.flag?('use-libraries')
30
+ @use_modular_headers = argv.flag?('use-modular-headers', true)
31
+ @use_static_frameworks = argv.flag?('use-static-frameworks')
32
+ @source_urls = argv.option('sources', Pod::TrunkSource::TRUNK_REPO_URL).split(',')
33
+ @platforms = argv.option('platforms', '').split(',')
34
+ @swift_version = argv.option('swift-version', nil)
35
+ @include_podspecs = argv.option('include-podspecs', '').split(',').map { |path| Pathname.new(path).expand_path }
36
+ @external_podspecs = argv.option('external-podspecs', '').split(',').map { |path| Pathname.new(path).expand_path }
37
+ @podspecs_paths = argv.arguments!
38
+ @configuration = argv.option('configuration', nil)
39
+ end
40
+
41
+ def validate!
42
+ super
43
+ end
44
+
45
+ # help
46
+ def self.options
47
+ [
48
+ ['--no-build', 'Is or is not to build xcframework'],
49
+ ['--build-library-for-distribution', ' Enables BUILD_LIBRARY_FOR_DISTRIBUTION'],
50
+ ['--use-latest', 'When multiple dependencies with different sources, use latest.'],
51
+ ['--local', 'podpsecs is local or not'],
52
+ ['--output-dir=/project/dir/', 'Gen output dir'],
53
+ ['--allow-warnings', 'Gen even if warnings are present'],
54
+ ['--subspecs=NAME/NAME', 'Gen only the given subspecs'],
55
+ ['--no-clean', 'Gen leaves the build directory intact for inspection'],
56
+ ['--use-libraries', 'Gen uses static libraries to install the spec'],
57
+ ['--use-modular-headers', 'Gen uses modular headers during installation'],
58
+ ['--use-static-frameworks', 'Gen uses static frameworks during installation'],
59
+ ["--sources=#{Pod::TrunkSource::TRUNK_REPO_URL}", 'The sources from which to pull dependent pods ' \
60
+ "(defaults to #{Pod::TrunkSource::TRUNK_REPO_URL}). Multiple sources must be comma-delimited"],
61
+ ['--platforms=ios,macos', 'Gen against specific platforms (defaults to all platforms supported by the ' \
62
+ 'podspec). Multiple platforms must be comma-delimited'],
63
+ ['--swift-version=VERSION', 'The `SWIFT_VERSION` that should be used to gen the spec. ' \
64
+ 'This takes precedence over the Swift versions specified by the spec or a `.swift-version` file'],
65
+ ['--include-podspecs=**/*.podspec', 'Additional ancillary podspecs which are used for gening via :path'],
66
+ ['--external-podspecs=**/*.podspec', 'Additional ancillary podspecs which are used for gening '\
67
+ 'via :podspec. If there are --include-podspecs, then these are removed from them'],
68
+ ['--configuration=CONFIGURATION', 'Build using the given configuration (defaults to Release)']
69
+ ].concat(super)
70
+ end
71
+
72
+ def run
73
+ generator = ProjectGenerator.new(@source_urls, @platforms)
74
+ generator.local = @local
75
+ generator.no_clean = !@clean
76
+ generator.use_latest = @use_latest
77
+ generator.allow_warnings = @allow_warnings
78
+ generator.only_subspecs = @only_subspecs
79
+ generator.use_frameworks = @use_frameworks
80
+ generator.use_modular_headers = @use_modular_headers
81
+ generator.use_static_frameworks = @use_static_frameworks
82
+ generator.swift_version = @swift_version
83
+ generator.include_podspecs = @include_podspecs
84
+ generator.external_podspecs = @external_podspecs
85
+ if @local
86
+ generator.include_podspecs += podspecs_to_gen
87
+ generator.include_podspecs.uniq!
88
+ else
89
+ generator.external_podspecs += podspecs_to_gen
90
+ generator.external_podspecs.uniq!
91
+ end
92
+ if generator.include_podspecs.empty? && generator.external_podspecs.empty?
93
+ raise Informative, 'Unable to find podspecs in the working. Is local or not local?'
94
+ end
95
+
96
+ generator.configuration = @configuration
97
+ xc_gen = ProjectGen::XcframeworkGen.new(generator)
98
+ xc_gen.generate_xcframework(@output_dir, build: @build, build_library_for_distribution: @build_library_for_distribution)
99
+ end
100
+
101
+ private
102
+
103
+ # !@group Private helpers
104
+
105
+ # @return [Pathname] The path of the podspec found in the current
106
+ # working directory.
107
+ #
108
+ # @raise If no podspec is found.
109
+ # @raise If multiple podspecs are found.
110
+ #
111
+ def podspecs_to_gen
112
+ if @podspecs_paths.empty?
113
+ Pathname.glob(Pathname.pwd.join('*.podspec{.json,}'))
114
+ else
115
+ Array(@podspecs_paths).map { |path| Pathname.new(path).expand_path }
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
@@ -1,3 +1,3 @@
1
1
  module ProjectGen
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.3"
3
3
  end
@@ -0,0 +1,104 @@
1
+ require 'fileutils'
2
+ require 'cocoapods/sandbox'
3
+
4
+ module ProjectGen
5
+ # Provides support for managing a header directory. It also keeps track of
6
+ # the header search paths.
7
+ #
8
+ class HeadersStore
9
+ SEARCH_PATHS_KEY = Struct.new(:platform_name, :target_name, :use_modular_headers)
10
+
11
+ # @return [Pathname] the absolute path of this header directory.
12
+ #
13
+ def root(source: false)
14
+ root = if source
15
+ sandbox.sources_root
16
+ else
17
+ sandbox.headers_root
18
+ end
19
+
20
+ root + @relative_path
21
+ end
22
+
23
+ # @return [Sandbox] the sandbox where this header directory is stored.
24
+ #
25
+ attr_reader :sandbox
26
+
27
+ # @param [Sandbox] @see #sandbox
28
+ #
29
+ # @param [String] relative_path
30
+ # the relative path to the sandbox root and hence to the Pods
31
+ # project.
32
+ #
33
+ # @param [Symbol] visibility_scope
34
+ # the header visibility scope to use in this store. Can be `:private` or `:public`.
35
+ #
36
+ def initialize(sandbox, relative_path, visibility_scope)
37
+ @sandbox = sandbox
38
+ @relative_path = relative_path
39
+ @search_paths = []
40
+ @search_paths_cache = {}
41
+ @visibility_scope = visibility_scope
42
+ end
43
+
44
+ #-----------------------------------------------------------------------#
45
+
46
+ # @!group Adding headers
47
+
48
+ # Adds headers to the directory.
49
+ #
50
+ # @param [Pathname] namespace
51
+ # the path where the header file should be stored relative to the
52
+ # headers directory.
53
+ #
54
+ # @param [Array<Pathname>] relative_header_paths
55
+ # the path of the header file relative to the Pods project
56
+ # (`PODS_ROOT` variable of the xcconfigs).
57
+ #
58
+ # @note This method does _not_ add the files to the search paths.
59
+ #
60
+ # @return [Array<Pathname>]
61
+ #
62
+ def add_files(namespace, relative_header_paths, ln: false, source: false)
63
+ root(source: source).join(namespace).mkpath unless relative_header_paths.empty?
64
+ relative_header_paths.map do |relative_header_path|
65
+ add_file(namespace, relative_header_path, ln: ln, mkdir: false, source: source)
66
+ end
67
+ end
68
+
69
+ # Adds a header to the directory.
70
+ #
71
+ # @param [Pathname] namespace
72
+ # the path where the header file should be stored relative to the
73
+ # headers directory.
74
+ #
75
+ # @param [Pathname] relative_header_path
76
+ # the path of the header file relative to the Pods project
77
+ # (`PODS_ROOT` variable of the xcconfigs).
78
+ #
79
+ # @note This method does _not_ add the file to the search paths.
80
+ #
81
+ # @return [Pathname]
82
+ #
83
+ def add_file(namespace, relative_header_path, ln: false, mkdir: true, source: false)
84
+ namespaced_path = root(source: source) + namespace
85
+ namespaced_path.mkpath if mkdir
86
+
87
+ absolute_source = (sandbox.root + relative_header_path)
88
+ source = absolute_source.relative_path_from(namespaced_path)
89
+ full_namespaced_path = namespaced_path.join(relative_header_path.basename)
90
+ return full_namespaced_path if full_namespaced_path.exist?
91
+
92
+ if ln
93
+ if Gem.win_platform?
94
+ FileUtils.ln(absolute_source, namespaced_path, force: true)
95
+ else
96
+ FileUtils.ln_sf(source, namespaced_path)
97
+ end
98
+ else
99
+ FileUtils.cp_r(absolute_source, namespaced_path)
100
+ end
101
+ full_namespaced_path
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,47 @@
1
+ require 'cocoapods/executable'
2
+
3
+ module ProjectGen
4
+ module XcodeBuild
5
+
6
+ def self.archive?(args, project_path, scheme, archive_path)
7
+ command = %w[archive -showBuildTimingSummary]
8
+ command += args
9
+ command += %W[-project #{project_path} -scheme #{scheme} -archivePath #{archive_path}]
10
+ command += %w[SKIP_INSTALL=NO]
11
+ results = Results.new
12
+ output = begin
13
+ Pod::Executable.execute_command('xcodebuild', command, true)
14
+ rescue StandardError => e
15
+ message = 'Returned an unsuccessful exit code.'
16
+ results.error('xcodebuild', message)
17
+ e.message
18
+ end
19
+ results.translate_xcodebuild_output_to_messages(output)
20
+ return false unless results.result_type == :error
21
+
22
+ results.print_results
23
+ true
24
+ end
25
+
26
+ def self.create_xcframework?(args, output_path)
27
+ command = %w[-create-xcframework]
28
+ command += args
29
+ command += %W[-output #{output_path}]
30
+
31
+ results = Results.new
32
+ output = begin
33
+ Pod::Executable.execute_command('xcodebuild', command, true)
34
+ rescue StandardError => e
35
+ message = 'Returned an unsuccessful exit code.'
36
+ results.error('xcodebuild', message)
37
+ e.message
38
+ end
39
+
40
+ results.translate_xcodebuild_output_to_messages(output)
41
+ return false unless results.result_type == :error
42
+
43
+ results.print_results
44
+ true
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,71 @@
1
+ module ProjectGen
2
+ # This modules groups all the constants known to .
3
+ #
4
+ module Constants
5
+ PRODUCT_DIR = 'Products'.freeze
6
+
7
+ # The default version of Swift to use when linting pods
8
+ #
9
+ DEFAULT_SWIFT_VERSION = '4.0'.freeze
10
+
11
+ # The valid platforms for linting
12
+ #
13
+ VALID_PLATFORMS = Pod::Platform.all.freeze
14
+
15
+ COPY_LIBRARY_SWIFT_HEADERS = 'Copy-Library-Swift-Headers'.freeze
16
+
17
+ # Whether the platform with the specified name is valid
18
+ #
19
+ # @param [Platform] platform
20
+ # The platform to check
21
+ #
22
+ # @return [Boolean] True if the platform is valid
23
+ #
24
+ def self.valid_platform?(platform)
25
+ VALID_PLATFORMS.any? { |p| p.name == platform.name }
26
+ end
27
+
28
+ def self.sdks(platform_name)
29
+ case platform_name
30
+ when :osx, :macos
31
+ %i[macosx]
32
+ when :ios
33
+ %i[iphonesimulator iphoneos]
34
+ when :watchos
35
+ %i[watchsimulator watchos]
36
+ when :tvos
37
+ %i[appletvsimulator appletvos]
38
+ end
39
+ end
40
+
41
+ # @return [Hash] The extensions or the various product UTIs.
42
+ #
43
+ PRODUCT_UTI_EXTENSIONS = {
44
+ framework: 'framework',
45
+ dynamic_framework: 'dynamic_framework',
46
+ dynamic_library: 'dylib',
47
+ static_library: 'a',
48
+ bundle: 'bundle'
49
+ }.freeze
50
+
51
+ SDK_ARCHS = {
52
+ iphonesimulator: %w[x86_64 arm64 i386],
53
+ iphoneos: %w[arm64],
54
+ watchos: %w[armv7k arm64_32],
55
+ watchsimulator: %w[x86_64 arm64],
56
+ appletvos: %w[x86_64 arm64],
57
+ appletvsimulator: %w[x86_64 arm64],
58
+ macosx: %w[x86_64 arm64]
59
+ }.freeze
60
+
61
+ SDK_DESTINATION = {
62
+ iphonesimulator: 'iOS Simulator',
63
+ iphoneos: 'iOS',
64
+ watchos: 'watchOS',
65
+ watchsimulator: 'watchOS Simulator',
66
+ appletvos: 'tvOS',
67
+ appletvsimulator: 'tvOS Simulator',
68
+ macosx: 'macOS'
69
+ }.freeze
70
+ end
71
+ end
@@ -0,0 +1,50 @@
1
+ module ProjectGen
2
+ class PodDirCopyCleaner
3
+ def initialize(podspecs)
4
+ @podspecs = podspecs
5
+ end
6
+
7
+ # Copies the `source` directory to `destination`, cleaning the directory
8
+ # of any files unused by `spec`.
9
+ #
10
+ # @return [Void]
11
+ #
12
+ def copy_and_clean(root, sandbox)
13
+ @podspecs.each do |spec|
14
+ destination = root + spec.name
15
+ source = sandbox.pod_dir(spec.name)
16
+ specs_by_platform = group_subspecs_by_platform(spec)
17
+ destination.parent.mkpath
18
+ FileUtils.rm_rf(destination)
19
+ copy(source, destination, specs_by_platform)
20
+ end
21
+ end
22
+
23
+ def group_subspecs_by_platform(spec)
24
+ specs_by_platform = {}
25
+ [spec, *spec.recursive_subspecs].each do |ss|
26
+ ss.available_platforms.each do |platform|
27
+ specs_by_platform[platform] ||= []
28
+ specs_by_platform[platform] << ss
29
+ end
30
+ end
31
+ specs_by_platform
32
+ end
33
+
34
+ def copy(source, destination, specs_by_platform)
35
+ path_list = Pod::Sandbox::PathList.new(source)
36
+ file_accessors = specs_by_platform.flat_map do |platform, specs|
37
+ specs.flat_map do |spec|
38
+ Pod::Sandbox::FileAccessor.new(path_list, spec.consumer(platform))
39
+ end
40
+ end
41
+ used_files = Pod::Sandbox::FileAccessor.all_files(file_accessors)
42
+ used_files.each do |path|
43
+ path = Pathname(path)
44
+ n_path = destination.join(path.relative_path_from(source))
45
+ n_path.dirname.mkpath
46
+ FileUtils.cp_r(path, n_path.dirname)
47
+ end
48
+ end
49
+ end
50
+ end