Initial gitzilla commit.
commit
c0abda84b7
|
@ -0,0 +1,4 @@
|
|||
include *.txt
|
||||
include *.py
|
||||
recursive-include etc *
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
|
||||
NAME=gitzilla
|
||||
PY2DSC=$(shell which py2dsc)
|
||||
BUILDCMD=$(shell which dpkg-buildpackage)
|
||||
DEPENDENCIES=python-setuptools
|
||||
BUILDOPTS= -rfakeroot -uc -us
|
||||
VERSION:=$(shell perl -ne 'print $$1 if /version=.(\S+).,/' setup.py)
|
||||
ETC_DIR=/etc
|
||||
|
||||
define CONFIG_REPLACEMENT_STUB
|
||||
binary: build \
|
||||
\n\tdh install --until dh_install\
|
||||
\n\tmkdir -p debian/python-${NAME}${ETC_DIR}\
|
||||
\n\tcp etc/* debian/python-${NAME}${ETC_DIR}\
|
||||
\n\tdh install --after dh_install\
|
||||
\n\tdh binary
|
||||
endef
|
||||
|
||||
DEPS_REPLACEMENT:="s/$$/, ${DEPENDENCIES}/ if /^Depends: /"
|
||||
CONF_REPLACEMENT:="s(binary: build.*$$)(${CONFIG_REPLACEMENT_STUB})"
|
||||
|
||||
.PHONY: check-prerequisites deb debianize-source edit-source build clean bumpversion
|
||||
|
||||
deb: check-prerequisites build
|
||||
$(info collecting packages ...)
|
||||
@mkdir -p debian
|
||||
@mv ${TARGETDIR}/deb_dist/python-${NAME}*.deb debian/
|
||||
@mv ${TARGETDIR}/deb_dist/*.orig.tar.gz debian/
|
||||
@mv ${TARGETDIR}/deb_dist/*.diff.gz debian/
|
||||
@mv ${TARGETDIR}/deb_dist/*.dsc debian/
|
||||
@rm -rf ${TARGETDIR}
|
||||
|
||||
dist/${NAME}-${VERSION}.tar.gz: setup.py
|
||||
$(info preparing source distribution ...)
|
||||
@python setup.py sdist
|
||||
@rm -rf ${NAME}.egg-info
|
||||
|
||||
debianize-source: dist/${NAME}-${VERSION}.tar.gz
|
||||
$(info debianizing ${NAME} via py2dsc ...)
|
||||
@cd ${TARGETDIR} ; \
|
||||
cp ${CURDIR}/dist/${NAME}-${VERSION}.tar.gz . ; \
|
||||
${PY2DSC} *.tar.gz ;
|
||||
|
||||
edit-source: debianize-source
|
||||
$(info changing build dependencies for ${NAME} ...)
|
||||
@cd ${TARGETDIR}/deb_dist/${NAME}-${VERSION} ; \
|
||||
perl -pi -e 's/python-all-dev/python-dev/' debian/control ; \
|
||||
perl -pi -e ${DEPS_REPLACEMENT} debian/control ; \
|
||||
BUILD_STR=`grep 'binary: build' debian/rules 2>/dev/null` ; \
|
||||
if [ x"$$BUILD_STR" == x ]; then \
|
||||
echo -e "${CONFIG_REPLACEMENT_STUB}" >> debian/rules ; \
|
||||
else \
|
||||
perl -pi -e ${CONF_REPLACEMENT} debian/rules ; \
|
||||
fi
|
||||
|
||||
build: edit-source
|
||||
$(info building ${NAME} version ${VERSION} ...)
|
||||
@cd ${TARGETDIR}/deb_dist/${NAME}-${VERSION} ; \
|
||||
${BUILDCMD} ${BUILDOPTS}
|
||||
|
||||
check-prerequisites:
|
||||
ifeq ($(PY2DSC), )
|
||||
$(error no py2dsc found)
|
||||
else ifeq ($(BUILDCMD), )
|
||||
$(error no dpkg-buildpackage found)
|
||||
else ifeq ($(VERSION), )
|
||||
$(error could not determine version from setup.py)
|
||||
else
|
||||
TARGETDIR:=$(shell mktemp -d)
|
||||
endif
|
||||
|
||||
|
||||
clean:
|
||||
@rm -rf ${NAME}.egg-info
|
||||
@rm -rf dist
|
||||
@rm -rf ${TARGETDIR}
|
||||
@rm -rf debian
|
||||
|
||||
bumpversion:
|
||||
@${EDITOR} setup.py
|
||||
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
|
||||
GitZilla
|
||||
========
|
||||
|
||||
GitZilla is Python magic to support Git-Bugzilla integration. There are
|
||||
various ways of using GitZilla.
|
||||
|
||||
Note that GitZilla must be installed on the machine receiving commits from
|
||||
everyone - home to the the "official" or the "central" repository.
|
||||
|
||||
Simple ready scripts
|
||||
--------------------
|
||||
|
||||
To quickly start using GitZilla:
|
||||
|
||||
* Install GitZilla. You may choose the .deb for easy installation on
|
||||
Debian/Ubuntu systems. Otherwise, just unpack the source and install in
|
||||
the usual setuptools way:
|
||||
|
||||
sudo python setup.py install
|
||||
|
||||
* Switch to the hooks directory (/path/to/repository/.git/hooks) and delete
|
||||
the 'post-receive' and 'update' hooks.
|
||||
|
||||
* Link (or copy) the gitzilla provided hooks:
|
||||
|
||||
ln -s $(which gitzilla-post-receive) post-receive
|
||||
ln -s $(which gitzilla-update) update
|
||||
|
||||
* Read and edit the config file at /etc/gitzillarc
|
||||
|
||||
* Commit away!
|
||||
|
||||
|
||||
Custom GitZilla
|
||||
---------------
|
||||
|
||||
Coming soon. Till then, import the modules gitzilla and gitzilla.hooks in a
|
||||
python interactive shell and dooc at the module help.
|
||||
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
|
||||
"""
|
||||
GitZilla
|
||||
|
||||
Git-Bugzilla integration in a Python module.
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
- Python (tested with 2.6, should work with >= 2.5)
|
||||
- pybugz (tested with 0.8.0)
|
||||
|
||||
pybugs can be obtained from http://github.com/ColdWind/pybugz/downloads
|
||||
|
||||
"""
|
||||
|
||||
__version__ = '1.0'
|
||||
__author__ = 'Devendra Gera <gera@theoldmonk.net>'
|
||||
__license__ = """Copyright 2010, Devendra Gera <gera@theoldmonk.net>,
|
||||
All rights reserved.
|
||||
|
||||
This is Free Software, released under the terms of the GNU General Public
|
||||
License, version 3. A copy of the license can be obtained by emailing the
|
||||
author, or from http://www.gnu.org/licenses/gpl-3.0.html
|
||||
|
||||
As noted in the License, this software does not come with any warranty,
|
||||
explicit or implied, to the extent permissible by law.
|
||||
This program might, and would be buggy. Use it at your own risk.
|
||||
"""
|
||||
|
||||
sDefaultSeparator = "~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~."
|
||||
|
||||
sDefaultFormatSpec = """
|
||||
commit %H
|
||||
parents %P
|
||||
Author %aN (%aE)
|
||||
Date %aD
|
||||
Commit By %cN (%cE)
|
||||
Commit Date %cD
|
||||
|
||||
%s
|
||||
|
||||
%b
|
||||
""".replace("\n", "%n")
|
||||
|
||||
import re
|
||||
|
||||
oDefaultBugRegex = re.compile(r"bug\s*(?:#|)\s*(?P<bug>\d+)",
|
||||
re.MULTILINE | re.DOTALL | re.IGNORECASE)
|
||||
|
||||
import logging
|
||||
|
||||
class NullHandler(logging.Handler):
|
||||
def emit(self, record):
|
||||
pass
|
||||
|
||||
NullLogger = logging.getLogger("gitzilla")
|
||||
NullLogger.addHandler(NullHandler())
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
|
||||
# The gitzilla config file.
|
||||
# This file is in the ConfigParser format. This is something like:
|
||||
#
|
||||
# [Section_Name]
|
||||
# item: value
|
||||
# another_item: value2
|
||||
#
|
||||
|
||||
|
||||
# Each git repository should have it's own section. The global config
|
||||
# at /etc/gitzillarc MUST specify bugzilla_url, bugzilla_user and
|
||||
# bugzilla_password
|
||||
#
|
||||
# The bugzilla_user and bugzilla_password may be overridden by user
|
||||
# specific config files at ~/.gitzillarc
|
||||
#
|
||||
# Note that the global config would be readable by all and is required
|
||||
# to contain a username/password for bugzilla. If you think this is a
|
||||
# problem, you could put in dummy values. In that case however, users
|
||||
# MUST put their own credentials in their ~/.gitzillarc files if the
|
||||
# update hook is being used with the allowed_bug_states option set. If
|
||||
# that is not the case, users can get away by not having their
|
||||
# credentials available, and their commits would not show up in bugziila
|
||||
# comments.
|
||||
#
|
||||
# The format of the user specific files is the same, and they must
|
||||
# have a section for each repository to be configured.
|
||||
#
|
||||
# Mandatory values for /etc/gitzillarc:
|
||||
#
|
||||
# * bugzilla_url
|
||||
# * bugzilla_user
|
||||
# * bugzilla_password
|
||||
#
|
||||
#
|
||||
# Optional values for /etc/gitzillarc:
|
||||
#
|
||||
# * allowed_bug_states
|
||||
#
|
||||
# a comma separated set of states that a bug must be in, in order
|
||||
# for the commit to be allowed by the update hook. If this is set,
|
||||
# working bugzilla credentials are required.
|
||||
#
|
||||
# * formatspec
|
||||
#
|
||||
# appended to '--format=format:' in 'git whatchanged'. See the
|
||||
# 'git whatchanged' manpage for more info.
|
||||
#
|
||||
# * separator
|
||||
#
|
||||
# a string which would never occur in commit messages. You should
|
||||
# not need to set this, as it is already at a dafe default.
|
||||
#
|
||||
# * bug_regex
|
||||
#
|
||||
# the (Python) regex for capturing bug numbers. MUST capture all
|
||||
# the digits of the bug id in a named group called 'bug'. This
|
||||
# regex is compiled internally with the MULTILINE, DOTALL, and
|
||||
# IGNORECASE options set. The default regex captures the
|
||||
# following forms:
|
||||
# - bug 123
|
||||
# - Bug # 123
|
||||
# - BUG123
|
||||
# - bug# 123
|
||||
# - Bug #123
|
||||
#
|
||||
# * logfile
|
||||
#
|
||||
# the file to log to. Must be writable by the uid of the git
|
||||
# process. In case of ssh pushes, it usually means that it should
|
||||
# be writable by all.
|
||||
#
|
||||
# * loglevel
|
||||
#
|
||||
# can be 'info' or 'debug' - defaults to 'debug'.
|
||||
#
|
||||
#
|
||||
#
|
||||
# The user specific files are entirely optional. The only values
|
||||
# they override are bugzilla_user and bugzilla_password.
|
||||
#
|
||||
|
||||
# sample configuration:
|
||||
#
|
||||
# [/path/to/repository/.git]
|
||||
# bugzilla_url: https://repo.example.com/bugzilla/
|
||||
# bugzilla_user: foo@example.com
|
||||
# bugzilla_password: barbarblah
|
||||
|
|
@ -0,0 +1,173 @@
|
|||
|
||||
"""
|
||||
hooks - git hooks provided by gitzilla.
|
||||
|
||||
"""
|
||||
|
||||
import re
|
||||
import sys
|
||||
from utils import get_changes, post_to_bugzilla, get_bug_status, notify_and_exit
|
||||
from gitzilla import sDefaultSeparator, sDefaultFormatSpec, oDefaultBugRegex
|
||||
from gitzilla import NullLogger
|
||||
import bugz.bugzilla
|
||||
import traceback
|
||||
|
||||
|
||||
def post_receive(sBZUrl, sBZUser, sBZPasswd, sFormatSpec=None, oBugRegex=None, sSeparator=None, logger=None):
|
||||
"""
|
||||
a post-recieve hook handler which extracts bug ids and adds the commit
|
||||
info to the comment. If multiple bug ids are found, the comment is added
|
||||
to each of those bugs.
|
||||
|
||||
sBZUrl is the base URL for the Bugzilla installation.
|
||||
|
||||
oBugRegex specifies the regex used to search for the bug id in the commit
|
||||
messages. It MUST provide a named group called 'bug' which contains the bug
|
||||
id (all digits only). If oBugRegex is None, a default bug regex is used,
|
||||
which is:
|
||||
|
||||
r"bug\s*(?:#|)\s*(?P<bug>\d+)"
|
||||
|
||||
This matches forms such as:
|
||||
- bug 123
|
||||
- bug #123
|
||||
- BUG # 123
|
||||
- Bug#123
|
||||
- bug123
|
||||
|
||||
The format spec is appended to "--format=format:" and passed to
|
||||
"git whatchanged". See the git whatchanged manpage for more info on the
|
||||
format spec.
|
||||
|
||||
If sFormatSpec is None, a default format spec is used.
|
||||
|
||||
The separator is a string that would never occur in a commit message.
|
||||
If sSeparator is None, a default separator is used, which should be
|
||||
good enough for everyone.
|
||||
|
||||
If a logger is provided, it would be used for all the logging. If logger
|
||||
is None, logging will be disabled. The logger must be a Python
|
||||
logging.Logger instance.
|
||||
"""
|
||||
if sFormatSpec is None:
|
||||
sFormatSpec = sDefaultFormatSpec
|
||||
|
||||
if sSeparator is None:
|
||||
sSeparator = sDefaultSeparator
|
||||
|
||||
if oBugRegex is None:
|
||||
oBugRegex = oDefaultBugRegex
|
||||
|
||||
if logger is None:
|
||||
logger = NullLogger
|
||||
|
||||
sPrevRev = None
|
||||
for sLine in iter(sys.stdin.readline, ""):
|
||||
(sOldRev, sNewRev, sRefName) = sLine.split(" ")
|
||||
if sPrevRev is None:
|
||||
sPrevRev = sOldRev
|
||||
logger.debug("oldrev: '%s', newrev: '%s'", (sOldRev, sNewRev))
|
||||
asChangeLogs = get_changes(sOldRev, sNewRev, sFormatSpec, sSeparator)
|
||||
|
||||
for sMessage in asChangeLogs:
|
||||
logger.debug("Considering commit:\n%s", (sMessage,))
|
||||
oMatch = re.search(oBugRegex, sMessage)
|
||||
if oMatch is None:
|
||||
logger.info("Bug id not found in commit:\n%s", (sMessage,))
|
||||
continue
|
||||
for oMatch in re.finditer(oBugRegex, sMessage):
|
||||
iBugId = int(oMatch.group("bug"))
|
||||
logger.debug("Found bugid %d", (iBugId,))
|
||||
try:
|
||||
post_to_bugzilla(iBugId, sMessage, sBZUrl, sBZUser, sBZPasswd)
|
||||
except Exception, e:
|
||||
logger.exception("Could not add comment to bug %d", (iBugId,))
|
||||
|
||||
|
||||
|
||||
def update(oBugRegex=None, asAllowedStatuses=None, sSeparator=None, sBZUrl=None, sBZUser=None, sBZPasswd=None, logger=None):
|
||||
"""
|
||||
an update hook handler which rejects commits without a bug reference.
|
||||
This looks at the sys.argv array, so make sure you don't modify it before
|
||||
calling this function.
|
||||
|
||||
oBugRegex specifies the regex used to search for the bug id in the commit
|
||||
messages. It MUST provide a named group called 'bug' which contains the bug
|
||||
id (all digits only). If oBugRegex is None, a default bug regex is used,
|
||||
which is:
|
||||
|
||||
r"bug\s*(?:#|)\s*(?P<bug>\d+)"
|
||||
|
||||
This matches forms such as:
|
||||
- bug 123
|
||||
- bug #123
|
||||
- BUG # 123
|
||||
- Bug#123
|
||||
- bug123
|
||||
|
||||
asAllowedStatuses is an array containing allowed statuses for the found
|
||||
bugs. If a bug is not in one of these states, the commit will be rejected.
|
||||
If asAllowedStatuses is None, status checking is diabled.
|
||||
|
||||
The separator is a string that would never occur in a commit message.
|
||||
If sSeparator is None, a default separator is used, which should be
|
||||
good enough for everyone.
|
||||
|
||||
If status checking is enabled, sBZUrl specifies the base URL for the
|
||||
Bugzilla installation.
|
||||
|
||||
If a logger is provided, it would be used for all the logging. If logger
|
||||
is None, logging will be disabled. The logger must be a Python
|
||||
logging.Logger instance.
|
||||
"""
|
||||
if oBugRegex is None:
|
||||
oBugRegex = oDefaultBugRegex
|
||||
|
||||
if sSeparator is None:
|
||||
sSeparator = sDefaultSeparator
|
||||
|
||||
if logger is None:
|
||||
logger = NullLogger
|
||||
|
||||
sFormatSpec = sDefaultFormatSpec
|
||||
|
||||
if asAllowedStatuses is not None:
|
||||
# sanity checking
|
||||
for item in (sBZUrl, sBZUser):
|
||||
if item is None:
|
||||
raise ValueError("Bugzilla info required for status checks")
|
||||
|
||||
# create and cache bugzilla instance
|
||||
oBZ = bugz.bugzilla.Bugz(sBZUrl, user=sBZUser, password=sBZPasswd)
|
||||
|
||||
(sOldRev, sNewRev) = sys.argv[2:4]
|
||||
logger.debug("oldrev: '%s', newrev: '%s'", (sOldRev, sNewRev))
|
||||
|
||||
asChangeLogs = get_changes(sOldRev, sNewRev, sFormatSpec, sSeparator)
|
||||
|
||||
for sMessage in asChangeLogs:
|
||||
logger.debug("Checking for bug refs in commit:\n%s", (sMessage,))
|
||||
oMatch = re.search(oBugRegex, sMessage)
|
||||
if oMatch is None:
|
||||
logger.error("No bug ref found in commit:\n%s", (sMessage,))
|
||||
print "No bug ref found in commit:\n%s" % (sMessage,)
|
||||
sys.exit(1)
|
||||
else:
|
||||
if asAllowedStatuses is not None:
|
||||
# check all bug statuses
|
||||
for oMatch in re.finditer(oBugRegex, sMessage):
|
||||
iBugId = int(oMatch.group("bug"))
|
||||
logger.debug("Found bug id %d", (iBugId,))
|
||||
try:
|
||||
sStatus = get_bug_status(oBZ, iBugId)
|
||||
if sStatus is None:
|
||||
notify_and_exit("Bug %d does not exist" % (iBugId,))
|
||||
except Exception, e:
|
||||
logger.exception("Could not get status for bug %d", (iBugId,))
|
||||
notify_and_exit("Could not get staus for bug %d" % (iBugId,))
|
||||
|
||||
logger.debug("status for bug %d is %s", (iBugId, sStatus))
|
||||
if sStatus not in asAllowedStatuses:
|
||||
logger.info("Cannot accept commit for bug %d in state %s", (iBugId, sStatus))
|
||||
notify_and_exit("Bug %d['%s'] is not in %s" % (iBugId, sStatus, asAllowedStatuses))
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
|
||||
"""
|
||||
hookscripts - ready to use hook scripts for gitzilla.
|
||||
|
||||
These pick up configuration values from the environment.
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import gitzilla.hooks
|
||||
import logging
|
||||
import ConfigParser
|
||||
|
||||
def get_or_default(conf, section, option, default=None):
|
||||
if conf.has_option(section, option):
|
||||
return conf.get(section, option)
|
||||
return None
|
||||
|
||||
|
||||
def get_bz_data(siteconfig, userconfig):
|
||||
sRepo = os.getcwd()
|
||||
|
||||
try:
|
||||
sBZUrl = siteconfig.get(sRepo, "bugzilla_url")
|
||||
sBZUser = siteconfig.get(sRepo, "bugzilla_user")
|
||||
sBZPasswd = siteconfig.get(sRepo, "bugzilla_password")
|
||||
except:
|
||||
print "missing/incomplete bugzilla conf"
|
||||
sys.exit(1)
|
||||
|
||||
if userconfig.has_section(sRepo):
|
||||
if userconfig.has_option(sRepo, "bugzilla_user") and \
|
||||
userconfig.has_option(sRepo, "bugzilla_password"):
|
||||
sBZUser = userconfig.get(sRepo, "bugzilla_user")
|
||||
sBZPasswd = userconfig.get(sRepo, "bugzilla_password")
|
||||
|
||||
return (sBZUrl, sBZUser, sBZPasswd)
|
||||
|
||||
|
||||
|
||||
def get_logger(siteconfig):
|
||||
sRepo = os.getcwd()
|
||||
logger = None
|
||||
if siteconfig.has_option(sRepo, "logfile"):
|
||||
logger = logging.getLogger("gitzilla")
|
||||
logger.addHandler(logging.FileHandler(siteconfig.get(sRepo, "logfile")))
|
||||
# default to debug, but switch to info if asked.
|
||||
sLogLevel = get_or_default(siteconfig, sRepo, "loglevel", "debug")
|
||||
logger.setLevel({"info": logging.INFO}.get(sLogLevel, logging.DEBUG))
|
||||
|
||||
return logger
|
||||
|
||||
|
||||
def get_bug_regex(siteconfig):
|
||||
sRepo = os.getcwd()
|
||||
oBugRegex = None
|
||||
if siteconfig.has_option(sRepo, "bug_regex"):
|
||||
oBugRegex = re.compile(siteconfig.get(sRepo, "bug_regex"),
|
||||
re.MULTILINE | re.DOTALL | re.IGNORECASE)
|
||||
|
||||
return oBugRegex
|
||||
|
||||
|
||||
|
||||
|
||||
def post_receive():
|
||||
"""
|
||||
The gitzilla-post-receive hook script.
|
||||
|
||||
The configuration is picked up from /etc/gitzillarc and ~/.gitzillarc
|
||||
|
||||
The user specific configuration is allowed to override the bugzilla
|
||||
username and password.
|
||||
"""
|
||||
siteconfig = ConfigParser.SafeConfigParser()
|
||||
siteconfig.readfp(file("/etc/gitzillarc"))
|
||||
sRepo = os.getcwd()
|
||||
|
||||
if not siteconfig.has_section(sRepo):
|
||||
print "No %s section found in /etc/gitzillarc" % (sRepo,)
|
||||
sys.exit(1)
|
||||
|
||||
userconfig = ConfigParser.SafeConfigParser()
|
||||
userconfig.read(os.path.expanduser("~/.gitzillarc"))
|
||||
|
||||
(sBZUrl, sBZUser, sBZPasswd) = get_bz_data(siteconfig, userconfig)
|
||||
|
||||
logger = get_logger(siteconfig)
|
||||
oBugRegex = get_bug_regex(siteconfig)
|
||||
sSeparator = get_or_default(siteconfig, sRepo, "separator")
|
||||
sFormatSpec = get_or_default(siteconfig, sRepo, "formatspec")
|
||||
|
||||
gitzilla.hooks.post_receive(sBZUrl, sBZUser, sBZPasswd, sFormatSpec,
|
||||
oBugRegex, sSeparator, logger)
|
||||
|
||||
|
||||
|
||||
def update():
|
||||
"""
|
||||
The gitzilla-update hook script.
|
||||
|
||||
The configuration is picked up from /etc/gitzillarc and ~/.gitzillarc
|
||||
|
||||
The user specific configuration is allowed to override the bugzilla
|
||||
username and password.
|
||||
"""
|
||||
siteconfig = ConfigParser.SafeConfigParser()
|
||||
siteconfig.readfp(file("/etc/gitzillarc"))
|
||||
sRepo = os.getcwd()
|
||||
|
||||
if not siteconfig.has_section(sRepo):
|
||||
print "No %s section found in /etc/gitzillarc" % (sRepo,)
|
||||
sys.exit(1)
|
||||
|
||||
logger = get_logger(siteconfig)
|
||||
oBugRegex = get_bug_regex(siteconfig)
|
||||
sSeparator = get_or_default(siteconfig, sRepo, "separator")
|
||||
sFormatSpec = get_or_default(siteconfig, sRepo, "formatspec")
|
||||
sBZUrl = None
|
||||
sBZUser = None
|
||||
sBZPasswd = None
|
||||
|
||||
asAllowedStatuses = None
|
||||
if siteconfig.has_option(sRepo, "allowed_bug_states"):
|
||||
asAllowedStatuses = map(lambda x: x.strip(),
|
||||
siteconfig.get(sRepo, "allowed_bug_states").split(","))
|
||||
|
||||
# and then we need the bugzilla info as well.
|
||||
userconfig = ConfigParser.SafeConfigParser()
|
||||
userconfig.read(os.path.expanduser("~/.gitzillarc"))
|
||||
(sBZUrl, sBZUser, sBZPasswd) = get_bz_data(siteconfig, userconfig)
|
||||
|
||||
|
||||
gitzilla.hooks.update(oBugRegex, asAllowedStatuses, sSeparator,
|
||||
sBZUrl, sBZUser, sBZPasswd, logger)
|
||||
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
# fix broken behaviour - hardlinks are a FS attribute, not an OS attribute
|
||||
# without doing this, the builds fail on encfs, AFS, NFS etc.
|
||||
import os
|
||||
if hasattr(os, 'link'):
|
||||
delattr(os, 'link')
|
||||
|
||||
from setuptools import setup
|
||||
args = dict(
|
||||
name='gitzilla',
|
||||
description='Git-Bugzilla integration',
|
||||
author='Devendra Gera',
|
||||
author_email='gera@theoldmonk.net',
|
||||
url='http://www.theoldmonk.net/gitzilla/',
|
||||
version='1.0',
|
||||
requires=['pybugz'],
|
||||
package_dir={'gitzilla': '.'},
|
||||
packages=['gitzilla'],
|
||||
package_data={'': ['etc/*']},
|
||||
include_package_data=True,
|
||||
entry_points={
|
||||
'console_scripts': [
|
||||
'gitzilla-post-receive = gitzilla.hookscripts:post_receive',
|
||||
'gitzilla-update = gitzilla.hookscripts:update',
|
||||
],
|
||||
}
|
||||
)
|
||||
|
||||
setup(**args)
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
|
||||
"""
|
||||
utils module for gitzilla
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import bugz.bugzilla
|
||||
|
||||
|
||||
def execute(asCommand, bSplitLines=False, bIgnoreErrors=False):
|
||||
"""
|
||||
Utility function to execute a command and return the output.
|
||||
"""
|
||||
p = subprocess.Popen(asCommand,
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
shell=False,
|
||||
close_fds=True,
|
||||
universal_newlines=True,
|
||||
env=None)
|
||||
if bSplitLines:
|
||||
data = p.stdout.readlines()
|
||||
else:
|
||||
data = p.stdout.read()
|
||||
iRetCode = p.wait()
|
||||
if iRetCode and not bIgnoreErrors:
|
||||
print >>sys.stderr, 'Failed to execute command: %s\n%s' % (command, data)
|
||||
sys.exit(-1)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
|
||||
def get_changes(sOldRev, sNewRev, sFormatSpec, sSeparator):
|
||||
"""
|
||||
returns an array of chronological changes, between sOldRev and sNewRev,
|
||||
according to the format spec sFormatSpec.
|
||||
"""
|
||||
sChangeLog = execute(["git", "whatchanged",
|
||||
"--format=format:%s%s" % (sSeparator, sFormatSpec),
|
||||
"%s..%s" % (sOldRev, sNewRev)])
|
||||
asChangeLogs = sChangeLog.split(sSeparator)
|
||||
asChangeLogs.reverse()
|
||||
|
||||
return asChangeLogs[:-1]
|
||||
|
||||
|
||||
|
||||
def post_to_bugzilla(iBugId, sComment, sBZUrl, sBZUser, sBZPasswd):
|
||||
"""
|
||||
posts the comment to the given bug id.
|
||||
"""
|
||||
for item in (sBZUrl, sBZUser, sBZPasswd):
|
||||
if item is None:
|
||||
raise ValueError("Bad bugzilla info")
|
||||
|
||||
oBZ = bugz.bugzilla.Bugz(sBZUrl, user=sBZUser, password=sBZPasswd)
|
||||
oBZ.modify(iBugId, comment=sComment)
|
||||
|
||||
|
||||
|
||||
def get_bug_status(oBugz, iBugId):
|
||||
"""
|
||||
given the bugz.bugzilla.Bugz instance and the bug id, returns the bug
|
||||
status.
|
||||
"""
|
||||
oBug = oBugz.get(iBugId)
|
||||
if oBug is None:
|
||||
return None
|
||||
return oBug.getroot().find("bug/bug_status").text
|
||||
|
||||
|
||||
def notify_and_exit(sMsg):
|
||||
"""
|
||||
notifies the error and exits.
|
||||
"""
|
||||
print """
|
||||
|
||||
======================================================================
|
||||
Cannot accept commit.
|
||||
|
||||
%s
|
||||
|
||||
======================================================================
|
||||
|
||||
""" % (sMsg,)
|
||||
sys.exit(1)
|
||||
|
Loading…
Reference in New Issue