Strony

czwartek, 26 listopada 2009

eol once again

Here is another pre-commit hook I wrote for Subversion repositories. Let's assume many people (not always smart enough) accessing and committing to your Subversion repository. They don't know how to configure their svn client, but you want to be sure, that all text files have the same line endings (e.g. Unix = LF). So, to be sure that all line endings are consistent, you could run this hook, which blocks commit operation if svn:eol-style is not set to required one.

As always you should modify also your pre-commit file, usually stored in repo/hooks directory, e.g.:

And that's it! ;)

poniedziałek, 23 listopada 2009

subversion hook for "syncing" inside one repository

The old school CVS has a very nice ability to make an alias in one module, which points to another one. In Subversion the situation is different, as svn is using it's own "file-system". Of course you can use svn:externals property to pull to your working copy some external source tree required during compilation. But what if you just want for some reason store exactly the same file tree in two different locations in your repo?

For that one you can use post-commit hook, which checks the change list of transaction and if required merge the changes made in one location to another:


#!/usr/bin/env python
##
# @file sync.py
# @author Krzysztof Daniel Ciba (Krzysztof.Ciba@NOSPAMgmail.com)
# @date 06/05/2009
# @brief post-commit hook for syncing two locations in repository
import os, sys
import datetime
import getopt
try:
my_getopt = getopt.gnu_getopt
except AttributeError:
my_getopt = getopt.getopt
import StringIO
from subprocess import Popen
from subprocess import PIPE

twinPaths = { "/destpath/dest1" : "/some/path/src1" }

svnhome = "/PATH/TO/YOUR/REPO/"
svnroot = "file:///PATH/TO/YOUR/REPO"
svnCmd = "/usr/bin/svn"
svnlookCmd = "/usr/bin/svnlook"

## make sync between twin packages
# @param rev revision number
def sync(rev):

svnlook = svnlookCmd + " changed " + svnhome + " -r " + rev
changed = Popen( svnlook.split(), stdout=PIPE).communicate()[0]
changed = StringIO.StringIO( changed )
changed = changed.read()

changed = changed.split( "\n" )

twins = []
for line in changed:
if ( line != "" ):
change, where = line.split()
where = where.strip()
sys.stdout.write( change + " in " + where + "\n" )
for srcPath, dstPath in twinPaths.iteritems():
print where + " " + srcPath

if ( where.startswith( srcPath ) ):
twins.append( ( srcPath, dstPath ) )

noDupes = []
[ noDupes.append(i) for i in twins if not noDupes.count(i) ]
twins = noDupes
if ( len( twins ) ):

for ( srcPath, dstPath ) in twins:
srcURI = svnroot + "/" + srcPath + "@" + rev
dstURI = svnroot + "/" + dstPath

cmd = "#!/bin/sh\n"
cmd += svnCmd + " co " + dstURI + "\n"
cmd += svnCmd + " merge " + dstURI + " " + srcURI + " " + dstPath +"\n"
cmd += svnCmd + " ci " + dstPath + " -m 'syncing " + dstPath + " with " + srcPath + "'\n"
cmd += "rm -rf "+ dstPath +"\n"

sys.stdout.write( cmd )
stdin, stdout, stderr = os.popen3( cmd )
err = stderr.read()
stderr.close()
out = stdout.read()
if ( err != "" ): return False
return True

## write usage and exit
def usage_and_exit(error_msg=None):
import os.path
stream = error_msg and sys.stderr or sys.stdout
if error_msg:
stream.write("ERROR: %s\n\n" % error_msg)
stream.write("USAGE: %s -r REV REPOS\n"
% (os.path.basename(sys.argv[0])))
sys.exit(error_msg and 1 or 0)

## main processing
def main( argv ):
repos_path = None
rev = None
try:
opts, args = my_getopt(argv[1:], 'r:h?', ["help"])
except:
usage_and_exit("problem processing arguments/options")
for opt, value in opts:
if opt == '--help' or opt == '-h' or opt == '-?':
usage_and_exit()
elif opt == '-r':
rev = value
else:
usage_and_exit("unknown option '%s'" % opt)

if rev is None:
usage_and_exit("must provide -r argument")
if len(args) != 1:
usage_and_exit("only one argument allowed (the repository).")

if ( sync(rev) ): return 0
return 1

## start processing
if __name__ == '__main__':
sys.exit( main( sys.argv ) )


Then of course you should modify your post-commit file, in my case it is very simple:


#!/bin/sh
REPOS="$1"
REV="$2"
# synchronisation between packages
SYNC=/PATH/TO/REPO/hooks/sync.py
$SYNC -r "$REV" "$REPOS"


And that's it! Every change (commit) made in /some/path/src1 would be merged and committed to /destpath/dest1.

środa, 18 listopada 2009

No i proszę, założyłem swojego bloga... Kto by pomyślał.

A dzisiaj dzień nie wesoły: starszy syn choruje, awansu w pracy nie ma, żona zła, atmosfera pod zdechłym psem. I nawet sam blogger pyta mnie: "Czy jesteś już członkiem?". Hmmm... No właśnie się tak dobrze czuję...