Refactoring of the wescamp tool and svn library, changes all over the place.

This commit is contained in:
Mark de Wever 2007-11-09 21:45:52 +00:00
parent 775bfa61f3
commit bd73d33d2f
2 changed files with 227 additions and 141 deletions

View file

@ -17,7 +17,7 @@ This library provides an interface to svn, the interface is build upon
the command line svn tool.
"""
import os, shutil;
import os, shutil, logging;
class result:
"""V Result object for most svn functions
@ -39,9 +39,9 @@ class SVN:
checkout the root of the local checkout eg /src/wesnoth
do not include a trailing slash!
"""
def __init__(self, checkout, log_level = 1):
def __init__(self, checkout):
self.checkout_path = checkout
"""status masks
A = add
D = delete
@ -57,16 +57,6 @@ class SVN:
self.STATUS_FLAG_NON_SVN = 0x10
self.STATUS_FLAG_NON_EXISTANT = 0x20
self.LOG_LEVEL_ERROR = 0
self.LOG_LEVEL_WARNING = 1
self.LOG_LEVEL_INFO = 2
self.LOG_LEVEL_DEBUG = 3
self.log_level = log_level
self.out = ""
self.err = ""
"""V Makes a new checkout.
@ -78,7 +68,7 @@ class SVN:
"""
def svn_checkout(self, repo):
self.log(self.LOG_LEVEL_DEBUG, "checkout " + repo)
logging.debug("checkout " + repo)
out, err = self.execute("svn co --non-interactive " + repo + " " +
self.checkout_path)
@ -99,7 +89,7 @@ class SVN:
"""
def svn_commit(self, msg, files = None):
self.log(self.LOG_LEVEL_DEBUG, "commit msg " + msg)
logging.debug("commit msg " + msg)
command = "svn commit --non-interactive -m " + '"' + msg + '"'
if(files != None):
@ -150,7 +140,7 @@ class SVN:
"""
def copy_to_svn(self, src, exclude):# = None):
self.log(self.LOG_LEVEL_DEBUG, "copy_to_svn :\n\tsvn = "
logging.debug("copy_to_svn :\n\tsvn = "
+ self.checkout_path + "\n\tsrc = " + src)
# check whether the status of the repo is clean
@ -189,8 +179,7 @@ class SVN:
"""
def sync_dir(self, src, dest, src_svn, exclude ):#= None):
self.log(self.LOG_LEVEL_DEBUG, "sync_dir :\n\tsrc = "
+ src + "\n\tdest = " + dest)
logging.debug("sync_dir :\n\tsrc = " + src + "\n\tdest = " + dest)
src_dirs, src_files = self.get_dir_contents(src, exclude)
dest_dirs, dest_files = self.get_dir_contents(dest, exclude)
@ -262,35 +251,35 @@ class SVN:
"""
def get_dir_contents(self, dir, exclude ):#= None):
self.log(self.LOG_LEVEL_DEBUG, "get dir :\n\tdir = " + dir)
logging.debug("get dir :\n\tdir = " + dir)
if(exclude != None):
self.log(self.LOG_LEVEL_DEBUG, "\t exclude = ")
self.log(self.LOG_LEVEL_DEBUG, exclude)
logging.debug("\t exclude = ")
logging.debug(exclude)
items = os.listdir(dir)
dirs = []
files = []
for item in items:
self.log(self.LOG_LEVEL_DEBUG, "\tTesting item " + item)
logging.debug("\tTesting item " + item)
# ignore .svn dirs
if(item == ".svn"):
self.log(self.LOG_LEVEL_DEBUG, "\t\tIgnore .svn")
logging.debug("\t\tIgnore .svn")
continue
# ignore exclude list
if(exclude != None and item in exclude):
self.log(self.LOG_LEVEL_DEBUG, "\t\tIgnore on the exclude list")
logging.debug("\t\tIgnore on the exclude list")
continue
# an item is either a directory or not, in the latter case it's
# assumed to be a file.
if(os.path.isdir(dir + "/" + item)):
self.log(self.LOG_LEVEL_DEBUG, "\t\tAdded directory")
logging.debug("\t\tAdded directory")
dirs.append(item)
else:
self.log(self.LOG_LEVEL_DEBUG, "\t\tAdded file")
logging.debug("\t\tAdded file")
files.append(item)
return dirs, files
@ -309,8 +298,7 @@ class SVN:
"""
def dir_add(self, src, dest, src_svn, exclude ):#= None):
self.log(self.LOG_LEVEL_DEBUG, "dir_add :\n\tsvn = "
+ self.checkout_path + "\n\tsrc = " + src)
logging.debug("dir_add :\n\tsvn = " + self.checkout_path + "\n\tsrc = " + src)
# add parent
os.mkdir(dest)
@ -476,7 +464,7 @@ class SVN:
"""
def execute(self, command):
self.log(self.LOG_LEVEL_DEBUG, "Execute: " + command)
logging.debug("Execute: " + command)
stdin, stdout, stderr = os.popen3(command)
stdin.close()
@ -486,8 +474,3 @@ class SVN:
stdout.close()
return out, err
def log(self, level, msg):
if(level <= self.log_level):
print msg

View file

@ -19,7 +19,7 @@ This utility provides two tools
* update the translations in a campaign (in the packed campaign)
"""
import sys, os, optparse, tempfile, shutil
import sys, os, optparse, tempfile, shutil, logging
# in case the wesnoth python package has not been installed
sys.path.append("data/tools")
import wmldata as wmldata
@ -34,8 +34,9 @@ class tempdir:
def __init__(self):
self.path = tempfile.mkdtemp()
# for some reason we need to need a variable to shutil
# otherwise the __del__() will fail
# for some reason we need to need a variable to shutil otherwise the
#__del__() will fail. This is caused by import of campaignserver_client
# or libsvn, according to esr it's a bug in Python.
self.dummy = shutil
def __del__(self):
@ -43,94 +44,104 @@ class tempdir:
if __name__ == "__main__":
def extract(server, campaign, path):
"""Download an addon from the server.
server The url of the addon server eg
campaigns.wesnoth.org:15003.
addon The name of the addon.
path Directory to unpack the campaign in.
returns Nothing, errors are not detected.
"""
def extract(server, addon, path):
logging.debug("extract addon server = '%s' addon = '%s' path = '%s'",
server, addon, path)
wml = libwml.CampaignClient(server)
data = wml.get_campaign(campaign)
wml.unpackdir(data, path, 0, True)
data = wml.get_campaign(addon)
wml.unpackdir(data, path)
optionparser = optparse.OptionParser("%prog [options]")
optionparser.add_option("-u", "--upload", help = "upload a campaign to wescamp") # T
"""Get a list of addons on the server.
optionparser.add_option("-d", "--download", help = "download the translations from wescamp") #
optionparser.add_option("-x", "--extract", help = "downloads and extracts a file from the campaign server") # T
optionparser.add_option("-l", "--list", action = "store_true", help = "list available campaigns") # T
optionparser.add_option("--execute", help = "executes a program on the data directory (read wmllint)") #
optionparser.add_option("-s", "--server", help = "server to connect to") # T
optionparser.add_option("-t", "--target", help = "directory to write data to / read data from") # T
optionparser.add_option("-w", "--wescamp-checkout", help = "the directory containing the wescamp checkout root") # \
optionparser.add_option("-v", "--verbose", action = "store_true", help = "show more verbose output") # \
optionparser.add_option("-P", "--password", help = "The master password for the campaigne server") # \
options, args = optionparser.parse_args()
server = "localhost"
if(options.server != None):
server = options.server
target = None
tmp = tempdir()
if(options.target != None):
target = options.target
else:
target = tmp.path
wescamp = None
if(options.wescamp_checkout):
wescamp = options.wescamp_checkout
verbose = options.verbose
password = ""
if(options.password):
password = options.password
if(options.list):
if(server == None):
print("No server specified")
sys.exit(2)
server The url of the addon server eg
campaigns.wesnoth.org:15003.
translatable_only If True only returns translatable addons.
returns A dictonary with the addon as key and the translatable
status as value
"""
def list(server, translatable_only):
logging.debug("list addons server = '%s' translatable_only = %s",
server, translatable_only)
wml = libwml.CampaignClient(server)
data = wml.list_campaigns()
data.debug(True)
# Item [0] hardcoded seems to work
campaigns = data.data[0]
result = {}
for c in campaigns.get_all("campaign"):
print c.get_text_val("title")
translatable = c.get_text_val("translate")
if(translatable == "true"):
result[c.get_text_val("title")] = True
else:
# when the campaign isn't marked for translation skip it
if(translatable_only):
continue
else:
result[c.get_text_val("title")] = False
elif(options.upload != None):
if(server == None):
print("No server specified")
sys.exit(2)
return result
if(target == None):
# FIXME this should be an optional parameter, if ommitted
# use a temp dir which gets cleared after termination
print("No target specified.")
sys.exit(2)
"""Upload a addon from the server to wescamp.
server The url of the addon server eg
campaigns.wesnoth.org:15003.
addon The name of the addon.
temp_dir The directory where the unpacked campaign can be stored.
svn_dir The directory containing a checkout of wescamp.
"""
def upload(server, addon, temp_dir, svn_dir):
if(wescamp == None):
print("No wescamp checkout specified")
sys.exit(2)
logging.debug("upload addon to wescamp server = '%s' addon = '%s' "
+ "temp_dir = '%s' svn_dir = '%s'",
server, addon, temp_dir, svn_dir)
extract(server, options.upload, target)
svn = libsvn.SVN(wescamp + "/" + options.upload, 3) # debug level hard coded
# Is the addon in the list with campaigns to be translated.
campaigns = list(server, True)
if((addon in campaigns) == False):
logging.info("Addon '%s' is not marked as translatable "
+ "upload aborted.", addon)
return
# Download the addon.
extract(server, addon, temp_dir)
# If the directory in svn doesn't exist we need to create and commit it.
message = "wescamp.py automatic update"
if(os.path.isdir(svn_dir + "/" + addon) == False):
logging.info("Creating directory in svn '%s'",
svn_dir + "/" + addon)
svn = libsvn.SVN(svn_dir)
# Don't update we're in the root and if we update the status of all
# other campaigns is lost and no more updates are executed.
os.mkdir(svn_dir + "/" + addon)
res = svn.svn_add(svn_dir + "/" + addon)
res = svn.svn_commit("Adding directory for initial wescamp inclusion")
# Update the directory
svn = libsvn.SVN(svn_dir + "/" + addon)
res = svn.svn_update()
if(res == -1):
print res.err
logging.error("svn update of '%s' failed with message: %s",
svn_dir + "/" + addon, res.err)
sys.exit(1)
res = svn.copy_to_svn(target, ["translations"])
res = svn.copy_to_svn(temp_dir, ["translations"])
if(res.err != ""):
print "Error :" + res.err
@ -141,29 +152,34 @@ if __name__ == "__main__":
print "Error :" + res.err
sys.exit(1)
elif(options.download != None):
if(server == None):
print("No server specified")
"""Update the translations from wescamp to the server.
server The url of the addon server eg
campaigns.wesnoth.org:15003.
addon The name of the addon.
temp_dir The directory where the unpacked campaign can be stored.
svn_dir The directory containing a checkout of wescamp.
password The master upload password.
"""
def download(server, addon, temp_dir, svn_dir, password):
if(target == None):
# FIXME also allow temp dir
print("No target specified.")
sys.exit(2)
logging.debug("download addon from wescamp server = '%s' addon = '%s' "
+ "temp_dir = '%s' svn_dir = '%s' password is not shown",
server, addon, temp_dir, svn_dir)
extract(server, options.extract, target)
if(wescamp == None):
print("No wescamp checkout specified")
sys.exit(2)
extract(server, addon, temp_dir)
# update the wescamp checkout for the translation,
# if nothing changed we're done.
# Test the entire archive now and use that, might get optimized later
svn = libsvn.SVN(wescamp + "/" + options.download, 3) # debug level hard coded
svn = libsvn.SVN(wescamp + "/" + addon)
res = svn.svn_update()
if(res.status == 0):
# sys.exit(0) FIXME reenable
logging.info("svn Up to date, nothing to send to server")
sys.exit(0)
pass
elif(res.status == -1):
sys.exit(1)
@ -171,38 +187,125 @@ if __name__ == "__main__":
# test whether the svn has a translations dir, if not we can stop
# extract the campaign from the server
extract(server, options.download, target)
extract(server, addon, target)
# delete translations
if(os.path.isdir(target + "/" + options.download + "/translations")):
shutil.rmtree(target + "/" + options.download + "/translations")
if(os.path.isdir(target + "/" + addon + "/translations")):
shutil.rmtree(target + "/" + addon + "/translations")
# copy the new translations
if(os.path.isdir(target + "/" + options.download + "/translations") == False):
os.mkdir(target + "/" + options.download + "/translations")
if(os.path.isdir(target + "/" + addon + "/translations") == False):
os.mkdir(target + "/" + addon + "/translations")
res = svn.sync_dir(svn.checkout_path + "/" + options.download + "/translations" ,
target + "/" + options.download + "/translations", True, None)
res = svn.sync_dir(svn.checkout_path + "/" + addon + "/translations" ,
target + "/" + addon + "/translations", True, None)
# upload to the server
wml = libwml.CampaignClient(server)
wml.put_campaign("", options.download, "", password, "", "", "",
target + "/" + options.download + ".cfg",
target + "/" + options.download)
wml.put_campaign("", addon, "", password, "", "", "",
target + "/" + addon + ".cfg", target + "/" + addon)
optionparser = optparse.OptionParser("%prog [options]")
optionparser.add_option("-u", "--upload", help = "upload a addon to wescamp") # V
optionparser.add_option("-d", "--download", help = "download the translations from wescamp") #
optionparser.add_option("-D", "--download-all", action = "store_true", help = "download all translations from wescamp") # \
optionparser.add_option("-l", "--list", action = "store_true", help = "list available campaigns" ) # V
optionparser.add_option("-L", "--list-translatable", action = "store_true", help = "list campaigns available for translation") # V
optionparser.add_option("-s", "--server", help = "server to connect to") # V
optionparser.add_option("-p", "--port", help = "port on the server to connect to") # V
optionparser.add_option("-t", "--temp-dir", help = "directory to store the tempory data, if omitted a tempdir is created and destroyed after usage, if specified the data is left in the tempdir") # V
optionparser.add_option("-w", "--wescamp-checkout", help = "the directory containing the wescamp checkout root") # V
optionparser.add_option("-v", "--verbose", action = "store_true", help = "show more verbose output") # V
optionparser.add_option("-P", "--password", help = "The master password for the campaigne server") # V
options, args = optionparser.parse_args()
server = "localhost"
if(options.server != None):
server = options.server
if(options.port != None):
server += ":" + options.port
target = None
tmp = tempdir()
if(options.temp_dir != None):
target = options.temp_dir
else:
target = tmp.path
wescamp = None
if(options.wescamp_checkout):
wescamp = options.wescamp_checkout
if(options.verbose):
logging.basicConfig(level=logging.DEBUG, format='[%(levelname)s] %(message)s')
else:
logging.basicConfig(level=logging.INFO, format='[%(levelname)s] %(message)s')
password = options.password
# List the addons on the server and optional filter on translatable
# addons.
if(options.list or options.list_translatable):
addons = list(server, options.list_translatable)
for k, v in addons.iteritems():
if(v):
print k + " translatable"
else:
print k
# Upload an addon to wescamp.
elif(options.upload != None):
if(wescamp == None):
logging.error("No wescamp checkout specified")
sys.exit(2)
upload(server, options.upload, target, wescamp)
# Download an addon from wescamp.
elif(options.download != None):
if(wescamp == None):
logging.error("No wescamp checkout specified")
sys.exit(2)
if(password == None):
logging.error("No upload password specified")
sys.exit(2)
download(server, options.download, target, wescamp, password)
# Download all addons from wescamp.
elif(options.download_all != None):
if(wescamp == None):
logging.error("No wescamp checkout specified")
sys.exit(2)
if(password == None):
logging.error("No upload password specified")
sys.exit(2)
addons = list(server, True)
for k, v in addons.iteritems():
download(server, k, target, wescamp, password)
# FIXME clear the tmp dir
elif(options.extract != None):
if(server == None):
print("No server specified")
sys.exit(2)
if(target == None):
print("No target specified.")
sys.exit(2)
extract(server, options.extract, target)
else:
optionparser.print_help()