require 'fileutils' module Temp # A Copier object provides various functions for creating a project from a # template. It can also be given a path to the directory where templates can # be found. class Copier attr_reader :options def initialize(options = {}) @options = options @template_dir = File.expand_path(options[:template_dir] || '~/.temp') end # Creates a new project with the given path from the given template name. def create_project(project, template) project = File.expand_path(project) template_path = File.expand_path(File.join(@template_dir, template)) raise 'project already exists' if File.exist? project raise 'template does not exist' unless File.exist? template_path ignore = read_tempignore(template) files = find_files(template, ignore) FileUtils.mkdir(project) files.each do |file| p = File.join(project, file) t = File.join(template_path, file) if File.directory? t FileUtils.mkdir(p) else FileUtils.cp(t, p) end end end # Returns an array of all files in a template, optionally ignoring all files # in ignore. def find_files(template, ignore = []) template = File.expand_path(File.join(@template_dir, template)) Dir.glob(File.join(template, '**/*')).map do |file| file.sub(template + '/', '') end - ignore end # Returns an array of files in a template to ignore. def read_tempignore(template) template = File.expand_path(File.join(@template_dir, template)) tempignore = File.join(template, '.tempignore') files = ['.tempignore'] if File.exist? tempignore files |= File.read(tempignore).split(?\n).map do |line| Dir.glob(File.join(template, line)).map do |file| file.sub(template + '/', '') end end.flatten end files end end end