Author: mriou
Date: Thu May 22 16:19:31 2008
New Revision: 659304

URL: http://svn.apache.org/viewvc?rev=659304&view=rev
Log:
Scripting magic from Victor.

Added:
    ode/trunk/ode-git.rb   (with props)

Added: ode/trunk/ode-git.rb
URL: http://svn.apache.org/viewvc/ode/trunk/ode-git.rb?rev=659304&view=auto
==============================================================================
--- ode/trunk/ode-git.rb (added)
+++ ode/trunk/ode-git.rb Thu May 22 16:19:31 2008
@@ -0,0 +1,410 @@
+#!/usr/bin/env ruby
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with this
+# work for additional information regarding copyright ownership.  The ASF
+# licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+# This file has been shamelessly copied and tweaked from the one written by
+# Victor Hugo Borja from Apache Buildr. Thanks Victor!
+
+# This script helps ODE developers to obtain their own git clone from
+# github, having a set of pre-defined aliases to work with Apache's SVN.
+
+require 'yaml'
+require 'optparse'
+require 'ostruct'
+
+# Pager from http://nex-3.com/posts/73-git-style-automatic-paging-in-ruby
+def run_pager
+  return if PLATFORM =~ /win32/
+  return unless STDOUT.tty?
+
+  read, write = IO.pipe
+
+  unless Kernel.fork # Child process
+    STDOUT.reopen(write)
+    STDERR.reopen(write) if STDERR.tty?
+    read.close
+    write.close
+    return
+  end
+
+  # Parent process, become pager
+  STDIN.reopen(read)
+  read.close
+  write.close
+
+  ENV['LESS'] = 'FSRX' # Don't page if the input is short enough
+
+  Kernel.select [STDIN] # Wait until we have input before we start the pager
+  pager = ENV['PAGER'] || 'less'
+  exec pager rescue exec "/bin/sh", "-c", pager
+end
+
+def header
+  <<HEADER
+
+ODE official commit channel is Apache's svn repository, however some
+developers may prefer to use git while working on several features and
+merging other's changes.
+
+This script will configure a ode-git copy on so you can commit to svn.
+
+Enter <-h> to see options, <-H> to see notes about configured aliases
+and recommended workflow, or any other option.
+
+Ctrl+D or an invalid option to abort
+HEADER
+end
+
+def notice
+  <<NOTICE
+ALIASES:
+
+  Some git aliases have been created for developer convenience:
+
+    git apache-fetch    # get changes from apache/trunk without merging them
+                        # you can inspect what's happening on trunk without
+                        # having to worry about merging conflicts.
+                        # Inspect the remote branch with `git log apache/trunk`
+                        # Or if you have a git-ui like `tig` you can use that.
+
+    git apache-merge    # Merge already fetched changes on the current branch
+                        # Use this command to get up to date with trunk changes
+                        # you can always cherry-pick from the apache/trunk 
+                        # branch.
+
+    git apache-pull     # get apache-fetch && git apache-merge
+   
+    git apache-push     # Push to Apache's SVN. Only staged changes (those 
+                        # recorded using `git commit`) will be sent to SVN. 
+                        # You need not to be on the master branch.
+                        # Actually you can work on a tiny-feature branch and
+                        # commit directly from it. 
+                        #
+                        # VERY IMPORTANT: 
+                        #
+                        # Missing commits on Apache's SVN will be sent using
+                        # your apache svn account. This means that you can
+                        # make some commits on behalf of others (like patches
+                        # comming from JIRA issues or casual contributors)
+                        # Review the apache-push alias on .git/config if you 
+                        # want to change login-name used for commit to SVN.
+                        # 
+                        # See the recommended workflow to avoid commiting 
+                        # other developers' changes and the following section.
+
+THE GITHUB MIRROR:
+
+   ODE has an unofficial git mirror on github, maintained by Matthieu: 
+
+     http://github.com/matthieu/apache-ode
+
+   Actually it's not Matthieu who manually updates it, he has a cron-job on his
+   server, that only runs
+
+     git synchronize 
+
+   A command you also have configured on your .git/config file.
+
+   However there are some limitations due to the fact that git-svn cannot 
+   commit as multiple authors (unless all of them provided their passwords
+   to Matthieu, yet he doesn't want to take over the world.)
+   This means that if a commit is pushed to matthieu/apache-ode/master and has 
not
+   already been pushed by YOU to Apache's SVN by using `git apache-push` 
+   your change will be commited to apache/trunk having Matthieu as the author
+   (that's how he gains meritocratic points at Apache :P). 
+
+   So, it's very important - if you care about meritocracy - to follow or at 
+   least that you get an idea of the recommended workflow.
+
+RECOMMENDED WORKFLOW:
+   
+   So now that you have your local ODE copy you can create topic branches 
+   to work on independent features, and still merge easily with head changes. 
+
+   They may seem lots of things to consider, but it's all for ODE's healt.
+   As all things git, you can always follow your own workflow and even create
+   aliases on you .git/config file to avoid typing much. So, here they are:
+
+   1) get your ode-git configured 
+     (you have already do so, this was the most difficult part)
+
+   2) create a topic branch to work on, say.. you want to add cool-feature:
+
+        git checkout -b cool-feature master 
+        # now on branch cool-feature
+
+   3) hack hack hack.. use the source luke.
+      every time you feel you have something important like added failing 
+      spec, added part of feature, or resolved some conflict from merges,
+      you can commit your current progress. If you want to be selective, use: 
+      
+        git commit --interactive
+
+   3) review your changes, get ALL specs passing, repeat step 3 as needed
+
+   4) let's see what are they doing on trunk
+
+        git apache-fetch
+        # You can inspect the upstream changes without having to merge them
+        git log apache/trunk # what are they doing!!
+      
+   5) integrate mainstream changes to your cool-feature branch, you can always
+      use `git cherry-pick` to select only some commits.
+
+        git merge apache/trunk cool-feature
+   
+   6) Go to 3 unless ALL specs are passing.
+
+   7.a) (Skip to 7.b you have commit bit on Apache's SVN)
+      Create a patch using `git format-patch`
+      Promote your changes, create a JIRA issue and upload it granting Apache
+      license to include your code:
+
+        https://issues.apache.org/jira/browse/ODE
+        [EMAIL PROTECTED]
+
+   7.b) Now you have everyhing on staging area and merged important changes 
+      from apache/trunk, it's time to commit them to Apache's SVN.
+
+        git apache-push 
+
+   8) Optional. If you can push to matthieu/apache-ode/master mirror, you can 
just 
+     synchronize the mirror helping others to get changes without having to 
+     wait on Matthieu's cronjob to run every hour (useful for urgent changes).
+
+        git synchronize
+
+   9) Pull changes from origin frequently.
+        
+        git fetch origin
+        git rebase --onto origin/master master master
+
+   10) Unconditionally, Go to step 2 ;)
+       Share your ode-git workflow, git tips, etc.
+
+RESOURCES:
+
+   http://github.com/matthieu/apache-ode/tree/master
+   http://git.or.cz/gitwiki/GitCheatSheet
+   http://groups.google.com/group/git-users/web/git-references
+
+NOTICE
+end # notice method
+
+def optparse(options = OpenStruct.new, argv = ARGV)
+  opt = OptionParser.new do |opt|
+    
+    if `git status 2>/dev/null`.chomp.empty?
+      options.local = File.expand_path('ode', Dir.pwd)
+    else
+      puts "Current directory is a git repo: #{Dir.pwd}"
+      options.local = Dir.pwd 
+    end
+
+    options.svn_branch = "apache/trunk"
+    options.origin = "git://github.com/matthieu/apache-ode.git"
+    options.member = false
+
+    opt.banner = "Usage: ode-git.rb [options]"
+    opt.separator ""
+    opt.separator "OPTIONS:"
+
+    opt.on('-a', "--anon", "Use git://github.com/matthieu/apache-ode.git as 
origin") do 
+      options.origin = "git://github.com/matthieu/apache-ode.git"
+    end
+    opt.on('-A', "--auth", "Use [EMAIL PROTECTED]:matthieu/apache-ode.git as 
origin") do
+      options.origin = "[EMAIL PROTECTED]:matthieu/apache-ode.git"
+    end
+    opt.on("-o", "--origin GIT_URL", "Clone from GIT_URL origin") do |value|
+      options.origin = value
+    end
+    opt.on('-l', "--local DIRECTORY", "Create local git clone on DIRECTORY") 
do |value|
+      options.local = value
+    end
+    opt.on('-b', "--branch GIT_SVN_BRANCH", 
+           "Set the name for svn branch instead of apache/trunk") do |value|
+      options.svn_branch = value
+    end
+    opt.on('-e', "--email EMAIL", 
+           "Configure git to use EMAIL for commits") do |value|
+      options.email = value
+    end
+    opt.on('-n', "--name USER_NAME", 
+           "Configure your USER_NAME for git commits") do |value|
+      options.user_name = value
+    end
+    opt.on('-h', "--help", "Show ode-git help") do 
+      puts opt
+      throw :exit
+    end
+    opt.on('-H', "--notice", "Show notice about aliases and git workflow") do
+      run_pager
+      puts notice
+      throw :exit
+    end
+  end
+  opt.parse!(argv)
+  options
+end # optparse method
+
+
+def main
+  catch :exit do
+    options = optparse
+    puts header
+    puts 
+    print '> '
+    if input = gets
+      options = optparse(options, input.split)
+    end
+    if input.nil? || (input != "\n" && input.empty?)
+      puts "Aborting."
+      return
+    end
+    perform(options)
+  end  
+end
+
+def perform(options)
+  origin = options.origin
+  member = origin =~ /@/
+  local = options.local
+  svn_branch = options.svn_branch
+  user_email = options.email
+  user_name = options.user_name
+  
+  `git clone #{origin} #{local} 1>&2` unless File.directory?(File.join('.git', 
origin))
+  
+  puts
+  puts "Entering #{local} directory"
+  puts
+  Dir.chdir(local) do
+    
+    # Load the list of git-svn committers
+    svn_authors_file = File.expand_path('git-svn-authors', Dir.pwd)
+    svn_authors = File.read(svn_authors_file)
+    svn_authors.gsub!(/\s+=\s+/, ': ')
+    svn_authors = YAML.load(svn_authors)
+
+    # set the git-svn-authors file
+    `git config svn.authorsfile "#{svn_authors_file}"`
+
+    # Check that git is configured for the developer
+    user_email ||= `git config --get user.email`.chomp
+    if user_email.empty?
+      if member
+        puts "Enter your email as listed on #{svn_authors_file}"
+        print "> "
+        user_email = gets.chomp
+      else
+        puts "Provide an email address for git usage:"
+        user_email = gets.chomp
+      end
+    end
+
+    # Check user is listed
+    unless user_email.empty?
+      svn_user, git_contact = *svn_authors.find { |entry| /#{user_email}/ === 
entry.join(' ') }
+    end
+
+    if member 
+      if git_contact.nil? # if using the authenticated git, he must be listed
+        puts <<-NOTICE
+          You need to be a ODE commmitter listed on #{svn_authors_file}. 
+          Perhaps you need to add yourself to it, commit it using SVN, and 
+          and run this script again.
+          Also checks your git global values for user.email and user.name
+        NOTICE
+        return
+      elsif /\s*(.*?)\s+\<(.+)\>\s*/ === git_contact
+        user_name, user_email = $1, $2
+      else
+        puts "Invalid contact string for #{svn_user}: #{git_contact.inspect}"
+        return
+      end
+    elsif user_email =~ /^\s*$/
+      puts "User email shall not include spaces: #{user_email.inspect}"
+      return
+    end
+    
+    user_name ||= `git config --get user.name`.chomp
+    if git_contact.nil? && user_name.empty?
+      puts "Provide a developer name for git usage:"
+      user_name = gets.chomp
+    end
+    
+    # Start the pager
+    run_pager
+    puts
+
+
+    old_origin = `git config --get remote.origin.url`.chomp
+    if member && old_origin !~ /@/
+      puts "Switching to authenticated origin #{origin}", ""
+      `git config remote.origin.url "#{origin}"`
+    elsif !member && old_origin =~ /@/
+      puts "Switching to anonymous origin #{origin}", ""
+      `git config remote.origin.url "#{origin}"`
+    end
+    
+    # Configure user name and email for git sake (and github's gravatar)
+    puts "You claim to be #{user_name.inspect} <#{user_email}> "
+    puts "with apache-svn user: #{svn_user}" if svn_user
+    puts
+    `git config user.name  "#{user_name}"`
+    `git config user.email "#{user_email}"`
+    
+    # Ok, now obtain the last svn commit from history
+    last_svn_log = `git log -n 10 | grep git-svn-id | head -n 1`
+    fail "No svn metadata on last 10 commits" unless last_svn_log =~ 
/git-svn-id/
+    svn_repo, svn_prev = last_svn_log.split[1].split("@")
+    
+    # Tell git where the svn repository is.
+    `git config svn-remote.#{svn_branch}.url #{svn_repo}`
+    `git config svn-remote.#{svn_branch}.fetch :refs/remotes/#{svn_branch}`
+    
+    # Create the svn branch, do this instead of pulling the full svn history
+    `git push --force . refs/remotes/origin/master:refs/remotes/#{svn_branch}`
+    
+    # Create apache aliases for developers git-workflow.
+    `git config alias.apache-fetch "!git-svn fetch #{svn_branch}"`
+    `git config alias.apache-merge "!git merge #{svn_branch}"`
+    `git config alias.apache-pull  "!git apache-fetch && git apache-merge"`
+    if svn_user
+      `git config alias.apache-push  "!git-svn dcommit --username #{svn_user}"`
+    else
+      `git config alias.apache-push  "!git-svn dcommit"`
+    end
+    
+    # Create github origin aliases
+    `git config alias.get "!git apache-fetch && git fetch origin"`
+    `git config alias.mrg "!git apache-merge && git merge origin"`
+    `git config alias.rbs "!git rebase --onto #{svn_branch} origin/master 
master"`
+    `git config alias.put "!git apache-push && git push origin"`
+    
+    # This is Matthieu's cronjob
+    `git config alias.synchronize "!git get && git rbs && git put"`
+    
+    # Final notices.
+    puts <<-NOTICE + notice
+
+    Your git repo #{local} has been configured, please review the 
+       #{File.join(local, '.git/config')} file.
+
+    NOTICE
+  end  
+end # perform method
+
+main

Propchange: ode/trunk/ode-git.rb
------------------------------------------------------------------------------
    svn:executable = *


Reply via email to