lib/svn2git/migration.rb in nirvdrum-svn2git-1.1.1 vs lib/svn2git/migration.rb in nirvdrum-svn2git-1.2.0
- old
+ new
@@ -1,119 +1,179 @@
+require 'optparse'
+require 'pp'
+
module Svn2Git
DEFAULT_AUTHORS_FILE = "~/.svn2git/authors"
-
+
class Migration
-
+
attr_reader :dir
-
- def initialize(url, options = {})
- @url = url
- @dir = @url.scan(/[^\/]+/).last
-
- @options = options
- @options[:trunk] ||= 'trunk'
- @options[:branches] ||= 'branches'
- @options[:tags] ||= 'tags'
-
- @authors = options[:authors]
- if @authors.nil? && File.exists?(File.expand_path(DEFAULT_AUTHORS_FILE))
- @authors = DEFAULT_AUTHORS_FILE
- end
+
+ def initialize(args)
+ @options = parse(args)
+ show_help_message("Missing SVN_URL parameter") if args.empty?
+ show_help_message('Too many arguments') if args.size > 1
+
+ @url = args.first
end
-
+
def run!
clone!
fix_tags
fix_branches
fix_trunk
optimize_repos
end
-
+
+ def parse(args)
+ # Set up reasonable defaults for options.
+ options = {}
+ options[:verbose] = false
+ options[:rootistrunk] = false
+ options[:trunk] = 'trunk'
+ options[:branches] = 'branches'
+ options[:tags] = 'tags'
+
+ if File.exists?(File.expand_path(DEFAULT_AUTHORS_FILE))
+ options[:authors] = DEFAULT_AUTHORS_FILE
+ end
+
+
+ # Parse the command-line arguments.
+ @opts = OptionParser.new do |opts|
+ opts.banner = 'Usage: svn2git SVN_URL [options]'
+
+ opts.separator ''
+ opts.separator 'Specific options:'
+
+ opts.on('--trunk TRUNK_PATH', 'Subpath to trunk from repository URL (default: trunk)') do |trunk|
+ options[:trunk] = trunk
+ end
+
+ opts.on('--branches BRANCHES_PATH', 'Subpath to branches from repository URL (default: branches)') do |branches|
+ options[:branches] = branches
+ end
+
+ opts.on('--tags TAGS_PATH', 'Subpath to tags from repository URL (default: tags)') do |tags|
+ options[:tags] = tags
+ end
+
+ opts.on('--authors AUTHORS_FILE', "Path to file containing svn-to-git authors mapping (default: #{DEFAULT_AUTHORS_FILE})") do |authors|
+ options[:authors] = authors
+ end
+
+ opts.on('--rootistrunk', 'Use this if the root level of the repo isequivalent to the trunk and there are no tags or branches') do
+ options[:rootistrunk] = true
+ end
+
+ opts.on('-v', '--verbose', 'Be verbose in logging -- useful for debugging issues') do
+ options[:verbose] = true
+ end
+
+ opts.separator ""
+
+ # No argument, shows at tail. This will print an options summary.
+ # Try it and see!
+ opts.on_tail('-h', '--help', 'Show this message') do
+ puts opts
+ exit
+ end
+ end
+
+ @opts.parse! args
+ options
+ end
+
private
-
+
def clone!
trunk = @options[:trunk]
branches = @options[:branches]
tags = @options[:tags]
rootistrunk = @options[:rootistrunk]
-
- if (!rootistrunk.nil?)
+ authors = @options[:authors]
+
+ if rootistrunk
# Non-standard repository layout. The repository root is effectively 'trunk.'
run_command("git svn init --no-metadata --trunk=#{@url}")
-
+
else
cmd = "git svn init --no-metadata "
-
+
# Add each component to the command that was passed as an argument.
cmd += "--trunk=#{trunk} " unless trunk.nil?
cmd += "--tags=#{tags} " unless tags.nil?
cmd += "--branches=#{branches} " unless branches.nil?
-
+
cmd += @url
-
+
run_command(cmd)
end
-
- run_command("git config svn.authorsfile #{@authors}") if @authors
+
+ run_command("git config svn.authorsfile #{authors}") if authors
run_command("git svn fetch")
-
+
get_branches
end
-
+
def get_branches
@remote = `git branch -r`.split(/\n/)
@tags = @remote.find_all { |b| b.strip =~ %r{^#{@options[:tags]}\/} }
end
-
+
def fix_tags
@tags.each do |tag|
id = tag.strip.gsub(%r{^#{@options[:tags]}\/}, '')
subject = `git log -1 --pretty=format:"%s" #{tag.strip()}`
date = `git log -1 --pretty=format:"%ci" #{tag.strip()}`
`export GIT_COMMITER_DATE="#{date}"`
run_command("git tag -a -m '#{subject}' '#{id.strip()}' '#{tag.strip()}'")
run_command("git branch -d -r #{tag.strip()}")
end
end
-
+
def fix_branches
svn_branches = @remote.find_all { |b| not @tags.include?(b) }
svn_branches.each do |branch|
branch = branch.strip
next if branch == 'trunk'
run_command("git checkout #{branch}")
run_command("git checkout -b #{branch}")
end
end
-
+
def fix_trunk
trunk = @remote.find { |b| b.strip == 'trunk' }
if trunk
run_command("git checkout trunk")
run_command("git branch -D master")
run_command("git checkout -f -b master")
run_command("git branch -d -r trunk")
end
end
-
+
def optimize_repos
run_command("git gc")
end
-
+
def run_command(cmd)
log "Running command: #{cmd}"
-
+
IO.popen(cmd) do |stdout|
stdout.each do |line|
log line
end
end
end
- private
-
def log(msg)
puts msg if @options[:verbose]
+ end
+
+ def show_help_message(msg)
+ puts "Error starting script: #{msg}\n\n"
+ puts @opts.help
+ exit
end
end
end