diff --git a/bin/jekyll b/bin/jekyll index e712616b35d..b8467fb112d 100755 --- a/bin/jekyll +++ b/bin/jekyll @@ -145,6 +145,10 @@ opts = OptionParser.new do |opts| puts "Jekyll " + Jekyll::VERSION exit 0 end + + opts.on( "--keep-files filename1,filename2", Array, "Whether to keep files that match the filename (default: .git)") do |names| + options['keep_files'] = names + end end # Read command line options into `options` hash diff --git a/lib/jekyll.rb b/lib/jekyll.rb index eef5ab1cbed..2e5a681e733 100644 --- a/lib/jekyll.rb +++ b/lib/jekyll.rb @@ -60,6 +60,7 @@ module Jekyll 'destination' => File.join(Dir.pwd, '_site'), 'plugins' => File.join(Dir.pwd, '_plugins'), 'layouts' => '_layouts', + 'keep_files' => ['.git','.svn'], 'future' => true, 'lsi' => false, diff --git a/lib/jekyll/site.rb b/lib/jekyll/site.rb index 7dbf1336aac..6afa3c9e57b 100644 --- a/lib/jekyll/site.rb +++ b/lib/jekyll/site.rb @@ -5,7 +5,8 @@ module Jekyll class Site attr_accessor :config, :layouts, :posts, :pages, :static_files, :categories, :exclude, :include, :source, :dest, :lsi, :pygments, - :permalink_style, :tags, :time, :future, :safe, :plugins, :limit_posts + :permalink_style, :tags, :time, :future, :safe, :plugins, :limit_posts, + :keep_files attr_accessor :converters, :generators @@ -26,6 +27,7 @@ def initialize(config) self.include = config['include'] || [] self.future = config['future'] self.limit_posts = config['limit_posts'] || nil + self.keep_files = config['keep_files'] || [] self.reset self.setup @@ -222,8 +224,12 @@ def render def cleanup # all files and directories in destination, including hidden ones dest_files = Set.new - Dir.glob(File.join(self.dest, "**", "*")) do |file| - dest_files << file + Dir.glob(File.join(self.dest, "**", "*"), File::FNM_DOTMATCH) do |file| + if self.keep_files.length > 0 + dest_files << file unless file =~ /\/\.{1,2}$/ || file =~ keep_file_regex + else + dest_files << file unless file =~ /\/\.{1,2}$/ + end end # files to be written @@ -244,10 +250,21 @@ def cleanup files.merge(dirs) obsolete_files = dest_files - files - FileUtils.rm_rf(obsolete_files.to_a) end + # Private: creates a regular expression from the keep_files array + # + # Examples + # ['.git','.svn'] creates the following regex: /\/(\.git|\/.svn)/ + # + # Returns the regular expression + def keep_file_regex + or_list = self.keep_files.join("|") + pattern = "\/(#{or_list.gsub(".", "\.")})" + Regexp.new pattern + end + # Write static files, pages, and posts. # # Returns nothing. diff --git a/test/test_site.rb b/test/test_site.rb index 03f1886e3d1..f71a95996f5 100644 --- a/test/test_site.rb +++ b/test/test_site.rb @@ -200,12 +200,22 @@ class TestSite < Test::Unit::TestCase File.open(dest_dir('qux/obsolete.html'), 'w') # empty directory FileUtils.mkdir(dest_dir('quux')) + FileUtils.mkdir(dest_dir('.git')) + FileUtils.mkdir(dest_dir('.svn')) + FileUtils.mkdir(dest_dir('.hg')) + # single file in repository + File.open(dest_dir('.git/HEAD'), 'w') + File.open(dest_dir('.svn/HEAD'), 'w') + File.open(dest_dir('.hg/HEAD'), 'w') end teardown do FileUtils.rm_f(dest_dir('obsolete.html')) FileUtils.rm_rf(dest_dir('qux')) FileUtils.rm_f(dest_dir('quux')) + FileUtils.rm_rf(dest_dir('.git')) + FileUtils.rm_rf(dest_dir('.svn')) + FileUtils.rm_rf(dest_dir('.hg')) end should 'remove orphaned files in destination' do @@ -213,6 +223,22 @@ class TestSite < Test::Unit::TestCase assert !File.exist?(dest_dir('obsolete.html')) assert !File.exist?(dest_dir('qux')) assert !File.exist?(dest_dir('quux')) + assert File.exist?(dest_dir('.git')) + assert File.exist?(dest_dir('.git/HEAD')) + end + + should 'remove orphaned files in destination - keep_files .svn' do + config = Jekyll::DEFAULTS.merge({'source' => source_dir, 'destination' => dest_dir, 'keep_files' => ['.svn']}) + @site = Site.new(config) + @site.process + assert !File.exist?(dest_dir('.htpasswd')) + assert !File.exist?(dest_dir('obsolete.html')) + assert !File.exist?(dest_dir('qux')) + assert !File.exist?(dest_dir('quux')) + assert !File.exist?(dest_dir('.git')) + assert !File.exist?(dest_dir('.git/HEAD')) + assert File.exist?(dest_dir('.svn')) + assert File.exist?(dest_dir('.svn/HEAD')) end end