From 4c46e311b55e893dd419183e73393a35a47098fe Mon Sep 17 00:00:00 2001 From: Adam Williams Date: Fri, 20 Jan 2012 00:16:58 -0500 Subject: [PATCH] Loading plugins listed in plugin.yml. --- octopress/.gitignore | 1 + octopress/Gemfile | 1 + .../step_definitions/octopress_steps.rb | 1 + octopress/lib/octopress.rb | 13 ++++ octopress/lib/octopress/commands/create.rb | 71 +++++++------------ octopress/lib/octopress/plugins/titlecase.rb | 36 ---------- .../octopress/template/_plugins/octopress.rb | 9 --- octopress/lib/octopress/util.rb | 61 ++++++++++++++++ octopress/spec/octopress/util_spec.rb | 48 +++++++++++++ 9 files changed, 150 insertions(+), 91 deletions(-) delete mode 100644 octopress/lib/octopress/plugins/titlecase.rb delete mode 100644 octopress/lib/octopress/template/_plugins/octopress.rb create mode 100644 octopress/lib/octopress/util.rb create mode 100644 octopress/spec/octopress/util_spec.rb diff --git a/octopress/.gitignore b/octopress/.gitignore index 75b6846..9d78327 100644 --- a/octopress/.gitignore +++ b/octopress/.gitignore @@ -1,2 +1,3 @@ Gemfile.lock vendor/ruby +tmp diff --git a/octopress/Gemfile b/octopress/Gemfile index 348421b..f230e2e 100644 --- a/octopress/Gemfile +++ b/octopress/Gemfile @@ -1,4 +1,5 @@ source :rubygems gemspec +gem 'fakefs', git:'git://github.com/defunkt/fakefs.git' gem 'ruby-debug19' diff --git a/octopress/features/step_definitions/octopress_steps.rb b/octopress/features/step_definitions/octopress_steps.rb index 1123925..849623e 100644 --- a/octopress/features/step_definitions/octopress_steps.rb +++ b/octopress/features/step_definitions/octopress_steps.rb @@ -11,6 +11,7 @@ Then /a theme-classic project structure should exist/ do .rbenv-version _config.yml Gemfile + _plugins/titlecase.rb ), true) # Classic theme files diff --git a/octopress/lib/octopress.rb b/octopress/lib/octopress.rb index 533f6ba..dae5d9a 100644 --- a/octopress/lib/octopress.rb +++ b/octopress/lib/octopress.rb @@ -1,8 +1,21 @@ module Octopress + + # Answers the url of the plugins.yml file. Octopress will fetch the latest + # version of this file when plugins are installed. This allows for bumping + # plugin versions or adding new plugins without Gem releases. + # + # TODO: This needs to be finalized once we move the code out of the branch + # and into the octopress organization. + # + def Octopress.plugins_url + 'https://raw.github.com/imathis/octopress/rubygemcli/octopress/plugins.yml' + end + def Octopress.template_root File.join File.expand_path(File.dirname(__FILE__)), 'octopress', 'template' end end require 'octopress/version' +require 'octopress/util' require 'octopress/commands' diff --git a/octopress/lib/octopress/commands/create.rb b/octopress/lib/octopress/commands/create.rb index 41e5d81..1635dcd 100644 --- a/octopress/lib/octopress/commands/create.rb +++ b/octopress/lib/octopress/commands/create.rb @@ -1,6 +1,5 @@ -require 'fileutils' - class Octopress::Commands::Create + include Octopress::Util def initialize(project_path) @project_root = File.expand_path project_path @@ -12,51 +11,31 @@ class Octopress::Commands::Create FileUtils.mkdir_p @project_root FileUtils.cp_r File.join(@template_root, '.'), @project_root FileUtils.mkdir File.join(@project_root, '_posts') - zip_file_path = download 'https://github.com/octopress/theme-classic/zipball/master', 'theme-classic.zip' - unzip zip_file_path, @project_tmp - extracted_root = Dir[File.join(@project_tmp, 'octopress-theme-classic-*')].first + install_plugins + install_theme + end + + def install_plugins + plugins_path = download Octopress.plugins_url, @project_tmp + plugins = YAML.load_file plugins_path + + plugins_root = File.join(@project_root, '_plugins') + FileUtils.mkdir_p plugins_root + plugins.each do |plugin_url| + install_plugin plugin_url, plugins_root + end + end + + def install_plugin(url, destination) + zip_file_path = download url, @project_tmp + extracted_root = unzip zip_file_path, @project_tmp + FileUtils.cp_r Dir.glob(File.join(extracted_root, '*.rb')), destination + end + + def install_theme + zip_file_path = download 'https://github.com/octopress/theme-classic/zipball/master', @project_tmp + extracted_root = unzip zip_file_path, @project_tmp FileUtils.cp_r Dir.glob(File.join(extracted_root, '*')), @project_root end - def read_url(url, &block) - require 'net/http' - success_response, limit, tries = false, 5, 0 - uri = URI(url) - until success_response || tries == limit - tries += 1 - Net::HTTP.start(uri.host, uri.port, use_ssl:(uri.scheme == 'https')) do |http| - http.request_get(uri.path) { |response| - case response - when Net::HTTPRedirection - success_response = false - uri = URI(response['location']) - when Net::HTTPSuccess - success_response = true - block.call response - end - } - end - end - end - - def download(url, filename) - FileUtils.mkdir_p @project_tmp - File.join(@project_tmp, filename).tap do |download_path| - File.open(download_path, 'w') do |f| - read_url(url) { |resp| resp.read_body { |segment| f.write(segment) } } - end - end - end - - def unzip(file, destination) - require 'zip/zip' - Zip::ZipFile.open(file) do |zip_file| - zip_file.each do |f| - f_path = File.join(destination, f.name) - FileUtils.mkdir_p File.dirname(f_path) - zip_file.extract f, f_path unless File.exist?(f_path) - end - end - end - end diff --git a/octopress/lib/octopress/plugins/titlecase.rb b/octopress/lib/octopress/plugins/titlecase.rb deleted file mode 100644 index 7648932..0000000 --- a/octopress/lib/octopress/plugins/titlecase.rb +++ /dev/null @@ -1,36 +0,0 @@ -class String - def titlecase - small_words = %w(a an and as at but by en for if in of on or the to v v. via vs vs.) - - x = split(" ").map do |word| - # note: word could contain non-word characters! - # downcase all small_words, capitalize the rest - small_words.include?(word.gsub(/\W/, "").downcase) ? word.downcase! : word.smart_capitalize! - word - end - # capitalize first and last words - x.first.to_s.smart_capitalize! - x.last.to_s.smart_capitalize! - # small words are capitalized after colon, period, exclamation mark, question mark - x.join(" ").gsub(/(:|\.|!|\?)\s?(\W*#{small_words.join("|")}\W*)\s/) { "#{$1} #{$2.smart_capitalize} " } - end - - def titlecase! - replace(titlecase) - end - - def smart_capitalize - # ignore any leading crazy characters and capitalize the first real character - if self =~ /^['"\(\[']*([a-z])/ - i = index($1) - x = self[i,self.length] - # word with capitals and periods mid-word are left alone - self[i,1] = self[i,1].upcase unless x =~ /[A-Z]/ or x =~ /\.\w+/ - end - self - end - - def smart_capitalize! - replace(smart_capitalize) - end -end diff --git a/octopress/lib/octopress/template/_plugins/octopress.rb b/octopress/lib/octopress/template/_plugins/octopress.rb deleted file mode 100644 index fda6fcd..0000000 --- a/octopress/lib/octopress/template/_plugins/octopress.rb +++ /dev/null @@ -1,9 +0,0 @@ -# Files in this directory are loaded by Jekyll. Learn more at -# https://github.com/mojombo/jekyll/wiki/Plugins. - -# The Title Case plugin adds some handy String methods: -# -# "my string".titlecase -> "My String" -# "my string".smart_capitalize -> "???" -# -# require 'octopress/plugins/titlecase' diff --git a/octopress/lib/octopress/util.rb b/octopress/lib/octopress/util.rb new file mode 100644 index 0000000..0c05772 --- /dev/null +++ b/octopress/lib/octopress/util.rb @@ -0,0 +1,61 @@ +require 'net/http' +require 'fileutils' +require 'tempfile' +require 'zip/zip' + +module Octopress::Util + + def download(url, dir, filename=nil) + download_path = nil + read_url(url) do |response| + if !filename && response['content-disposition'].to_s =~ /filename=(.*);?/ + filename = $1 + end + filename ||= File.basename(url) + download_path = File.join(dir, filename) + + FileUtils.mkdir_p dir + File.open(download_path, 'w') do |file| + response.read_body {|segment| file.write(segment)} + end + end + download_path + end + + # Unzip the file at path into dir. Assumes that the Zip file has a single + # root directory, answering the path to it. + # + def unzip(path, destdir) + root = nil + Zip::ZipFile.open(path) do |zip_file| + zip_file.each do |f| + f_path = File.join(destdir, f.name) + root ||= f_path + FileUtils.mkdir_p File.dirname(f_path) + zip_file.extract f, f_path unless File.exist?(f_path) + end + end + root + end + + def read_url(url, &block) + success_response, limit, tries = false, 5, 0 + uri = URI(url) + until success_response || tries == limit + tries += 1 + Net::HTTP.start(uri.host, uri.port, use_ssl:(uri.scheme == 'https')) do |http| + http.request_get(uri.path) { |response| + case response + when Net::HTTPRedirection + success_response = false + uri = URI(response['location']) + when Net::HTTPSuccess + success_response = true + block.call response + end + } + end + end + end + +end diff --git a/octopress/spec/octopress/util_spec.rb b/octopress/spec/octopress/util_spec.rb new file mode 100644 index 0000000..c07530e --- /dev/null +++ b/octopress/spec/octopress/util_spec.rb @@ -0,0 +1,48 @@ +require 'spec_helper' + +describe Octopress::Util do + include FakeFS::SpecHelpers + include described_class + + describe 'download' do + let(:url) { 'http://hostname.com/myfile.txt' } + let(:path) { './some/path' } + let(:filename) { 'specified.txt' } + let(:content) { 'my file' } + + let(:file) do + stub_request(:get, url).to_return(body:content) + download url, path + end + + before do + FileUtils.mkdir 'tmp' # So that Tempfile will work + end + + it 'answers the downloaded file path' do + file.should == File.join(path, 'myfile.txt') + end + + it 'saves content to file' do + File.read(file).should == content + end + + it 'uses the filename in the url' do + File.basename(file).should == 'myfile.txt' + end + + it 'uses the filename in the response header' do + stub_request(:get, url).to_return( + headers:{ 'Content-Disposition' => "attachment; filename=#{filename}" }, + body:content) + file = download url, path + File.basename(file).should == filename + end + + it 'uses provided filename' do + stub_request(:get, url).to_return(body:content) + file = download url, path, filename + File.basename(file).should == filename + end + end +end