## Wednesday, November 3, 2010

### Showing transitive dependencies with Leiningen

When you specify a dependency on a Java library in Leiningen, you might pull in all sorts of random transitive dependencies (eg there are no less than three logging frameworks/facades that could be pulled in). Figuring out which artifacts pull in those transitive dependencies is a snap in Leiningen; just do this:

# Generate a pom for Maven to parse
lein pom
# Create a dependency tree with Maven
mvn dependency:tree


You'll get some output that looks like this:

[INFO] +- org.clojure:clojure:jar:1.2.0:compile
[INFO] +- org.clojure:clojure-contrib:jar:1.2.0:compile
[INFO] +- org.clojars.sids:htmlcleaner:jar:2.1:compile
[INFO] +- commons-lang:commons-lang:jar:2.5:compile
[INFO] +- commons-io:commons-io:jar:1.4:compile
[INFO] +- clj-file-utils:clj-file-utils:jar:0.1.2:compile
[INFO] +- log4j:log4j:jar:1.2.15:compile
[INFO] +- lein-daemon:lein-daemon:jar:0.2.1:compile
[INFO] |  \- commons-daemon:commons-daemon:jar:1.0.1:compile
[INFO] |  +- commons-logging:commons-logging:jar:1.0.4:compile
[INFO] |  +- org.slf4j:slf4j-api:jar:1.4.3:runtime
[INFO] |  +- org.slf4j:slf4j-log4j12:jar:1.4.3:runtime
[INFO] |  +- commons-httpclient:commons-httpclient:jar:3.1:runtime
[INFO] |  +- commons-cli:commons-cli:jar:1.2:compile
[INFO] |  +- commons-net:commons-net:jar:1.4.1:runtime
[INFO] |  |  \- oro:oro:jar:2.0.8:runtime
[INFO] |  +- javax.servlet:servlet-api:jar:2.5:runtime
[INFO] |  +- org.mortbay.jetty:jetty:jar:6.1.14:compile
[INFO] |  |  +- org.mortbay.jetty:jetty-util:jar:6.1.14:compile
[INFO] |  |  \- org.mortbay.jetty:servlet-api-2.5:jar:6.1.14:compile
[INFO] |  +- org.mortbay.jetty:jsp-2.1:jar:6.1.14:compile
[INFO] |  |  +- org.eclipse.jdt:core:jar:3.1.1:compile
[INFO] |  |  \- ant:ant:jar:1.6.5:compile
[INFO] |  +- org.mortbay.jetty:jsp-api-2.1:jar:6.1.14:compile
[INFO] |  +- commons-el:commons-el:jar:1.0:runtime
[INFO] |  +- org.apache.ant:ant:jar:1.7.0:runtime
[INFO] |  |  \- org.apache.ant:ant-launcher:jar:1.7.0:runtime
[INFO] |  +- net.java.dev.jets3t:jets3t:jar:0.6.1:runtime
[INFO] |  \- xmlenc:xmlenc:jar:0.52:runtime
[INFO] \- clj-http:clj-http:jar:0.1.1:compile
[INFO]    +- org.apache.httpcomponents:httpclient:jar:4.0.1:compile
[INFO]    |  \- org.apache.httpcomponents:httpcore:jar:4.0.1:compile
[INFO]    \- commons-codec:commons-codec:jar:1.4:compile


Easy peasy.

## Tuesday, November 2, 2010

### Tips for ignoring files with Git

There are 3 different ways to ignore files in Git:

1. Global: create a .gitignore file in your home directory
2. Per project: create a .gitignore file in the project's root source directory
3. Per project: create a .git/info/exclude file in the project's hidden git directory

# Update

Well... okay, so really, there are 4 ways, but the 4th way I haven't found a good use case for.

Amazingly, this flexibility in design does have a purpose (I don't believe the original intention was for the developer to close his eyes and pick a gitignore to stick files in randomly). The granularity offered in this design allows you to have a clear separation of what is generated by the build, and what is ignored by personal preference. For example, you can commit a .gitignore that only ignores logs and test output, while using a global gitignore file to ignore your vim or emacs swap files.

If you don't pollute your project space with files or data that may not be useful to everybody, it's easier for new developers to jump onto your project and figure out what's going on without wading through the fluff. For example, here's a good reason for not checking in your .classpath or .project files in Eclipse. Going one step further, it's probably not even a good idea to commit a gitignore file that names them.

On a project with enough people, it's simply not feasible to commit a .gitignore that names swap files for every editor, project files for every IDE, DS_Store for people who only use macs, thumb.db files for people who only use windows, and so on. For smaller projects, it doesn't hurt anything, but there are other places where this information could possibly be stored. Here is what I propose for each method of ignoring files:

1. Global .gitignore should ignore your favorite editor's swap files, the .DS_Store on a mac, or thumbs.db on windows; basically anything you personally need ignored for every project.
2. Per project .gitignore should ignore only files generated by the build (logs, test output, build targets).
3. Per project .git/info/exclude should ignore files you personally need, but only for this project. For example, if you are normally an Eclipse user, your global .gitignore should contain the .classpath and .project files, but for a particular project where you must use Netbeans, consider placing the nbproject directory in this file.