Tag: svn

SVN customized bash prompt (and Git!)

I recently had to split an SVN repository of mine into a TRUNK and a TAGged branch. Nothing fancy: a tag to identify the REV1.x and the TRUNK to keep developing.

From time to time I have to svn switch, jumping from the tagged branch to the trunk (testing, merging, usual staff…). And you know what? I’m keeping committing on the tagged branch! And that is bad (more on this with an appropriate future post. I promise).

How beautiful could be having a bash prompt that will costantly display the branch I’m in and the svn repository revision of the current directory?

So, here we are:

append this code to your ~/.bashrc, logout/login and enter a svn managed directory (beware: I’ve tested it only on my Ubuntu box… the key here is to use the PROMPT_COMMAND env variabile, passing it the function that does the “sniffing”. The PROMPT_COMMAND command will be executed every time, just before displaying the shell prompt).

PROMPT_COMMAND=prompt_command

prompt_command() {

  if [[ -d ".svn" ]] ; then
    local info rev url ver
    info=$(LC_MESSAGES=C svn info 2>/dev/null)
    rev=$(echo "${info}" | awk '/^Revision: [0-9]+/{print $2}')
    url=$(echo "${info}" | awk '/^URL: .*/{print $2}')

    echo ${url} | grep -q "/trunk\b"
    if [[ $? -eq 0 ]] ; then
      ver=trunk
    else
      echo ${url} | grep -q "/tags\b"
      if [[ $? -eq 0 ]] ; then
        ver=tag-$(echo ${url} | grep -o "/tags.*" | awk -F/ '{print $3}')
      fi
    fi

    echo -e "\e[00;33m[svn:r${rev}@${ver}]\e[00m"
  fi

}

The svn information will be displayed in yellow (is the 33 in the final echo line). Change it at your liking.

UPDATE: Giovanni Bajo gives the hints for the "-q" switch and the LC_MESSAGES trick to avoid locale inconsistences.

Giovanni has gone a step forward, giving us the code for a git enhanced prompt too.

Here it is:

  local gitout
  gitout=$(git branch -v --abbrev --no-color 2>/dev/null)
  if [[ $? -eq 0 ]]; then
    local full branch sha1
    full=$(echo "${gitout}" | grep '^*')
    branch=$(echo "${full}" | awk '/^* \w+ \w+/{print $2}')
    sha1=$(echo "${full}" | awk '/^* \w+ \w+/{print $3}')
    echo -e "\e[00;33m[git:${sha1}@${branch}]\e[00m"
  fi

Thanks to Uqbar on Freenode IRC for the awk hints!

example:

claudioc@enebish:~/Sites$
claudioc@enebish:~/Sites$ cd scrive2/
[svn:r452@trunk]
claudioc@enebish:~/Sites/scrive2$ svn switch $myrepos/tags/R2.4
[svn:r431@tag-R2.4]
claudioc@enebish:~/Sites/scrive2$

A script to query SVN logs by SQL

Quite often I find myself lost trying to do things that should be simply but they are not: try to answer this question “Being in a SVN working directory, how do you find all the log messages for the revisions that has been committed by someusername in the last month?”

Not so simple.

For this and other reasons, I’d like to have the power of SQL under my fingers, while inspecting SVN logs. So, in an hour, I hacked up this script that will permit you to query the (local) SVN logs with a (very) sql like interface.

It uses Ruby and Sqlite3, via gem. Basically it loads the log (in memory) as XML, then parses it and store revision informations in a (in memory) sqlite database. It then offers you a prompt from which you’ll be able to run queries.

Some example queries are:

  • revision (lists all the revisions)
  • revision where author=’claudioc’ (lists all the revisions by claudioc)
  • count(*) where author=’claudioc’ (how many commits by claudioc?)
  • message where date between ‘2007-01-01’ and ‘2007-02-01’ order by revision desc’ (list the log messages in a 2 months window, and order the list by revision number)

You can download the script here

Some extra notes:

The script is released under a creative commons license and you’re then welcome to change or patch the program as you like (you may want to report back patches).

The program works in memory, so the bigger the log file, the bigger the memory usage. It could be much better if the temporary table would be filled WHILE reading the XML (and not after).

The program use the current directory of the working copy a the starting point to inspect log. If you want to query the WHOLE application log, then move yourself in the root directory of your wc.

Due to the lack of real data types in Sqllite, date range checks could fail… a better approach (using the Ruby extensibily of the Sqlite gem) should be applied.

As usual, HTH


svn:externals micro howto

Disclaimer: what follows reflects my actual setup. It could be “a quick and dirty hack” or something, and couldn’t be very polite and/or technically perfect. But it works.

If your projects share a common code base (a library, a framework, a bunch of javascript scripts residing somewhere on a svn repository), what you really need is the help of the svn:externals capabilities. Let’s call this “shared code base” the SCB. By using this feature, your project:

  • uses an actual physical copy of the SCB (not symlinks)
  • should not care about changes in the SCB: they will be in syncrony upon each update, transparently as usual

What follows is my actual setup. My PHP projects share a common set of PHP scripts (they are the framework, shudder!). They reside in a repository by their own.

I decided to put those scripts in a directory in the project source tree, calling it “lib”.

I then went in the directory where “lib” will be created, and I instructed svn to hook here a copy of some externals file (that is, the framework). The svn command to use is propedit, being svn:externals a svn property.

Ok, sitting in the parent directory of “lib”, I issued something like:

svn propedit svn:externals .

(please note the final “.”)

What I said, in substance, was: “Please edit the values of the svn:externals property for the current directory”. Indeed The System fired up my editor to enter the actual values (what? No editor? An error, instead? No worries: “export EDITOR=vim” and retry).

Those values are a list (line by line) of pairs. Each pair is composed by a directory name and a repository path. So, getting a “library” residing in the trunk of my “uberfw” repository this residing on www.mysecretretrepository.com is a matter of writing:

lib svn://www.mysecretrepository.com/uberfw/trunk/library

Save the file and you’re done.

Now you have to “svn update”. This time the “externals” will be actually fetched and the “lib” created.

Finally (I swear), commit (nothing apparently will be transmitted).

A BIG note of WARNING: what have to be clear is that the externals are NOT an exported snapshot of a repository path: they are an actual working copy. BUT! If you make changes into a directory provided as an external, you have to explicity commit BEING INSIDE that directory, otherwise the changes will not be committed.

Instead, an update on the root directory of the project will fetch also the (eventual) externals changes.

Learn more on this topic from the subversion book.


Protecting .svn entries

If you, like me, use subversion to directly deploy your test environment (“svn update” and you’re done) don’t forget to hide the .svn directories to the public. The .svn directory contains a file, entries, where you can read the URL of your repository and even the last user who committed. Maybe you have ironed your repository with solid password, and denied the checkout from anonymous users. Maybe not.

The easiest and more raliable way to hide .svn’s entries, is to use .htaccess with this entry:

<Files "entries">
  Deny from All
</Files>

In that way every request to any file named entries will result to a HTTP 403: Forbidden.

But if you can use mod_rewrite within your httpd server, I suggest this approach (works in a .htaccess too):

RewriteEngine On
RewriteRule ^.svn/(.*)$ http://subversion.tigris.org [R]

This way, every request for a file above a .svn directory will be nicely redirected to the subversion site :)

Fredrik suggested that removing the ^ from the regexp will match any directory in the tree that is called .svn, instead of just in the root directory.


I contenuti di questo sito sono distribuiti con una licenza Creative Commons 2.5 eccetto dove diversamente specificato.

Tema WordPress Punto5 sviluppato da Claudio Cicali; icone del set famfamfam silk e komodomedia.

© 2005-2010
Claudio Cicali