svn_branch 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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)
|