From 98405edf61a02b4a8697a05ec2320c9337d844c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20K=C3=B6plinger?= Date: Fri, 28 Nov 2014 20:26:50 +0100 Subject: [PATCH 1/4] Add a Jekyll doctor warning for URLs that only differ by case Those URLs are problematic on case-insensitive file systems because one of the URLs is overwritten by the other. Fixes #3035 --- lib/jekyll/commands/doctor.rb | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/lib/jekyll/commands/doctor.rb b/lib/jekyll/commands/doctor.rb index 0fab8b3a..5d3dfc61 100644 --- a/lib/jekyll/commands/doctor.rb +++ b/lib/jekyll/commands/doctor.rb @@ -31,7 +31,8 @@ module Jekyll def healthy?(site) [ !deprecated_relative_permalinks(site), - !conflicting_urls(site) + !conflicting_urls(site), + !urls_only_differ_by_case(site) ].all? end @@ -63,6 +64,22 @@ module Jekyll conflicting_urls end + def urls_only_differ_by_case(site) + urls_only_differ_by_case = false + urls = {} + urls = collect_urls_case_insensitive(urls, site.pages, site.dest) + urls = collect_urls_case_insensitive(urls, site.posts, site.dest) + urls.each do |case_insensitive_url, real_urls| + if real_urls.uniq.size > 1 + urls_only_differ_by_case = true + Jekyll.logger.warn "Warning:", "The following URLs only differ" + + " by case. On a case-insensitive file system one of the URLs" + + " will be overwritten by the other: #{real_urls.join(", ")}" + end + end + urls_only_differ_by_case + end + private def collect_urls(urls, things, destination) @@ -77,6 +94,17 @@ module Jekyll urls end + def collect_urls_case_insensitive(urls, things, destination) + things.each do |thing| + dest = thing.destination(destination) + if urls[dest.downcase] + urls[dest.downcase] << dest + else + urls[dest.downcase] = [dest] + end + end + urls + end end end From a0da18e4f85c9b844bd29da5bfc7c1b24aedcdd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20K=C3=B6plinger?= Date: Sun, 30 Nov 2014 14:30:22 +0100 Subject: [PATCH 2/4] Incorporate code review feedback --- lib/jekyll/commands/doctor.rb | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/lib/jekyll/commands/doctor.rb b/lib/jekyll/commands/doctor.rb index 5d3dfc61..8da68956 100644 --- a/lib/jekyll/commands/doctor.rb +++ b/lib/jekyll/commands/doctor.rb @@ -95,13 +95,10 @@ module Jekyll end def collect_urls_case_insensitive(urls, things, destination) - things.each do |thing| - dest = thing.destination(destination) - if urls[dest.downcase] - urls[dest.downcase] << dest - else - urls[dest.downcase] = [dest] - end + things.inject(urls) do |memo, thing| + dest = thing.destination(destination) + (memo[dest.downcase] ||= []) << dest + memo end urls end From 6055f112fb248e90f5bc8378f7c06942645296ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20K=C3=B6plinger?= Date: Sun, 30 Nov 2014 14:52:16 +0100 Subject: [PATCH 3/4] Incorporate code review feedback --- lib/jekyll/commands/doctor.rb | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/jekyll/commands/doctor.rb b/lib/jekyll/commands/doctor.rb index 8da68956..d238f0d1 100644 --- a/lib/jekyll/commands/doctor.rb +++ b/lib/jekyll/commands/doctor.rb @@ -66,9 +66,7 @@ module Jekyll def urls_only_differ_by_case(site) urls_only_differ_by_case = false - urls = {} - urls = collect_urls_case_insensitive(urls, site.pages, site.dest) - urls = collect_urls_case_insensitive(urls, site.posts, site.dest) + urls = case_insensitive_urls(site.pages + site.posts, site.dest) urls.each do |case_insensitive_url, real_urls| if real_urls.uniq.size > 1 urls_only_differ_by_case = true @@ -94,13 +92,12 @@ module Jekyll urls end - def collect_urls_case_insensitive(urls, things, destination) - things.inject(urls) do |memo, thing| + def case_insensitive_urls(things, destination) + things.inject(Hash.new) do |memo, thing| dest = thing.destination(destination) (memo[dest.downcase] ||= []) << dest memo end - urls end end From 34ff0bbb36916dff4bd719981c2f15d903f862a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20K=C3=B6plinger?= Date: Mon, 15 Dec 2014 21:26:47 +0100 Subject: [PATCH 4/4] Added tests for new jekyll doctor warning --- .../_urls_differ_by_case_invalid/page1.html | 6 ++++ .../_urls_differ_by_case_invalid/page2.html | 6 ++++ .../_urls_differ_by_case_valid/page1.html | 6 ++++ test/test_doctor_command.rb | 36 +++++++++++++++++++ 4 files changed, 54 insertions(+) create mode 100644 test/source/_urls_differ_by_case_invalid/page1.html create mode 100644 test/source/_urls_differ_by_case_invalid/page2.html create mode 100644 test/source/_urls_differ_by_case_valid/page1.html create mode 100644 test/test_doctor_command.rb diff --git a/test/source/_urls_differ_by_case_invalid/page1.html b/test/source/_urls_differ_by_case_invalid/page1.html new file mode 100644 index 00000000..a6a79f93 --- /dev/null +++ b/test/source/_urls_differ_by_case_invalid/page1.html @@ -0,0 +1,6 @@ +--- +title: About +permalink: /about/ +--- + +About the site diff --git a/test/source/_urls_differ_by_case_invalid/page2.html b/test/source/_urls_differ_by_case_invalid/page2.html new file mode 100644 index 00000000..21f679f3 --- /dev/null +++ b/test/source/_urls_differ_by_case_invalid/page2.html @@ -0,0 +1,6 @@ +--- +title: About +permalink: /About/ +--- + +About the site diff --git a/test/source/_urls_differ_by_case_valid/page1.html b/test/source/_urls_differ_by_case_valid/page1.html new file mode 100644 index 00000000..a6a79f93 --- /dev/null +++ b/test/source/_urls_differ_by_case_valid/page1.html @@ -0,0 +1,6 @@ +--- +title: About +permalink: /about/ +--- + +About the site diff --git a/test/test_doctor_command.rb b/test/test_doctor_command.rb new file mode 100644 index 00000000..43fa602c --- /dev/null +++ b/test/test_doctor_command.rb @@ -0,0 +1,36 @@ +require 'helper' +require 'jekyll/commands/doctor' + +class TestDoctorCommand < Test::Unit::TestCase + context 'urls only differ by case' do + setup do + clear_dest + end + + should 'return success on a valid site/page' do + @site = Site.new(Jekyll.configuration({ + "source" => File.join(source_dir, '/_urls_differ_by_case_valid'), + "destination" => dest_dir + })) + @site.process + output = capture_stderr do + ret = Jekyll::Commands::Doctor.urls_only_differ_by_case(@site) + assert_equal false, ret + end + assert_equal "", output + end + + should 'return warning for pages only differing by case' do + @site = Site.new(Jekyll.configuration({ + "source" => File.join(source_dir, '/_urls_differ_by_case_invalid'), + "destination" => dest_dir + })) + @site.process + output = capture_stderr do + ret = Jekyll::Commands::Doctor.urls_only_differ_by_case(@site) + assert_equal true, ret + end + assert_equal "\e[33m Warning: The following URLs only differ by case. On a case-insensitive file system one of the URLs will be overwritten by the other: #{dest_dir}/about/index.html, #{dest_dir}/About/index.html\e[0m\n", output + end + end +end