#!/usr/bin/python
# rsvn: svn wrapper to add repository support
# Copyright (C) 2004 rm (rm atsign arcsin dot org)
# 
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#



import sys
import os



USER_HOME_DIR = os.environ['HOME']
DEFAULT_CONFIG_FILE = USER_HOME_DIR+"/.rsvn"
FILE_HEADER_MSG = (
"""###
### This is rsvn's config file.  rsvn is a tool for keeping track of 
### repositories used with svn.
###
### don't edit this by hand too much.
###

""")


usage_msg = """%s:
	help			Print svn help
	rep-help		This message
	reps          		List the repositories current associated
	rep-register name url	Associate name with the reposoitory url
	rep-remove   name 	Unassociate name with repository

	Otherwise svn is called with the given arguments.
	//name/      substitutes the repository URL associated with 'name'
	///          substitutes the repository URL associated with 'default'
"""%sys.argv[0]

def create_new_config_file(path):
	try:
		f = open(path, "w+")
		f.write(FILE_HEADER_MSG)
		f.close()
	except:
		print "%s: couldn't create config file '%s'."%(sys.argv[0], 
							      path)
	# end try
# end def


def read_configurations(f):
	config_dict = {}
	lineno = 0
	while 1:
		line = f.readline()

		if (line == ""):
			break
		# end if
		lineno += 1
		line.lstrip()
		if (line == "\n" or line[0] == "#"):
			continue
		# end if
		
		# break off any end of line commentsn
		comment_split = line.split("#")
		line = comment_split[0]

		fields = line.split(" ", 1)
		if (len(fields) < 2):
			print "%s: error reading config file at line %i"%(sys.argv[0], lineno)
			sys.exit(-1)
		# end def
	
		name = fields[0].strip()
		location = fields[1].strip()
		config_dict[name] = location
	# end while
	return config_dict
# end def


def write_configurations(f, config_dict):
	for name in config_dict:
		f.write("%s %s\n"%(name, config_dict[name])) 		
	# end for
# end def


def read_config_file(alt_config_file_path = None):
	if (not alt_config_file_path):
		path = DEFAULT_CONFIG_FILE
	else: 
		path = alt_config_file_path
	# end if

	if (not os.access(path, os.F_OK)):
		print "%s: config file doesn't exist."%sys.argv[0]
		# only create the default config file
		if (not alt_config_file_path):
			create_new_config_file(path)
		# end if
	# end if

	f = open(path)
	config_dict = read_configurations(f)
	f.close()

	return config_dict
# end if


def move_file_to_backup(config_file):
	dir = os.path.dirname(config_file)
	base = os.path.basename(config_file)
	os.rename(config_file, dir+"/"+base+"~")
# end def

def cmd_usage():
	print usage_msg
	sys.exit(0)
# end def

def cmd_svn_help():
	os.execvp("svn", [ "svn", "help" ])
# end def

def cmd_register(config_file, config_dict, name, url):

	if (name in config_dict):
		print """%s: '%s' is already registered to %s; use rep-remove before re-assigning it """%(sys.argv[0], name, url)
		sys.exit(-1)
	# end if
	config_dict[name] = url
	move_file_to_backup(config_file)
	f = open(config_file, "w+")
	f.write(FILE_HEADER_MSG)
	write_configurations(f, config_dict)
	f.write("\n")
	f.close()

	print "%s: repository '%s' registered."%(sys.argv[0], name)
# end def

def cmd_remove(config_file, config_dict, name):

	if (name not in config_dict):
		print """%s: '%s' is not registered."""%(sys.argv[0], name)
		sys.exit(-1)
	# end if
	del config_dict[name]

	move_file_to_backup(config_file)
	f = open(config_file, "w+")
	f.write(FILE_HEADER_MSG)
	write_configurations(f, config_dict)
	f.write("\n")
	f.close()

	print "repository '%s' removed."%name

# end def

def get_repository_for_name(config_dict, name):
	if (name not in config_dict):
		print "%s: '%s' is not a registered repository."%(sys.argv[0], 
								name)
		sys.exit(-1)
	# end if
	return config_dict[name]
# end def

def substitute_arg(config_dict, arg):
	
	if (arg[2] == "/"):
		name = "default"
		rest = arg[2:]
		return get_repository_for_name(config_dict, name) + rest
	else:	
		arg = arg[2:]	
		fields = arg.split("/", 1)
		name = fields[0]
		if (len(fields) > 1):
			rest = "/"+fields[1]
		else:
			rest = ""
		# end if
		return get_repository_for_name(config_dict, name) + rest
	# end if
# end def

def main():


	if (len(sys.argv) < 2):
		cmd_svn_help()
		return
	# end if

	config_file = DEFAULT_CONFIG_FILE
	config_dict = read_config_file()


	if (sys.argv[1].lower() == "rep-register"):

		if (len(sys.argv) < 4):
			cmd_usage()
			return
		# end if

		name = sys.argv[2]
		url = sys.argv[3]
		cmd_register(config_file, config_dict, name, url)
		return
	# end if

	if (sys.argv[1].lower() == "reps"):
		for key in config_dict:
			print "\t"+key+"\t"+config_dict[key]
		# end for
		return
	# end if

	if (sys.argv[1].lower() == "rep-remove"):

		if (len(sys.argv) < 3):
			cmd_usage()
			return
		# end if

		name = sys.argv[2]
		cmd_remove(config_file, config_dict, name)
		return
	# end if

	if (sys.argv[1].lower() == "rep-help"):
		cmd_usage()
		return
	# end if


	# substitute arguments
	new_args = [ "svn" ]
	for arg in sys.argv[1:]:
		if (arg[0:2] == "//"):
			arg = substitute_arg(config_dict, arg)
		# end def
		new_args.append(arg)
	# end def
	os.execvp("svn", new_args)
# end def


if (__name__ == "__main__"):
	main()
# end if

