Pro tip on git rebase -i

2012-05-15  |   |  tool   git  

Here is a small tip to improve your efficiency when using dynamic rebasing in Git.

I do my work on topic branches that are forked of master. Before I push my work for review via a GitHub pull request, I like to clean it up a bit by:

  • reordering some commits
  • squashing some commits together
  • rewriting commit messages

Nothing fancy but it helps improve history readability.

You can of course do that by using git rebase -i and most examples show how you can go back in time a couple of commits.

git rebase -i HEAD^4 #go back 4 commits ago

There is a nicer and more efficient to do that when you work on topic branches

git rebase -i master

That's it. Pretty stupid but, since you can put any Git object reference, why not use the object where you started to fork off? The rebase will show you all commits between master and your branch.

If you are on a Mac, I highly recommend using GitX or one of his forks. In particular, you can amend the last commit and graphically select what should be staged and unstaged.


Setting global environment variables in IntelliJ IDEA and other test config goodies

2012-05-09  |   |  tool   ide  

When you run a test from IntelliJ idea, you can customize some of the settings by selecting the list of tests and click Edit Configurations. From there you can change things like:

  • under which module classpath the test is run
  • the working directory the test should run from
  • virtual machine parameters
  • specific environment variables to use

In Hibernate OGM, we use the same test site for all NoSQL solutions. Changing the module classpath is useful in this situation. We also let you refine via an environment variable which hostname runs say MongoDB.

Unfortunately in Mac OS X, graphic applications do not inherit your .bash_profile config. I know, stupid, but what can you do against the Empire? Workaround!

You can set environment variables from each test but it gets tedious quickly. Alternatively, you can set an environment variable globally in IntelliJ - what they call parent environment variables. Go to Preferences and search for Path Variables. Set your global environment variables here and you are good to go. Note that you can ask a test not to inherit these global variables if you want to - in the test configuration.


Update:
It turns out I was wrong. Paths Variables is not where global environment variables can be set. If you know where, please let me know.

Update 2:
To set an environment variable visible by applications in Mac OS X, use

launchctl setenv MYPATH myvar

then restart your IDE (you might need to log out and back in as well).

Thanks @aagahi for the info. This is not great as it's remote from my IDE but at least that works. BTW, launchctl is supposed to set the data in /etc/lanuchd.conf or $HOME/.launchd.conf. Not on my system. If anyone knows where the data is put, I'm interested.


Notes to JetBrains:

  • your environment variable UI is plain counter productive: either give us a text free area or make tabs and co working
  • an option to inherit the .bash_profile configuration would be awesome :)


Bash script to expand file templates

2012-04-26  |   |  tool  

I am working on pushing all my "dotfiles" into a Git repo. Some contains passwords or other private data. It took me longer than expected to write an expander script in bash. So here it is.

Properties are stored as Java properties.

gittoken=123456789012345ab3bc
backup_destination=emmanuel@devnull.com:./backup

The template uses the $placeholder syntax.

# .gitconfig file
[user]
    name = Emmanuel Bernard
[github]
    user = emmanuelbernard
    token = $gittoken 
[alias]
    co = checkout
    undo = reset --hard
    cb = checkout -b
    br = branch
    cp = cherry-pick
[random]
    complex-backup-link = $backup_destination

The script is used like

./properties-expander.sh <properties file> <template> <destination>

# For example
./properties-expander.sh ~/secret.properties ~/templates/gitconfig ~/.gitconfig

The script itself is fairly compact though some parts were fairly tricky - thanks stackoverflow :) :

#!/bin/bash
#
# Released under the WTFPL license version 2 http://sam.zoy.org/wtfpl/
# Copyright (c) 2012 Emmanuel Bernard
# -----
# Usage: properties-expander.sh <properties file> <template> <destination>
#
# Properties file:
#   PROPERTY1=value1
#   PROPERTY2=value2

#help
if [[ $# -ne 3 ]]; then 
  echo "properties-expander.sh <properties file> <template> <destination>"
  exit 0;
fi

echo Expanding $2 to $3 with properties from $1

#read each line including the last one
while IFS=$'\n' read -r line || [[ -n "$line" ]]; do
    #get the property name before the first =
    property=${line%%=*}
    #get the value after the first =
    value=${line#*=}

    #find a suitable separation character as the value might contain /
    candidates='/:.|@#%^&;,!~abcABC'  # candidates for separation character
    char=$(echo "$candidates" | tr -d "$line")  
    char=${char:0:1}   # choose the first candidate that doesn't appear in the user input

    if [ -z "$char" ]    # this test checks for exhaustion of the candidate character set
    then
        echo "Unusable user input: $line"
        exit 1
    fi

    #add regexp rule
    SEDEXEC="s${char}\$$property${char}$value${char}g;$SEDEXEC"
done < $1

SEDEXEC="sed -e '$SEDEXEC' $2 > $3"
eval $SEDEXEC

For simplicity, I have put the script in a GitHub gist. Please fork, improve and give me feedback :)


Feedback on Twitter Bootstrap

2012-04-11  |   |  css   website   tool  

Everyone and his dog is in love with Twitter Bootstrap, so I figured I would give it a try and build my website with it.

What is Twitter Bootstrap

Twitter Bootstrap is a HTML(5), CSS and JavaScript toolkit offering a grid based scaffolding and a set of UI components to quickly get started. And best of all it does not look bad :)

It is not too difficult to get into it. While it will not really revolutionize people already familiar with Blueprint CSS and CSS in general, it does however bring a set of standardized components that tend to bring good practice to your website:

  • nice styling for common constructs like code, tables, inputs etc
  • nice set of sprited icons for various elements
  • good looking buttons and labels
  • nice navigation tools like breadcrumbs, pagination, and of course nav bars
  • good largely spaced headline styles
  • closable alert and informative messages
  • progress bar
  • and many more things both static and dynamic

Responsive design

One very interesting feature is built-in support for responsive design. By combining the grid scaffolding and a bit of JavaScript magic, the content of the page adjusts itself to look best for your browser size. That's particularly useful to make a website that looks nice for both big screens and smartphones.

Check it out, change the size of your browser's window and you will see how the website reacts. It's not perfect and cannot match a dedicated website but that's pretty good.

Using it

Understanding how Twitter Bootstrap works and how to use it is relatively easy and quick. The documentation is pretty good and driven by examples. It could use a few extra examples here and there though.

It is not exempt of bugs but overall things are working as expected. I stumbled upon several bugs but most of them were fixed in their latest version (2.0.3). I am unfortunately stuck on version 2.0.1. Does it work on Internet Explorer? Good question, I don't have a IE installed to check it out. If my website looks like crap and you are using Internet Explorer, then the answer is no.

Twitter Bootstrap is built using Less. I unfortunately use SCSS and had to use a port that has not upgraded to 2.0.3 yet.

The curse

Now the big problem with Twitter Bootstrap is that pretty much all websites using it look alike. The most defining element is the nav bar that unfortunately is one of the main signature component of a website. Some themes exist, otherwise you will have to use Less or their Boostrap customizer to get something more unique. I am also not a big fan of their default font style and size which I changed personally.

Verdict

Overall it was a good experience and the UI components at my disposal helped me make a better website. Yes my site look like many Twitter Bootstrap sites out there ; though I took the extra time to customize it more than the average Joe. It is hopefully different enough :)

If you want to explore Twitter Bootstrap with a practical example, check out my website source code.


Customize titles of your terminal window

2012-02-28  |   |  Mac OS X   tool  

If you are like me, you use many many tabs in your command line terminal. By the way, iTerm2 is a very nice improvement over the vanilla OS X Terminal app.

To recognize tabs, I like to display the name of the current directory and add the directory it is contained in if more space are left. Open your .bash_profile or .profile file and add the following

function local_dir_and_within {

__LAST="${PWD##*/}"

__IN="${PWD%/*}"

__IN="${__IN/#$HOME/~}"

TITLE_TAB="$__LAST in $__IN"

echo -n $TITLE_TAB

}

export PROMPT_COMMAND='echo -ne "\033]0;$(local_dir_and_within)\007"'

Your tab title will now look like hibernate-search in ~/code.


Configuring VirtualBox guests to access the internet and be accessible from the host

2012-02-28  |   |  tool  

I recently had to create a VirtualBox virtual machine hosting Fedora 16. It took me a little while to achieve both

  • access the internet from the Fedora 16 guest
  • reach the Fedora 16 guest from the host (say via SSH).

It's relatively straightforward if you know the details.

To get access to the internet from the guest, you need to enable the NAT network adaptor.

  • On your (shutdown) VM, open up settings->Network
  • In adapter 1, enable network adapter and use attached to NAT

To get access to the guest VM, we need to give it a static IP and be accessible to the host.

  • On VirtualBox, open up (general) preferences -> network
  • Add a host-only network (if none exist)
  • Configure the host-only network with an IP address (eg 192.168.56.1)
  • Optionally enable the DHCP server and make sure to leave room for static addresses (eg by setting lower address bound to 192.168.56.101
  • On the guest VM settings -> Network, active a second adapter and use attached to Host-only Adapter with the name of the network you have defined globally (usually vboxnet0)
  • Make sure to note down the MAC address (visible in the advanced section)
  • Boot your guest VM and add the network interface

In Fedora 16, to add a network interface, create a file ifcfg-eth1 in /etc/sysconfig/network-scripts (or an alternative ethn name).

Fill it up with

DEVICE="eth1"

HWADDR="08:00:27:0B:74:DE"

BOOTPROTO="static"

IPADDR=192.168.56.100

NETMASK=255.255.255.0

ONBOOT="yes"

NM_CONTROLLED="yes"

Make sure to change DEVICE if you use a different ethn name. Make sure to replace HWADDR with the MAC address that you copied from adapter 2. Finally, make sure the static address is not within the range of DHCP addresses. I my example 192.168.56.100 would do fine. Reboot for good measure, you should be able to access the guest from the host at 192.168.56.100. You can even edit your host's /etc/hosts and add the following line

192.168.56.100 my-guest

In my case, I can then SSH into the guest using ssh emmanuel@my-guest

That's pretty much basic stuff but a working example always helps :)


In search for a 2560x1600 display

2012-02-13  |   |  apple   productivity   tool  

I have been using a Samsung SyncMaster 305T+ 30" monitor for 4.5 years now and have been very very happy with the screen real estate. Yes two monitors are nice but a big massive one wins for me. Anyways, it's failing me. The screen blinks more and more - luckily I'm epileptic - often and a few straps that used to display true back now are dark green. It won't last long. I am looking for a replacement.

I have a MacBook Pro with a mini DisplayPort but pre thunderbolt (by a couple of month...). I am quite interested in the Apple Thunderbolt Display:

  • it has the resolution I'm looking for,
  • great ports (USB, Firewire, Ethernet)
  • it's a breathe to dock a MacBook Pro
  • good reviews

There is one catch, it won't work on my current MacBook Pro - i tried. And that sucks big time. I can't justify buying a new MacBook Pro to secure a future proof screen and I could not find a way to make this Thunderbolt monitor work on a mini DisplayPort computer (no adapter, no nothing). Which means Apple will force me in the past :(

The alternatives I have are:

  • the Dell U3011 (30", 2560x1600, DisplayPort, DVI, HDMI)
  • the HP ZR30w (30", 2560x1600, DisplayPort, DVI)
  • the Apple LED Cinema Display (27", 2560x1600,mini DisplayPort, MagSafe power adaptor)

It seems to me the best option is the Apple Cinema Display. Despite the smaller screen, it's the same resolution, it's cheaper (by 200 to 400 euros) and I will have less cable to plug my laptop to. The sad thing is I'm not sure it will work on future Thunderbolt MacbookPro, let alone if I need to plug other Thunderbolt accessories in between, and for sure it will be inconvenient compared to a nice and well connected Apple Thunderbolt Display. And spending that much money on previous generation when the next gen is the same price really pisses me off.

Do I have any other alternatives? I looked for refurbished or second hand Apple Cinema Display (27", mini DisplayPort) but could not find any around Paris.

By the way, 4.5 years ago for a 30" 2560x1600 monitor, I paid the same price or less than what these beasts sell for today. Granted, these are new technology and new panels (IPS) but at constant size and resolution, price has not drop a penny. Where the hell have Moore's law corollaries gone? Oh and is 4.5 years old for a screen?


What to do when Gradle raises unexpected NoClassDefFoundException

2011-10-26  |   |  groovy   java   tool  

I have just lost an hour thanks to some obscure bug in Gradle caching mechanism.

If all of the sudden, Gradle raises Frankenstein errors at you like

$ gradle clean build

:buildSrc:compileJava UP-TO-DATE

:buildSrc:compileGroovy

Note: /Users/manu/projects/notbackedup/git/core/buildSrc/src/main/groovy/org/hibernate/gradle/testing/database/DatabaseMatrixPlugin.java uses unchecked or unsafe operations.

Note: Recompile with -Xlint:unchecked for details.

>>> a serious error occurred: hudson/util/DBAllocation

>>> stacktrace:

java.lang.NoClassDefFoundError: hudson/util/DBAllocation

at java.lang.Class.getDeclaredMethods0(Native Method)

at java.lang.Class.privateGetDeclaredMethods(Class.java:2427)

at java.lang.Class.getDeclaredMethods(Class.java:1791)

at org.codehaus.groovy.vmplugin.v5.Java5.configureClassNode(Java5.java:318)

at org.codehaus.groovy.ast.ClassNode.lazyClassInit(ClassNode.java:263)

at org.codehaus.groovy.ast.ClassNode.getInterfaces(ClassNode.java:341)

at org.codehaus.groovy.ast.ClassNode.declaresInterface(ClassNode.java:929)

at org.codehaus.groovy.ast.ClassNode.implementsInterface(ClassNode.java:909)

at org.codehaus.groovy.ast.ClassNode.isDerivedFromGroovyObject(ClassNode.java:899)

at org.codehaus.groovy.classgen.AsmClassGenerator.isGroovyObject(AsmClassGenerator.java:2752)

at org.codehaus.groovy.classgen.AsmClassGenerator.visitPropertyExpression(AsmClassGenerator.java:2728)

at org.codehaus.groovy.ast.expr.PropertyExpression.visit(PropertyExpression.java:55)

at org.codehaus.groovy.classgen.AsmClassGenerator.visitAndAutoboxBoolean(AsmClassGenerator.java:4122)

at org.codehaus.groovy.classgen.AsmClassGenerator.makeCallSite(AsmClassGenerator.java:2182)

at org.codehaus.groovy.classgen.AsmClassGenerator.makeCall(AsmClassGenerator.java:2019)

at org.codehaus.groovy.classgen.AsmClassGenerator.makeCall(AsmClassGenerator.java:2005)

at org.codehaus.groovy.classgen.AsmClassGenerator.makeInvokeMethodCall(AsmClassGenerator.java:1990)

at org.codehaus.groovy.classgen.AsmClassGenerator.visitMethodCallExpression(AsmClassGenerator.java:2342)

at org.codehaus.groovy.ast.expr.MethodCallExpression.visit(MethodCallExpression.java:75)

at org.codehaus.groovy.classgen.AsmClassGenerator.visitBooleanExpression(AsmClassGenerator.java:1959)

at org.codehaus.groovy.ast.expr.BooleanExpression.visit(BooleanExpression.java:40)

at org.codehaus.groovy.classgen.AsmClassGenerator.visitIfElse(AsmClassGenerator.java:913)

at org.codehaus.groovy.ast.stmt.IfStatement.visit(IfStatement.java:41)

at org.codehaus.groovy.ast.CodeVisitorSupport.visitBlockStatement(CodeVisitorSupport.java:35)

at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitBlockStatement(ClassCodeVisitorSupport.java:165)

at org.codehaus.groovy.classgen.AsmClassGenerator.visitBlockStatement(AsmClassGenerator.java:738)

at org.codehaus.groovy.ast.stmt.BlockStatement.visit(BlockStatement.java:69)

at org.codehaus.groovy.classgen.AsmClassGenerator.visitIfElse(AsmClassGenerator.java:921)

at org.codehaus.groovy.ast.stmt.IfStatement.visit(IfStatement.java:41)

at org.codehaus.groovy.ast.CodeVisitorSupport.visitBlockStatement(CodeVisitorSupport.java:35)

at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitBlockStatement(ClassCodeVisitorSupport.java:165)

at org.codehaus.groovy.classgen.AsmClassGenerator.visitBlockStatement(AsmClassGenerator.java:738)

at org.codehaus.groovy.ast.stmt.BlockStatement.visit(BlockStatement.java:69)

at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitClassCodeContainer(ClassCodeVisitorSupport.java:101)

at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitConstructorOrMethod(ClassCodeVisitorSupport.java:112)

at org.codehaus.groovy.classgen.AsmClassGenerator.visitStdMethod(AsmClassGenerator.java:626)

at org.codehaus.groovy.classgen.AsmClassGenerator.visitConstructorOrMethod(AsmClassGenerator.java:601)

at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitMethod(ClassCodeVisitorSupport.java:123)

at org.codehaus.groovy.classgen.AsmClassGenerator.visitMethod(AsmClassGenerator.java:696)

at org.codehaus.groovy.ast.ClassNode.visitContents(ClassNode.java:1039)

at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitClass(ClassCodeVisitorSupport.java:50)

at org.codehaus.groovy.classgen.AsmClassGenerator.visitClass(AsmClassGenerator.java:276)

at org.codehaus.groovy.control.CompilationUnit$12.call(CompilationUnit.java:748)

at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:942)

at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:519)

at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:497)

at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:474)

at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:453)

at org.codehaus.groovy.tools.FileSystemCompiler.compile(FileSystemCompiler.java:67)

at org.codehaus.groovy.tools.FileSystemCompiler.doCompilation(FileSystemCompiler.java:180)

at org.codehaus.groovy.tools.FileSystemCompiler.commandLineCompile(FileSystemCompiler.java:148)

at org.codehaus.groovy.tools.FileSystemCompiler.main(FileSystemCompiler.java:162)

Caused by: java.lang.ClassNotFoundException: hudson.util.DBAllocation

at java.net.URLClassLoader$1.run(URLClassLoader.java:202)

at java.security.AccessController.doPrivileged(Native Method)

at java.net.URLClassLoader.findClass(URLClassLoader.java:190)

at java.lang.ClassLoader.loadClass(ClassLoader.java:306)

at groovy.lang.GroovyClassLoader.loadClass(GroovyClassLoader.java:696)

at groovy.lang.GroovyClassLoader.loadClass(GroovyClassLoader.java:793)

at java.lang.ClassLoader.loadClass(ClassLoader.java:247)

... 52 more

FAILURE: Build failed with an exception.

* What went wrong:

Execution failed for task ':compileGroovy'.

Cause: Forked groovyc returned error code: 1

* Try:

Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

Simply nuke the Gradle cache from your project. I don't know if they are supposed to be in a standard location but for Hibernate the following commands did the trick

rm -fR .gradle

rm -fR buildSrc/.gradle

I wonder what will happen first, tools just working or world peace :)


Packt Open Source Awards and some reflections on CMSes

2011-09-15  |   |  oss   tool  

Packt Publishing, a fairly known technical book publisher is organizing an Open Source Awards contest. Some of the categories are interesting like mobile toolkit and libraries, business applications (always tough for OSS software), Javascript libs and multimedia. It's funny to see the categories evolve over time. Back in my days, it used to be best Java Middleware framework, best database tool etc.

Votes start soon (sept 19th) and end oct 31st. Go cast your vote, it's always nice for an (open source) team to receive such a prize. And no I don't think any JBoss framework is contending.

One of the category is Open Source CMS. Two of the big contenders in this space are Drupal and Joomla!. I have been involved in setting up Joomla! for my friend and... wife. I've got to admit that if I had to do it again, I would use something like Jekyll or Awestruct (my current favorite in this category). The website targeted was fairly simple but very quickly she ran into limitations and badly generated HTML (at least not customizable enough from a CSS point of view). She is a marketing person, so if she has decided that the picture, menu, color, text need to be that way, it must be that way. Teaching her Markdown and a few extra HTML tag is trivial. Heck she even learnt how to hack some CSS sheets. The big limitation is of course the lack of ready to use templates. That's about the main issues for simple solutions like Jekyll or Awestruct.

Next time you deploy a CMS, consider a simpler HTML generator and see if it could fit your needs.

PS: My wife's website is at Innora.fr.


Awestruct: building dynamic static web sites

2011-07-08  |   |  git   tool   website  

I've been wanting to update my personal site for a while as it was done in iWeb and Apple is basically killing the product. Through discussions at Red Hat, I tried Awestruct, a tool to generate static web sites while still benefitting from templating, blog support and other kind of neat automations.

Awestruct is a project started and lead by Bob McWhirter, a JBoss fellow known amongst other things for the awesomeness of his project names. Let me tell you this tool is fantastic. It is a ruby based tool that generates a fully static website (.html, .css and resource files) based on:
  • content written in a few available markup languages (Markdown is one, haml is another)
  • layouts letting you template the structure of your website
  • style via Sass, a superset of CSS that ends up generating .css files

I am not a web savvy guy. I know HTML a bit and CSS half a bit. Actually, I know that the best resource on the web is w3Schools.com and that's it. I was able to redo my website in about half a day from downloading Awestruct to deploying the generated site. The beauty is that I can now add pages very easily in an extremely consistent look.

Another useful part is Awestruct extensions and helpers. While the site is a static website, any content you can generate based on some structured data can end up as a part of your website:

  • a blog (ie take elements in a directory and render them as blog entries including the rss feed)
  • display a tag cloud and generate the list of pages per tag
  • display the list of your project releases
  • your own extension (if you know some Ruby, you should be good)

Now add some dust of Javascript and you can add things like

  • Google Analytics integration with one line of config
  • Comments support on your static website thanks to the javascript integration with IntenseDebase.

What I like about Awestruct is that the good libraries are picked for you (Haml, Compass-style etc) but the killer features are two-fold:

  • you can tell it to deploy and it will rsync the new website for you in one simple command (it has profiles too like dev, staging and production)
  • you can store everything in Git

Now you have a Git stored, simply deployable, easily customizable and templated website. With a bit of scripting you could get people pushing content in Git and get the website automatically generated and published. Heck you can even generate content automatically as part of a project release and script that (my dream!).

Awestruct sites are in the middle between fully dynamic sites reading stuffs from a datasource and purely static pages manually edited. It's kind of a dynamic static website.

The only feature I miss is a search engine but one could imagine:

  • generating index pages during the website construction (/index/emmanuel.html, /index/hibernate.html ...)
  • get some piece of Javascript that read queries and do n intersection of the content stored in all matching indexes

Bob, got some free time?


Name: Emmanuel Bernard
Bio tags: French, Open Source actor, Hibernate, (No)SQL, JCP, JBoss, Snowboard, Economy
Employer: JBoss by Red Hat
Resume: LinkedIn
Team blog: in.relation.to
Personal blog: No relation to
Microblog: Twitter, Google+
Geoloc: Paris, France

Tags