GNA.org allows only static HTML hosting from a Subversion repository, so ikiwiki was an ideal candidate. The source for the wiki is at http://svn.gna.org/viewcvs/freeeq/website/ikiwiki-src/ and the generated content is at http://svn.gna.org/viewcvs/freeeq/website/ikiwiki/ .
To automatically put the generated output into the repository, I wrote a Python script that checks out a working copy of the destination SVN location and then synchronizes it with the local directory containing the generated content.
#!/usr/bin/env python
import filecmp
import optparse
import os
import pysvn
import shutil
import stat
import sys
import tempfile
"""
svnsync.cfg format:
===================
# Comment
localPath = /some/local/dir
svnURL = https://some.svn.host/path
checkin = true
message = Log message
"""
class Config:
def __init__( self ):
self.keys = set( [ "localPath", "svnURL", "checkin", "message" ] )
self.localPath = ""
self.svnURL = ""
self.checkin = False
self.message = ""
def read( self, file ):
try:
for line in file.readlines():
line = line.split( '#' )[0].strip()
if line == "":
continue
name, value = line.split( '=' )
name = name.strip()
value = value.strip()
assert name in self.keys
assert value != ""
self.__dict__[ name ] = value
except:
print "Error parsing config file!"
sys.exit( 1 )
def getCheckin( self ):
return self.checkin == "yes" or self.checkin == "true"
cfg = Config()
if os.path.isfile( "svnsync.cfg" ):
print "Reading config file"
cfg.read( open( "svnsync.cfg" ) )
op = optparse.OptionParser()
op.add_option( "-l", "--local-path", dest = "localPath", default = "",
help = "Read from local directory DIR", metavar = "DIR" )
op.add_option( "-s", "--svn-url", dest = "svnURL", default = "",
help = "Sync to svn repository at URL", metavar = "URL" )
op.add_option( "-c", "--checkin", dest = "checkin", action = "store_true", default = False,
help = "Commit changes after synching" )
op.add_option( "-m", "--message", dest = "message", default = "",
help = "Commit message" )
(options, args) = op.parse_args()
if options.localPath != "":
cfg.localPath = options.localPath
if options.svnURL != "":
cfg.svnURL = options.svnURL
if options.checkin:
cfg.checkin = "true"
if options.message != "":
cfg.message = options.message
if not os.path.isdir( cfg.localPath ):
print "Error: Invalid localPath"
sys.exit( 1 )
if cfg.svnURL == "":
print "Error: No svnURL specified"
sys.exit( 1 )
if cfg.getCheckin() and cfg.message == "":
print "Error: Empty commit message"
sys.exit( 1 )
workingCopyDirName = tempfile.mkdtemp( "", "svnsync_", "." )
client = pysvn.Client()
client.checkout( cfg.svnURL, workingCopyDirName )
def doTree( localPath, workingCopyPath ):
dc = filecmp.dircmp( localPath, workingCopyPath, [".svn"] )
for f in dc.right_only:
print "Removing stale file/directory '%s'" % f
client.remove( "%s/%s" % ( workingCopyPath, f ) )
for f in dc.left_only:
print "Adding new file/directory '%s'" % f
src = "%s/%s" % ( localPath, f )
mode = os.stat( src )[ stat.ST_MODE ]
if stat.S_ISDIR( mode ):
shutil.copytree( src, "%s/%s" % ( workingCopyPath, f ) )
elif stat.S_ISREG( mode ):
shutil.copy( src, "%s/" % ( workingCopyPath ) )
else:
print "Ignoring '%s'" % src
continue
client.add( "%s/%s" % ( workingCopyPath, f ) )
for f in dc.diff_files:
print "Updating '%s'" % f
shutil.copy( "%s/%s" % ( localPath, f ), "%s/%s" % ( workingCopyPath, f ) )
for f in dc.common_dirs:
doTree( "%s/%s" % ( localPath, f ), "%s/%s" % ( workingCopyPath, f ) )
doTree( cfg.localPath, workingCopyDirName )
print "Done synching"
print "Working copy at '%s'" % workingCopyDirName
if cfg.getCheckin():
print "Commiting changes"
client.checkin( workingCopyDirName, cfg.message )
0 comments:
Post a Comment