Add add-counts filter
[omc-tools.git] / git-import
1 #! /usr/bin/env python
2 """Import a list of commits specified on the commandline into the license
3 database tables."""
4
5 import mysql.connector, os, re, subprocess, sys
6 import string, random
7
8 if not os.environ.has_key('GIT_DIR'):
9     raise SystemExit, '$GIT_DIR not set'
10
11 Author = re.compile("Author: (.*) <(.*)>")
12 ReviewedBy = re.compile(" *Reviewed-by:")
13 Email = re.compile(".*?([_0-9a-z.-]+@[0-9a-z.-]+).*", re.I)
14
15 # Accented/multi-byte characters we just filter out.
16 Stripchars = ''.join([chr(x) for x in range(128,255)])
17
18 def hackfilter(s):
19     """Gross hack to just filter out the highbit chars we've seen in
20     our commit logs.  :("""
21     return s.translate(None, Stripchars)
22
23 alphabet = string.uppercase + string.lowercase + string.digits
24
25 def makesecret():
26     """Make a password/secret."""
27     return "".join( [ random.choice(alphabet) for i in xrange(20) ] )
28
29 def parse(commit):
30     """Parse a commit message and return a tuple of the email
31     addresses involved, the date of the commit, and the abbreviated
32     text description."""
33     args = ('git', 'log', '-1', '--format=%cI %s', commit)
34     # 0         1         2
35     # 012345678901234567890123456
36     # 2015-05-22T16:15:08+00:00 Commit message text...\n
37     proc = subprocess.Popen(args, stdout=subprocess.PIPE)
38     l = proc.stdout.read()
39     cdate = l[0:10]
40     descrip = hackfilter(l[26:-1])
41     descrip = descrip[:60]
42     proc.wait()
43     names = {}
44     proc = subprocess.Popen(('git', 'show', commit), stdout=subprocess.PIPE)
45     for l in proc.stdout:
46         if ReviewedBy.match(l):
47             # Reviewers are not contributors, skip them.
48             continue
49         m = Author.match(l)
50         if m and m.group(2) not in names:
51             names[hackfilter(m.group(2))] = hackfilter(m.group(1))
52             continue
53         m = Email.match(l)
54         # If matched, and has a domain, and not seen before.
55         if m and m.group(1).find('.') != -1 and m.group(1) not in names:
56             names[hackfilter(m.group(1))] = hackfilter(m.group(1))
57             continue
58     proc.wait()
59     return (names, cdate, descrip)
60
61 #def execute(q, t):
62 #    try:
63 #        cusor.execute(q, t)
64 #    except:
65 #        print "Execute failed. SQL = |", q, '|'
66 #        print "Data follows:\n", t
67
68 dbconfig = {
69         'user': 'license',
70         'password': open('rwpass.txt').read().strip(),
71         'database': 'license'
72         }
73 conn = mysql.connector.connect(**dbconfig)
74 cursor = conn.cursor()
75 userids = {}
76
77 for commit in sys.argv[1:]:
78     names, cdate, descrip = parse(commit)
79     q = 'SELECT cid FROM commits WHERE commit = %s LIMIT 1'
80     cursor.execute(q, (commit,))
81     row = cursor.fetchone()
82     if row and row[0]:
83         sys.stdout.write(commit[:7] + ', ')
84         cid = row[0]
85     else:
86         sys.stdout.write(commit[:7] + '. ')
87         data = { 'commit': commit, 'date': cdate, 'descrip': descrip }
88         t = ("INSERT IGNORE INTO commits (commit, date, descrip) "
89              " VALUES (%(commit)s, %(date)s, %(descrip)s)")
90         try:
91             cursor.execute(t, data)
92         except:
93             print "FAILED\n", "|" + t + "|\n", data
94         cid = cursor.lastrowid
95     q = 'SELECT uid FROM users WHERE email = %s LIMIT 1'
96     for email in names:
97         uid = userids.get(email, None)
98         if not uid:
99             # Not already seen -- try the database
100             try:
101                 cursor.execute(q, (email,))
102                 row = cursor.fetchone()
103             except:
104                 row = None
105             if row:
106                 uid = userids[email] = row[0]
107         if not uid:
108             # Create the user
109             secret = makesecret();
110             data = { 'email': email, 'name': names[email],
111                     'reply': '-', 'secret': secret }
112             t = ("INSERT INTO users (email, name, reply, secret)"
113                  " VALUES (%(email)s, %(name)s, %(reply)s, %(secret)s)")
114             cursor.execute(t, data)
115             conn.commit()
116             cursor.execute(q, (email,))
117             row = cursor.fetchone()
118             if row:
119                 uid = row[0]
120         if not uid:
121             print "Can't find or add", email
122             continue
123         data = { 'cid': cid, 'uid': uid }
124         t = ("INSERT IGNORE INTO log (cid, uid)"
125              " VALUES (%(cid)s, %(uid)s)")
126         cursor.execute(t, data)
127         conn.commit()