svn_branch 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +8 -0
- data/Manifest.txt +17 -0
- data/README.txt +6 -0
- data/Rakefile +95 -0
- data/lib/svn_branch/version.rb +9 -0
- data/lib/svn_branch.rb +1 -0
- data/lib/tasks/create.rake +86 -0
- data/lib/tasks/merge.rake +72 -0
- data/scripts/txt2html +67 -0
- data/setup.rb +1585 -0
- data/test/test_helper.rb +2 -0
- data/test/test_svn_branch.rb +11 -0
- data/website/index.html +98 -0
- data/website/index.txt +42 -0
- data/website/javascripts/rounded_corners_lite.inc.js +285 -0
- data/website/stylesheets/screen.css +129 -0
- data/website/template.rhtml +48 -0
- metadata +75 -0
data/History.txt
ADDED
data/Manifest.txt
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
History.txt
|
2
|
+
Manifest.txt
|
3
|
+
README.txt
|
4
|
+
Rakefile
|
5
|
+
lib/svn_branch.rb
|
6
|
+
lib/svn_branch/version.rb
|
7
|
+
lib/tasks/create.rake
|
8
|
+
lib/tasks/merge.rake
|
9
|
+
scripts/txt2html
|
10
|
+
setup.rb
|
11
|
+
test/test_helper.rb
|
12
|
+
test/test_svn_branch.rb
|
13
|
+
website/index.html
|
14
|
+
website/index.txt
|
15
|
+
website/javascripts/rounded_corners_lite.inc.js
|
16
|
+
website/stylesheets/screen.css
|
17
|
+
website/template.rhtml
|
data/README.txt
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
README for svn_branch
|
2
|
+
=====================
|
3
|
+
|
4
|
+
A collection of rake tasks to automate the svn functions within a project, with special support for rails projects.
|
5
|
+
|
6
|
+
For example, the creation of new branch, plus for rails apps, a new database.yml and new databases for development and test, for the branch.
|
data/Rakefile
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/clean'
|
4
|
+
require 'rake/testtask'
|
5
|
+
require 'rake/packagetask'
|
6
|
+
require 'rake/gempackagetask'
|
7
|
+
require 'rake/rdoctask'
|
8
|
+
require 'rake/contrib/rubyforgepublisher'
|
9
|
+
require 'fileutils'
|
10
|
+
require 'hoe'
|
11
|
+
include FileUtils
|
12
|
+
require File.join(File.dirname(__FILE__), 'lib', 'svn_branch', 'version')
|
13
|
+
|
14
|
+
AUTHOR = 'nicwilliams' # can also be an array of Authors
|
15
|
+
EMAIL = "drnicwilliams@gmail.com"
|
16
|
+
GEM_NAME = 'svn_branch' # what ppl will type to install your gem
|
17
|
+
config = YAML.load(File.read(File.expand_path("~/.rubyforge/user-config.yml")))
|
18
|
+
RUBYFORGE_USERNAME = config["username"]
|
19
|
+
RUBYFORGE_PROJECT = 'drnicutilities' # The unix name for your project
|
20
|
+
HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
|
21
|
+
DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
|
22
|
+
|
23
|
+
NAME = "svn_branch"
|
24
|
+
REV = nil # UNCOMMENT IF REQUIRED: File.read(".svn/entries")[/committed-rev="(d+)"/, 1] rescue nil
|
25
|
+
VERS = SvnBranch::VERSION::STRING + (REV ? ".#{REV}" : "")
|
26
|
+
CLEAN.include ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store']
|
27
|
+
RDOC_OPTS = ['--quiet', '--title', 'svn_branch documentation',
|
28
|
+
"--opname", "index.html",
|
29
|
+
"--line-numbers",
|
30
|
+
"--main", "README",
|
31
|
+
"--inline-source"]
|
32
|
+
|
33
|
+
class Hoe
|
34
|
+
def extra_deps
|
35
|
+
@extra_deps.reject { |x| Array(x).first == 'hoe' }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Generate all the Rake tasks
|
40
|
+
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
41
|
+
hoe = Hoe.new(GEM_NAME, VERS) do |p|
|
42
|
+
p.author = AUTHOR
|
43
|
+
p.description = p.paragraphs_of("README.txt", 1..1).join("\n\n")
|
44
|
+
p.email = EMAIL
|
45
|
+
p.summary = p.paragraphs_of("README.txt", 1..2).join("\n\n")
|
46
|
+
p.url = HOMEPATH
|
47
|
+
p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
|
48
|
+
p.test_globs = ["test/**/test_*.rb"]
|
49
|
+
p.clean_globs |= CLEAN #An array of file patterns to delete on clean.
|
50
|
+
|
51
|
+
# == Optional
|
52
|
+
p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
|
53
|
+
p.extra_deps = [['gemsonrails', '>=0.5.0']] # An array of rubygem dependencies [name, version], e.g. [ ['active_support', '>= 1.3.1'] ]
|
54
|
+
#p.spec_extras = {} # A hash of extra values to set in the gemspec.
|
55
|
+
end
|
56
|
+
|
57
|
+
CHANGES = hoe.paragraphs_of('History.txt', 0..1).join("\n\n")
|
58
|
+
PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "\#{RUBYFORGE_PROJECT}/\#{GEM_NAME}"
|
59
|
+
hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
|
60
|
+
|
61
|
+
desc 'Generate website files'
|
62
|
+
task :website_generate do
|
63
|
+
Dir['website/**/*.txt'].each do |txt|
|
64
|
+
sh %{ ruby scripts/txt2html #{txt} > #{txt.gsub(/txt$/,'html')} }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
desc 'Upload website files to rubyforge'
|
69
|
+
task :website_upload do
|
70
|
+
host = "#{config["username"]}@rubyforge.org"
|
71
|
+
# remote_dir = "/var/www/gforge-projects/#{RUBYFORGE_PROJECT}/"
|
72
|
+
remote_dir = "/var/www/gforge-projects/#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
|
73
|
+
local_dir = 'website'
|
74
|
+
sh %{rsync -av #{local_dir}/ #{host}:#{remote_dir}}
|
75
|
+
end
|
76
|
+
|
77
|
+
desc 'Generate and upload website files'
|
78
|
+
task :website => [:website_generate, :website_upload]
|
79
|
+
|
80
|
+
desc 'Release the website and new gem version'
|
81
|
+
task :deploy => [:check_version, :website, :release]
|
82
|
+
|
83
|
+
desc 'Create website and install gem locally'
|
84
|
+
task :local_deploy => [:website_generate, :install_gem]
|
85
|
+
|
86
|
+
task :check_version do
|
87
|
+
unless ENV['VERSION']
|
88
|
+
puts 'Must pass a VERSION=x.y.z release version'
|
89
|
+
exit
|
90
|
+
end
|
91
|
+
unless ENV['VERSION'] == VERS
|
92
|
+
puts "Please update your version.rb to match the release version, currently #{VERS}"
|
93
|
+
exit
|
94
|
+
end
|
95
|
+
end
|
data/lib/svn_branch.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Dir[File.join(File.dirname(__FILE__), 'svn_branch/**/*.rb')].sort.each { |lib| require lib }
|
@@ -0,0 +1,86 @@
|
|
1
|
+
namespace :svn do
|
2
|
+
namespace :branch do
|
3
|
+
desc 'Creates a new branch using NAME=branch_name [APP_NAME=app_name]'
|
4
|
+
task :create => :environment do
|
5
|
+
require 'highline'
|
6
|
+
|
7
|
+
|
8
|
+
puts "Usage: NAME=branch_name" and next unless name = ENV['NAME']
|
9
|
+
|
10
|
+
svn_info = `svn info`
|
11
|
+
puts "Not under svn; ignoring request" and next unless svn_info
|
12
|
+
repo_root = (svn_info.match(/^Repository Root:\s(.*)$/) || [nil,nil])[1]
|
13
|
+
repo_curr = (svn_info.match(/^URL:\s(.*)$/) || [nil,nil])[1]
|
14
|
+
puts "ERROR: cannot find Repository Root via `svn info`" and next unless repo_root
|
15
|
+
puts "ERROR: cannot find URL via `svn info`" and next unless repo_curr
|
16
|
+
puts "Repository Root: #{repo_root}"
|
17
|
+
puts "Checkout URL: #{repo_curr}"
|
18
|
+
puts "ERROR: svn project is not setup for branching (needs trunk,branches,tags subfolders)" and next if repo_root == repo_curr
|
19
|
+
puts "ERROR: only perform this operation from the trunk checkout" and next if repo_curr.sub(repo_root, '') != '/trunk'
|
20
|
+
|
21
|
+
app_name = ENV['APP_NAME']
|
22
|
+
app_name ||= repo_root.split('/').last
|
23
|
+
|
24
|
+
curr_path = Dir.pwd
|
25
|
+
target_path = File.join(curr_path, '..', "#{app_name}_#{name}")
|
26
|
+
repo_branch = File.join(repo_root, 'branches', name)
|
27
|
+
puts "Current path: #{curr_path}"
|
28
|
+
puts "*Branch path: #{target_path}"
|
29
|
+
|
30
|
+
puts "*Repos branch: #{repo_branch}"
|
31
|
+
|
32
|
+
trunk_database_yml = File.read(File.join(curr_path, 'config/database.yml'))
|
33
|
+
config = YAML.load(trunk_database_yml)
|
34
|
+
adapter = config["development"]["adapter"]
|
35
|
+
puts "Adapter: #{adapter}"
|
36
|
+
|
37
|
+
unless %w[postgresql mysql].include? adapter
|
38
|
+
puts "ERROR: Adapter #{adapter} not yet supported. Please ask for it - drnicwilliams@gmail.com"
|
39
|
+
next
|
40
|
+
end
|
41
|
+
question = HighLine.new
|
42
|
+
puts "Quitting." and next unless question.agree("Create branch? [y/N]", true)
|
43
|
+
|
44
|
+
repo_from = repo_curr # TODO allow task to be called from non-trunk to clone branches
|
45
|
+
repo_to = repo_branch
|
46
|
+
puts `svn copy #{repo_curr} #{repo_to}`
|
47
|
+
puts `svn co #{repo_to} #{target_path}`
|
48
|
+
|
49
|
+
# Now clone the trunk/config/database.yml and gsub(/#{app_name}/,"#{app_name}_#{name}")
|
50
|
+
# get database adapter type
|
51
|
+
# now create dev + test dbs
|
52
|
+
if adapter == 'postgresql'
|
53
|
+
createdb = "createdb -E utf8"
|
54
|
+
createdb += " --username=#{config["development"]["username"]} --password" if config["development"]["username"]
|
55
|
+
elsif adapter == 'mysql'
|
56
|
+
createdb = "mysqladmin"
|
57
|
+
createdb += " -u #{config["development"]["username"]} " +
|
58
|
+
"-p" if config["development"]["username"]
|
59
|
+
createdb += " create"
|
60
|
+
end
|
61
|
+
createdb += " %s"
|
62
|
+
%w[development test].each do |db_type|
|
63
|
+
db_name = "#{app_name}_#{name}_#{db_type}"
|
64
|
+
puts expr = createdb % db_name
|
65
|
+
puts `#{expr}`
|
66
|
+
end
|
67
|
+
|
68
|
+
puts "Creating config/database.yml from existing version..."
|
69
|
+
File.open(File.join(target_path, "config/database.yml"),'w') do |f|
|
70
|
+
f.write(trunk_database_yml.gsub(/database:\s+#{app_name}/,"database: #{app_name}_#{name}"))
|
71
|
+
end
|
72
|
+
|
73
|
+
puts "Creating #{target_path}/log folder if necessary..."
|
74
|
+
FileUtils.mkdir_p File.join(target_path, 'log')
|
75
|
+
|
76
|
+
Dir.chdir target_path do
|
77
|
+
|
78
|
+
exprs = ["rake db:migrate", "rake db:test:clone", "rake test"]
|
79
|
+
exprs.each do |expr|
|
80
|
+
puts expr
|
81
|
+
puts `#{expr}`
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
namespace :svn do
|
2
|
+
namespace :branch do
|
3
|
+
desc 'Merges the trunk into this branch'
|
4
|
+
task :merge_to_branch do
|
5
|
+
require 'highline'
|
6
|
+
|
7
|
+
# Ideas on merging come from http://svnbook.red-bean.com/en/1.0/ch04s04.html
|
8
|
+
|
9
|
+
svn_info = `svn info`
|
10
|
+
puts "Not under svn; ignoring request" and next unless svn_info
|
11
|
+
repo_root = (svn_info.match(/^Repository Root:\s(.*)$/) || [nil,nil])[1]
|
12
|
+
repo_curr = (svn_info.match(/^URL:\s(.*)$/) || [nil,nil])[1]
|
13
|
+
branch_name = repo_curr.split('/').last
|
14
|
+
|
15
|
+
repo_trunk = "#{repo_root}/trunk"
|
16
|
+
svn_info_trunk = `svn info #{repo_trunk}`
|
17
|
+
puts "SVN path #{repo_trunk} does not exist; cannot perform branch - contact Dr Nic" and next unless svn_info_trunk
|
18
|
+
unless svn_info_trunk[/Last Changed Rev:\s(\d+)/]
|
19
|
+
puts "Cannot find 'Last Changed Rev: xxx' in `svn info #{repo_trunk}`"
|
20
|
+
return
|
21
|
+
end
|
22
|
+
trunk_version = $1.to_i
|
23
|
+
|
24
|
+
# look in props for previous merge version, else get original branch version
|
25
|
+
# or look for rXXX:YYY in log comments, and use that version, e.g. YYY+1
|
26
|
+
if `svn log --verbose --stop-on-copy`[/r(\d+)\s/]
|
27
|
+
branch_version = $1.to_i
|
28
|
+
puts "Branch #{branch_name} created at version #{branch_version}; never merged with trunk yet."
|
29
|
+
end
|
30
|
+
|
31
|
+
puts "Merging changes btw r#{branch_version}:#{trunk_version} from trunk into this branch..."
|
32
|
+
|
33
|
+
puts merge = "svn merge -r #{branch_version}:#{trunk_version} #{repo_trunk}"
|
34
|
+
puts `#{merge}`
|
35
|
+
|
36
|
+
puts status = "svn status"
|
37
|
+
puts `#{status}`
|
38
|
+
|
39
|
+
puts "1) Now fix up any 'C' conflicts and remove the temporary files"
|
40
|
+
puts "2) Fix up your migrations (may need to rollback and put new migrations at the end of the list)"
|
41
|
+
puts "3) svn commit -m \"Merged trunk changes into #{branch_name}; r#{branch_version}:#{trunk_version}\""
|
42
|
+
end
|
43
|
+
|
44
|
+
desc 'Merge branch back into trunk; run from trunk'
|
45
|
+
task :merge_to_trunk do
|
46
|
+
puts "Usage: NAME=branch_name" and next unless name = ENV['NAME']
|
47
|
+
|
48
|
+
svn_info = `svn info`
|
49
|
+
puts "Not under svn; ignoring request" and next unless svn_info
|
50
|
+
repo_root = (svn_info.match(/^Repository Root:\s(.*)$/) || [nil,nil])[1]
|
51
|
+
repo_curr = (svn_info.match(/^URL:\s(.*)$/) || [nil,nil])[1]
|
52
|
+
branch_name = repo_curr.split('/').last
|
53
|
+
repo_branch = "#{repo_root}/branches/#{name}"
|
54
|
+
|
55
|
+
# get the last r(\d+) number
|
56
|
+
svn_log = `svn log --verbose --stop-on-copy #{repo_branch}`
|
57
|
+
branch_rev = svn_log.scan(/^r(\d+)\s/).last
|
58
|
+
# merge branch_rev:HEAD
|
59
|
+
puts merge = "svn merge -r #{branch_rev}:HEAD #{repo_branch}"
|
60
|
+
puts `#{merge}`
|
61
|
+
|
62
|
+
# fix conflicts
|
63
|
+
|
64
|
+
puts "1) Now fix up any 'C' conflicts and remove the temporary files"
|
65
|
+
puts "2) Fix up your migrations (may need to increment branch migrations forward)"
|
66
|
+
puts "3) rake db:migrate"
|
67
|
+
puts "4) rake db:test:clone"
|
68
|
+
puts "5) rake"
|
69
|
+
puts "6) svn commit -m \"Merged branch changes from #{branch_name}; r#{branch_rev}:HEAD\""
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/scripts/txt2html
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'redcloth'
|
5
|
+
require 'syntax/convertors/html'
|
6
|
+
require 'erb'
|
7
|
+
require File.dirname(__FILE__) + '/../lib/svn_branch/version.rb'
|
8
|
+
|
9
|
+
version = SvnBranch::VERSION::STRING
|
10
|
+
download = 'http://rubyforge.org/projects/svn_branch'
|
11
|
+
|
12
|
+
class Fixnum
|
13
|
+
def ordinal
|
14
|
+
# teens
|
15
|
+
return 'th' if (10..19).include?(self % 100)
|
16
|
+
# others
|
17
|
+
case self % 10
|
18
|
+
when 1: return 'st'
|
19
|
+
when 2: return 'nd'
|
20
|
+
when 3: return 'rd'
|
21
|
+
else return 'th'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class Time
|
27
|
+
def pretty
|
28
|
+
return "#{mday}#{mday.ordinal} #{strftime('%B')} #{year}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def convert_syntax(syntax, source)
|
33
|
+
return Syntax::Convertors::HTML.for_syntax(syntax).convert(source).gsub(%r!^<pre>|</pre>$!,'')
|
34
|
+
end
|
35
|
+
|
36
|
+
if ARGV.length >= 1
|
37
|
+
src, template = ARGV
|
38
|
+
template ||= File.dirname(__FILE__) + '/../website/template.rhtml'
|
39
|
+
|
40
|
+
else
|
41
|
+
puts("Usage: #{File.split($0).last} source.txt [template.rhtml] > output.html")
|
42
|
+
exit!
|
43
|
+
end
|
44
|
+
|
45
|
+
template = ERB.new(File.open(template).read)
|
46
|
+
|
47
|
+
title = nil
|
48
|
+
body = nil
|
49
|
+
File.open(src) do |fsrc|
|
50
|
+
title_text = fsrc.readline
|
51
|
+
body_text = fsrc.read
|
52
|
+
syntax_items = []
|
53
|
+
body_text.gsub!(%r!<(pre|code)[^>]*?syntax=['"]([^'"]+)[^>]*>(.*?)</>!m){
|
54
|
+
ident = syntax_items.length
|
55
|
+
element, syntax, source = $1, $2, $3
|
56
|
+
syntax_items << "<#{element} class='syntax'>#{convert_syntax(syntax, source)}</#{element}>"
|
57
|
+
"syntax-temp-#{ident}"
|
58
|
+
}
|
59
|
+
title = RedCloth.new(title_text).to_html.gsub(%r!<.*?>!,'').strip
|
60
|
+
body = RedCloth.new(body_text).to_html
|
61
|
+
body.gsub!(%r!(?:<pre><code>)?syntax-temp-(d+)(?:</code></pre>)?!){ syntax_items[$1.to_i] }
|
62
|
+
end
|
63
|
+
stat = File.stat(src)
|
64
|
+
created = stat.ctime
|
65
|
+
modified = stat.mtime
|
66
|
+
|
67
|
+
$stdout << template.result(binding)
|