Commit f871e7e45ad228c1abf33e611a2ae1f587e83c14:
use only temp dirs when publishing minutes
Branch: refs/heads/master
Author: Sam Ruby <[email protected]>
Committer: Sam Ruby <[email protected]>
Pusher: rubys <[email protected]>
------------------------------------------------------------
lib/whimsy/asf/svn.rb | +++++++++++++++
www/board/agenda/Rakefile | +++++++++++++
www/board/agenda/views/actions/publish.json.rb | +++ -------
------------------------------------------------------------
140 changes: 90 additions, 50 deletions.
------------------------------------------------------------
diff --git a/lib/whimsy/asf/svn.rb b/lib/whimsy/asf/svn.rb
index fe9091c..4982479 100644
--- a/lib/whimsy/asf/svn.rb
+++ b/lib/whimsy/asf/svn.rb
@@ -1,6 +1,8 @@
require 'uri'
require 'thread'
require 'open3'
+require 'fileutils'
+require 'tmpdir'
module ASF
@@ -60,6 +62,61 @@ def self.find!(name)
result
end
+
+ # update a file in SVN, working entirely in a temporary directory
+ def self.update(path, msg, env, _)
+ dir = File.dirname(path)
+ basename = File.basename(path)
+
+ if path.start_with? '/' and not path.include? '..' and File.exist?(path)
+ dir.untaint
+ basename.untaint
+ end
+
+ tmpdir = Dir.mktmpdir.untaint
+ tmpfile = File.join(tmpdir, basename).untaint
+
+ begin
+ # create an empty checkout
+ _.system ['svn', 'checkout', '--depth', 'empty',
+ ['--username', env.user, '--password', env.password],
+ `svn info #{dir}`[/URL: (.*)/, 1], tmpdir]
+
+ # retrieve the file to be updated (may not exist)
+ _.system ['svn', 'update',
+ ['--username', env.user, '--password', env.password],
+ tmpfile]
+
+ # determine the new contents
+ if File.file? tmpfile
+ contents = yield tmpdir, File.read(tmpfile)
+ else
+ contents = yield tmpdir, ''
+ end
+
+ # update the temporary copy
+ if contents and not contents.empty?
+ File.write tmpfile, contents
+ elsif File.file? tmpfile
+ File.unlink tmpfile
+ _.system ['svn', 'delete',
+ ['--username', env.user, '--password', env.password],
+ tmpfile]
+ end
+
+ # commit the changes
+ _.system ['svn', 'commit', '--message', msg.untaint,
+ ['--username', env.user, '--password', env.password],
+ tmpfile]
+
+ # fail if there are pending changes
+ unless `svn st`.empty?
+ raise "svn failure #{File.join(svn, basename)}"
+ end
+ ensure
+ FileUtils.rm_rf tmpdir
+ end
+ end
end
end
diff --git a/www/board/agenda/Rakefile b/www/board/agenda/Rakefile
index f07de50..b33e65d 100644
--- a/www/board/agenda/Rakefile
+++ b/www/board/agenda/Rakefile
@@ -6,6 +6,19 @@ task :default => :spec
task :spec => 'test:setup'
task :test => :spec
+# setup authentication
+task :auth do
+ require 'etc'
+ require 'io/console'
+ require 'base64'
+
+ user = ENV['USER'] || ETC.getlogin
+ STDOUT.write "Enter password for #{user}: "
+ password = STDIN.noecho(&:gets).chomp
+ ENV['HTTP_AUTHORIZATION'] = "Basic #{Base64.encode64("#{user}:#{password}")}"
+ STDOUT.puts
+end
+
task :server => [:bundle, :listen] do
ENV['RACK_ENV']='development'
at_exit {sleep 0.5}
diff --git a/www/board/agenda/views/actions/publish.json.rb
b/www/board/agenda/views/actions/publish.json.rb
index e198938..2e77c26 100755
--- a/www/board/agenda/views/actions/publish.json.rb
+++ b/www/board/agenda/views/actions/publish.json.rb
@@ -44,72 +44,42 @@
calendar.sub! /^(\s*-\s+#{fdate}\s*\n)/, ''
#Commit the Minutes
-Dir.chdir MINUTES do
- unless Dir.exist? year.to_s
- _.system "mkdir #{year}"
- _.system "svn add #{year}"
+ASF::SVN.update MINUTES, @message, env, _ do |tmpdir, old_contents|
+ tmp = File.join(tmpdir, File.basename(MINUTES), year.to_s).untaint
+
+ unless Dir.exist? tmp
+ _.system "mkdir #{tmp}"
+ _.system "svn add #{tmp}"
end
if not File.exist? "#{year}/board_minutes_#{@date}.txt"
- _.system "cp #{BOARD_PRIVATE}/board_minutes_#{@date}.txt #{year}"
- _.system "svn add #{year}/board_minutes_#{@date}.txt"
-
- _.system [
- 'svn', 'commit', '-m', @message, year.to_s,
- ['--no-auth-cache', '--non-interactive'],
- (['--username', env.user, '--password', env.password] if env.password)
- ]
-
- File.unlink 'svn-commit.tmp' if File.exist? 'svn-commit.tmp'
-
- unless `svn st`.empty?
- raise "svn failure #{MINUTES}"
- end
+ _.system "cp #{BOARD_PRIVATE}/board_minutes_#{@date}.txt #{tmp}"
+ _.system "svn add #{tmp}/board_minutes_#{@date}.txt"
end
+
+ nil
end
# Update the Calendar
-Dir.chdir BOARD_SITE do
- if File.read(CALENDAR) != calendar
- File.open(CALENDAR, 'w') {|fh| fh.write calendar}
-
- _.system [
- 'svn', 'commit', '-m', @message, File.basename(CALENDAR),
- ['--no-auth-cache', '--non-interactive'],
- (['--username', env.user, '--password', env.password] if env.password)
- ]
-
- unless `svn st`.empty?
- raise "svn failure #{BOARD_SITE}"
- end
+if File.read(CALENDAR) != calendar
+ ASF::SVN.update CALENDAR, @message, env, _ do |tmpdir, old_contents|
+ calendar
end
end
# Clean up board directory
-Dir.chdir BOARD_PRIVATE do
- updated = false
+ASF::SVN.update BOARD_PRIVATE, @message, env, _ do |tmpdir, old_contents|
+ tmp = File.join(tmpdir, File.basename(BOARD_PRIVATE)).untaint
- if File.exist? "board_minutes_#{@date}.txt"
- _.system "svn rm board_minutes_#{@date}.txt"
- updated = true
+ if File.exist? "#{tmp}/board_minutes_#{@date}.txt"
+ _.system "svn rm #{tmp}/board_minutes_#{@date}.txt"
end
- if File.exist? "board_agenda_#{@date}.txt"
- _.system "svn mv board_agenda_#{@date}.txt archived_agendas"
- updated = true
+ if File.exist? "#{tmp}/board_agenda_#{@date}.txt"
+ _.system "svn mv #{tmp}/board_agenda_#{@date}.txt #{tmp}/archived_agendas"
end
- if updated
- _.system [
- 'svn', 'commit', '-m', @message,
- ['--no-auth-cache', '--non-interactive'],
- (['--username', env.user, '--password', env.password] if env.password)
- ]
-
- unless `svn st`.empty?
- raise "svn failure: #{BOARD_PRIVATE}"
- end
- end
+ nil
end
Dir.chdir(BOARD_PRIVATE) {Dir['board_minutes_*.txt'].sort}