]> sigrok.org Git - sigrok-util.git/blame - source/new-driver
sigrok-cross-android: Factor out $REPO_BASE.
[sigrok-util.git] / source / new-driver
CommitLineData
5a7a5f5c 1#!/usr/bin/env python3
0af91589
UH
2##
3## This file is part of the sigrok-util project.
4##
5## Copyright (C) 2012 Bert Vermeulen <bert@biot.com>
6##
7## This program is free software: you can redistribute it and/or modify
8## it under the terms of the GNU General Public License as published by
9## the Free Software Foundation, either version 3 of the License, or
10## (at your option) any later version.
11##
12## This program is distributed in the hope that it will be useful,
13## but WITHOUT ANY WARRANTY; without even the implied warranty of
14## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15## GNU General Public License for more details.
16##
17## You should have received a copy of the GNU General Public License
18## along with this program. If not, see <http://www.gnu.org/licenses/>.
19##
a65d66c0
BV
20
21import os
22import sys
23import tempfile
fe85502e 24from subprocess import Popen, PIPE, check_output
a65d66c0
BV
25import shutil
26import re
27import socket
28import datetime
29
bc02c2bf 30TMPL_AUTOCONF_DRIVER = "SR_DRIVER([{name}], [{short}])\n"
7d787983 31
ad18a0b3 32TMPL_FILES = ('protocol.h', 'protocol.c', 'api.c')
a65d66c0 33
bc02c2bf 34TMPL_HWMAKE_DRIVERLIB = """if HW_{upper}
5b447f4c 35src_libdrivers_la_SOURCES +="""
bc02c2bf 36for tmpl_file in TMPL_FILES:
ad18a0b3 37 TMPL_HWMAKE_DRIVERLIB += " \\\n\tsrc/hardware/{short}/" + tmpl_file
e8ef2b49 38TMPL_HWMAKE_DRIVERLIB += "\nendif\n"
a65d66c0 39
a65d66c0 40
bc02c2bf
DD
41def tmpl(template, names):
42 return template.format(**names)
a65d66c0 43
a65d66c0 44
bc02c2bf
DD
45def tmpl_file(filename, tmpldir, names):
46 with open(os.path.join(tmpldir, filename)) as template:
47 return tmpl(template.read(), names)
a65d66c0
BV
48
49
bc02c2bf 50def new_driver(srcurl, tmpldir, names):
a65d66c0
BV
51 tmp = tempfile.mkdtemp()
52 try:
bc02c2bf 53 process = Popen(['git', 'clone', '--depth=1', srcurl, tmp],
e21df210 54 stdout=PIPE, stderr=PIPE)
617f4da0
AJ
55 out, err = process.communicate()
56 if process.returncode:
a65d66c0 57 raise Exception(err.decode())
bc02c2bf
DD
58 gitdir = tmp
59 do_autoconf(gitdir, names)
60 do_automake(gitdir, names)
61 do_driverskel(gitdir, tmpldir, names)
89b783df 62 make_patch(gitdir, names)
a65d66c0 63 except Exception as e:
bc02c2bf 64 raise
a65d66c0 65 print(e)
e3f27bc0
DD
66 finally:
67 shutil.rmtree(tmp)
a65d66c0
BV
68
69
bc02c2bf
DD
70# add DRIVER entry to configure.ac
71def do_autoconf(gitdir, names):
b63f8cef 72 cacpath = os.path.join(gitdir, 'configure.ac')
a65d66c0
BV
73 configure_ac = open(cacpath).read()
74
a65d66c0 75 out = ''
3e61a9d8
BV
76 state = 'driver'
77 active = False
a65d66c0 78 for line in configure_ac.split('\n')[:-1]:
3e61a9d8 79 if state == 'driver':
fe85502e 80 m = re.match(r'SR_DRIVER\(\[([^\]]+)', line)
a65d66c0 81 if m:
3e61a9d8
BV
82 active = True
83 if active:
84 if (m and m.group(1).upper() > names['name'].upper()) or m is None:
bc02c2bf 85 out += tmpl(TMPL_AUTOCONF_DRIVER, names)
3e61a9d8 86 state = 'done'
fe85502e 87 active = False
a65d66c0
BV
88 out += line + '\n'
89 if state != 'done':
fe85502e 90 raise Exception('No SR_DRIVER entries found in configure.ac')
3e61a9d8 91 open(cacpath, 'w').write(out)
a65d66c0 92
a65d66c0 93
3e61a9d8 94# add HW_ entry to Makefile.am
bc02c2bf 95def do_automake(gitdir, names):
b63f8cef 96 path = os.path.join(gitdir, 'Makefile.am')
a65d66c0
BV
97 hwmake = open(path).read()
98
a65d66c0
BV
99 out = ''
100 state = 'copy'
101 for line in hwmake.split('\n')[:-1]:
fe85502e 102 if state == 'copy' and re.match(r'if\s+HW_\w+$', line):
3e61a9d8
BV
103 state = 'drivers'
104 if state == 'drivers':
fe85502e 105 m = re.match(r'if\s+HW_(\w+)$', line)
d51b5323
BV
106 if m:
107 drv_short = m.group(1)
108 if drv_short > names['upper']:
bc02c2bf 109 out += tmpl(TMPL_HWMAKE_DRIVERLIB, names)
d51b5323 110 state = 'done'
5b447f4c 111 elif not re.match(r'\s*src_libdrivers_la_SOURCES\b|\s*src/hardware/|endif\b', line):
3e61a9d8
BV
112 print("[%s]" % line.strip())
113 # we passed the last entry
bc02c2bf 114 out += tmpl(TMPL_HWMAKE_DRIVERLIB, names)
3e61a9d8 115 state = 'done'
a65d66c0 116 out += line + '\n'
7d787983 117 if state != 'done':
3e61a9d8
BV
118 raise Exception('No "if HW_" markers found in Makefile.am')
119 open(path, 'w').write(out)
a65d66c0
BV
120
121
bc02c2bf 122def do_driverskel(gitdir, tmpldir, names):
b63f8cef 123 drvdir = os.path.join(gitdir, 'src', 'hardware', names['short'])
a65d66c0 124 os.mkdir(drvdir)
bc02c2bf
DD
125 for fname in TMPL_FILES:
126 with open(os.path.join(drvdir, fname), 'w') as outf:
127 outf.write(tmpl_file('drv-{0}'.format(fname), tmpldir, names))
128
129
130def make_patch(gitdir, names):
131 cwd = os.getcwd()
132 try:
133 os.chdir(gitdir)
134 command(['git', 'add', os.path.join('src', 'hardware', names['short'])])
135 cmd = ['git', 'commit',
136 '-m', '%s: Initial driver skeleton.' % names['short'],
137 'configure.ac', 'Makefile.am',
138 os.path.join('src', 'hardware', names['short'])]
139 command(cmd)
140 cmd = ['git', 'format-patch', 'HEAD~1']
141 out, err = Popen(cmd, stdout=PIPE, stderr=PIPE).communicate()
142 if err:
143 raise Exception(err.decode())
144 patch = out.decode().strip()
145 shutil.move(os.path.join(gitdir, patch), cwd)
146 print("Patch {0} has been generated in {1}".format(patch, cwd))
147 finally:
148 os.chdir(cwd)
a65d66c0
BV
149
150
151def command(cmd):
e21df210 152 out, err = Popen(cmd, stderr=PIPE).communicate()
a65d66c0
BV
153 if err:
154 raise Exception(err.decode())
155
156
157def parse_gitconfig():
0af91589 158 try:
fe85502e 159 author = check_output(["git", "config", "user.name"]).decode().strip();
bc02c2bf
DD
160 except:
161 author = None
162 try:
fe85502e 163 email = check_output(["git", "config", "user.email"]).decode().strip();
0af91589 164 except:
bc02c2bf 165 email = None
0af91589 166 return author, email
a65d66c0 167
bc02c2bf 168
a65d66c0
BV
169#
170# main
171#
172
bc02c2bf
DD
173if __name__ == '__main__':
174 from argparse import ArgumentParser
175
176 defaulturl = 'git://sigrok.org/libsigrok'
177 defaultdir = os.path.abspath(os.path.dirname(__file__))
178 author, email = parse_gitconfig()
179
180 parser = ArgumentParser(description='Bootstrap a new sigrok hardware driver')
181 parser.add_argument('name', help='new driver name')
182 parser.add_argument('--giturl', default=defaulturl,
183 help='URL of the libsigrok git repository '
184 '(defaults to {0})'.format(defaulturl))
185 parser.add_argument('--tmpl-dir', default=defaultdir,
186 help='Directory in which the templates are stored '
187 '(defaults to {0})'.format(defaultdir))
188 parser.add_argument('--author', default=author, required=not author,
189 help='User name to write the Copyright lines')
190 parser.add_argument('--email', default=email, required=not email,
191 help='Email address to write the Copyright lines')
192 opts = parser.parse_args()
193
194 if not opts.author or not opts.email:
195 parser.error('Please provide your username and email address, '
196 'or set your git configuration up.')
197 name = opts.name
198 names = {
199 'name': name,
200 'short': re.sub('[^a-z0-9]', '-', name.lower()),
201 'lib': re.sub('[^a-z0-9]', '_', name.lower()),
202 'upper': re.sub('[^A-Z0-9]', '_', name.upper()),
203 'year': datetime.datetime.now().year,
204 'author': opts.author,
205 'email': opts.email,
206 }
207 new_driver(opts.giturl, opts.tmpl_dir, names)
a65d66c0 208