class Metadata::SfdcDirectoryService
Public Class Methods
# File lib/metadata_services/sfdc_directory_service.rb, line 13 def initialize(args = {}) @args = args @output_file_name = tempfile_name("zip") find_source_dir end
Public Instance Methods
copy files from original directory to be xml_filtered when creating zip Create zip file with contents of force.com project Return absolute path to the file
# File lib/metadata_services/sfdc_directory_service.rb, line 22 def make_project_zip begin @zip_io = Zip::File.open(@output_file_name, Zip::File::CREATE) raise "package.xml NOT FOUND" unless verify_package_xml p "making temporary copy of project folder" tmpdir = Dir.mktmpdir FileUtils.cp_r(@input_dir_name, tmpdir) @input_dir_name = tmpdir.to_s + "/src" entries = dir_content(@input_dir_name) p "excluding specified components from deployment" write_entries(entries, "") ensure @zip_io.close # close before deleting tmpdir, or NOT_FOUND exception FileUtils.remove_entry(tmpdir) p "deleted temporary copy of project folder" end return @output_file_name end
Private Instance Methods
Returns array of files for the specified directory (full_path) without current_dir “.” and prev directory “..”
# File lib/metadata_services/sfdc_directory_service.rb, line 146 def dir_content(full_path) content = Dir.entries(full_path) content.delete("..") content.delete(".") return content end
# File lib/metadata_services/sfdc_directory_service.rb, line 134 def exclude_file?(filename) raise Exception if (filename.nil? or filename.empty?) if (@files_to_exclude.nil? or @files_to_exclude.empty?) @files_to_exclude = Set.new() prepare_files_to_exclude end return @files_to_exclude.include?(filename) end
Opens file. Removes all bad xml snippets. Rewrites results back into original file
# File lib/metadata_services/sfdc_directory_service.rb, line 91 def filter_xml(filename) prepare_xml_nodes_to_exclude if @snippets_to_exclude.nil? doc = Nokogiri::XML(File.read(filename)) file_modified = false @snippets_to_exclude.each do |suffix, expressions| next unless filename.end_with?(suffix.to_s) expressions.each do |search_string, should_remove_parent| nodes = doc.search(search_string.to_s) unless nodes.empty? file_modified = true nodes.each do |n| parent = n.parent n.remove unless should_remove_parent # remove only node if parent to stay parent.remove if should_remove_parent # remove the whole parent node with all children including current node end end end end File.open(filename, "w") do |file| file.print(doc.to_xml) end if file_modified end
# File lib/metadata_services/sfdc_directory_service.rb, line 46 def find_source_dir raise Exception unless Dir.exists?(@args[:source]) @input_dir_name = "" Find.find(@args[:source]) do |entry| if entry.end_with?("src") && File.directory?(entry) @input_dir_name = entry p "found 'src' directory" break end end raise "'src' directory NOT FOUND" if @input_dir_name.empty? end
check if destination server is Production
# File lib/metadata_services/sfdc_directory_service.rb, line 184 def is_production return (@args[:host].start_with?("https://login") or @args[:host].start_with?("login")) end
# File lib/metadata_services/sfdc_directory_service.rb, line 59 def prepare_files_to_exclude exclude_filename = @args[:exclude_components] # if not specified, load default exclude_components.yml if exclude_filename.nil? || !(File.exists?(exclude_filename)) p "using default exclude_components.yml" exclude_filename = File.expand_path("../exclude_components.yml", __FILE__) else p "using exclude_components.yml from forcer_config" end @files_to_exclude = Set.new YAML.load_file(exclude_filename).each do |name| @files_to_exclude.add(name.to_s.downcase) end end
# File lib/metadata_services/sfdc_directory_service.rb, line 76 def prepare_xml_nodes_to_exclude exclude_filename = @args[:exclude_xml] # if not specified, load default exclude_xml_nodes.yml if exclude_filename.nil? || !(File.exists?(exclude_filename)) p "using default exclude_xml_nodes.yml" exclude_filename = File.expand_path("../exclude_xml_nodes.yml", __FILE__) else p "using exclude_xml_nodes.yml from forcer_config" end @snippets_to_exclude = YAML.load_file(exclude_filename) end
Creates random string to guarantee uniqueness of filename Adds extension to filename
# File lib/metadata_services/sfdc_directory_service.rb, line 155 def random_filename(extension) return "#{SecureRandom.urlsafe_base64}.#{extension}" end
Creates unique filename including path to temporary directory Adds extension to filename. Default is “zip”.
# File lib/metadata_services/sfdc_directory_service.rb, line 167 def tempdir_name() return "#{Dir.tmpdir}/#{random_filename("")}" end
Creates unique filename including path to temporary directory Adds extension to filename. Default is “zip”.
# File lib/metadata_services/sfdc_directory_service.rb, line 161 def tempfile_name(extension = "zip") return "#{Dir.tmpdir}/#{random_filename(extension)}" end
check if exists or create if doesn’t
# File lib/metadata_services/sfdc_directory_service.rb, line 172 def verify_package_xml path = File.join(File.expand_path(@input_dir_name, __FILE__), "package.xml") if File.exists?(path) p "package.xml FOUND" return true else # todo logic to create package.xml. use default file return false end end
# File lib/metadata_services/sfdc_directory_service.rb, line 114 def write_entries(entries, path) entries.each do |entry| # need relative local file path to use in new zip file too zip_file_path = (path == "" ? entry : File.join(path, entry)) # maybe without if/else next if exclude_file?(zip_file_path.downcase) # need full file path to use in copy/paste disk_file_path = File.join(@input_dir_name, zip_file_path) if File.directory?(disk_file_path) @zip_io.mkdir(zip_file_path) sub_dir = dir_content(disk_file_path) write_entries(sub_dir, zip_file_path) else filter_xml(disk_file_path) unless xml_exclusion_skipped_for?(disk_file_path) @zip_io.add(zip_file_path, disk_file_path) end end end
By default for Production it only processes package.xml and other files (objects, profiles, …) are ignored (xml exclusions are OFF except package.xml). By default for Sandbox all xml exclusion are turned ON. Package.xml exclusions are OK because they allow skip deployment of certain objects/files. To turn ON all xml exclusion for Production, set –forcerExclude to TRUE To turn OFF absolutely all exclusions (package.mxl too), set –skipExclude to TRUE
# File lib/metadata_services/sfdc_directory_service.rb, line 194 def xml_exclusion_skipped_for?(full_filename) raise Exception if (full_filename.nil? or full_filename.empty?) return true if @args[:skipExclude] if full_filename.end_with?("package.xml") return false else return (is_production unless @args[:forceExclude]) end end