<% # Copyright 2011 The Closure Script Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. require 'rexml/document' require 'thread' # This is an example of a complex Closure Script. # It would be easier to read and more performant if split up # into an includable .rb file and multiple templates. # But speed isn't a problem and the single file format makes # it just a touch easier to share and move around. # Example usage: # render 'svn', :svn_name => 'Closure Library', :svn_path => 'closure-library', # :svn_url => 'http://closure-library.googlecode.com/svn/trunk/' # # Include as many as you want and they can all be updating at once. # Don't supply any locals if you just want Closure::Svn for manual use. class Closure::Svn # Repository objects are held in global class variable. # Checking out or updating runs in a background thread. # repo = Closure::Svn['lib-folder', 'http://svn.example.org/trunk'] # repo.update if repo.update_available? @repos ||= {} def self.[](path, url=nil, name=nil) repo = @repos[path] raise "url and name requried for setup" if !repo and (!url or !name) repo = @repos[path] ||= new(path, url) repo.name ||= url repo.name = name if name repo end # Configurable Subversion shell command def self.svn; @svn ||= 'svn'; end def self.svn=(svn); @svn = svn; end def initialize(path, url) @semaphore = Mutex.new @running = false @path = path @url = url @name = '' @updating_to = '' @log = nil end attr_reader :running attr_reader :path attr_reader :url attr_accessor :name attr_reader :updating_to attr_accessor :log # Update or checkout a Subverion repository. # Closure Script is thread-safe and so is this. # Although the locks in Subversion would prevent it # from corrupting (one would hope), we don't want our # global object to be in an indeterminate state with two # threads running because submit was hit twice. def update(revision='HEAD') @semaphore.synchronize do return if running @running = true Thread.new do @updating_to = revision.to_s @log = "Updating to #{updating_to}. Stand by..." if File.exist? path @local_revision = 'UPDATING' cmd = "#{self.class.svn.dump} update --revision #{revision.dump} #{path.dump}" @log = "$ #{cmd}\n" + `#{cmd} 2>&1` else @local_revision = 'INSTALLING' cmd = "#{self.class.svn.dump} checkout --revision #{revision.dump} #{url.dump} #{path.dump}" @log = "$ #{cmd}\n" + `#{cmd} 2>&1` end @updating_to = '' @local_revision = nil @running = false end end end def info(location) doc = ::REXML::Document.new `#{self.class.svn.dump} info --xml #{location.dump}` source = doc.root.elements['//info/entry/url'].text doc.elements.each('info/entry/commit') do |element| return {:url => source, :revision => element.attributes['revision']} end rescue return {:url => nil, :revision => 'ERROR'} end def local_revision return @local_revision if @local_revision local_info = info(path) @found_url, @local_revision = local_info[:url], local_info[:revision] @local_revision = 'NEW' unless File.exist?(path) @local_revision end def url local_revision # sets real @url from info, if found @found_url || @url end def remote_revision begin # Check every 12 hours raise if Time.now - @remote_revision_checked > 43200 rescue @remote_revision = nil @remote_revision_checked = Time.now end @remote_revision ||= info(url)[:revision] end def update_available? return false if remote_revision == 'ERROR' remote_revision != local_revision end end if defined? svn_path and defined? svn_url and defined? svn_name svn = Closure::Svn[svn_path, svn_url, svn_name] if defined? svn_update svn.update svn_update end elsif params['svn_path'] svn = Closure::Svn[params['svn_path']] if post? svn.update params['svn_update'] response.redirect params['return_to'] end end if get? and svn and render_stack.size > 1 is_running = !!svn.running action = expand_src File.join File.dirname(__FILE__), File.basename(__FILE__, File.extname(__FILE__)) input_value = svn.remote_revision input_value = '' if !svn.update_available? input_value = 'HEAD' if svn.remote_revision == 'ERROR' -%>
<%=h svn.name %> <% if is_running -%> updating to <%=h svn.updating_to %>. <% elsif svn.local_revision =~ /\d/ -%> revision <%=h svn.local_revision %>. <% else -%> not installed. <% end -%>    <% if is_running %> <% unless @svn_document_reload_on_page @svn_document_reload_on_page = true -%> <% end else -%>    <% end -%> <% if is_running -%> Stand by... <% elsif svn.log -%> <% unless svn.remote_revision =~ /\d/ and svn.local_revision =~ /\d/ -%> ERROR: <% end -%> VIEW LOG <% elsif svn.update_available? -%> Newer revision available. <% end -%>
<% elsif get? and svn -%> Back

<%=h svn.name %>

Local folder:<%=h svn.path %>
Local revision:<%=h svn.local_revision %>
Repository URL:<%=h svn.url %>
Repository revision:<%=h svn.remote_revision %>
<% if svn.log -%>

Results of last run:

<%=h svn.log %>
Back <% svn.log = nil %> <% end -%> <% end -%>