fixup packaging
authorEric Wong <normalperson@yhbt.net>
Sat, 26 Jun 2010 08:14:21 +0000 (26 08:14 +0000)
committerEric Wong <normalperson@yhbt.net>
Sat, 26 Jun 2010 08:48:42 +0000 (26 08:48 +0000)
Switch to the same system used by some of my other projects,
which includes Atom feeds and Freshmeat/RAA updating.

12 files changed:
.document
.gitignore
COPYING [moved from LICENSE.txt with 100% similarity]
GIT-VERSION-GEN [new file with mode: 0755]
GNUmakefile
History.txt [deleted file]
LICENSE [new file with mode: 0644]
Manifest.txt [deleted file]
README [moved from README.txt with 82% similarity]
Rakefile
lib/local_openid.rb
local-openid.gemspec [new file with mode: 0644]

index 34f4172..956b42d 100644 (file)
--- a/.document
+++ b/.document
@@ -1,4 +1,5 @@
-History.txt
-LICENSE.txt
-README.txt
-bin/local-openid
+NEWS
+LICENSE
+ChangeLog
+README
+lib/
index b6fc95d..5b6817b 100644 (file)
@@ -1,2 +1,14 @@
 pkg
 doc
+*.rbc
+/.config
+/InstalledFiles
+/doc
+pkg/
+/NEWS
+/ChangeLog
+/.manifest
+/GIT-VERSION-FILE
+/man
+tags
+TAGS
similarity index 100%
rename from LICENSE.txt
rename to COPYING
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
new file mode 100755 (executable)
index 0000000..e36125a
--- /dev/null
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+GVF=GIT-VERSION-FILE
+DEF_VER=v0.2.0.GIT
+
+LF='
+'
+
+# First see if there is a version file (included in release tarballs),
+# then try git-describe, then default.
+if test -f version
+then
+       VN=$(cat version) || VN="$DEF_VER"
+elif test -d .git -o -f .git &&
+       VN=$(git describe --abbrev=4 HEAD 2>/dev/null) &&
+       case "$VN" in
+       *$LF*) (exit 1) ;;
+       v[0-9]*)
+               git update-index -q --refresh
+               test -z "$(git diff-index --name-only HEAD --)" ||
+               VN="$VN-dirty" ;;
+       esac
+then
+       VN=$(echo "$VN" | sed -e 's/-/./g');
+else
+       VN="$DEF_VER"
+fi
+
+VN=$(expr "$VN" : v*'\(.*\)')
+
+if test -r $GVF
+then
+       VC=$(sed -e 's/^GIT_VERSION = //' <$GVF)
+else
+       VC=unset
+fi
+test "$VN" = "$VC" || {
+       echo >&2 "GIT_VERSION = $VN"
+       echo "GIT_VERSION = $VN" >$GVF
+}
dissimilarity index 62%
index 531f07a..b20efba 100644 (file)
-all:
-
-publish_doc:
-       -git set-file-times
-       $(MAKE) doc
-       $(MAKE) doc_gz
-       rsync -av --delete doc/ dcvr:/srv/bogomips/local-openid/
-       git ls-files | xargs touch
-
-doc: .document
-       rdoc -Na -m README.txt -t "$(shell sed -ne '1s/^= //p' README.txt)"
-
-# Create gzip variants of the same timestamp as the original so nginx
-# "gzip_static on" can serve the gzipped versions directly.
-doc_gz: suf := html js css
-doc_gz: globs := $(addprefix doc/*.,$(suf)) $(addprefix doc/*/*.,$(suf))
-doc_gz: docs := $(wildcard $(globs))
-doc_gz:
-       for i in $(docs); do gzip < $$i > $$i.gz; touch -r $$i $$i.gz; done
+all::
+RUBY = ruby
+RAKE = rake
+RSYNC = rsync
+GIT_URL = git://git.bogomips.org/local-openid.git
+
+GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
+       @./GIT-VERSION-GEN
+-include GIT-VERSION-FILE
+
+pkg_extra := GIT-VERSION-FILE NEWS ChangeLog
+manifest: $(pkg_extra)
+       $(RM) .manifest
+       $(MAKE) .manifest
+
+.manifest:
+       (git ls-files && \
+         for i in $@ $(pkg_extra) $(man1_paths); \
+        do echo $$i; done) | LC_ALL=C sort > $@+
+       cmp $@+ $@ || mv $@+ $@
+       $(RM) $@+
+
+NEWS: GIT-VERSION-FILE
+       $(RAKE) -s news_rdoc > $@+
+       mv $@+ $@
+
+SINCE = 0.1.0
+ChangeLog: LOG_VERSION = \
+  $(shell git rev-parse -q "$(GIT_VERSION)" >/dev/null 2>&1 && \
+          echo $(GIT_VERSION) || git describe)
+ifneq ($(SINCE),)
+ChangeLog: log_range = v$(SINCE)..$(LOG_VERSION)
+endif
+ChangeLog: GIT-VERSION-FILE
+       @echo "ChangeLog from $(GIT_URL) ($(log_range))" > $@+
+       @echo >> $@+
+       git log $(log_range) | sed -e 's/^/    /' >> $@+
+       mv $@+ $@
+
+news_atom := http://bogomips.org/local-openid/NEWS.atom.xml
+cgit_atom := http://git.bogomips.org/cgit/local-openid.git/atom/?h=master
+atom = <link rel="alternate" title="Atom feed" href="$(1)" \
+             type="application/atom+xml"/>
+
+doc: .document NEWS ChangeLog
+       find bin lib -type f -name '*.rbc' -exec rm -f '{}' ';'
+       rdoc -a -t "$(shell sed -ne '1s/^= //p' README)"
+       install -m644 COPYING doc/COPYING
+       install -m644 $(shell grep '^[A-Z]' .document)  doc/
+       $(RUBY) -i -p -e \
+         '$$_.gsub!("</title>",%q{\&$(call atom,$(cgit_atom))})' \
+         doc/ChangeLog.html
+       $(RUBY) -i -p -e \
+         '$$_.gsub!("</title>",%q{\&$(call atom,$(news_atom))})' \
+         doc/NEWS.html doc/README.html
+       $(RAKE) -s news_atom > doc/NEWS.atom.xml
+       cd doc && ln README.html tmp && mv tmp index.html
+
+publish_doc:
+       -git set-file-times
+       $(RM) -r doc ChangeLog NEWS
+       $(MAKE) doc LOG_VERSION=$(shell git tag -l | tail -1)
+       @awk 'BEGIN{RS="=== ";ORS=""}NR==2{sub(/\n$$/,"");print RS""$$0 }' \
+        < NEWS > doc/LATEST
+       find doc/images doc/js -type f | \
+               TZ=UTC xargs touch -d '1970-01-01 00:00:00' doc/rdoc.css
+       $(MAKE) doc_gz
+       chmod 644 $$(find doc -type f)
+       $(RSYNC) -av --delete doc/ bogomips.org:/srv/bogomips/local-openid/
+       git ls-files | xargs touch
+
+ifneq ($(VERSION),)
+rfproject := qrp
+rfpackage := local-openid
+pkggem := pkg/$(rfpackage)-$(VERSION).gem
+pkgtgz := pkg/$(rfpackage)-$(VERSION).tgz
+release_notes := release_notes-$(VERSION)
+release_changes := release_changes-$(VERSION)
+
+release-notes: $(release_notes)
+release-changes: $(release_changes)
+$(release_changes):
+       $(RAKE) -s release_changes > $@+
+       $(VISUAL) $@+ && test -s $@+ && mv $@+ $@
+$(release_notes):
+       GIT_URL=$(GIT_URL) $(RAKE) -s release_notes > $@+
+       $(VISUAL) $@+ && test -s $@+ && mv $@+ $@
+
+# ensures we're actually on the tagged $(VERSION), only used for release
+verify:
+       test x"$(shell umask)" = x0022
+       git rev-parse --verify refs/tags/v$(VERSION)^{}
+       git diff-index --quiet HEAD^0
+       test `git rev-parse --verify HEAD^0` = \
+            `git rev-parse --verify refs/tags/v$(VERSION)^{}`
+
+fix-perms:
+       -git ls-tree -r HEAD | awk '/^100644 / {print $$NF}' | xargs chmod 644
+       -git ls-tree -r HEAD | awk '/^100755 / {print $$NF}' | xargs chmod 755
+
+gem: $(pkggem)
+
+install-gem: $(pkggem)
+       gem install $(CURDIR)/$<
+
+$(pkggem): manifest fix-perms
+       gem build $(rfpackage).gemspec
+       mkdir -p pkg
+       mv $(@F) $@
+
+$(pkgtgz): distdir = $(basename $@)
+$(pkgtgz): HEAD = v$(VERSION)
+$(pkgtgz): manifest fix-perms
+       @test -n "$(distdir)"
+       $(RM) -r $(distdir)
+       mkdir -p $(distdir)
+       tar cf - `cat .manifest` | (cd $(distdir) && tar xf -)
+       cd pkg && tar c $(basename $(@F)) | gzip -9 > $(@F)+
+       mv $@+ $@
+
+package: $(pkgtgz) $(pkggem)
+
+test-release: verify package $(release_notes) $(release_changes)
+release: verify package $(release_notes) $(release_changes)
+       # make tgz release on RubyForge
+       rubyforge add_release -f -n $(release_notes) -a $(release_changes) \
+         $(rfproject) $(rfpackage) $(VERSION) $(pkgtgz)
+       # push gem to Gemcutter
+       gem push $(pkggem)
+       # in case of gem downloads from RubyForge releases page
+       -rubyforge add_file \
+         $(rfproject) $(rfpackage) $(VERSION) $(pkggem)
+else
+gem install-gem: GIT-VERSION-FILE
+       $(MAKE) $@ VERSION=$(GIT_VERSION)
+endif
+
+# Create gzip variants of the same timestamp as the original so nginx
+# "gzip_static on" can serve the gzipped versions directly.
+doc_gz: docs = $(shell find doc -type f ! -regex '^.*\.\(gif\|jpg\|png\|gz\)$$')
+doc_gz:
+       touch doc/NEWS.atom.xml -d "$$(awk 'NR==1{print $$4,$$5,$$6}' NEWS)"
+       for i in $(docs); do \
+         gzip --rsyncable -9 < $$i > $$i.gz; touch -r $$i $$i.gz; done
+.PHONY: .FORCE-GIT-VERSION-FILE doc manifest
diff --git a/History.txt b/History.txt
deleted file mode 100644 (file)
index 9ec159b..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-=== 0.1.1 / 2009-04-06
-
-* add Sinatra dependency
-
-=== 0.1.0 / 2009-04-04
-
-* initial
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..d796ed9
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,5 @@
+local-openid is copyrighted free software by all contributors, see logs
+in revision control for names and email addresses of all of them.  You
+can redistribute it and/or modify it under either the terms of the GNU
+Affero General Public License, version 3.  See the link:COPYING file
+for details.
diff --git a/Manifest.txt b/Manifest.txt
deleted file mode 100644 (file)
index 3715975..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-.document
-.gitignore
-GNUmakefile
-History.txt
-LICENSE.txt
-Manifest.txt
-README.txt
-Rakefile
-bin/local-openid
-setup.rb
similarity index 82%
rename from README.txt
rename to README
index 5286175..b8def5e 100644 (file)
+++ b/README
@@ -1,9 +1,5 @@
 = local-openid: Single User, Ephemeral OpenID Provider
 
-* http://bogomips.org/local-openid
-
-== Description
-
 local-openid allows users with shell accounts on servers to authenticate
 with OpenID consumers by editing a YAML file in their home directory
 instead of authenticating through HTTP/HTTPS.
@@ -43,17 +39,26 @@ setup.rb is also provided for non-Rubygems users.
 == Requirements
 
 local-openid is a small Sinatra application.  It requires the Ruby
-OpenID library (2.x), Sinatra (0.9+), Rack (0.9+), and any Rack-enabled
+OpenID library (2.x), Sinatra (1.0), Rack and any Rack-enabled
 server.  To be useful, it also depends on having a user account on a
 machine with a publically-accessible IP and DNS name to use as your
 OpenID identity.
 
+"local-openid" should be installed in your $PATH by RubyGems.
+It is a Sinatra application and takes all the usual command-line
+arguments.  Run "local-openid -h" for help.
+
 == Hacking
 
 I don't have any plans for more development with local-openid.  It was
 after all, just a weekend hack.  It does what I want it to and nothing
 more.
 
+You can use the {mailing list}[mailto:local.openid@librelist.com] to
+share ideas, patches, pull requests with other users.  Remember, I
+wrote local-openid because I find the web difficult to use.  So I'll
+only accept communication about local-openid via email :)
+
 Feel free to fork it and customize it to your needs.  Of course, drop me
 a line if you fix any bugs or notice any security holes in it.
 
@@ -69,11 +74,6 @@ You may browse the code from the web and download the latest tarballs here:
 * http://git.bogomips.org/cgit/local-openid.git
 * http://repo.or.cz/w/local-openid.git (gitweb mirror)
 
-== License
-
-Copyright 2009 Eric Wong.  It is licensed under the GNU Affero General
-Public License, version 3.  See the LICENSE file for details.
-
 == Disclaimer
 
 There is NO WARRANTY whatsoever, implied or otherwise.  OpenID may not
@@ -84,5 +84,6 @@ credentials when your provider implementation has 99.999% downtime :)
 
 == Contact
 
-Eric Wong, normalperson@yhbt.net
-OpenID: http://e.yhbt.net/
+* Original author: Eric Wong, normalperson@yhbt.net
+* OpenID: http://e.yhbt.net/
+* mailing list: local.openid@librelist.com
dissimilarity index 98%
index 16fd51a..3f4b240 100644 (file)
--- a/Rakefile
+++ b/Rakefile
-require 'rubygems'
-require 'hoe'
-
-readme = File.readlines('README.txt')
-
-Hoe.new('local-openid', '0.1.1') do |p|
-   p.rubyforge_name = 'qrp'
-   p.developer('Eric Wong', 'normalperson@yhbt.net')
-   p.summary = readme[0].split(/\s*:\s*/)[1]
-   p.url = 'http://bogomips.org/local-openid'
-   p.extra_deps << [ 'sinatra', '>= 0.9' ]
-end
+# -*- encoding: binary -*-
+autoload :Gem, 'rubygems'
+
+def tags
+  timefmt = '%Y-%m-%dT%H:%M:%SZ'
+  @tags ||= `git tag -l`.split(/\n/).map do |tag|
+    if %r{\Av[\d\.]+\z} =~ tag
+      header, subject, body = `git cat-file tag #{tag}`.split(/\n\n/, 3)
+      header = header.split(/\n/)
+      tagger = header.grep(/\Atagger /).first
+      body ||= "initial"
+      {
+        :time => Time.at(tagger.split(/ /)[-2].to_i).utc.strftime(timefmt),
+        :tagger_name => %r{^tagger ([^<]+)}.match(tagger)[1].strip,
+        :tagger_email => %r{<([^>]+)>}.match(tagger)[1].strip,
+        :id => `git rev-parse refs/tags/#{tag}`.chomp!,
+        :tag => tag,
+        :subject => subject,
+        :body => body,
+      }
+    end
+  end.compact.sort { |a,b| b[:time] <=> a[:time] }
+end
+
+cgit_url = "http://git.bogomips.org/cgit/local-openid.git"
+git_url = ENV['GIT_URL'] || 'git://git.bogomips.org/local-openid.git'
+
+desc 'prints news as an Atom feed'
+task :news_atom do
+  require 'nokogiri'
+  new_tags = tags[0,10]
+  puts(Nokogiri::XML::Builder.new do
+    feed :xmlns => "http://www.w3.org/2005/Atom" do
+      id! "http://bogomips.org/local-openid/NEWS.atom.xml"
+      title "local-openid news"
+      subtitle %q{Single User, Ephemeral OpenID Provider}
+      link! :rel => 'alternate', :type => 'text/html',
+            :href => 'http://bogomips.org/local-openid/NEWS.html'
+      updated(new_tags.empty? ? "1970-01-01T00:00:00Z" : new_tags.first[:time])
+      new_tags.each do |tag|
+        entry do
+          title tag[:subject]
+          updated tag[:time]
+          published tag[:time]
+          author {
+            name tag[:tagger_name]
+            email tag[:tagger_email]
+          }
+          url = "#{cgit_url}/tag/?id=#{tag[:tag]}"
+          link! :rel => "alternate", :type => "text/html", :href =>url
+          id! url
+          message_only = tag[:body].split(/\n.+\(\d+\):\n {6}/s).first.strip
+          content({:type =>:text}, message_only)
+          content(:type =>:xhtml) { pre tag[:body] }
+        end
+      end
+    end
+  end.to_xml)
+end
+
+desc 'prints RDoc-formatted news'
+task :news_rdoc do
+  tags.each do |tag|
+    time = tag[:time].tr!('T', ' ').gsub!(/:\d\dZ/, ' UTC')
+    puts "=== #{tag[:tag].sub(/^v/, '')} / #{time}"
+    puts ""
+
+    body = tag[:body]
+    puts tag[:body].gsub(/^/sm, "  ").gsub(/[ \t]+$/sm, "")
+    puts ""
+  end
+end
+
+desc "print release changelog for Rubyforge"
+task :release_changes do
+  version = ENV['VERSION'] or abort "VERSION= needed"
+  version = "v#{version}"
+  vtags = tags.map { |tag| tag[:tag] =~ /\Av/ and tag[:tag] }.sort
+  prev = vtags[vtags.index(version) - 1]
+  if prev
+    system('git', 'diff', '--stat', prev, version) or abort $?
+    puts ""
+    system('git', 'log', "#{prev}..#{version}") or abort $?
+  else
+    system('git', 'log', version) or abort $?
+  end
+end
+
+desc "print release notes for Rubyforge"
+task :release_notes do
+  spec = Gem::Specification.load('local-openid.gemspec')
+  puts spec.description.strip
+  puts ""
+  puts "* #{spec.homepage}"
+  puts "* #{spec.email}"
+  puts "* #{git_url}"
+
+  _, _, body = `git cat-file tag v#{spec.version}`.split(/\n\n/, 3)
+  print "\nChanges:\n\n"
+  puts body
+end
+
+desc "read news article from STDIN and post to rubyforge"
+task :publish_news do
+  require 'rubyforge'
+  IO.select([STDIN], nil, nil, 1) or abort "E: news must be read from stdin"
+  msg = STDIN.readlines
+  subject = msg.shift
+  blank = msg.shift
+  blank == "\n" or abort "no newline after subject!"
+  subject.strip!
+  body = msg.join("").strip!
+
+  rf = RubyForge.new.configure
+  rf.login
+  rf.post_news('qrp', subject, body)
+end
+
+desc "post to RAA"
+task :raa_update do
+  require 'net/http'
+  require 'net/netrc'
+  rc = Net::Netrc.locate('local-openid-raa') or abort "~/.netrc not found"
+  password = rc.password
+
+  s = Gem::Specification.load('local-openid.gemspec')
+  desc = [ s.description.strip ]
+  desc << ""
+  desc << "* #{s.email}"
+  desc << "* #{git_url}"
+  desc << "* #{cgit_url}"
+  desc = desc.join("\n")
+  uri = URI.parse('http://raa.ruby-lang.org/regist.rhtml')
+  form = {
+    :name => s.name,
+    :short_description => s.summary,
+    :version => s.version.to_s,
+    :status => 'stable',
+    :owner => s.authors.first,
+    :email => s.email,
+    :category_major => 'Application',
+    :category_minor => 'WWW',
+    :url => s.homepage,
+    :download => 'http://rubyforge.org/frs/?group_id=5626',
+    :license => "OpenSource", # AGPLv3, specifically
+    :description_style => 'Plain',
+    :description => desc,
+    :pass => password,
+    :submit => "Update",
+  }
+  res = Net::HTTP.post_form(uri, form)
+  p res
+  puts res.body
+end
+
+desc "post to FM"
+task :fm_update do
+  require 'tempfile'
+  require 'net/http'
+  require 'net/netrc'
+  require 'json'
+  version = ENV['VERSION'] or abort "VERSION= needed"
+  uri = URI.parse('http://freshmeat.net/projects/local-openid/releases.json')
+  rc = Net::Netrc.locate('local-openid-fm') or abort "~/.netrc not found"
+  api_token = rc.password
+  changelog = tags.find { |t| t[:tag] == "v#{version}" }[:body]
+  tmp = Tempfile.new('fm-changelog')
+  tmp.syswrite(changelog)
+  system(ENV["VISUAL"], tmp.path) or abort "#{ENV["VISUAL"]} failed: #$?"
+  changelog = File.read(tmp.path).strip
+
+  req = {
+    "auth_code" => api_token,
+    "release" => {
+      "tag_list" => "Stable",
+      "version" => version,
+      "changelog" => changelog,
+    },
+  }.to_json
+  Net::HTTP.start(uri.host, uri.port) do |http|
+    p http.post(uri.path, req, {'Content-Type'=>'application/json'})
+  end
+end
index 34ff753..3d87d5f 100644 (file)
@@ -2,7 +2,7 @@
 # a YAML file on the server where this application runs
 # (~/.local-openid/config.yml by default) instead of via HTTP/HTTPS
 # form authentication in the browser.
-
+#:stopdoc:
 require 'tempfile'
 require 'time'
 require 'yaml'
@@ -299,3 +299,4 @@ class LocalOpenID < Sinatra::Base
       err("Lock: #{lock} exists! Possible hijacking attempt") rescue nil
   end
 end
+#:startdoc:
diff --git a/local-openid.gemspec b/local-openid.gemspec
new file mode 100644 (file)
index 0000000..ac16906
--- /dev/null
@@ -0,0 +1,34 @@
+ENV["VERSION"] or abort "VERSION= must be specified"
+manifest = File.readlines('.manifest').map! { |x| x.chomp! }
+
+Gem::Specification.new do |s|
+  s.name = %q{local-openid}
+  s.version = ENV["VERSION"]
+
+  s.authors = ["Eric Wong"]
+  s.date = Time.now.utc.strftime('%Y-%m-%d')
+  s.description = File.read("README").split(/\n\n/)[1]
+  s.email = %q{local-openid@librelist.com}
+  s.executables = %w(local-openid)
+
+  s.extra_rdoc_files = File.readlines('.document').map! do |x|
+    x.chomp!
+    if File.directory?(x)
+      manifest.grep(%r{\A#{x}/})
+    elsif File.file?(x)
+      x
+    else
+      nil
+    end
+  end.flatten.compact
+
+  s.files = manifest
+  s.homepage = %q{http://bogomips.org/local-openid/}
+  s.summary = %q{Single User, Ephemeral OpenID Provider}
+  s.rdoc_options = [ "-a", "-t", "local-openid - #{s.summary}" ]
+  s.require_paths = %w(lib)
+  s.rubyforge_project = %q{qrp}
+  s.add_dependency(%q<sinatra>, ["~> 1.0.0"])
+  s.add_dependency(%q<ruby-openid>, ["~> 2.1.7"])
+  # s.licenses = %w(AGPLv3) # accessor not compatible with older RubyGems
+end