summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xgitnoti.py108
1 files changed, 108 insertions, 0 deletions
diff --git a/gitnoti.py b/gitnoti.py
new file mode 100755
index 0000000..4b5d27e
--- /dev/null
+++ b/gitnoti.py
@@ -0,0 +1,108 @@
+#!/usr/bin/env python
+
+import git, os, sys
+from optparse import OptionParser
+from twisted.words.protocols import irc
+from twisted.internet import reactor, protocol
+from twisted.internet.task import LoopingCall
+
+parser = OptionParser()
+parser.add_option('-s', '--host')
+parser.add_option('-n', '--nick', default = 'git')
+parser.add_option('-d', '--dir')
+parser.add_option('-c', '--channel')
+
+(options, args) = parser.parse_args()
+
+if not options.host or not options.dir or not options.channel or not options.nick:
+ parser.print_help()
+ sys.exit(1)
+
+root = options.dir
+
+repos = None
+
+def repo_commit_msg(repo, commit):
+ stat = '%d files,' % commit.stats.total['files']
+ stat += ' \00305--%d\017' % commit.stats.total['deletions']
+ stat += ' \00303++%d\017' % commit.stats.total['insertions']
+ msg = '\002%s\002 pushed to \002%s\002 by \002%s\002 (%s) %s' % (
+ os.path.basename(repo.path),
+ commit.id_abbrev,
+ commit.committer.name if commit.author.name == commit.committer.name else '%s/%s' % (commit.committer.name, commit.author.name),
+ stat,
+ commit.summary
+ )
+ return msg
+
+def check_repos(bot):
+ global repos
+ repo_paths = [x for x in os.listdir(root) if x.endswith('.git')]
+ if not repos:
+ repos = [[git.Repo('%s/%s' % (root, x)), None] for x in repo_paths]
+ bot.gitmsg('Repos initialized: %s' % (', '.join([os.path.basename(x[0].path) for x in repos])))
+ else:
+ old_paths = [os.path.basename(x[0].path) for x in repos]
+ new_paths = [x for x in repo_paths if not x in old_paths]
+ for n in new_paths:
+ repos.append([git.Repo('%s/%s' % (root, x)), None])
+ if new_paths:
+ bot.gitmsg('New repo%s: %s' % ('' if len(new_paths) == 1 else 's', ', '.join(new_paths)))
+
+ for i, v in enumerate(repos):
+ repo = v[0]
+ last = v[1]
+ if last == None:
+ last = repo.commits()[0].id
+ repos[i][1] = last
+ nlast = repo.commits()[0]
+ if last and nlast.id != last:
+ msg = repo_commit_msg(repo, nlast)
+ bot.gitmsg(msg)
+ repos[i][1] = nlast.id
+
+class Bot(irc.IRCClient):
+ nickname = options.nick
+
+ def gitmsg(self, msg):
+ self.say(options.channel, msg)
+
+ def signedOn(self):
+ self.join(options.channel)
+ self.repeater = LoopingCall(check_repos, self)
+ self.repeater.start(5)
+
+ def privmsg(self, user, channel, message):
+ private = channel == self.nickname
+ target = nick if private else channel
+ nick = user.split('!')[0]
+ messagelist = message.split()
+ if len(messagelist) < 2:
+ return
+ if messagelist[0].startswith(self.nickname):
+ cmd = messagelist[1].lower()
+ if cmd == 'list':
+ s = 'Repos: %s' % ', '.join([os.path.basename(x[0].path) for x in repos])
+ self.msg(target, s)
+ elif cmd == 'last':
+ repo = messagelist[2].lower() if len(messagelist) > 2 else None
+ if not repo:
+ self.msg(target, 'Which repo?')
+ return
+ repo = [r for r in repos if os.path.basename(r[0].path).startswith(repo)]
+ if len(repo) == 1:
+ r = repo[0][0]
+ msg = repo_commit_msg(r, r.commits()[0])
+ self.msg(target, msg)
+ elif len(repo) == 0:
+ self.msg(target, 'No repo found.')
+ else:
+ self.msg(target, 'Ambiguous name: %s' % (', '.join([os.path.basename(x[0].path) for x in repos])))
+
+class BotFactory(protocol.ReconnectingClientFactory):
+ protocol = Bot
+
+if __name__ == '__main__':
+ f = BotFactory()
+ reactor.connectTCP(options.host, 6667, f)
+ reactor.run()