- Author:
- jsandell
- Posted:
- September 20, 2008
- Language:
- Python
- Version:
- 1.0
- Score:
- 3 (after 3 ratings)
I needed a quick way to send e-mails to other people involved in a project when I committed code - so that designers would know that templatetag x was available (or fixed), etc - and am really fond of how unfuddle handles their subversion notifications. This isn't nearly as polished as theirs, but I figured it was a good place to start.
Hope someone else finds this as handy as I have.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | #!/usr/bin/python
# post-commit.py
# symlinked in /path/to/repository/hooks/post-commit
import pysvn
import sys
import os
from datetime import datetime
# Begin Django bootstrap code
# You'll need to change this to match your own specific host /
# development path.
host_dir = '/var/www/hosts/example.com'
site_dir = '%s/site' % host_dir
site_root = '%s/root' % site_dir
# I keep various versions of Django, and supporting Django apps,
# outside of the normal Python path. If you install via setup.py
# you might not need to loop this.
for p in ('/usr/local/codebase/framework',
'/usr/local/codebase/apps',
site_root,
'%s/project' % site_root):
sys.path.append(p)
os.environ['DJANGO_SETTINGS_MODULE'] = 'project.settings'
# End Django bootstrap code
def getChangedFiles(path, revno):
"""
Query svn repository for changes in a given changeset.
"""
client = pysvn.Client()
revision = pysvn.Revision(pysvn.opt_revision_kind.number, revno)
previous = pysvn.Revision(pysvn.opt_revision_kind.number, int(revno)-1)
changes = client.diff_summarize(
url_or_path1 = path,
revision1 = previous,
revision2 = revision,
)
formatted = []
if changes:
for c in changes:
# Create a list of two-tuples, containing the svn 'action'
# (add, delete, modify, etc.) and the file that's been acted upon.
formatted.append(('%s' % c.summarize_kind, '%s' % c.path))
return tuple(formatted)
if __name__ == '__main__':
# We should get something like
# /path/to/repository <revision number>
# i.e., "/var/svn/sites/apps 46"
#
# argv[0], of course, is our script name.
assert len(sys.argv) == 3
# Django imports
from django.core.mail import EmailMessage
from django.template import Context, Template
from django.conf import settings
from django.contrib.sites.models import Site
# Load the svn client
client = pysvn.Client()
# Create a "proper" svn url
repo_url = 'file://%s' % sys.argv[1]
# Get our revision number.
rev = sys.argv[2]
# Send our url and the revision number to getChangedFiles
changes = getChangedFiles(repo_url, rev)
# Only act if there have been changes.
if changes:
# Attempt to ascertain which site this is for.
site = Site.objects.all(pk=settings.SITE_ID)
# Get the 'from' email setting from settings.py
from_email = settings.DEFAULT_FROM_EMAIL
# I'm pulling from 'MANAGERS', which by default is set from
# 'ADMINS', but it could just as easily pull from a database
# query.
admin_list = [mail_tuple[1] for mail_tuple in settings.MANAGERS]
# Get the commit metadata - author, commit date, etc.
log = client.log(repo_url,
revision_start = pysvn.Revision(pysvn.opt_revision_kind.head),
revision_end=pysvn.Revision(pysvn.opt_revision_kind.number,
int(rev)))[0]
# Convert the float timestamp into a UTC datetime object.
stamp = datetime.utcfromtimestamp(log['date'])
# Further convert it into something more human readable.
friendly_date = stamp.strftime('%A %b %d, %Y')
friendly_time = stamp.strftime('%I:%M %P')
# Get the author / committer.
author = log['author']
# Get the commit message
message = log['message']
# Build our template context.
c = Context(dict(
site = site,
author = author,
date = friendly_date,
time = friendly_time,
divider = '-' * 67,
revision = rev,
changes = changes,
message = message,
))
# Create our subject and body templates. We can also use normal
# templates for this, but that goes beyond the context of this
# snippet.
s = Template("Commit for {{ site }}")
b = Template("""Revision: {{ revision }}
Author: {{ author }}
Date: {{ date }} {{ time }}
{{ divider }}
{{ message|default:"(no commit message)" }}
{% for action, path in changes %}
{{ action|capfirst }} {{ path }}{% endfor %}
""")
# Render our templates.
subject = s.render(c)
body = b.render(c)
# Set up our email message.
mail = EmailMessage(subject, body, from_email, admin_list)
# Send using text. Change to 'html' to use rich formatting.
mail.content_subtype = 'plain'
# Send our commit information!
mail.send()
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 10 months, 2 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 2 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
- Help text hyperlinks by sa2812 1 year, 6 months ago
Comments
Please login first before commenting.