I recently posted a series of helper-scripts I keep in my local ~/bin for branching and merging in subversion. After noticing the large volume of patches I keep floating around in working copies, I decided to also create a stash system akin to that in git. Git's stash feature allows users to stage uncommitted change-sets into their working copy, without pushing them up-stream or integrating them into the revision history. I use this behavior frequently to pause what I am doing, do something else, and come back to what I was doing. Or to pause what I am doing, switch branches, and review someone else's incoming change-set. The commands for my svn stash are very similar to git. Quickly stash change-sets sit in a LIFO queue, and are named with uuidgen if you do not name them explicitly.
I've integrated this into my wrapper so svn help stash emits basic usage information for the command set.
scott@optimusprime:~/code/leapfrog/inmon> svn help stash Usage: svn stash <command> [ <name> ] list - Display all stashed changesets. show - View the change-set patch. save - Save a new changeset. apply - Apply a changeset from the stash. delete - Delete a changeset from the stash. pop - Apply a changeset from the stash, and delete it. help - This message
The svn stash list command lists stashes that have been queued. This is simply for managing the stashes.
scott@optimusprime:~/code/leapfrog/inmon> svn stash list 482 2010-08-02 15:53 0a95b587-bdbd-4c70-8ca4-9d9c2ed02c5b 86851 2010-08-02 15:33 3f5d08c9-b9be-428d-9fb7-55dfa904e670 16756 2010-08-03 11:25 6dfd3d16-65a6-4be5-abb2-8c32d4eea4d9
Inspecting stashed changesets
Stashed change-sets can be inspected using svn stash show <stash>.
scott@optimusprime:~/code/leapfrog/inmon> svn stash show 0a95b587-bdbd-4c70-8ca4-9d9c2ed02c5b Index: pom.xml =================================================================== --- pom.xml (revision 5272) +++ pom.xml (working copy) @@ -1,4 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> + <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.leapfrog.inmon</groupId>
Stashes can be applied using either svn stash apply, or svn stash pop. stash apply applies a stash without removing it. stash pop applies a stash and removes it, respectively. If no stash is specified with pop, the latest stash is the one applied. A summary of the changes made is displayed (assuming application goes as expected and there are no conflicts).
scott@optimusprime:~/code/leapfrog/inmon> svn stash apply 0a95b587-bdbd-4c70-8ca4-9d9c2ed02c5b Unstaging stash "0a95b587-bdbd-4c70-8ca4-9d9c2ed02c5b". M pom.xml scott@optimusprime:~/code/leapfrog/inmon> svn revert -R . Reverted 'pom.xml'
scott@optimusprime:~/code/leapfrog/inmon> svn stash pop Unstaging stash "6dfd3d16-65a6-4be5-abb2-8c32d4eea4d9". M services/src/main/java/com/leapfrog/inmon/services/game/play/GamePlayEventHandler.java M services/src/main/java/com/leapfrog/inmon/services/game/play/etl/PointsConversionETLProcessHandler.java M services/src/main/java/com/leapfrog/inmon/services/game/play/GameMetaDataAccessFacade.java M services/src/main/java/com/leapfrog/inmon/services/points/bank/MyfrogPointsBankClient.java Stash "6dfd3d16-65a6-4be5-abb2-8c32d4eea4d9" removed.
Since pop removes the stash, it will no longer appear in the list.
scott@optimusprime:~/code/leapfrog/inmon> svn stash list 482 2010-08-02 15:53 0a95b587-bdbd-4c70-8ca4-9d9c2ed02c5b 86851 2010-08-02 15:33 3f5d08c9-b9be-428d-9fb7-55dfa904e670
It can be re-staged using svn stash, or otherwise just used, since the changes are currently applied to the active working-copy.
scott@optimusprime:~/code/leapfrog/inmon> svn status ? queue.mem M services/src/main/java/com/leapfrog/inmon/services/game/play/GamePlayEventHandler.java M services/src/main/java/com/leapfrog/inmon/services/game/play/etl/PointsConversionETLProcessHandler.java M services/src/main/java/com/leapfrog/inmon/services/game/play/GameMetaDataAccessFacade.java M services/src/main/java/com/leapfrog/inmon/services/points/bank/MyfrogPointsBankClient.java
Cleaning up stashes
Removing stashes is fairly straight forward, svn stash delete (remove and rm are aliases for this command) removes a stash without applying it. From that point on the change-set is in the bit-bucket and cannot be retrieved.
scott@optimusprime:~/code/leapfrog/inmon> svn stash delete 0a95b587-bdbd-4c70-8ca4-9d9c2ed02c5b Stash "0a95b587-bdbd-4c70-8ca4-9d9c2ed02c5b" removed. scott@optimusprime:~/code/leapfrog/inmon> svn stash list 86851 2010-08-02 15:33 3f5d08c9-b9be-428d-9fb7-55dfa904e670
Simply svn stash creates an anonymous stash from the current working-copy changes. If a label is preferred so the stash can be identified later, then svn stash save <label> will do this for you. Further interactions require using this label. It must be a single command line argument, so quotes are required if the label contains spaces.
scott@optimusprime:~/code/leapfrog/inmon> svn stash save "Point Conversion ETL changes" Changes stashed as: "Point Conversion ETL changes" Working copy reverted to 5272 scott@optimusprime:~/code/leapfrog/inmon> svn stash pop "Point Conversion ETL changes" Unstaging stash "Point Conversion ETL changes". M services/src/main/java/com/leapfrog/inmon/services/game/play/GamePlayEventHandler.java M services/src/main/java/com/leapfrog/inmon/services/game/play/etl/PointsConversionETLProcessHandler.java M services/src/main/java/com/leapfrog/inmon/services/game/play/GameMetaDataAccessFacade.java M services/src/main/java/com/leapfrog/inmon/services/points/bank/MyfrogPointsBankClient.java Stash "Point Conversion ETL changes" removed.
I found this much easier to deal with than manually juggling patches, although it only automates the same process. It also gracefully handles newly added and deleted files in stashes, without leaving relic artifacts in un-staged change-sets.
I've found this useful, hopefully you will as well.
Here are some helper scripts I've created for subversion. If you add these scripts to your path, and run the command svn help, you will notice the menu has changed.
scott@optimusprime:~/code/leapfrog/inmon> svn help usage: svn <subcommand> [options] [args] ... *snip* ... Helper commands: tags - List all tags relevant to this trunk branches - List all branches relevant to this trunk tag - Tag a trunk or branch copy. branch - Branch a trunk or tag working copy. mergebranch, mb - Merge a branch into this trunk mergetrunk, mt - Merge the trunk into this branch gettrunk, trunk - Switch to the trunk gettag, gt - Switch to a given tag getbranch, gb - Switch to a given branch
These commands, as describe above, help simplify branching, tagging and merging in a subversion repository. It also helps you switch between trunk, tags, and branches of a given project. To use it, simply start by checking out your project trunk:
scott@optimusprime:~/code/leapfrog> svn co http://<company-svn>/inmon/trunk inmon scott@optimusprime:~/code/leapfrog> cd inmon scott@optimusprime:~/code/leapfrog/inmon>
Now you can peruse the available tags using the svn tags command:
scott@optimusprime:~/code/leapfrog/inmon> svn tags 0.0-SNAPSHOT.4.953 1.10 1.15.8 1.17.10 0.0.1-prototype 1.11 1.15.9 1.17.11 1.0 1.12 1.15.10 1.17.13 1.0P1 1.13.2 1.16.1 1.17.16 1.1 1.13.4 1.16.2 1.17.17 1.2 1.13.5 220.127.116.11 1.17.18 1.3 1.14.2 18.104.22.168 1.17.19 1.4p2 1.14.3 22.214.171.124 1.18.0 1.4p3 1.14.4 126.96.36.199 1.18.1 1.5 1.15.1 1.17.1 1.18.2 1.5p1 188.8.131.52 1.17.2 1.18.3 1.6 184.108.40.206 1.17.3 1.18.4 1.6p1 1.15.2 1.17.4 1.18.5 1.7 1.15.3 1.17.5 1.18.6 1.8 1.15.4 1.17.6 1.18.7 1.8.1 1.15.5 1.17.7 1.18.8 1.9 1.15.6 1.17.8 1.18.9 1.9.1 1.15.7 1.17.9
Similarly, svn branches will list the available branches:
scott@optimusprime:~/code/leapfrog/leapfrog-util> svn branches 1003-file-copying java-1.5
To fetch a branch, simply run svn getbranch <branch name>.
scott@optimusprime:~/code/leapfrog/leapfrog-util> svn getbranch java-1.5 Switching working copy to branch java-1.5 D src/test/java/com/leapfrog/util/ChainedIteratorTest.java U src/test/java/com/leapfrog/util/FilesTest.java U src/test/java/com/leapfrog/util/StringsTest.java D src/test/resources/data/1269759740713.log U src/test/resources/unit-tests.xml D src/main/java/com/leapfrog/util/UnsafeByteArrayOutputStream.java D src/main/java/com/leapfrog/util/ChainedIterator.java D src/main/java/com/leapfrog/util/ByteBufferOutputStream.java U src/main/java/com/leapfrog/util/Files.java D src/main/java/com/leapfrog/util/concurrent/CallerRunsExecutor.java U src/main/java/com/leapfrog/util/concurrent/AtomicInitializer.java U src/main/java/com/leapfrog/util/Strings.java U src/main/java/com/leapfrog/util/Streams.java U pom.xml Updated to revision 200.
Your working copy is now in this branch, to switch back to the trunk simply run svn trunk.
scott@optimusprime:~/code/leapfrog/leapfrog-util> svn trunk Switching working copy to trunk U src/test/java/com/leapfrog/util/FilesTest.java A src/test/java/com/leapfrog/util/ChainedIteratorTest.java U src/test/java/com/leapfrog/util/StringsTest.java A src/test/resources/data/1269759740713.log U src/test/resources/unit-tests.xml A src/main/java/com/leapfrog/util/UnsafeByteArrayOutputStream.java U src/main/java/com/leapfrog/util/Files.java U src/main/java/com/leapfrog/util/concurrent/AtomicInitializer.java A src/main/java/com/leapfrog/util/concurrent/CallerRunsExecutor.java A src/main/java/com/leapfrog/util/ChainedIterator.java U src/main/java/com/leapfrog/util/Strings.java A src/main/java/com/leapfrog/util/ByteBufferOutputStream.java U src/main/java/com/leapfrog/util/Streams.java U pom.xml Updated to revision 200.
Your working copy changes will typically survive these actions, unless there are conflicts. To create a branch from the trunk, a tag, or another branch simply call svn branch <branchname>.
scott@optimusprime:~/code/leapfrog/leapfrog-util> svn branch persistent-queue-fixes Creating branch persistent-queue-fixes from http://source.leapfrog.com/Web/Utils/util/trunk Committed revision 201. http://source.leapfrog.com/Web/Utils/util/branches/persistent-queue-fixes
You can then switch to it:
scott@optimusprime:~/code/leapfrog/leapfrog-util> svn getbranch persistent-queue-fixes Switching working copy to branch persistent-queue-fixes At revision 201.
svn tag works similarly. This script depends on an awk script I've written called tabulate. Simply add them both to your $PATH and mark them +x.
This script contains some helper functions I use for enhancing compiler integration with gvim and maven. The command MvnAutoCompile toggles a mode which writing a java file starts offline re-compilation in maven for the current module. It works rather properly in multi-module projects, compiling only the current module. It then invokes copen, cancelling if there are no compilation errors, giving you a "quick-fix" list quite similar to that provided by IDEs such as eclipse. Projects which use the maven-aspectj-plugin to compile can turn on aspect-j weaving first calling the command MvnEnableAspectj.
For imports, it searches the classpath using an index created by a script which is included called mvn-classpath-index. This script, when invoked from the working directory of a project module, creates a file called target/classpath-index.txt which is a list of all fully qualified class names in the current classpath of the maven project. Using the macro \im when the cursor is hovered over a class name searches this classpath for that name, and imports the match. If multiple matches are discovered, a choice-list is provided and a selection can be made. If the class appears to have already been imported, the macro is a no-op.
The command MvnListErrors searches the surefire test reports for unit test failures, and opens the corresponding text reports if they are available.
Also included in the attached package is the maven compiler integration script, slightly modified so it will also work with aspect-j. To use this, simply call:
:compiler mvn :make <goal>
Lastly, the other script included in the package is one called mvn-debug, which simply runs apache maven 2 using jdb. I've found this handy for both debugging unit tests and debugging web applications using the Maven Jetty Plugin. To use it, first get familiar with the java debugger, and then simply run
You can use this as you would otherwise execute "mvn <goal>", set your breakpoints, and fire it up with the run command in jdb. It properly configures your source path, assuming it's executed from the project root. I often use this for stepping through unit tests.
All of the vim plugin behavior assumes your current process is running chdir'd to the project root. In gvim, I frequently just call
— where I keep my code, before I open any files.
Another feature I find incredibly important, is to simply set your path to "**". Do this by running the following:
I've added this to my ~/.vimrc, so that features such as CTRL-W_f will properly search the source path for the class name under the cursor. Other things which help are proper ordering of method declarations (i.e. define before use) in source files so that commands such as gD work properly.
In the first writing I've shared in some years, here is another anecdotal update to the 100 lines or less "series" (this is #2). In this article, I outline a monitoring problem which was recently presented to me in preparation for the expected holiday traffic of 2009. This article outlines the solution in some detail, and provides an example of using it.
This version has been bcopified, so to install it (on an ubuntu system) perform the following:
$ sudo apt-get install compiz-dev compiz-bcop $ make install
It does not need to be built or installed as root. It will install in the local user space by default. This is just a forward-port to compiz 0.8.4, and a cleanup. Download it. To know more about keynav, check out the original keynav post.
Do you use compiz-fusion? Have you ever wished you could focus on the window to the right of the window you're currently in, and not have to reach for the mouse? And not have to flip through a bunch of windows with 3D effects? I do.
For years I used pekwm, and this was one of my favorite features (along with sloppy window grouping and the ability to extend windows to use empty space, maximize vertically and horizontally - all of which are otherwise available with compiz plugins). And lately, it's driven me so mad that I can't just go to my build terminal that I decided to solve it myself.
So attached to this wiki page is a plugin which accomplishes this. It works rather well. I'll submit it for inclusion with compiz-fusion, we'll see if it gets included.