↓ Skip to main content

Ruby

Git bits 2

·204 words·1 min
Using the Scala source repo to demonstrate - see Github Show merged and unmerged branches # This command allows you to show all local branches merged / unmerged to current branch ➜ scala git:(2.12.x) git branch -a --merged * 2.12.x remotes/origin/2.11.x remotes/origin/2.12.x remotes/origin/HEAD -> origin/2.12.x ➜ scala git:(2.12.x) git branch -a --no-merged remotes/origin/2.10.x remotes/origin/2.8.x remotes/origin/2.9.x remotes/origin/DarkDimius-patch-1 remotes/origin/gh-pages remotes/origin/legacy/msil This shows you all local branches merged into named branch:

Git - find unmerged commits

·1000 words·5 mins
This is Ruby script I found way back and was using it since. The credits for creation goes to Zach Dennis. The script is decribed in his blog post The source is here Example # This is beginning of very long output from Groovy source The code # #!/usr/bin/env ruby require 'rubygems' gem 'term-ansicolor', '>=1.0.5' require 'term/ansicolor' class GitCommit attr_reader :content def initialize(content) @content = content end def sha @content.split[1] end def to_s `git log --pretty=format:"%h %ad %an - %s" #{sha}~1..#{sha}` end def unmerged? content =~ /^\+/ end def equivalent? content =~ /^\-/ end end class GitBranch attr_reader :name, :commits def initialize(name, commits) @name = name @commits = commits end # Returns origin from origin/some/branch/here def repository name.split("/", 2).first end # Returns some/branch/here from origin/some/branch/here def branch_name name.split("/", 2).last end def unmerged_commits commits.select{ |commit| commit.unmerged? } end def equivalent_commits commits.select{ |commit| commit.equivalent? } end end class GitBranches < Array def self.clean_branch_output(str) str.split(/\n/).map{ |e| e.strip.gsub(/\*\s+/, '') }.reject{ |branch| branch =~ /\b#{Regexp.escape(UPSTREAM)}\b/ }.sort end def self.local_branches clean_branch_output `git branch` end def self.remote_branches clean_branch_output `git branch -r` end def self.load(options) git_branches = new branches = if options[:local] local_branches elsif options[:remote] remote_branches end branches.each do |branch| raw_commits = `git cherry -v #{UPSTREAM} #{branch}`.split(/\n/).map{ |c| GitCommit.new(c) } git_branches << GitBranch.new(branch, raw_commits) end git_branches end def unmerged reject{ |branch| branch.commits.empty? }.sort_by{ |branch| branch.name } end def any_missing_commits? select{ |branch| branch.commits.any? }.any? end end class GitUnmerged VERSION = "1.1" include Term::ANSIColor attr_reader :branches def initialize(args) @options = {} @branches_to_prune = [] extract_options_from_args(args) end def load @branches ||= GitBranches.load(:local => local?, :remote => remote?) @branches.reject!{|b| @options[:exclude].include?(b.name)} if @options[:exclude].is_a?(Array) @branches.select!{|b| @options[:only].include?(b.name)} if @options[:only].is_a?(Array) end def print_overview load if @options[:exclude] && @options[:exclude].length > 0 puts "The following branches have been excluded" @options[:exclude].each do |branch_name| puts " #{branch_name}" end puts end if @options[:only] && @options[:only].length > 0 puts "The following branches will be compared against:" @options[:only].each do |branch_name| puts " #{branch_name}" end puts end if branches.any_missing_commits? puts "The following branches possibly have commits not merged to #{upstream}:" branches.each do |branch| num_unmerged = yellow(branch.unmerged_commits.size.to_s) num_equivalent = green(branch.equivalent_commits.size.to_s) puts %| #{branch.name} (#{num_unmerged}/#{num_equivalent} commits)| end end end def print_help puts <<-EOT.gsub(/^\s+\|/, '') |Usage: #{$0} [-a] [--upstream <branch>] [--remote] [--prune] | |This script wraps the "git cherry" command. It reports the commits from all local |branches which have not been merged into an upstream branch. | | #{yellow("yellow")} commits have not been merged | #{green("green")} commits have equivalent changes in <upstream> but different SHAs | |The default upstream is 'master' (or 'origin/master' if running with --remote) | |OPTIONS: | -a display all unmerged commits (verbose) | --remote (-r) compare remote branches instead of local branches | --upstream <branch> specify a specific upstream branch (defaults to master) | --exclude <branch>[,<branch>,...] specify a comma-separated list of branches to exclude | --only <branch>[,<branch>,...] specify a comma-separated list of branches to include | --prune prompts user to delete branches which have no differences with the upstream | |EXAMPLE: check for all unmerged commits | #{$0} | |EXAMPLE: check for all unmerged commits and merged commits (but with a different SHA) | #{$0} -a | |EXAMPLE: use a different upstream than master | #{$0} --upstream otherbranch | |EXAMPLE: compare remote branches against origin/master | #{$0} --remote (-r) | |EXAMPLE: delete branches without unmerged commits | #{$0} --prune | |EXAMPLE: delete remote branches without unmerged commits | #{$0} --remote --prune | |GITCONFIG: | If you name this file git-unmerged and place it somewhere in your PATH | you will be able to type "git unmerged" to use it. If you'd like to name | it something else and still refer to it with "git unmerged" then you'll | need to set up an alias: | git config --global alias.unmerged \\!#{$0} | |Version: #{VERSION} |Author: Zach Dennis <zdennis@mutuallyhuman.com> EOT exit end def print_version puts "#{VERSION}" end def branch_description local? ? "local" : "remote" end def print_specifics load if branches.any_missing_commits? print_breakdown else puts "There are no #{branch_description} branches out of sync with #{upstream}" end end def print_breakdown puts "Below is a breakdown for each branch. Here's a legend:" puts print_legend branches.each do |branch| puts print "#{branch.name}:" if branch.unmerged_commits.empty? && !show_equivalent_commits? print "(no unmerged commits" if prune? print ",", red(" this will be pruned") @branches_to_prune << branch end print ")\n" else puts end branch.unmerged_commits.each { |commit| puts yellow(commit.to_s) } if show_equivalent_commits? branch.equivalent_commits.each do |commit| puts green(commit.to_s) end end end end def print_legend load puts " " + yellow("yellow") + " commits have not been merged" puts " " + green("green") + " commits have equivalent changes in #{UPSTREAM} but different SHAs" if show_equivalent_commits? end def prune return unless prune? if @branches_to_prune.empty? puts "", "There are no branches to prune." else # Protects Heroku repo's rejected_master_branches = @branches_to_prune.reject!{|branch| branch.branch_name =~ /master/} puts "", "Are you sure you want to prune the following #{@branches_to_prune.size} branches?", "" puts red("(Keep in mind this will remove these branches from the remote repository)") if @remote @branches_to_prune.each do |branch| puts red(" #{branch.name}") end puts "(omitting branches named master)" if rejected_master_branches puts print "y or n: " if STDIN.gets=~/y/i @branches_to_prune.each do |branch| if local? `git branch -D #{branch.name}` elsif remote? puts "pruning: #{branch.branch_name} with 'git push #{branch.repository} :#{branch.branch_name}'" `git push #{branch.repository} :#{branch.branch_name}` end end puts "", "Pruned #{@branches_to_prune.size} branches." else puts "", "Pruning aborted. All branches were left unharmed." end end end def prune? ; @options[:prune ] ; end def show_help? ; @options[:show_help] ; end def show_equivalent_commits? ; @options[:show_equivalent_commits] ; end def show_version? ; @options[:show_version] ; end def upstream if @options[:upstream] @options[:upstream] elsif local? "master" elsif remote? "origin/master" end end private def extract_options_from_args(args) if args.include?("--remote") || args.include?("-r") @options[:remote] = true else @options[:local] = true end @options[:prune] = true if args.include?("--prune") @options[:show_help] = true if args.include?("-h") || args.include?("--help") @options[:show_equivalent_commits] = true if args.include?("-a") @options[:show_version] = true if args.include?("-v") || args.include?("--version") if index=args.index("--upstream") @options[:upstream] = args[index+1] end if index=args.index("--exclude") @options[:exclude] = args[index+1].split(',') end if index=args.index("--only") @options[:only] = args[index+1].split(',') end end def local? ; @options[:local] ; end def remote? ; @options[:remote] ; end end unmerged = GitUnmerged.new ARGV UPSTREAM = unmerged.upstream if unmerged.show_help? unmerged.print_help exit elsif unmerged.show_version? unmerged.print_version exit else unmerged.print_overview puts unmerged.print_specifics unmerged.prune end

Finding unmerged commits in all branches

·669 words·4 mins
This one goes beyond git, but is very useful. Ruby script that produces this: Here is the script #!/usr/bin/env ruby require 'rubygems' gem 'term-ansicolor', '=1.3.0' require 'term/ansicolor' class GitCommit attr_reader :content def initialize(content) @content = content end def sha @content.split[1] end def to_s `git log --pretty=format:"%h %ad %an - %s" #{sha}~1..#{sha}` end def unmerged? content =~ /^\+/ end def equivalent? content =~ /^\-/ end end class GitBranch attr_reader :name, :commits def initialize(name, commits) @name = name @commits = commits end def unmerged_commits commits.select{ |commit| commit.unmerged? } end def equivalent_commits commits.select{ |commit| commit.equivalent? } end end class GitBranches < Array def self.clean_branch_output(str) str.split(/\n/).map{ |e| e.strip.gsub(/\*\s+/, '') }.reject{ |branch| branch =~ /\b#{Regexp.escape(UPSTREAM)}\b/ }.sort end def self.local_branches clean_branch_output `git branch` end def self.remote_branches clean_branch_output `git branch -r` end def self.load(options) git_branches = new branches = if options[:local] local_branches elsif options[:remote] remote_branches end branches.each do |branch| raw_commits = `git cherry -v #{UPSTREAM} #{branch}`.split(/\n/).map{ |c| GitCommit.new(c) } git_branches << GitBranch.new(branch, raw_commits) end git_branches end def unmerged reject{ |branch| branch.commits.empty? }.sort_by{ |branch| branch.name } end def any_missing_commits? select{ |branch| branch.commits.any? }.any? end end class GitUnmerged VERSION = "1.0.1" include Term::ANSIColor attr_reader :branches def initialize(args) @options = {} extract_options_from_args(args) end def load @branches ||= GitBranches.load(:local => local?, :remote => remote?) end def print_overview load if branches.any_missing_commits? puts "The following branches possibly have commits not merged to #{upstream}:" branches.each do |branch| num_unmerged = yellow(branch.unmerged_commits.size.to_s) num_equivalent = green(branch.equivalent_commits.size.to_s) puts %| #{branch.name} (#{num_unmerged}/#{num_equivalent} commits)| end end end def print_help puts <<-EOT.gsub(/^\s+\|/, '') |Usage: #{$0} [-a] [--upstream <branch>] [--remote] | |This script wraps the "git cherry" command. It reports the commits from all local |branches which have not been merged into an upstream branch. | | #{yellow("yellow")} commits have not been merged | #{green("green")} commits have equivalent changes in <upstream> but different SHAs | |The default upstream is 'master'. | |OPTIONS: | -a display all unmerged commits (verbose) | --remote compare remote branches instead of local branches | --upstream <branch> specify a specific upstream branch | |EXAMPLE: check for all unmerged commits | #{$0} | |EXAMPLE: check for all unmerged commits and merged commits (but with a different SHA) | #{$0} -a | |EXAMPLE: use a different upstream than master | #{$0} --upstream otherbranch | |EXAMPLE: compare remote branches against origin/master | #{$0} --remote | |GITCONFIG: | If you name this file git-unmerged and place it somewhere in your PATH | you will be able to type "git unmerged" to use it. If you'd like to name | it something else and still refer to it with "git unmerged" then you'll | need to set up an alias: | git config --global alias.unmerged \\!#{$0} | |Version: #{VERSION} |Author: Zach Dennis <zdennis@mutuallyhuman.com> EOT exit end def print_version puts "#{VERSION}" end def branch_description local? ? "local" : "remote" end def print_specifics load if branches.any_missing_commits? print_breakdown else puts "There are no #{branch_description} branches out of sync with #{upstream}" end end def print_breakdown puts "Below is a breakdown for each branch. Here's a legend:" puts print_legend branches.each do |branch| puts print "#{branch.name}:" if branch.unmerged_commits.empty? && !show_equivalent_commits? print "(no umerged commits, must have merged commits with different SHAs)\n" else puts end branch.unmerged_commits.each { |commit| puts yellow(commit.to_s) } if show_equivalent_commits? branch.equivalent_commits.each do |commit| puts green(commit.to_s) end end end end def print_legend load puts " " + yellow("yellow") + " commits have not been merged" puts " " + green("green") + " commits have equivalent changes in #{UPSTREAM} but different SHAs" if show_equivalent_commits? end def show_help? ; @options[:show_help] ; end def show_equivalent_commits? ; @options[:show_equivalent_commits] ; end def show_version? ; @options[:show_version] ; end def upstream if @options[:upstream] @options[:upstream] elsif local? "master" elsif remote? "origin/master" end end private def extract_options_from_args(args) if args.include?("--remote") @options[:remote] = true else @options[:local] = true end @options[:show_help] = true if args.include?("-h") || args.include?("--help") @options[:show_equivalent_commits] = true if args.include?("-a") @options[:show_version] = true if args.include?("-v") || args.include?("--version") if index=args.index("--upstream") @options[:upstream] = args[index+1] end end def local? ; @options[:local] ; end def remote? ; @options[:remote] ; end end unmerged = GitUnmerged.new ARGV UPSTREAM = unmerged.upstream if unmerged.show_help? unmerged.print_help exit elsif unmerged.show_version? unmerged.print_version exit else unmerged.print_overview puts unmerged.print_specifics end

Bye bye Ruby, hello Groovy

·1049 words·5 mins
I first time discovered Ruby back in 2006 (yes, I know, I was late to the game), and immediately fell in love with it. The dynamic nature of the language, the consistency, pure esthaetics and practicality certainly changed the way how I saw software development and programming languages. Since that time, I made several attempts to integrate Ruby into my professional life and make it part of the toolbox. It was cool to play with Ruby in my spare time, but I wanted to use it on projects whose main development language/platform was mainly Java. Use it as scripting, glue language. Use it as toolkit language to e.g. generate test data, access databases, convert files, build projects and maybe even build a piece of Web applications (admin apps for example).

Rails 2 - really good tutorial

·43 words·1 min
Akita published two part tutorial that leads you through building the famous 15 minute blog application in Rails 2.0. Read the parts one and two - or follow the screencast by the same author. Thanks a lot, Akita - very nicely done !

Starting Ruby on Rails 2 with Netbeans and AWDWR book

·701 words·4 mins
After some break, I got back to Rails land. The return is not as smooth as I hoped: since Rails 2.0, many things work differently and quite a few steps learned from "The Book" do not work any more. The issues are more often than not quite easy to fix, but there is quite a few of them. All the following is related to NetbeansRuby build 6327 from Jan 26th with JRuby 1.1RC1

Showstopper issue with JRuby ?

·606 words·3 mins
After some break, I dusted off the Ruby to try out one interesting idea Peter presented yesterday that literally ASKS for Rails. So I grabbed the latest and greatest RubyNetBeans from Ruby Hudson. For some reason it stopped updates on January 26th so the latest version I have got was build 6327. It is bundled with JRuby 1.1RC1 and the Rails version that comes preinstalled is 1.2.6. Using the menu Tools -> Ruby Gems, they can be easily upgraded to latest and greatest 2.0.2.

JRuby - keeping your database.yml really DRY

·180 words·1 min
I am experimenting in JRuby and use database in virtual machine (VMWare Fusion). This is great because you can have multiple versions of multiple databases ready without polluting the notebook. One downsize though is that IP address of the database will change between the VM restarts. First important setting in Fusion is to use the 'NAT' option rather than 'Bridged'. With NAT, you database host IP address will not follow the network. It was quite annoying to change it from 192.168.X to 192.168.Y everytime I reconnected at home from work or vice versa.

JRuby trunk - issues with JDBC connectivity

·344 words·2 mins
Following the book on JRuby I am discovering small differences when trying the examples. After installing activerecord-jdbc gem which is available in version 0.5, the shoplet application fails with Rails 2.0, as soon as you click on the 'About your application environment' link. => Booting Mongrel (use 'script/server webrick' to force WEBrick) => Rails application starting on http://0.0.0.0:3000 => Call with -d to detach => Ctrl-C to shutdown server ** Starting Mongrel listening at 0.0.0.0:3000 ** Starting Rails with development environment... ** Rails loaded. ** Loading any Rails specific GemPlugins ** Signals ready. TERM => stop. USR2 => restart. INT => stop (no restart). ** Rails signals registered. HUP => reload (without restart). It might not work well. ** Mongrel 1.1.2 available at 0.0.0.0:3000 ** Use CTRL-C to stop. Processing InfoController#properties (for 127.0.0.1 at 2007-12-23 23:13:25) [GET] Session ID: BAh7BiIKZmxhc2hJQzonQWN0aW9uQ29udHJvbGxlcjo6Rmxhc2g6OkZsYXNo%0ASGFzaHsABjoKQHVzZWR7AA%3D%3D--9791be23205677745e457b5bf62c50eba6e3813f Parameters: {"controller"=>"rails/info", "action"=>"properties"} Exception in thread "Ruby Thread11043409" java.lang.NoSuchMethodError: org.jruby.runtime.builtin.IRubyObject.setInstanceVariable(Ljava/lang/String;Lorg/jruby/runtime/builtin/IRubyObject;)Lorg/jruby/runtime/builtin/IRubyObject; at JdbcAdapterInternalService.set_connection(JdbcAdapterInternalService.java:122) at JdbcAdapterInternalServiceInvoker$set_connection_FS1.call(Unknown Source) at org.jruby.runtime.callback.FastInvocationCallback.execute(FastInvocationCallback.java:55) at org.jruby.internal.runtime.methods.SimpleCallbackMethod.call(SimpleCallbackMethod.java:70) at org.jruby.runtime.CallSite$InlineCachingCallSite.call(CallSite.java:158) at org.jruby.runtime.CallSite$ArgumentBoxingCallSite.call(CallSite.java:103) at org.jruby.evaluator.ASTInterpreter.fCallNode(ASTInterpreter.java:1092) at org.jruby.evaluator.ASTInterpreter.evalInternal(ASTInterpreter.java:345) at org.jruby.evaluator.ASTInterpreter.blockNode(ASTInterpreter.java:626) at org.jruby.evaluator.ASTInterpreter.evalInternal(ASTInterpreter.java:293) at org.jruby.evaluator.ASTInterpreter.eval(ASTInterpreter.java:168) at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:147) at org.jruby.runtime.CallSite$InlineCachingCallSite.call(CallSite.java:158) at org.jruby.runtime.CallSite$ArgumentBoxingCallSite.call(CallSite.java:76) at org.jruby.evaluator.ASTInterpreter.vcallNode(ASTInterpreter.java:1734) at org.jruby.evaluator.ASTInterpreter.evalInternal(ASTInterpreter.java:474) at org.jruby.evaluator.ASTInterpreter.blockNode(ASTInterpreter.java:626) at org.jruby.evaluator.ASTInterpreter.evalInternal(ASTInterpreter.java:293) at org.jruby.evaluator.ASTInterpreter.rescueNode(ASTInterpreter.java:1499) at org.jruby.evaluator.ASTInterpreter.evalInternal(ASTInterpreter.java:442) at org.jruby.evaluator.ASTInterpreter.eval(ASTInterpreter.java:168) I found out that there is newer version of activerecord-jdbc, which is also renamed to activerecord-jdbc-adapter. It is important to uninstall the old gem as well as install the new one, otherwise the application will not work.

Installation of Mongrel gem on JRuby

·159 words·1 min
I bought the Ola Bini's eBook on JRuby and started to work through the examples. The installation of the Mongrel gem in JRuby (trunk revision 5341 fails with the following error code: ``` $ jruby -S gem install -y mongrel> INFO: `gem install -y` is now default and will be removed> INFO: use --ignore-dependencies to install only the gems you list> Building native extensions. This could take a while...> extconf.rb:1:in `require': no such file to load -- mkmf (LoadError)> ERROR: Error installing mongrel:> ERROR: Failed to build gem native extension.[/sourcecode]> This error is logged in JIRA with id JRUBY-1771Workaround (possibly applicable for other gems is to explicitly specify the plaform:> [sourcecode language='ruby']> $ jruby -S gem install -y mongrel --platform jruby> INFO: `gem install -y` is now default and will be removed> INFO: use --ignore-dependencies to install only the gems you list> Successfully installed mongrel-1.1.2> 1 gem installed> Installing ri documentation for mongrel-1.1.2...> Installing RDoc documentation for mongrel-1.1.2... ```