grim/hggravatar

13a2db7b58db
add support for setting themes, sizes, and ratings
# vi:et:ts=4 st=4 sts=4
import errno
import hashlib
import json
import os
import os.path
from mercurial.i18n import _
from mercurial import (
cmdutil,
error,
registrar,
scmutil,
util,
)
from mercurial.utils import stringutil
urlreq = util.urlreq
urlencode = urlreq.urlencode
cmdtable = {}
command = registrar.command(cmdtable)
def find_authors(ui, repo, *pats, **opts):
ui.write('caching authors ... ')
# now walk the dag
m = scmutil.match(repo[None], pats, opts)
authors = {}
def prep(ctx, fns):
"""callback for cmdutil.walkchangerevs that just adds unique email
address to the authors dict."""
email = stringutil.email(ctx.user())
normalized = email.lower().strip()
if not email in authors:
authors[email] = hashlib.md5(normalized).hexdigest()
for ctx in cmdutil.walkchangerevs(repo, m, opts, prep):
# we handle everything in the callback closure so nothing to do here
continue
try:
os.makedirs(opts.get('output'))
except os.error as err:
if err.errno != errno.EEXIST:
raise
map_file = os.path.join(opts.get('output'), 'author_map')
with open(map_file, 'w') as ofp:
json.dump(authors, ofp, indent=2)
ui.write('done.\n')
return authors
def save_avatars(ui, repo, authors, *pats, **opts):
"""this function downloads all the avatars and stores them in the output
directory as pngs. """
url = opts.get('url')
params = {}
rating = opts.get('rating')
if rating != '':
params['r'] = rating
size = opts.get('size')
if size != '':
params['s'] = size
theme = opts.get('theme')
if theme != '':
params['d'] = theme
qs = urlencode(params)
for author, key in authors.items():
ui.write('downloading image for %s ... ' % author)
filename = '%s.png' % key
uri = os.path.join(url, filename)
if qs != '':
uri += '?' + qs
img = urlreq.urlopen(uri)
if img.getcode() != 200:
img.close()
ui.write('failed.\n')
continue
with open(os.path.join(opts.get('output'), filename), 'w') as ofp:
ofp.write(img.read())
img.close()
ui.write('done.\n')
def validate_arguments(**opts):
rating = opts.get('rating')
valid = ['g', 'pg', 'r', 'x']
if rating != '' and not rating in valid:
raise error.Abort(_('invalid rating %s, accepted values are %s' % (rating, ', '.join(valid))))
size = opts.get('size')
if size != '':
try:
sz = int(size)
if sz < 1 or sz > 2048:
raise error.Abort(_('invalid size %d, it much be between 1 and 2048' % sz))
except ValueError:
raise error.Abort(_('invalid size %s, it is not an integer between 1 and 2048' % size))
theme = opts.get('theme')
valid = ['404', 'mp', 'identicon', 'monsterid', 'wavatar', 'retro', 'robohash', 'blank']
if theme != '' and not theme in valid:
raise error.Abort(_('invalid theme %s, accepted values are %s' % (theme, ', '.join(valid))))
@command(
'gravatar',
[
('o', 'output', '.hg/cache/gravatar/', _('output directory'), _('DIR')),
('r', 'rating', '', _('rating'), _('RATING')),
('s', 'size', '', _('size'), _('SIZE')),
('t', 'theme', '', _('theme'), _('THEME')),
('u', 'url', 'https://www.gravatar.com/avatar', _('gravatar url'), _('URL')),
],
_("hg gravatar [-u URL] [-o DIR]"),
inferrepo=True,
)
def gravatar(ui, repo, *pats, **opts):
validate_arguments(**opts)
authors = find_authors(ui, repo, *pats, **opts)
save_avatars(ui, repo, authors, *pats, **opts)