Further implement libgithub.

Most functions from libsvn that are used now have an equivalent.
This commit is contained in:
Alexander van Gessel 2011-11-10 15:49:35 +01:00
parent 82e7164878
commit d20499613d
2 changed files with 89 additions and 16 deletions

View file

@ -10,7 +10,7 @@ import os
try:
# Externally distributed, usually more up-to-date
import simplejson as json
except:
except ImportError:
# Distributed with python since 2.6
import json
import subprocess
@ -54,16 +54,81 @@ class Addon(object):
Returns whether anything changed.
"""
logging.debug("Updating add-on {0}".format(self.name))
out, err = self._execute(["git", "pull"])
out, err = self._execute(["git", "pull"], check_error=True)
#TODO: make this less hacky
return len(out.split("\n")) > 2
#TODO: any commit has to be ended with "git push -u origin master"
def sync_from(self, src, exclude):
"""Synchronises add-on from another directory.
src: Directory with new add-on version.
exclude: List of files to ignore.
Returns whether anything changed.
Raises libgithub.Error if the checkout is not clean.
"""
logging.debug("Syncing add-on {0} from add-on server ({1})".format(self.name, src))
status = self._status()
if status:
raise Error("Checkout is not clean:\n{0}".format("\n".join(status)))
self._rmtree(".", exclude)
#actual copying
shutil.copytree(src, self._get_dir(), ignore=lambda src,names: [n for n in names if n in exclude])
self._execute(["git", "add", self._get_dir()], check_error=True)
status = self._status()
return len(status) > 0
def commit(self, message):
"""Commits and pushes add-on to git repo.
message: Commit message.
Raises libgithub.Error if something went wrong
"""
logging.debug("Committing and pushing add-on {0}".format(self.name))
tmpname = os.tmpnam()
tmpfile = open(tmpname)
tmpfile.write(message)
tmpfile.close()
self._execute(["git", "commit", "-F", tmpname], check_error=True)
os.remove(tmpname)
self._execute(["git", "push", "-u", "origin", "master"], check_error=True)
# Internal functions
def _rmtree(self, directory, exclude):
logging.debug("Deleting tree {0}, except for {1}".format(self.name, ",".join(exclude)))
# Ensure the os calls all happen in the right directory
# not needed for _execute, as that does the cwd manipulation itself
# so only the os.chdir and os.path.isdir here need it
# Another option would be to os.path.join with self._get_dir
os.chdir(self._get_dir())
for entry in os.listdir(directory):
if entry in exclude:
continue
if entry == ".git":
continue
relpath = os.path.join(directory, entry)
if os.path.isdir(relpath):
self._rmtree(relpath, exclude)
self._execute(["rmdir", "--ignore-fail-on-non-empty", relpath])
else:
self._execute(["git", "rm", relpath], check_error=True)
def _status(self):
out, err = self._execute(["git", "status", "--porcelain"])
if err:
raise Error("Status failed with message: {0}".format(err))
return [line for line in out.split('\n') if len(line)]
def _get_dir(self):
return os.path.join(self.github.directory, self.name)
def _execute(self, command):
return self.github._execute(command, cwd=self._get_dir())
def _execute(self, command, check_error = False):
return self.github._execute(command, cwd=self._get_dir(), check_error=check_error)
_GITHUB_API_BASE = "https://api.github.com/"
_GITHUB_API_REPOS = "orgs/wescamp/repos"
@ -76,8 +141,8 @@ class GitHub(object):
def __init__(self, directory, version):
"""Initializes a GitHub object.
Directory: Directory in which the git repos for this wesnoth branch live.
Version: The version of this wesnoth branch.
directory: Directory in which the git repos for this wesnoth branch live.
version: The version of this wesnoth branch.
"""
logging.debug("GitHub created with directory {0} and version {1}".format(directory, version))
self.directory = directory
@ -116,7 +181,7 @@ class GitHub(object):
def create_addon(self, name):
"""Creates a new add-on on github.
name: Name of the add-on
name: Name of the add-on.
Returns an Addon object for the new add-on.
"""
logging.debug("Creating new add-on {0}".format(name))
@ -130,10 +195,10 @@ class GitHub(object):
def _clone(self, name, url):
target = self._absolute_path(name)
self._execute(["git", "clone", url, target])
self._execute(["git", "clone", url, target], check_error=True)
def _get_new_addons(self):
"""Checks out any new add-ons
"""Check out any new add-ons.
Returns whether anything changed.
"""
@ -170,7 +235,7 @@ class GitHub(object):
for repo in repos if repo["name"].endswith(version_suffix)]
def _github_repos_create(self, name):
"""Create a new repository
"""Create a new repository.
name: The name of the add-on for which the repository will be created.
"""
@ -188,11 +253,14 @@ class GitHub(object):
except IOError as e:
raise Error("GitHub API failure: " + str(e))
def _execute(self, command, cwd=None):
def _execute(self, command, cwd=None, check_error=False):
"""Executes a command.
command: The command to execute
Returns stdout, stderr
command: The command to execute.
cwd: Directory to execute the command from.
check_error: Whether to raise an exception if there's stderr output.
Returns stdout, stderr.
Raises libgithub.Error if check_error and len(err).
"""
logging.debug("execute command = '%s'", command)
@ -209,5 +277,8 @@ class GitHub(object):
logging.debug("===== stdout ====\n\n\n%s\n\n\n===== stdout ====", out)
logging.debug("===== stderr ====\n\n\n%s\n\n\n===== stderr ====", err)
if check_error and len(err):
raise Error("Failure executing command '{0}': {1}".format(" ".join(command), err))
return out, err

View file

@ -184,9 +184,11 @@ if __name__ == "__main__":
# The other files are present in wescamp and shouldn't be deleted.
ignore_list = ["translations", "po", "campaign.def",
"config.status", "Makefile"]
if(svn.copy_to_svn(temp_dir, ignore_list) and not use_git): #TODO: use_git
if(addon_obj.sync_from(temp_dir, ignore_list)
if use_git
else svn.copy_to_svn(temp_dir, ignore_list)):
svn.commit("wescamp_client: automatic update of addon '"
(addon_obj if use_git else svn).commit("wescamp_client: automatic update of addon '"
+ addon + "'")
logging.info("New version of addon '%s' uploaded.", addon)
else: