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 ADDED
@@ -0,0 +1,8 @@
1
+ == 0.2.1 2007-06-17
2
+
3
+ * Fixed up svn:branch:merge_to_trunk
4
+
5
+ == 0.0.2 2007-06-10
6
+
7
+ * 1 major enhancement:
8
+ * Initial release
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
@@ -0,0 +1,9 @@
1
+ module SvnBranch #:nodoc:
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 2
5
+ TINY = 1
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ 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)