module VMC::Cli module FileHelper class SYSIgnore def initialize(patterns,project_root = "") @patterns = patterns + [ ".git/" ] @project_root = project_root end def included_files(filenames) exclude_dots_only(filenames).reject do |filename| exclude = false @patterns.each do |pattern| if is_negative_pattern?(pattern) exclude = false if negative_match(pattern,filename) else exclude ||= match(pattern,filename) end end exclude end end def exclude_dots_only(filenames) filenames.reject do |filename| base = File.basename(filename) base == "." || base == ".." end end def excluded_files(filenames) filenames - included_files(filenames) end def self.from_file(project_root) f = "#{project_root}/.sysignore" if File.exists?(f) contents = File.read(f).split("\n") SYSIgnore.new(contents,project_root) else SYSIgnore.new([],project_root) end end def match(pattern,filename) filename = filename.sub(/^#{@project_root}\//,'') # remove any project directory prefix return false if pattern =~ /^\s*$/ # ignore blank lines return false if pattern =~ /^#/ # lines starting with # are comments return false if pattern =~ /^!/ # lines starting with ! are negated if pattern =~ /\/$/ # pattern ending in a slash should ignore directory and all its children dirname = pattern.sub(/\/$/,'') return filename == dirname || filename =~ /^#{dirname}\/.*$/ end if pattern =~ /^\// parts = filename.split('/') return File.fnmatch(pattern.sub(/^\//,''),parts[0]) end if pattern.include? '/' return File.fnmatch(pattern,filename) end File.fnmatch(pattern,filename,File::FNM_PATHNAME) end def is_negative_pattern?(pattern) pattern =~ /^!/ end def negative_match(pattern,filename) return false unless pattern =~ /^!/ match(pattern.sub(/^!/,''),filename) end end def ignore_sockets(files) files.reject { |f| File.socket? f } end def check_unreachable_links(path,files) pwd = Pathname.new(path) abspath = pwd.realpath.to_s unreachable = [] files.each do |f| file = Pathname.new(f) if file.symlink? && !file.realpath.to_s.start_with?(abspath) unreachable << file.relative_path_from(pwd).to_s end end unless unreachable.empty? root = pwd.relative_path_from(pwd).to_s err "Can't deploy application containing links '#{unreachable.join(",")}' that reach outside its root '#{root}'" end end def copy_files(project_root,files,dest_dir) project_root = Pathname.new(project_root) files.each do |f| dest = Pathname.new(f).relative_path_from(project_root) if File.symlink?(f) FileUtils.copy_entry(f,"#{dest_dir}/#{dest}") elsif File.directory?(f) FileUtils.mkdir_p("#{dest_dir}/#{dest}") else FileUtils.cp(f,"#{dest_dir}/#{dest}") end end end end end