Add a transform method when merging artifacts to transform file contents
authorAntoine Toulme <antoine@lunar-ocean.com>
Sun, 30 Jul 2017 09:06:25 +0000 (02:06 -0700)
committerAntoine Toulme <antoine@lunar-ocean.com>
Sun, 30 Jul 2017 21:51:51 +0000 (14:51 -0700)
CHANGELOG
lib/buildr/packaging/archive.rb
lib/buildr/packaging/tar.rb
lib/buildr/packaging/ziptask.rb
spec/packaging/archive_spec.rb

index 91b01e4..f99cfa9 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,6 +2,7 @@
 * Added: Support to compiling Kotlin
 * Fixed: Remove section on development builds in the Contributing section.
 * Added: New way to concatenate file contents when merging several archives together.
+* Added: New way to transform file contents when merging several archives together.
 
 1.5.3 (2017-05-17)
 * Change: Add support for gwt 2.8.1 to gwt addon.
index cd24fa4..78df00e 100644 (file)
@@ -112,9 +112,9 @@ module Buildr #:nodoc:
         expanders = files.collect do |file|
           @sources << proc { file.to_s }
           expander = ZipExpander.new(file)
-          @actions << proc do |file_map|
+          @actions << proc do |file_map, transform_map|
             file.invoke() if file.is_a?(Rake::Task)
-            expander.expand(file_map, path)
+            expander.expand(file_map, transform_map, path)
           end
           expander
         end
@@ -133,8 +133,8 @@ module Buildr #:nodoc:
         @sources.map{ |source| source.call }.flatten
       end
 
-      def add_files(file_map) #:nodoc:
-        @actions.each { |action| action.call(file_map) }
+      def add_files(file_map, transform_map) #:nodoc:
+        @actions.each { |action| action.call(file_map, transform_map) }
       end
 
       # :call-seq:
@@ -272,6 +272,11 @@ module Buildr #:nodoc:
         @expanders.each { |expander| expander.concatenate(*files) }
         self
       end
+      
+      def transform(*files, &block)
+        @expanders.each { |expander| expander.transform(*files, &block) }
+        self
+      end
     end
 
 
@@ -283,6 +288,7 @@ module Buildr #:nodoc:
         @includes = []
         @excludes = []
         @concatenates = []
+        @transforms = {}
       end
 
       def include(*files)
@@ -300,8 +306,13 @@ module Buildr #:nodoc:
         @concatenates |= files
         self
       end
+      
+      def transform(*files, &block)
+        @transforms[[files].flatten] = block
+        self
+      end
 
-      def expand(file_map, path)
+      def expand(file_map, transform_map, path)
         @includes = ['*'] if @includes.empty?
         Zip::File.open(@zip_file) do |source|
           source.entries.reject { |entry| entry.directory? }.each do |entry|
@@ -311,6 +322,14 @@ module Buildr #:nodoc:
               trace "Adding #{dest}"
               if @concatenates.any? { |pattern| File.fnmatch(pattern, entry.name) }
                 file_map[dest] << ZipEntryData.new(source, entry)
+              elsif @transforms.each_pair.detect do |transform, transform_block|\
+                  if transform.any? { |pattern| File.fnmatch(pattern, entry.name) }
+                    file_map[dest] << ZipEntryData.new(source, entry)
+                    
+                    transform_map[dest] = transform_block
+                    true
+                  end
+                end
               else
                 file_map[dest] = ZipEntryData.new(source, entry)
               end
@@ -343,6 +362,7 @@ module Buildr #:nodoc:
       # Make sure we're the last enhancements, so other enhancements can add content.
       enhance do
         @file_map = Hash.new {|h,k| h[k]=[]}
+        @transform_map = {}
         enhance do
           send 'create' if respond_to?(:create)
           # We're here because the archive file does not exist, or one of the files is newer than the archive contents;
@@ -353,9 +373,9 @@ module Buildr #:nodoc:
           begin
             @paths.each do |name, object|
               @file_map[name] = nil unless name.empty?
-              object.add_files(@file_map)
+              object.add_files(@file_map, @transform_map)
             end
-            create_from @file_map
+            create_from @file_map, @transform_map
           rescue
             rm name rescue nil
             raise
@@ -501,8 +521,9 @@ module Buildr #:nodoc:
       @prepares.clear
 
       file_map = Hash.new {|h,k| h[k]=[]}
+      transform_map = {}
       @paths.each do |name, path|
-        path.add_files(file_map)
+        path.add_files(file_map, transform_map)
       end
 
       # filter out Procs (dynamic content), nils and others
index 8e094a4..16a3816 100644 (file)
@@ -74,23 +74,25 @@ module Buildr #:nodoc:
 
     private
 
-    def create_from(file_map)
+    def create_from(file_map, transform_map)
       if gzip
         StringIO.new.tap do |io|
-          create_tar io, file_map
+          create_tar io, file_map, transform_map
           io.seek 0
           Zlib::GzipWriter.open(name) { |gzip| gzip.write io.read }
         end
       else
-        File.open(name, 'wb') { |file| create_tar file, file_map }
+        File.open(name, 'wb') { |file| create_tar file, file_map, transform_map }
       end
     end
 
-    def create_tar(out, file_map)
+    def create_tar(out, file_map, transform_map)
       Archive::Tar::Minitar::Writer.open(out) do |tar|
         options = { :mode=>mode || '0755', :mtime=>Time.now }
 
         file_map.each do |path, contents|
+          to_transform = []
+          transform = transform_map.key?(path)
           if contents.nil?
           elsif File.directory?(contents.to_s)
             stat = File.stat(contents.to_s)
@@ -110,15 +112,32 @@ module Buildr #:nodoc:
             tar.add_file path, combined_options do |os, opts|
               [contents].flatten.each do |content|
                 if content.respond_to?(:call)
-                  content.call os
+                  if transform
+                    output = StringIO.new
+                    content.call output
+                    to_transform << output.string
+                  else
+                    content.call os
+                  end
                 else
                   File.open content.to_s, 'rb' do |is| 
-                    while data = is.read(4096)
-                      os.write(data)
+                    if transform
+                      output = StringIO.new
+                      while data = is.read(4096)
+                        output << data
+                      end
+                      to_transform << output.string
+                    else
+                      while data = is.read(4096)
+                        os.write(data)
+                      end
                     end
                   end
                 end
               end
+              if transform_map.key?(path)
+                os.write(transform_map[path].call(to_transform))
+              end
             end
           end
           
index 3b9f97d..8190e7b 100644 (file)
@@ -51,7 +51,7 @@ module Buildr #:nodoc:
 
     private
 
-    def create_from(file_map)
+    def create_from(file_map, transform_map)
       Zip::OutputStream.open name do |zip|
         seen = {}
         mkpath = lambda do |dir|
@@ -69,14 +69,22 @@ module Buildr #:nodoc:
           warn "Warning:  Path in zipfile #{name} contains backslash: #{path}" if path =~ /\\/
           
           entry_created = false
+          to_transform = []
+          transform = transform_map.key?(path)
           [contents].flatten.each do |content|
             if content.respond_to?(:call)
               unless entry_created
-                entry = zip.put_next_entry(path, compression_level) unless entry_created
+                entry = zip.put_next_entry(path, compression_level)
                 entry.unix_perms = content.mode & 07777 if content.respond_to?(:mode)
                 entry_created = true
               end
-              content.call zip
+              if transform
+                output = StringIO.new
+                content.call output
+                to_transform << output.string
+              else
+                content.call zip
+              end
             elsif content.nil? || File.directory?(content.to_s)
               mkpath.call path
             else
@@ -86,14 +94,23 @@ module Buildr #:nodoc:
                   entry.unix_perms = is.stat.mode & 07777
                   entry_created = true
                 end
-                
-                
-                while data = is.read(4096)
-                  zip << data
+                if transform
+                  output = StringIO.new
+                  while data = is.read(4096)
+                    output << data
+                  end
+                  to_transform << output.string
+                else
+                  while data = is.read(4096)
+                    zip << data
+                  end
                 end
               end
             end
           end
+          if transform_map.key?(path)
+            zip << transform_map[path].call(to_transform)
+          end
         end
       end
     end
index 6da2365..46f1151 100644 (file)
@@ -320,6 +320,22 @@ shared_examples_for 'ArchiveTask' do
       archive['test1.txt'].should eql(content_for('test1.txt') * @files.size)
     end
   end
+  
+  it 'should merge archives, transforming file contents' do
+    @files = %w{foo1 foo2}.map { |folder| File.join(@dir, folder) }.
+      map do |dir|
+        txt_file = File.join(dir, 'test1.txt')
+        write txt_file, content_for('test1.txt')
+        zip(File.join(dir, 'test1.zip')).include(txt_file)
+      end
+    archive(@archive).merge(@files).transform("test1.txt") do |matches|
+      matches.join("\n=====\n")
+    end
+    archive(@archive).invoke
+    inspect_archive do |archive|
+      archive['test1.txt'].should eql("#{content_for('test1.txt')}\n=====\n#{content_for('test1.txt')}")
+    end
+  end
 
   it 'should expand another archive file into path' do
     create_for_merge do |src|