lib/svn2git/migration.rb in svn2git-2.0.0 vs lib/svn2git/migration.rb in svn2git-2.1.0

- old
+ new

@@ -34,15 +34,19 @@ def parse(args) # Set up reasonable defaults for options. options = {} options[:verbose] = false + options[:metadata] = false + options[:nominimizeurl] = false options[:rootistrunk] = false options[:trunk] = 'trunk' options[:branches] = 'branches' options[:tags] = 'tags' options[:exclude] = [] + options[:revision] = nil + options[:username] = nil if File.exists?(File.expand_path(DEFAULT_AUTHORS_FILE)) options[:authors] = DEFAULT_AUTHORS_FILE end @@ -56,17 +60,22 @@ opts.on('--rebase', 'Instead of cloning a new project, rebase an existing one against SVN') do options[:rebase] = true end + opts.on('--username NAME', 'Username for transports that needs it (http(s), svn)') do |username| + options[:username] = username + end + 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('--rootistrunk', 'Use this if the root level of the repo is equivalent to the trunk and there are no tags or branches') do @@ -86,10 +95,22 @@ opts.on('--notags', 'Do not try to import any tags') do options[:tags] = nil end + opts.on('--no-minimize-url', 'Accept URLs as-is without attempting to connect to a higher level directory') do + options[:nominimizeurl] = true + end + + opts.on('--revision REV', 'Start importing from SVN revision') do |revision| + options[:revision] = revision + end + + opts.on('-m', '--metadata', 'Include metadata in git logs (git-svn-id)') do + options[:metadata] = true + 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('--exclude REGEX', 'Specify a Perl regular expression to filter paths when fetching; can be used multiple times') do |regex| @@ -118,22 +139,38 @@ def clone! trunk = @options[:trunk] branches = @options[:branches] tags = @options[:tags] + metadata = @options[:metadata] + nominimizeurl = @options[:nominimizeurl] rootistrunk = @options[:rootistrunk] authors = @options[:authors] exclude = @options[:exclude] + revision = @options[:revision] + username = @options[:username] if rootistrunk # Non-standard repository layout. The repository root is effectively 'trunk.' - run_command("git svn init --no-metadata --trunk=#{@url}") + cmd = "git svn init --prefix=svn/ " + cmd += "--username=#{username} " unless username.nil? + cmd += "--no-metadata " unless metadata + if nominimizeurl + cmd += "--no-minimize-url " + end + cmd += "--trunk=#{@url}" + run_command(cmd) else - cmd = "git svn init --no-metadata " + cmd = "git svn init --prefix=svn/ " # Add each component to the command that was passed as an argument. + cmd += "--username=#{username} " unless username.nil? + cmd += "--no-metadata " unless metadata + if nominimizeurl + cmd += "--no-minimize-url " + end cmd += "--trunk=#{trunk} " unless trunk.nil? cmd += "--tags=#{tags} " unless tags.nil? cmd += "--branches=#{branches} " unless branches.nil? cmd += @url @@ -141,22 +178,23 @@ run_command(cmd) end run_command("git config svn.authorsfile #{authors}") unless authors.nil? - cmd = "git svn fetch" + cmd = "git svn fetch " + cmd += "-r #{revision}:HEAD " unless revision.nil? unless exclude.empty? # Add exclude paths to the command line; some versions of git support # this for fetch only, later also for init. regex = [] unless rootistrunk regex << "#{trunk}[/]" unless trunk.nil? regex << "#{tags}[/][^/]+[/]" unless tags.nil? regex << "#{branches}[/][^/]+[/]" unless branches.nil? end regex = '^(?:' + regex.join('|') + ')(?:' + exclude.join('|') + ')' - cmd += " '--ignore-paths=#{regex}'" + cmd += "'--ignore-paths=#{regex}'" end run_command(cmd) get_branches end @@ -166,17 +204,17 @@ # '*' character used to indicate the currently selected branch. @local = run_command("git branch -l --no-color").split(/\n/).collect{ |b| b.gsub(/\*/,'').strip } @remote = run_command("git branch -r --no-color").split(/\n/).collect{ |b| b.gsub(/\*/,'').strip } # Tags are remote branches that start with "tags/". - @tags = @remote.find_all { |b| b.strip =~ %r{^tags\/} } + @tags = @remote.find_all { |b| b.strip =~ %r{^svn\/tags\/} } end def fix_tags @tags.each do |tag| tag = tag.strip - id = tag.gsub(%r{^tags\/}, '').strip + id = tag.gsub(%r{^svn\/tags\/}, '').strip subject = run_command("git log -1 --pretty=format:'%s' #{tag}") date = run_command("git log -1 --pretty=format:'%ci' #{tag}") subject = escape_quotes(subject) date = escape_quotes(date) id = escape_quotes(id) @@ -185,30 +223,36 @@ end end def fix_branches svn_branches = @remote.find_all { |b| not @tags.include?(b) } - svn_branches.each do |branch| - branch = branch.strip + svn_branches = @remote.find_all { |b| b.strip =~ %r{^svn\/} } + if @options[:rebase] + run_command("git svn fetch") + end + + svn_branches.each do |branch| + branch = branch.gsub(/^svn\//,'').strip if @options[:rebase] && (@local.include?(branch) || branch == 'trunk') - branch = 'master' if branch == 'trunk' - run_command("git checkout -f #{branch}") - run_command("git svn rebase") + lbranch = branch + lbranch = 'master' if branch == 'trunk' + run_command("git checkout -f #{lbranch}") + run_command("git rebase remotes/svn/#{branch}") next end - next if branch == 'trunk' - run_command("git branch -t #{branch} remotes/#{branch}") + next if branch == 'trunk' || @local.include?(branch) + run_command("git branch --track #{branch} remotes/svn/#{branch}") run_command("git checkout #{branch}") end end def fix_trunk trunk = @remote.find { |b| b.strip == 'trunk' } if trunk && ! @options[:rebase] - run_command("git checkout trunk") + run_command("git checkout svn/trunk") run_command("git branch -D master") run_command("git checkout -f -b master") else run_command("git checkout -f master") end @@ -227,11 +271,11 @@ stdout.each do |line| log line ret << line end end - + ret end def log(msg) puts msg if @options[:verbose] @@ -240,15 +284,15 @@ def show_help_message(msg) puts "Error starting script: #{msg}\n\n" puts @opts.help exit end - + def verify_working_tree_is_clean status = run_command('git status --porcelain --untracked-files=no') unless status.strip == '' puts 'You have local pending changes. The working tree must be clean in order to continue.' - exit + exit -1 end end def escape_quotes(str) str.gsub("'", "'\\\\''")