Merge pull request #2882 from jekyll/security/centralize-path-sanitation

This commit is contained in:
Parker Moore 2014-11-05 10:21:57 -08:00
commit 2ec1dc1831
26 changed files with 240 additions and 176 deletions

View File

@ -68,11 +68,12 @@ module Jekyll
require 'jekyll/command'
require 'jekyll/liquid_extensions'
class << self
# Public: Tells you which Jekyll environment you are building in so you can skip tasks
# if you need to. This is useful when doing expensive compression tasks on css and
# images and allows you to skip that when working in development.
def self.env
def env
ENV["JEKYLL_ENV"] || "development"
end
@ -84,10 +85,12 @@ module Jekyll
# list of option names and their defaults.
#
# Returns the final configuration Hash.
def self.configuration(override)
def configuration(override = Hash.new)
config = Configuration[Configuration::DEFAULTS]
override = Configuration[override].stringify_keys
unless override.delete('skip_config_files')
config = config.read_config_files(config.config_files(override))
end
# Merge DEFAULTS < _config.yml < override
config = Utils.deep_merge_hashes(config, override).stringify_keys
@ -96,32 +99,49 @@ module Jekyll
config
end
# Static: Set the TZ environment variable to use the timezone specified
# Public: Set the TZ environment variable to use the timezone specified
#
# timezone - the IANA Time Zone
#
# Returns nothing
def self.set_timezone(timezone)
def set_timezone(timezone)
ENV['TZ'] = timezone
end
def self.logger
# Public: Fetch the logger instance for this Jekyll process.
#
# Returns the LogAdapter instance.
def logger
@logger ||= LogAdapter.new(Stevenson.new)
end
def self.logger=(writer)
# Public: Set the log writer.
# New log writer must respond to the same methods
# as Ruby's interal Logger.
#
# writer - the new Logger-compatible log transport
#
# Returns the new logger.
def logger=(writer)
@logger = LogAdapter.new(writer)
end
# Public: File system root
# Public: An array of sites
#
# Returns the root of the filesystem as a Pathname
def self.fs_root
@fs_root ||= "/"
# Returns the Jekyll sites created.
def sites
@sites ||= []
end
def self.sanitized_path(base_directory, questionable_path)
clean_path = File.expand_path(questionable_path, fs_root)
# Public: Ensures the questionable path is prefixed with the base directory
# and prepends the questionable path with the base directory if false.
#
# base_directory - the directory with which to prefix the questionable path
# questionable_path - the path we're unsure about, and want prefixed
#
# Returns the sanitized path.
def sanitized_path(base_directory, questionable_path)
clean_path = File.expand_path(questionable_path, "/")
clean_path.gsub!(/\A\w\:\//, '/')
unless clean_path.start_with?(base_directory)
File.join(base_directory, clean_path)
@ -129,6 +149,8 @@ module Jekyll
clean_path
end
end
end
end
require_all 'jekyll/commands'

View File

@ -29,7 +29,7 @@ module Jekyll
# Returns a Set with the file paths
def existing_files
files = Set.new
Dir.glob(File.join(site.dest, "**", "*"), File::FNM_DOTMATCH) do |file|
Dir.glob(site.in_dest_dir("**", "*"), File::FNM_DOTMATCH) do |file|
files << file unless file =~ /\/\.{1,2}$/ || file =~ keep_file_regex || keep_dirs.include?(file)
end
files
@ -76,7 +76,7 @@ module Jekyll
#
# Returns a Set with the directory paths
def keep_dirs
site.keep_files.map { |file| parent_dirs(File.join(site.dest, file)) }.flatten.to_set
site.keep_files.map { |file| parent_dirs(site.in_dest_dir(file)) }.flatten.to_set
end
# Private: Creates a regular expression from the config's keep_files array

View File

@ -35,7 +35,8 @@ module Jekyll
# Returns the sorted array of docs.
def read
filtered_entries.each do |file_path|
full_path = Jekyll.sanitized_path(directory, file_path)
full_path = collection_dir(file_path)
next if File.directory?(full_path)
if Utils.has_yaml_header? full_path
doc = Jekyll::Document.new(full_path, { site: site, collection: self })
doc.read
@ -54,8 +55,9 @@ module Jekyll
# relative to the collection's directory
def entries
return Array.new unless exists?
Dir.glob(File.join(directory, "**", "*.*")).map do |entry|
entry[File.join(directory, "")] = ''; entry
@entries ||=
Dir.glob(collection_dir("**", "*.*")).map do |entry|
entry["#{collection_dir}/"] = ''; entry
end
end
@ -65,8 +67,12 @@ module Jekyll
# Returns a list of filtered entry paths.
def filtered_entries
return Array.new unless exists?
@filtered_entries ||=
Dir.chdir(directory) do
entry_filter.filter(entries).reject { |f| File.directory?(f) }
entry_filter.filter(entries).reject do |f|
path = collection_dir(f)
File.directory?(path) || (File.symlink?(f) && site.safe)
end
end
end
@ -78,12 +84,25 @@ module Jekyll
@relative_directory ||= "_#{label}"
end
# The full path to the directory containing the
# The full path to the directory containing the collection.
#
# Returns a String containing th directory name where the collection
# is stored on the filesystem.
def directory
@directory ||= Jekyll.sanitized_path(site.source, relative_directory)
@directory ||= site.in_source_dir(relative_directory)
end
# The full path to the directory containing the collection, with
# optional subpaths.
#
# *files - (optional) any other path pieces relative to the
# directory to append to the path
#
# Returns a String containing th directory name where the collection
# is stored on the filesystem.
def collection_dir(*files)
return directory if files.empty?
site.in_source_dir(relative_directory, *files)
end
# Checks whether the directory "exists" for this collection.

View File

@ -43,7 +43,7 @@ module Jekyll
# Returns nothing.
def read_yaml(base, name, opts = {})
begin
self.content = File.read(Jekyll.sanitized_path(base, name),
self.content = File.read(site.in_source_dir(base, name),
merged_file_read_opts(opts))
if content =~ /\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)/m
self.content = $POSTMATCH

View File

@ -159,7 +159,8 @@ module Jekyll
#
# Returns the full path to the output file of this document.
def destination(base_directory)
path = Jekyll.sanitized_path(base_directory, url)
dest = site.in_dest_dir(base_directory)
path = site.in_dest_dir(dest, url)
path = File.join(path, "index.html") if url =~ /\/$/
path
end

View File

@ -14,8 +14,8 @@ module Jekyll
end
# Get the full path to the directory containing the draft files
def containing_dir(source, dir)
File.join(source, dir, '_drafts')
def containing_dir(dir)
site.in_source_dir(dir, '_drafts')
end
# The path to the draft source file, relative to the site source

View File

@ -106,7 +106,7 @@ module Jekyll
# Returns excerpt String
def extract_excerpt(post_content)
separator = site.config['excerpt_separator']
head, _, tail = post_content.partition(separator)
head, _, tail = post_content.to_s.partition(separator)
"" << head << "\n\n" << tail.scan(/^\[[^\]]+\]:.+$/).join("\n")
end

View File

@ -38,12 +38,12 @@ module Jekyll
end
def layout_directory_inside_source
Jekyll.sanitized_path(site.source, site.config['layouts'])
site.in_source_dir(site.config['layouts'])
end
def layout_directory_in_cwd
dir = Jekyll.sanitized_path(Dir.pwd, site.config['layouts'])
if File.directory?(dir)
if File.directory?(dir) && !site.safe
dir
else
nil

View File

@ -140,7 +140,7 @@ module Jekyll
#
# Returns the destination file path String.
def destination(dest)
path = Jekyll.sanitized_path(dest, URL.unescape_path(url))
path = site.in_dest_dir(dest, URL.unescape_path(url))
path = File.join(path, "index.html") if url =~ /\/$/
path
end

View File

@ -66,7 +66,7 @@ module Jekyll
# Returns an Array of plugin search paths
def plugins_path
if (site.config['plugins'] == Jekyll::Configuration::DEFAULTS['plugins'])
[Jekyll.sanitized_path(site.source, site.config['plugins'])]
[site.in_source_dir(site.config['plugins'])]
else
Array(site.config['plugins']).map { |d| File.expand_path(d) }
end

View File

@ -49,7 +49,7 @@ module Jekyll
def initialize(site, source, dir, name)
@site = site
@dir = dir
@base = containing_dir(source, dir)
@base = containing_dir(dir)
@name = name
self.categories = dir.downcase.split('/').reject { |x| x.empty? }
@ -88,8 +88,8 @@ module Jekyll
end
# Get the full path to the directory containing the post files
def containing_dir(source, dir)
return File.join(source, dir, '_posts')
def containing_dir(dir)
site.in_source_dir(dir, '_posts')
end
# Read the YAML frontmatter.
@ -268,7 +268,7 @@ module Jekyll
# Returns destination file path String.
def destination(dest)
# The url needs to be unescaped in order to preserve the correct filename
path = Jekyll.sanitized_path(dest, URL.unescape_path(url))
path = site.in_dest_dir(dest, URL.unescape_path(url))
path = File.join(path, "index.html") if path[/\.html?$/].nil?
path
end

View File

@ -46,8 +46,7 @@ module Jekyll
end
def most_recent_posts
recent_posts = site.posts.reverse - [post]
recent_posts.first(10)
@most_recent_posts ||= (site.posts.reverse - [post]).first(10)
end
def display(output)

View File

@ -3,11 +3,12 @@ require 'csv'
module Jekyll
class Site
attr_accessor :config, :layouts, :posts, :pages, :static_files,
:exclude, :include, :source, :dest, :lsi, :highlighter,
:permalink_style, :time, :future, :unpublished, :safe, :plugins, :limit_posts,
:show_drafts, :keep_files, :baseurl, :data, :file_read_opts, :gems,
:plugin_manager
attr_reader :source, :dest, :config
attr_accessor :layouts, :posts, :pages, :static_files,
:exclude, :include, :lsi, :highlighter, :permalink_style,
:time, :future, :unpublished, :safe, :plugins, :limit_posts,
:show_drafts, :keep_files, :baseurl, :data, :file_read_opts,
:gems, :plugin_manager
attr_accessor :converters, :generators
@ -15,16 +16,16 @@ module Jekyll
#
# config - A Hash containing site configuration details.
def initialize(config)
self.config = config.clone
@config = config.clone
%w[safe lsi highlighter baseurl exclude include future unpublished
show_drafts limit_posts keep_files gems].each do |opt|
self.send("#{opt}=", config[opt])
end
self.source = File.expand_path(config['source'])
self.dest = File.expand_path(config['destination'])
self.permalink_style = config['permalink'].to_sym
# Source and destination may not be changed after the site has been created.
@source = File.expand_path(config['source']).freeze
@dest = File.expand_path(config['destination']).freeze
self.plugin_manager = Jekyll::PluginManager.new(self)
self.plugins = plugin_manager.plugins_path
@ -32,6 +33,10 @@ module Jekyll
self.file_read_opts = {}
self.file_read_opts[:encoding] = config['encoding'] if config['encoding']
self.permalink_style = config['permalink'].to_sym
Jekyll.sites << self
reset
setup
end
@ -88,6 +93,30 @@ module Jekyll
end
end
# Public: Prefix a given path with the source directory.
#
# paths - (optional) path elements to a file or directory within the
# source directory
#
# Returns a path which is prefixed with the source directory.
def in_source_dir(*paths)
paths.reduce(source) do |base, path|
Jekyll.sanitized_path(base, path)
end
end
# Public: Prefix a given path with the destination directory.
#
# paths - (optional) path elements to a file or directory within the
# destination directory
#
# Returns a path which is prefixed with the destination directory.
def in_dest_dir(*paths)
paths.reduce(dest) do |base, path|
Jekyll.sanitized_path(base, path)
end
end
# The list of collections and their corresponding Jekyll::Collection instances.
# If config['collections'] is set, a new instance is created for each item in the collection.
# If config['collections'] is not set, a new hash is returned.
@ -132,7 +161,7 @@ module Jekyll
#
# Returns nothing.
def read_directories(dir = '')
base = File.join(source, dir)
base = in_source_dir(dir)
entries = Dir.chdir(base) { filter_entries(Dir.entries('.'), base) }
read_posts(dir)
@ -141,7 +170,7 @@ module Jekyll
limit_posts! if limit_posts > 0 # limit the posts if :limit_posts option is set
entries.each do |f|
f_abs = File.join(base, f)
f_abs = in_source_dir(base, f)
if File.directory?(f_abs)
f_rel = File.join(dir, f)
read_directories(f_rel) unless dest.sub(/\/$/, '') == f_abs
@ -198,7 +227,7 @@ module Jekyll
#
# Returns nothing
def read_data(dir)
base = Jekyll.sanitized_path(source, dir)
base = in_source_dir(dir)
read_data_to(base, self.data)
end
@ -217,7 +246,7 @@ module Jekyll
end
entries.each do |entry|
path = Jekyll.sanitized_path(dir, entry)
path = in_source_dir(dir, entry)
next if File.symlink?(path) && safe
key = sanitize_filename(File.basename(entry, '.*'))
@ -407,10 +436,10 @@ module Jekyll
#
# Returns the list of entries to process
def get_entries(dir, subfolder)
base = File.join(source, dir, subfolder)
base = in_source_dir(dir, subfolder)
return [] unless File.exist?(base)
entries = Dir.chdir(base) { filter_entries(Dir['**/*'], base) }
entries.delete_if { |e| File.directory?(File.join(base, e)) }
entries.delete_if { |e| File.directory?(in_source_dir(base, e)) }
end
# Aggregate post information

View File

@ -37,7 +37,7 @@ module Jekyll
#
# Returns destination file path.
def destination(dest)
File.join(*[dest, destination_rel_dir, @name].compact)
@site.in_dest_dir(*[dest, destination_rel_dir, @name].compact)
end
def destination_rel_dir

View File

@ -161,7 +161,7 @@ eos
end
def resolved_includes_dir(context)
Jekyll.sanitized_path(context.registers[:site].source, page_path(context))
context.registers[:site].in_source_dir(page_path(context))
end
end
end

View File

@ -30,10 +30,10 @@ class Test::Unit::TestCase
end
def site_configuration(overrides = {})
full_overrides = build_configs(overrides, build_configs({"destination" => dest_dir}))
build_configs({
"source" => source_dir,
"destination" => dest_dir
}, build_configs(overrides))
}, full_overrides)
end
def dest_dir(*subdirs)

View File

@ -4,15 +4,16 @@ class TestCleaner < Test::Unit::TestCase
context "directory in keep_files" do
setup do
clear_dest
stub(Jekyll).configuration do
Jekyll::Configuration::DEFAULTS.merge({'source' => source_dir, 'destination' => dest_dir})
end
FileUtils.mkdir_p(dest_dir('to_keep/child_dir'))
FileUtils.touch(File.join(dest_dir('to_keep'), 'index.html'))
FileUtils.touch(File.join(dest_dir('to_keep/child_dir'), 'index.html'))
@site = Site.new(Jekyll.configuration)
@site = Site.new(Jekyll.configuration({
"skip_config_files" => true,
"source" => source_dir,
"destination" => dest_dir
}))
@site.keep_files = ['to_keep/child_dir']
@cleaner = Site::Cleaner.new(@site)
@ -43,14 +44,15 @@ class TestCleaner < Test::Unit::TestCase
context "directory containing no files and non-empty directories" do
setup do
clear_dest
stub(Jekyll).configuration do
Jekyll::Configuration::DEFAULTS.merge({'source' => source_dir, 'destination' => dest_dir})
end
FileUtils.mkdir_p(source_dir('no_files_inside/child_dir'))
FileUtils.touch(File.join(source_dir('no_files_inside/child_dir'), 'index.html'))
@site = Site.new(Jekyll.configuration)
@site = Site.new(Jekyll.configuration({
"skip_config_files" => true,
"source" => source_dir,
"destination" => dest_dir
}))
@site.process
@cleaner = Site::Cleaner.new(@site)

View File

@ -187,6 +187,7 @@ class TestCollections < Test::Unit::TestCase
should "not allow symlinks" do
assert_not_include @collection.filtered_entries, "um_hi.md"
assert_not_include @collection.filtered_entries, "/um_hi.md"
end
should "not include the symlinked file in the list of docs" do

View File

@ -4,7 +4,11 @@ require 'ostruct'
class TestConvertible < Test::Unit::TestCase
context "yaml front-matter" do
setup do
@convertible = OpenStruct.new
@convertible = OpenStruct.new(
"site" => Site.new(Jekyll.configuration(
"source" => File.expand_path('../fixtures', __FILE__)
))
)
@convertible.extend Jekyll::Convertible
@base = File.expand_path('../fixtures', __FILE__)
end

View File

@ -13,6 +13,10 @@ class TestDocument < Test::Unit::TestCase
@document = @site.collections["methods"].docs.first
end
should "exist" do
assert !@document.nil?
end
should "know its relative path" do
assert_equal "_methods/configuration.md", @document.relative_path
end

View File

@ -8,8 +8,7 @@ class TestDraft < Test::Unit::TestCase
context "A Draft" do
setup do
clear_dest
stub(Jekyll).configuration { Jekyll::Configuration::DEFAULTS }
@site = Site.new(Jekyll.configuration)
@site = Site.new(site_configuration)
end
should "ensure valid drafts are valid" do

View File

@ -3,10 +3,7 @@ require 'helper'
class TestEntryFilter < Test::Unit::TestCase
context "Filtering entries" do
setup do
stub(Jekyll).configuration do
Jekyll::Configuration::DEFAULTS.merge({'source' => source_dir, 'destination' => dest_dir})
end
@site = Site.new(Jekyll.configuration)
@site = Site.new(site_configuration)
end
should "filter entries" do
@ -50,10 +47,7 @@ class TestEntryFilter < Test::Unit::TestCase
end
should "filter symlink entries when safe mode enabled" do
stub(Jekyll).configuration do
Jekyll::Configuration::DEFAULTS.merge({'source' => source_dir, 'destination' => dest_dir, 'safe' => true})
end
site = Site.new(Jekyll.configuration)
site = Site.new(site_configuration('safe' => true))
stub(File).symlink?('symlink.js') {true}
files = %w[symlink.js]
assert_equal [], site.filter_entries(files)
@ -66,10 +60,7 @@ class TestEntryFilter < Test::Unit::TestCase
end
should "not include symlinks in safe mode" do
stub(Jekyll).configuration do
Jekyll::Configuration::DEFAULTS.merge({'source' => source_dir, 'destination' => dest_dir, 'safe' => true})
end
site = Site.new(Jekyll.configuration)
site = Site.new(site_configuration('safe' => true))
site.read_directories("symlink-test")
assert_equal [], site.pages
@ -77,10 +68,7 @@ class TestEntryFilter < Test::Unit::TestCase
end
should "include symlinks in unsafe mode" do
stub(Jekyll).configuration do
Jekyll::Configuration::DEFAULTS.merge({'source' => source_dir, 'destination' => dest_dir, 'safe' => false})
end
site = Site.new(Jekyll.configuration)
site = Site.new(site_configuration)
site.read_directories("symlink-test")
assert_not_equal [], site.pages
@ -90,10 +78,7 @@ class TestEntryFilter < Test::Unit::TestCase
context "#glob_include?" do
setup do
stub(Jekyll).configuration do
Jekyll::Configuration::DEFAULTS.merge({'source' => source_dir, 'destination' => dest_dir})
end
@site = Site.new(Jekyll.configuration)
@site = Site.new(site_configuration)
@filter = EntryFilter.new(@site)
end

View File

@ -13,10 +13,7 @@ class TestExcerpt < Test::Unit::TestCase
context "With extraction disabled" do
setup do
clear_dest
stub(Jekyll).configuration do
Jekyll::Configuration::DEFAULTS.merge({'excerpt_separator' => ''})
end
@site = Site.new(Jekyll.configuration)
@site = Site.new(site_configuration('excerpt_separator' => ''))
@post = setup_post("2013-07-22-post-excerpt-with-layout.markdown")
end
@ -29,8 +26,7 @@ class TestExcerpt < Test::Unit::TestCase
context "An extracted excerpt" do
setup do
clear_dest
stub(Jekyll).configuration { Jekyll::Configuration::DEFAULTS }
@site = Site.new(Jekyll.configuration)
@site = Site.new(site_configuration)
@post = setup_post("2013-07-22-post-excerpt-with-layout.markdown")
@excerpt = @post.send :extract_excerpt
end

View File

@ -15,8 +15,11 @@ class TestPage < Test::Unit::TestCase
context "A Page" do
setup do
clear_dest
stub(Jekyll).configuration { Jekyll::Configuration::DEFAULTS }
@site = Site.new(Jekyll.configuration)
@site = Site.new(Jekyll.configuration({
"source" => source_dir,
"destination" => dest_dir,
"skip_config_files" => true
}))
end
context "processing pages" do

View File

@ -15,8 +15,11 @@ class TestPost < Test::Unit::TestCase
context "A Post" do
setup do
clear_dest
stub(Jekyll).configuration { Jekyll::Configuration::DEFAULTS }
@site = Site.new(Jekyll.configuration)
@site = Site.new(Jekyll.configuration({
"skip_config_files" => true,
"source" => source_dir,
"destination" => dest_dir
}))
end
should "ensure valid posts are valid" do
@ -145,7 +148,7 @@ class TestPost < Test::Unit::TestCase
do_render(post)
post.write(dest_dir)
assert !File.exist?(unexpected)
assert !File.exist?(unexpected), "../../../baddie.html should not exist."
assert File.exist?(File.expand_path("baddie.html", dest_dir))
end
@ -606,7 +609,7 @@ class TestPost < Test::Unit::TestCase
should "include templates" do
post = setup_post("2008-12-13-include.markdown")
post.site.source = File.join(File.dirname(__FILE__), 'source')
post.site.instance_variable_set(:@source, File.join(File.dirname(__FILE__), 'source'))
do_render(post)
assert_equal "<<< <hr />\n<p>Tom Preston-Werner\ngithub.com/mojombo</p>\n\n<p>This <em>is</em> cool</p>\n >>>", post.output
@ -685,7 +688,7 @@ class TestPost < Test::Unit::TestCase
context "site config with category" do
setup do
config = Jekyll::Configuration::DEFAULTS.merge({
config = site_configuration({
'defaults' => [
'scope' => {
'path' => ''
@ -712,7 +715,7 @@ class TestPost < Test::Unit::TestCase
context "site config with categories" do
setup do
config = Jekyll::Configuration::DEFAULTS.merge({
config = site_configuration({
'defaults' => [
'scope' => {
'path' => ''

View File

@ -8,7 +8,7 @@ class TestSite < Test::Unit::TestCase
end
should "look for plugins under the site directory by default" do
site = Site.new(Jekyll::Configuration::DEFAULTS.merge({'source' => File.expand_path(source_dir)}))
site = Site.new(site_configuration)
assert_equal [File.join(source_dir, '_plugins')], site.plugins
end
@ -44,30 +44,35 @@ class TestSite < Test::Unit::TestCase
end
context "creating sites" do
setup do
stub(Jekyll).configuration do
Jekyll::Configuration::DEFAULTS.merge({'source' => source_dir, 'destination' => dest_dir})
end
@site = Site.new(Jekyll.configuration)
@site = Site.new(site_configuration)
@num_invalid_posts = 4
end
teardown do
if defined?(MyGenerator)
self.class.send(:remove_const, :MyGenerator)
end
end
should "have an empty tag hash by default" do
assert_equal Hash.new, @site.tags
end
should "give site with parsed pages and posts to generators" do
@site.reset
@site.read
class MyGenerator < Generator
def generate(site)
site.pages.dup.each do |page|
raise "#{page} isn't a page" unless page.is_a?(Page)
raise "#{page} doesn't respond to :name" unless page.respond_to?(:name)
end
site.file_read_opts[:secret_message] = 'hi'
end
end
@site = Site.new(site_configuration)
@site.read
@site.generate
assert_not_equal 0, @site.pages.size
assert_equal 'hi', @site.file_read_opts[:secret_message]
end
should "reset data before processing" do
@ -221,22 +226,14 @@ class TestSite < Test::Unit::TestCase
context 'error handling' do
should "raise if destination is included in source" do
stub(Jekyll).configuration do
Jekyll::Configuration::DEFAULTS.merge({'source' => source_dir, 'destination' => source_dir})
end
assert_raise Jekyll::Errors::FatalException do
site = Site.new(Jekyll.configuration)
site = Site.new(site_configuration('destination' => source_dir))
end
end
should "raise if destination is source" do
stub(Jekyll).configuration do
Jekyll::Configuration::DEFAULTS.merge({'source' => source_dir, 'destination' => File.join(source_dir, "..")})
end
assert_raise Jekyll::Errors::FatalException do
site = Site.new(Jekyll.configuration)
site = Site.new(site_configuration('destination' => File.join(source_dir, "..")))
end
end
end
@ -281,7 +278,7 @@ class TestSite < Test::Unit::TestCase
end
should 'remove orphaned files in destination - keep_files .svn' do
config = Jekyll::Configuration::DEFAULTS.merge({'source' => source_dir, 'destination' => dest_dir, 'keep_files' => ['.svn']})
config = site_configuration('keep_files' => %w{.svn})
@site = Site.new(config)
@site.process
assert !File.exist?(dest_dir('.htpasswd'))
@ -308,7 +305,7 @@ class TestSite < Test::Unit::TestCase
end
custom_processor = "CustomMarkdown"
s = Site.new(Jekyll.configuration.merge({ 'markdown' => custom_processor }))
s = Site.new(site_configuration('markdown' => custom_processor))
assert_nothing_raised do
s.process
end
@ -331,7 +328,7 @@ class TestSite < Test::Unit::TestCase
end
bad_processor = "Custom::Markdown"
s = Site.new(Jekyll.configuration.merge({ 'markdown' => bad_processor }))
s = Site.new(site_configuration('markdown' => bad_processor))
assert_raise Jekyll::Errors::FatalException do
s.process
end
@ -345,13 +342,13 @@ class TestSite < Test::Unit::TestCase
should 'not throw an error at initialization time' do
bad_processor = 'not a processor name'
assert_nothing_raised do
Site.new(Jekyll.configuration.merge({ 'markdown' => bad_processor }))
Site.new(site_configuration('markdown' => bad_processor))
end
end
should 'throw FatalException at process time' do
bad_processor = 'not a processor name'
s = Site.new(Jekyll.configuration.merge({ 'markdown' => bad_processor }))
s = Site.new(site_configuration('markdown' => bad_processor))
assert_raise Jekyll::Errors::FatalException do
s.process
end
@ -360,7 +357,7 @@ class TestSite < Test::Unit::TestCase
context 'data directory' do
should 'auto load yaml files' do
site = Site.new(Jekyll.configuration)
site = Site.new(site_configuration)
site.process
file_content = SafeYAML.load_file(File.join(source_dir, '_data', 'members.yaml'))
@ -370,7 +367,7 @@ class TestSite < Test::Unit::TestCase
end
should 'auto load yml files' do
site = Site.new(Jekyll.configuration)
site = Site.new(site_configuration)
site.process
file_content = SafeYAML.load_file(File.join(source_dir, '_data', 'languages.yml'))
@ -380,7 +377,7 @@ class TestSite < Test::Unit::TestCase
end
should 'auto load json files' do
site = Site.new(Jekyll.configuration)
site = Site.new(site_configuration)
site.process
file_content = SafeYAML.load_file(File.join(source_dir, '_data', 'members.json'))
@ -390,7 +387,7 @@ class TestSite < Test::Unit::TestCase
end
should 'auto load yaml files in subdirectory' do
site = Site.new(Jekyll.configuration)
site = Site.new(site_configuration)
site.process
file_content = SafeYAML.load_file(File.join(source_dir, '_data', 'categories', 'dairy.yaml'))
@ -400,7 +397,7 @@ class TestSite < Test::Unit::TestCase
end
should "load symlink files in unsafe mode" do
site = Site.new(Jekyll.configuration.merge({'safe' => false}))
site = Site.new(site_configuration('safe' => false))
site.process
file_content = SafeYAML.load_file(File.join(source_dir, '_data', 'products.yml'))
@ -410,7 +407,7 @@ class TestSite < Test::Unit::TestCase
end
should "not load symlink files in safe mode" do
site = Site.new(Jekyll.configuration.merge({'safe' => true}))
site = Site.new(site_configuration('safe' => true))
site.process
assert_nil site.data['products']