#!/usr/bin/env ruby

# svnql : an sql like interface to svn log (from the working copy)
#
# This program is released under the terms of the "Creative Commons Attribution 3.0 License"
# http://creativecommons.org/licenses/by/3.0/
#
# svnql is copyright 2007, Claudio Cicali <claudio.cicali@gmail.com>

require 'rubygems'
require 'sqlite3'
require 'readline'
require 'rexml/document'
include REXML

def prompt
  print "# "
end

def help
  puts "Select one of: revision, author, date or message"
  if @q_orig != ''
    puts "Latest queries: #{@q_orig.uniq.join(' | ')}"
  end
  prompt and return true
end

db = SQLite3::Database.new(":memory:" )
db.execute('create table entries (revision integer, author varchar(100), date varchar(100), message varchar(255))')
rows = db.execute( "select * from entries" )

puts "Loading XML log..."
xml=''
qlog = IO.popen('svn log --xml', 'w+')
qlog.close_write
while entry = qlog.gets
  xml += entry
end

doc = Document.new(xml)

doc.root.elements.each do |el| 
  # Every element is a log entry
  revision = el.attributes['revision']
  author = el.elements['author'].text
  date = el.elements['date'].text[0..9]
  message = el.elements['msg'].text.to_s.gsub("'", "''")
  db.execute "insert into entries values (#{revision}, '#{author}', '#{date}', '#{message}') " 
end

puts db.get_first_value( "select count(*) from entries" ) + ' entries loaded.'

puts "Columns are: revision, author, date and message. Use Ctrl+d to quit or ? for a brief help."

print "Query? # "
@q_orig=[]
while q=readline do
  begin
    q.chomp!
    
    next unless q.strip != ''

    next if q=='?' and help

    @q_orig.push(q)
    
    q = q.strip.gsub('select', '')
    
    if match = q.match(/order by .*$/)
      order = match[0]
      q = q.gsub(/order by .*$/,'')
    end
    
    nr=-1
    q = 'select ' + q
    if q.match(/ where /)
      q = q.gsub('where', 'from entries where')
    else
      q += ' from entries'
    end
    
    q += " #{order.to_s}"
    
    db.execute(q)
    columns = nil
    db.execute2(q) do |row|
      nr += 1
      puts row.join(',')
    end
    puts "+------ #{nr} rows"
  rescue SQLite3::SQLException
    puts "in '#{q}' :" + $!
    prompt and next
  end
  puts 
  puts "Last query was '#{@q_orig.last}' (#{q})"
  prompt
end


