1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311
|
require "hoe/rake"
##
# Publish plugin for hoe.
#
# === Tasks Provided:
#
# announce:: Create news email file and optionally publish docs.
# debug_email:: Generate email announcement file.
# post_blog:: Post announcement to blog.
# publish_docs:: Publish RDoc to `rdoc_locations`.
# ridocs:: Generate ri locally for testing.
#
# === Extra Configuration Options:
#
# publish_on_announce:: Run +publish_docs+ when you run +release+.
# blogs:: An array of hashes of blog settings.
#
# The blogs entry can either look like:
#
# - path: ~/Work/p4/zss/www/blog.zenspider.com/releases
# type: zenweb
# cmd: rake sync (optional)
#
# or:
#
# - url: http://example.com/cgi-bin/blog.cgi
# blog_id: 1
# user: username
# password: passwd
# extra_headers:
# blah: whatever
module Hoe::Publish
##
# Optional: An array of the project's blog categories. Defaults to project
# name.
attr_accessor :blog_categories
##
# Optional: Name of destination directory for RDoc generated files.
# [default: doc]
attr_accessor :local_rdoc_dir
##
# Optional: Should RDoc and ri generation tasks be defined? [default: true]
#
# Allows you to define custom RDoc tasks then use the publish_rdoc task to
# upload them all. See also local_rdoc_dir
attr_accessor :need_rdoc
##
# Optional: An array of remote (rsync) paths to copy rdoc to.
#
# eg:
#
# rdoc_locations << "user@server:Sites/rdoc/#{remote_rdoc_dir}"
attr_accessor :rdoc_locations
##
# Optional: Name of RDoc destination directory. [default: +name+]
attr_accessor :remote_rdoc_dir
##
# Optional: Flags for RDoc rsync. [default: "-av --delete"]
attr_accessor :rsync_args
Hoe::DEFAULT_CONFIG["publish_on_announce"] = true
Hoe::DEFAULT_CONFIG["blogs"] = [
{
"user" => "user",
"password" => "password",
"url" => "url",
"blog_id" => "blog_id",
"extra_headers" => {
"mt_convert_breaks" => "markdown",
},
},
]
##
# Initialize variables for plugin.
def initialize_publish
self.blog_categories ||= [self.name]
self.local_rdoc_dir ||= "doc"
self.need_rdoc ||= true
self.rdoc_locations ||= []
self.remote_rdoc_dir ||= self.name
self.rsync_args ||= "-av -O --delete"
end
##
# Declare a dependency on rdoc, IF NEEDED.
def activate_publish_deps
dependency "rdoc", [">= 4.0", "< 7"], :developer if need_rdoc
end
##
# Define tasks for plugin.
def define_publish_tasks
if need_rdoc then
task :isolate # ensure it exists
desc "Generate rdoc"
task :docs => [:clobber_docs, :isolate] do
sh(*make_rdoc_cmd)
end
desc "Generate rdoc coverage report"
task :dcov => :isolate do
sh(*make_rdoc_cmd("-C"))
end
desc "Remove RDoc files"
task :clobber_docs do
rm_rf local_rdoc_dir
end
task :clobber => :clobber_docs
desc "Generate ri locally for testing."
task :ridocs => [:clean, :isolate] do
sh(*make_rdoc_cmd("--ri", "-o", "ri"))
end
end
desc "Publish RDoc to wherever you want."
task :publish_docs => [:clean, :docs] do
publish_docs_task
end
# no doco for this one
task :publish_on_announce do
publish_on_announce_task
end
desc "Generate email announcement file."
task :debug_email do
puts generate_email
end
desc 'Post announcement to blog. Uses the "blogs" array in your hoerc.'
task :post_blog do
post_blog_task
end
desc "Announce your release."
task :announce => [:post_blog, :publish_on_announce ]
end
def publish_docs_task # :nodoc:
warn "no rdoc_location values" if rdoc_locations.empty?
self.rdoc_locations.each do |dest|
sh %(rsync #{rsync_args} #{local_rdoc_dir}/ #{dest})
end
end
def publish_on_announce_task # :nodoc:
with_config do |config, _|
Rake::Task["publish_docs"].invoke if config["publish_on_announce"]
end
end
def post_blog_task # :nodoc:
with_config do |config, _path|
break unless config["blogs"]
config["blogs"].each do |site|
if site["path"] then
msg = "post_blog_#{site["type"]}"
send msg, site
system site["cmd"] if site["cmd"]
else
require "xmlrpc/client"
_, title, body, urls = announcement
body += "\n\n#{urls}"
server = XMLRPC::Client.new2(site["url"])
content = site["extra_headers"].merge(:title => title,
:description => body,
:categories => blog_categories)
server.call("metaWeblog.newPost",
site["blog_id"],
site["user"],
site["password"],
content,
true)
end
end
end
end
def make_rdoc_cmd(*extra_args) # :nodoc:
title = "#{name}-#{version} Documentation"
title = "#{group_name}'s #{title}" if group_name != name
rdoc = Gem.bin_wrapper "rdoc"
extra = nil
unless File.exist? rdoc then
warn "Can't find #{rdoc}. Falling back."
rdoc = "rdoc"
extra = "-S"
end
( # I don't understand this bug... but removing empties definitely fixes it.
%W[#{Gem.ruby} #{extra}
#{rdoc}
--title #{title}
-o #{local_rdoc_dir}
] +
spec.rdoc_options +
extra_args +
spec.require_paths +
spec.extra_rdoc_files
).reject(&:empty?)
end
def post_blog_zenweb site # :nodoc:
dir = site["path"]
_, title, body, urls = announcement
body += "\n\n#{urls}"
Dir.chdir File.expand_path dir do
time = Time.at Time.now.to_i # nukes fractions
path = [time.strftime("%Y-%m-%d-"),
title.sub(/\W+$/, "").gsub(/\W+/, "-"),
".html.md"].join
header = {
"title" => title,
"categories" => blog_categories,
"date" => time,
}
File.open path, "w" do |f|
f.puts header.to_yaml.gsub(/\s$/, "")
f.puts "..."
f.puts
f.puts body
end
end
end
def generate_email full = nil # :nodoc:
require "time"
abort "No email 'to' entry. Run `rake config_hoe` to fix." unless
!full || email_to
from_name, from_email = author.first, email.first
subject, title, body, urls = announcement
[
full && "From: #{from_name} <#{from_email}>",
full && "To: #{email_to.join(", ")}",
full && "Date: #{Time.now.rfc2822}",
"Subject: [ANN] #{subject}",
"",
title,
"",
urls,
"",
body,
].compact.join("\n")
end
def announcement # :nodoc:
changes = self.changes.rdoc_to_markdown
subject = "#{name} #{version} Released"
title = "#{name} version #{version} has been released!"
body = "#{description}\n\nChanges:\n\n#{changes}".rdoc_to_markdown
urls =
case self.urls
when Hash then
self.urls.map { |k, v| "* #{k}: <#{v.strip.rdoc_to_markdown}>" }
when Array then
self.urls.map { |s| "* <#{s.strip.rdoc_to_markdown}>" }
else
raise "unknown urls format: #{urls.inspect}"
end
return subject, title, body, urls.join("\n")
end
end
class ::Rake::SshDirPublisher # :nodoc:
attr_reader :host, :remote_dir, :local_dir
end
class String
##
# Very basic munge from rdoc to markdown format.
def rdoc_to_markdown
self.gsub(/^mailto:/, "").gsub(/^(=+)/) { "#" * $1.size }
end
end
|