Class: ZergXcode::Plugins::Import
- Inherits:
-
Object
- Object
- ZergXcode::Plugins::Import
- Includes:
- Objects
- Defined in:
- lib/zerg_xcode/plugins/import.rb
Instance Method Summary collapse
-
#bin_mappings(mappings, source) ⇒ Object
Bins merge mappings for a project into mappings to be merged and mappings to be overwritten.
- #clean_join(root, path) ⇒ Object
-
#compute_copies(source_root, source_paths, target_root) ⇒ Object
Computes the file copy operations in a merge.
-
#compute_deletes(root, old_paths, new_paths) ⇒ Object
Computes the file delete operations in a merge.
-
#cross_reference(source, target, strict = false, mappings = {}) ⇒ Object
Cross-references the objects in two object graphs that are to be merged.
-
#execute_file_ops!(file_ops) ⇒ Object
Executes the given file operations.
- #help ⇒ Object
-
#import_project!(source, target) ⇒ Object
Imports the objects of the source project into the target project.
-
#map!(object, mappings) ⇒ Object
Modifies an object’s attributes according to the given mappings.
-
#merge!(source, target) ⇒ Object
Merges the contents of a source object into the target object.
-
#overwrite!(source, target) ⇒ Object
Overwrites the contents of the target object with the source object.
- #run(args) ⇒ Object
Instance Method Details
#bin_mappings(mappings, source) ⇒ Object
Bins merge mappings for a project into mappings to be merged and mappings to be overwritten.
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/zerg_xcode/plugins/import.rb', line 122 def bin_mappings(mappings, source) merge_set = Set.new overwrite_set = Set.new # the project's top-level attributes are always merged source.attrs.each do |attr| merge_set << source[attr] if mappings[source[attr]] end mappings.each do |source_object, target_object| next if source_object == target_object next if merge_set.include? source_object if source_object.kind_of?(PBXGroup) && source_object['path'].nil? merge_set << source_object elsif source_object.kind_of? XCConfigurationList merge_set << source_object else overwrite_set << source_object end end overwrite_set.delete source { :merge => merge_set, :overwrite => overwrite_set } end |
#clean_join(root, path) ⇒ Object
116 117 118 |
# File 'lib/zerg_xcode/plugins/import.rb', line 116 def clean_join(root, path) Pathname.new(File.join(root, path)).cleanpath.to_s end |
#compute_copies(source_root, source_paths, target_root) ⇒ Object
Computes the file copy operations in a merge.
Copies all the files from the source project assuming they received the same path in the target project. The assumption is correct if source was imported into target.
109 110 111 112 113 114 |
# File 'lib/zerg_xcode/plugins/import.rb', line 109 def compute_copies(source_root, source_paths, target_root) source_paths.select { |path| path[0, 2] == './' }.map do |path| { :op => :copy, :from => clean_join(source_root, path), :to => clean_join(target_root, path) } end end |
#compute_deletes(root, old_paths, new_paths) ⇒ Object
Computes the file delete operations in a merge.
Deletes all the files that aren’t in the target project anymore.
97 98 99 100 101 102 |
# File 'lib/zerg_xcode/plugins/import.rb', line 97 def compute_deletes(root, old_paths, new_paths) new_path_set = Set.new(new_paths) old_paths.select { |path| path[0, 2] == './' }. reject { |path| new_path_set.include? path }. map { |path| { :op => :delete, :path => clean_join(root, path) } } end |
#cross_reference(source, target, strict = false, mappings = {}) ⇒ Object
Cross-references the objects in two object graphs that are to be merged. Returns a Hash associating objects in both the source and the target object graphs with the target objects that represent the same entities. Setting strict to true returns fewer matches, and should be used for entangling projects. Setting strict to false should work better for merges.
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 |
# File 'lib/zerg_xcode/plugins/import.rb', line 225 def cross_reference(source, target, strict = false, mappings = {}) if source.class != target.class raise "Attempting to cross-reference different kinds of objects - " + "#{source.class} != #{target.class}" end case target when ZergXcode::XcodeObject cross_op = :cross_reference_objects when Hash cross_op = :cross_reference_hashes when Enumerable cross_op = :cross_reference_enumerables else return mappings end self.send cross_op, source, target, strict, mappings end |
#execute_file_ops!(file_ops) ⇒ Object
Executes the given file operations.
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/zerg_xcode/plugins/import.rb', line 28 def execute_file_ops!(file_ops) file_ops.each do |op| case op[:op] when :delete FileUtils.rm_r op[:path] if File.exist? op[:path] when :copy target_dir = File.dirname op[:to] FileUtils.mkdir_p target_dir unless File.exist? target_dir if File.exist? op[:from] FileUtils.cp_r op[:from], op[:to] else print "Source does not have file #{op[:from]}\n" end end end end |
#help ⇒ Object
7 8 9 10 11 12 13 14 15 16 |
# File 'lib/zerg_xcode/plugins/import.rb', line 7 def help {:short => 'imports the objects from a project into another project', :long => <<"END" } Usage: import source_path [target_path] Imports the objects (build targets, files) from a source project into another target project. Useful when the source project wraps code that can be used as a library. END end |
#import_project!(source, target) ⇒ Object
Imports the objects of the source project into the target project.
Attempts to preserve reference integrity in the target project, as follows. If the source objects have counterparts in the target, their contents is merged into the target project’s objects.
Returns an array of file operations that need to be performed to migrate the files associated with the two projects.
The target project is modified in place.
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/zerg_xcode/plugins/import.rb', line 55 def import_project!(source, target) old_target_paths = target.all_files.map { |file| file[:path] } # duplicate the source, because the duplicate's object graph will be warped scrap_source = ZergXcode::XcodeObject.from source mappings = cross_reference scrap_source, target bins = bin_mappings mappings, scrap_source # special case for merging targets map! scrap_source, mappings merge! scrap_source['targets'], target['targets'] # merge the object graphs bins[:merge].each do |object| map! object, mappings merge! object, mappings[object] end bins[:overwrite].each do |object| map! object, mappings overwrite! object, mappings[object] end # make sure all the mappings point in the right place target.visit_once do |object, parent, key, value| if mappings[value] next mappings[value] else next true end end new_target_paths = target.all_files.map { |file| file[:path] } source_paths = source.all_files.map { |file| file[:path] } return compute_deletes(target.root_path, old_target_paths, new_target_paths) + compute_copies(source.root_path, source_paths, target.root_path) end |
#map!(object, mappings) ⇒ Object
Modifies an object’s attributes according to the given mappings. This explores the object graph, but does not go into sub-objects.
150 151 152 153 154 155 156 157 158 |
# File 'lib/zerg_xcode/plugins/import.rb', line 150 def map!(object, mappings) object.visit_once do |object, parent, key, value| if mappings[value] parent[key] = mappings[value] next false end next true end end |
#merge!(source, target) ⇒ Object
Merges the contents of a source object into the target object.
Warning: the target will share internal objects with the source. This is intended to be used in a bigger-level opration, where the source will be thrown away afterwards.
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/zerg_xcode/plugins/import.rb', line 165 def merge!(source, target) if source.class != target.class raise "Attempting to merge-combine different kinds of objects - " + "#{source.class} != #{target.class}" end case source when ZergXcode::XcodeObject merge! source._attr_hash, target._attr_hash when Hash source.each_key do |key| if !target.has_key?(key) target[key] = source[key] elsif source[key].kind_of? ZergXcode::XcodeObject target[key] = source[key] elsif source[key].kind_of?(String) target[key] = source[key] elsif !source[key].kind_of?(Enumerable) target[key] = source[key] else merge! source[key], target[key] end end when Enumerable target_set = Set.new(target.to_a) source.each do |value| next if target_set.include? value target << value end end end |
#overwrite!(source, target) ⇒ Object
Overwrites the contents of the target object with the source object.
Warning: the target will share internal objects with the source. This is intended to be used in a bigger-level opration, where the source will be thrown away afterwards.
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
# File 'lib/zerg_xcode/plugins/import.rb', line 202 def overwrite!(source, target) if source.class != target.class raise "Attempting to overwrite-combine different kinds of objects - " + "#{source.class} != #{target.class}" end case source when ZergXcode::XcodeObject overwrite! source._attr_hash, target._attr_hash when Hash target.clear target.merge! source when Enumerable target.clear source.each { |value| target << value } end end |