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}

Reply via email to