Skip to content

Instantly share code, notes, and snippets.

@edvakf
Created March 29, 2011 07:07
Show Gist options
  • Save edvakf/891925 to your computer and use it in GitHub Desktop.
Save edvakf/891925 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby
=begin
Opera's browser.js history in a git tree!
* http://get.geo.opera.com/res/servicefiles/userjsfiles/all/
Requirements:
* Unix-like system (cygwin is fine)
* Ruby
* Git command
Usage:
Download this script and run
> ruby browserjs.rb
On the first run, it creates two directories; repo and file.
* 'repo' is the git repository
* 'file' contains all files that was stored in the git repo
From the next time, it only updates the differences.
=end
require 'time'
require 'open-uri'
require 'fileutils'
class GitWrapper
def initialize(git_command, dir)
@git = git_command
@dir = dir
end
def exec(args, show_command=false, no_color=true, show_stderr=false)
FileUtils.cd(@dir)
command = "#{@git} #{args}"
puts command if show_command
#puts "> " + command
command += ' --no-color' if no_color
command += ' 2> /dev/null' unless show_stderr
`#{command}`
end
def add(file)
exec("add #{file}", false, false)
end
def commit(message, date=nil)
date = date.nil? ? "" : " --date=#{date}"
exec("commit#{date} -m '#{message}'", true, false)
end
def init
exec('init', true, false, true)
end
def branch_create(name)
exec("branch #{name}", true)
end
def branch_list
l = exec("branch")
branches = []
l.lines.each {|b|
if b =~ /^\*?\s*(.*)\s*$/
branches.push(Version.new($1))
end
}
return branches
end
def current_branch
l = exec("branch")
l.lines.each {|b|
if b =~ /^\*\s*(.*)\s*$/
return $1
end
}
end
def checkout(name)
exec("checkout #{name}", true, false)
end
def log1
exec("log -1")
end
end
class BrowserJSCommit
DefaultFilename = 'browser.js'
attr_reader :version, :time
def initialize(version, time, filename, parent_url, save_dir, repo_dir)
@version = version
@time = time
@url = "#{parent_url}/#{filename}"
@save_file = File.join(save_dir, filename)
@file = File.join(repo_dir, DefaultFilename)
end
def download_or_restore
if File.exist?(@save_file) && File.mtime(@save_file) == @time
puts "restoring #{@save_file}"
else
puts "downloading #{@url}"
download
end
FileUtils.cp(@save_file, @file)
return self
end
def download
open(@save_file, 'w') {|f|
open(@url) {|u|
f.print(u.read)
}
}
File.utime(@time, @time, @save_file)
end
def commit(git)
git.add(DefaultFilename)
git.commit("#{@version} / #{@time.to_s}", @time.to_i)
end
def <=>(other)
@time <=> other.time
end
end
class Version < String
attr_reader :major, :minor
def initialize(version_string)
super(version_string)
@major, @minor = version_string.split('.').map{|v| v.to_i}
end
def <=>(other)
if @major != other.major
return @major <=> other.major
else
return @minor <=> other.minor
end
end
end
class BrowserJS2Git
IndexURL = 'http://get.geo.opera.com/res/servicefiles/userjsfiles/all/'
Line = %r!<tr>.*<td><a href="(.*?)">.*?</a></td><td align="right">(.*?)</td>.*</tr>!
RepoDir = "repo"
FileDir = "file"
def initialize
@root = File.dirname(File.expand_path(__FILE__))
@branches = []
@commits = []
git = `which git 2> /dev/null`.chop
if git.empty?
puts "git not found"
exit(1)
end
@git = GitWrapper.new(git, File.join(@root, RepoDir))
end
def start
prepare_directories
prepare_repository
get_branches
check_last_commit
prepare_commits
update
end
def prepare_directories
[RepoDir, FileDir].each {|dir|
repo = File.join(@root, dir)
FileUtils.mkdir(repo) unless File.exist?(repo)
}
end
def prepare_repository
dot_git = File.join("#{@root}", RepoDir, ".git")
unless File.directory?(dot_git)
puts "initializing repository"
@git.init
FileUtils.touch('browser.js')
@git.add("browser.js")
@git.commit('master branch will not be used', 100000000)
end
end
def get_branches
branches = @git.branch_list
puts "existing branches : #{branches.join(", ")}"
@branches = branches.delete_if {|b| b == "master"}.sort{|a,b| a <=> b}
@git.checkout(@branches.last || "master")
end
def check_last_commit
last_commit = @git.log1
if last_commit.empty?
@last_commit_time = Time.at(0) # epoch zero
else
puts "last commit log :\n#{last_commit}"
@last_commit_time = Time.parse(last_commit.grep(/^Date:/)[0].sub(/^Date:/,'').chop)
end
end
def prepare_commits
open(IndexURL) {|u|
html = u.read
html.scan(Line) {|m|
file = m[0]
version = version_string(file)
next if version.nil?
version = Version.new(version)
time = Time.parse(m[1] + " UTC")
next if time <= @last_commit_time
@commits.push(BrowserJSCommit.new(version, time, file, IndexURL,
File.join(@root, FileDir),
File.join(@root, RepoDir)))
}
}
end
def update
@commits.sort.each { |co|
puts "------"
version = co.version
if @branches.include?(version)
@git.checkout(version)
else
# branch from the latest version not exceeding the committing version
@branches.push(version).sort!{|a,b| a <=> b}
idx = @branches.index(version)
@git.checkout(@branches[idx - 1]) if idx > 0
# create new branch
@git.branch_create(version)
@git.checkout(version)
end
co.download_or_restore.commit(@git)
sleep 0.5
}
end
def version_string(filename)
#if filename =~ /^browser-(\d\.\d\d)-/
#return $1
#if filename =~ /^browser-(\d)(\d\d)-/
#return "#{$1}.#{$2}"
#end
if filename =~ /^browserjs-desktop-(\d\d?\.\d\d)-/
return $1
end
return nil
end
end
BrowserJS2Git.new.start
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment