Recent posts

A local stash for subversion

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

Listing stashes

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>

Applying stashes

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

Creating stashes

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.

My subversion wrapper script(s)

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             1.16.2.1           1.17.18            
1.3                1.14.2             1.16.2.2           1.17.19            
1.4p2              1.14.3             1.16.2.3           1.18.0             
1.4p3              1.14.4             1.16.2.4           1.18.1             
1.5                1.15.1             1.17.1             1.18.2             
1.5p1              1.15.1.1           1.17.2             1.18.3             
1.6                1.15.1.2           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.

My tiny "plugin" for using maven and vim.

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

mvn-debug <goal>

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

:chdir ~/code/<organization>/project

— 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:

:set path=**

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.

keynav-0.1.2 released

Update to the keyboard navigation plugin: 0.1.2.

This minor update simply fixes all the warnings and cleaned up some cruft in the code.
Source code is available from my web dav folder.

git clone  http://svn.blisted.org/scott/keynav.git

The package is available for download here.

100 lines or less: A Concurrent Circular Buffer

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.

  • Posted: 2010-04-25 21:21
  • Author: scott
  • Categories: (none)
  • Comments (0)

Keynav 0.1.1 is available

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.

Compiz Keyboard Navigation

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.

  • Posted: 2008-12-06 09:45 (Updated: 2008-12-06 09:55)
  • Author: scott
  • Categories: compiz
  • Comments (0)