Ensime server crash because of transitive dependency

:: scala, emacs

The Scala layer for Spacemacs uses Ensime by default. There is an error that made me struggle for weeks: Bad source jar kills the server: ZipException: error in opening zip file

The offending JAR was a transitive dependency of a project, and the solution offered on the issue was not clear for me.

This problem is tricky if you previously loaded the project into an IDE: they download by default all transitive dependencies with sources and javadoc, and the ivy cache is shared by all projects in the same machine.

Here is my solution, as found also on the issue, in case it helps others:

  • determine which dependency is pulling the problem JAR with the sbt dependency graph plugin (note: the command whatDependsOn only works in interactive mode)
  • move away the current ivy cache folder console $ mv ~/.ivy2/ ~/.ivy2_old
  • (optional) create a new clone to have a known state console $ git clone $repo ~/dev/ensime-$repo
  • edit build.sbt to add an exclusion rule for the transitive dependency at the line of the explicit dependency that needs it, e.g. sbt libraryDependencies ++= Seq( "com.company.notifications" % "notifications-schema" exclude("org.json", "json") )
  • compile, go for a coffee while ivy downloads the internet :), then run ensime commands console $ sbt compile $ sbt ensimeConfig ensimeConfigProject

Maven does not find JAVA_HOME in Fish shell

:: fish, maven, java

After reinstalling java from brew cask, it could happen that Maven does not find anymore the JAVA_HOME. The error looks like this:

$ mvn clean install
The JAVA_HOME environment variable is not defined correctly
This environment variable is needed to run this program
NB: JAVA_HOME should point to a JDK not a JR

In Fish shell, on Mac OS X, the solution is to set the variable in universal mode:

$ set -U JAVA_HOME (/usr/libexec/java_home)

Some Git aliases

:: git

Here are some of the Git alias configurations that I use. My philosophy in writing them was to keep them descriptive, and not to keep them easy to type, following the approach in this blog post. In order to keep my typing short, I use the fish shell.

[alias]
	amend = commit --amend
	discard = checkout --
	docommit = commit --verbose --all
	hist = log --color --pretty=format:\"%C(yellow)%h%C(reset) %s%C(bold red)%d%C(reset) %C(green)%ad%C(reset) %C(blue)[%an]%C(reset)\" --relative-date --decorate
	lastedit = log --pretty=format: --name-only -n 1
	logshort = log --oneline -n 10
    lsmodified = diff --name-only head
	mkbranch = checkout -b
	rmbranch = branch -d

The aliases amend and discard are pretty self-explanatory. docommit reflects my own preferences when finishing a commit: just commit everything that is currently modified and add a diff under the commit message, so that I can review what I actually modified everywhere. hist is something I don’t use very much; I copied it from somewhere and I keep it around to avoid going to a GUI when I need to review history in-depth.

lastedit lists which files were edited in the last commit. I find it useful to just open them again in an editor:

$ vim (git lastedit)

logshort is probably the alias I use the most. It just gives me an idea of what was going on in a branch, without defaulting to show me all history since the beginning of time. lsmodified is a recent addition. It lists all files modified but not commited. It is intended to be used together with other aliases:

$ git discard (git lsmodified)

mkbranch and rmbranch are also quite useful to me. I tend to see Git as a file system: sometimes I start to type ls -l when I actually need git status. In that mindset, I tend to identify branches with directories, and therefore creating and deleting them as if they were directories makes sense.

Minimal C project structure with SCons

:: C, scons, build

This is a possible project structure in order to have a C project using SCons as the build system. It enables you to:

  • compile most files as a library, and link that to a main file with application code.
  • separate src and include directories
  • separate unit tests using libcheck
  • the unit tests link to the library
  • Macports-installed libraries

Layout your code like this:

.
├── include
│   └── core
│       └── mylib.h
├── sconstruct
├── src
│   ├── core
│   │   └── mylib.c
│   └── main.c
└── tests
    ├── core
    │   ├── test_mylib.c
    │   ├── test_mylib.h
    │   └── tests.h
    └── main.c

where mylib should have a more descriptive name for your project.

sconstruct is:

env = Environment(CPPPATH=['include', '/opt/local/include'])
env.Library(target='mylib', source=Glob('src/core/*.c'))
env.Program(target='mylib', source=Glob('src/*.c'),
            LIBS=['mylib'], LIBPATH=['.'])
env.Program(target='test_mylib', source=Glob('tests/*.c') + Glob('tests/**/*.c'),
            LIBS=['mylib', 'check'], LIBPATH=['.', '/opt/local/lib/'])