Initial import to Tizen
[profile/ivi/python-twisted.git] / twisted / scripts / tap2rpm.py
1 # -*- test-case-name: twisted.scripts.test.test_tap2rpm -*-
2 # Copyright (c) Twisted Matrix Laboratories.
3 # See LICENSE for details.
4
5 import sys, os, shutil, time, glob
6 import subprocess
7 import tempfile
8 import tarfile
9 from StringIO import StringIO
10 import warnings
11
12 from twisted.python import usage, log, versions, deprecate
13
14
15 #################################
16 #  data that goes in /etc/inittab
17 initFileData = '''\
18 #!/bin/sh
19 #
20 #  Startup script for a Twisted service.
21 #
22 #  chkconfig: - 85 15
23 #  description: Start-up script for the Twisted service "%(tap_file)s".
24
25 PATH=/usr/bin:/bin:/usr/sbin:/sbin
26
27 pidfile=/var/run/%(rpm_file)s.pid
28 rundir=/var/lib/twisted-taps/%(rpm_file)s/
29 file=/etc/twisted-taps/%(tap_file)s
30 logfile=/var/log/%(rpm_file)s.log
31
32 #  load init function library
33 . /etc/init.d/functions
34
35 [ -r /etc/default/%(rpm_file)s ] && . /etc/default/%(rpm_file)s
36
37 #  check for required files
38 if [ ! -x /usr/bin/twistd ]
39 then
40         echo "$0: Aborting, no /usr/bin/twistd found"
41         exit 0
42 fi
43 if [ ! -r "$file" ]
44 then
45         echo "$0: Aborting, no file $file found."
46         exit 0
47 fi
48
49 #  set up run directory if necessary
50 if [ ! -d "${rundir}" ]
51 then
52         mkdir -p "${rundir}"
53 fi
54
55
56 case "$1" in
57         start)
58                 echo -n "Starting %(rpm_file)s: twistd"
59                 daemon twistd  \\
60                                 --pidfile=$pidfile \\
61                                 --rundir=$rundir \\
62                                 --%(twistd_option)s=$file \\
63                                 --logfile=$logfile
64                 status %(rpm_file)s
65                 ;;
66
67         stop)
68                 echo -n "Stopping %(rpm_file)s: twistd"
69                 kill `cat "${pidfile}"`
70                 status %(rpm_file)s
71                 ;;
72
73         restart)
74                 "${0}" stop
75                 "${0}" start
76                 ;;
77
78     *)
79                 echo "Usage: ${0} {start|stop|restart|}" >&2
80                 exit 1
81                 ;;
82 esac
83
84 exit 0
85 '''
86
87 #######################################
88 #  the data for creating the spec file
89 specFileData = '''\
90 Summary:    %(description)s
91 Name:       %(rpm_file)s
92 Version:    %(version)s
93 Release:    1
94 License:    Unknown
95 Group:      Networking/Daemons
96 Source:     %(tarfile_basename)s
97 BuildRoot:  %%{_tmppath}/%%{name}-%%{version}-root
98 Requires:   /usr/bin/twistd
99 BuildArch:  noarch
100
101 %%description
102 %(long_description)s
103
104 %%prep
105 %%setup
106 %%build
107
108 %%install
109 [ ! -z "$RPM_BUILD_ROOT" -a "$RPM_BUILD_ROOT" != '/' ] \
110                 && rm -rf "$RPM_BUILD_ROOT"
111 mkdir -p "$RPM_BUILD_ROOT"/etc/twisted-taps
112 mkdir -p "$RPM_BUILD_ROOT"/etc/init.d
113 mkdir -p "$RPM_BUILD_ROOT"/var/lib/twisted-taps
114 cp "%(tap_file)s" "$RPM_BUILD_ROOT"/etc/twisted-taps/
115 cp "%(rpm_file)s.init" "$RPM_BUILD_ROOT"/etc/init.d/"%(rpm_file)s"
116
117 %%clean
118 [ ! -z "$RPM_BUILD_ROOT" -a "$RPM_BUILD_ROOT" != '/' ] \
119                 && rm -rf "$RPM_BUILD_ROOT"
120
121 %%post
122 /sbin/chkconfig --add %(rpm_file)s
123 /sbin/chkconfig --level 35 %(rpm_file)s
124 /etc/init.d/%(rpm_file)s start
125
126 %%preun
127 /etc/init.d/%(rpm_file)s stop
128 /sbin/chkconfig --del %(rpm_file)s
129
130 %%files
131 %%defattr(-,root,root)
132 %%attr(0755,root,root) /etc/init.d/%(rpm_file)s
133 %%attr(0660,root,root) /etc/twisted-taps/%(tap_file)s
134
135 %%changelog
136 * %(date)s %(maintainer)s
137 - Created by tap2rpm: %(rpm_file)s (%(version)s)
138 '''
139
140 ###############################
141 class MyOptions(usage.Options):
142     optFlags = [['quiet', 'q']]
143     optParameters = [
144                      ["tapfile", "t", "twistd.tap"],
145                      ["maintainer", "m", "tap2rpm"],
146                      ["protocol", "p", None],
147                      ["description", "e", None],
148                      ["long_description", "l",
149                          "Automatically created by tap2rpm"],
150                      ["set-version", "V", "1.0"],
151                      ["rpmfile", "r", None],
152                      ["type", "y", "tap", "type of configuration: 'tap', 'xml, "
153                       "'source' or 'python'"],
154                     ]
155
156     compData = usage.Completions(
157         optActions={"type": usage.CompleteList(["tap", "xml", "source",
158                                                 "python"]),
159                     "rpmfile": usage.CompleteFiles("*.rpm")}
160         )
161
162     def postOptions(self):
163         """
164         Calculate the default values for certain command-line options.
165         """
166         # Options whose defaults depend on other parameters.
167         if self['protocol'] is None:
168             base_tapfile = os.path.basename(self['tapfile'])
169             self['protocol'] = os.path.splitext(base_tapfile)[0]
170         if self['description'] is None:
171             self['description'] = "A TCP server for %s" % (self['protocol'],)
172         if self['rpmfile'] is None:
173             self['rpmfile'] = 'twisted-%s' % (self['protocol'],)
174
175         # Values that aren't options, but are calculated from options and are
176         # handy to have around.
177         self['twistd_option'] = type_dict[self['type']]
178         self['release-name'] = '%s-%s' % (self['rpmfile'], self['set-version'])
179
180
181     def opt_unsigned(self):
182         """
183         Generate an unsigned rather than a signed RPM. (DEPRECATED; unsigned
184         is the default)
185         """
186         msg = deprecate.getDeprecationWarningString(
187             self.opt_unsigned, versions.Version("Twisted", 12, 1, 0))
188         warnings.warn(msg, category=DeprecationWarning, stacklevel=2)
189
190     # Maintain the -u short flag
191     opt_u = opt_unsigned
192
193
194 type_dict = {
195     'tap': 'file',
196     'python': 'python',
197     'source': 'source',
198     'xml': 'xml',
199 }
200
201
202
203 ##########################
204 def makeBuildDir():
205     """
206     Set up the temporary directory for building RPMs.
207
208     Returns: buildDir, a randomly-named subdirectory of baseDir.
209     """
210     tmpDir = tempfile.mkdtemp()
211     #  set up initial directory contents
212     os.makedirs(os.path.join(tmpDir, 'RPMS', 'noarch'))
213     os.makedirs(os.path.join(tmpDir, 'SPECS'))
214     os.makedirs(os.path.join(tmpDir, 'BUILD'))
215     os.makedirs(os.path.join(tmpDir, 'SOURCES'))
216     os.makedirs(os.path.join(tmpDir, 'SRPMS'))
217
218     log.msg(format="Created RPM build structure in %(path)r",
219             path=tmpDir)
220     return tmpDir
221
222
223
224 def setupBuildFiles(buildDir, config):
225     """
226     Create files required to build an RPM in the build directory.
227     """
228     # Create the source tarball in the SOURCES directory.
229     tarballName = "%s.tar" % (config['release-name'],)
230     tarballPath = os.path.join(buildDir, "SOURCES", tarballName)
231     tarballHandle = tarfile.open(tarballPath, "w")
232
233     sourceDirInfo = tarfile.TarInfo(config['release-name'])
234     sourceDirInfo.type = tarfile.DIRTYPE
235     sourceDirInfo.mode = 0755
236     tarballHandle.addfile(sourceDirInfo)
237
238     tapFileBase = os.path.basename(config['tapfile'])
239
240     initFileInfo = tarfile.TarInfo(
241             os.path.join(
242                 config['release-name'],
243                 '%s.init' % config['rpmfile'],
244             )
245         )
246     initFileInfo.type = tarfile.REGTYPE
247     initFileInfo.mode = 0755
248     initFileRealData = initFileData % {
249             'tap_file': tapFileBase,
250             'rpm_file': config['release-name'],
251             'twistd_option': config['twistd_option'],
252         }
253     initFileInfo.size = len(initFileRealData)
254     tarballHandle.addfile(initFileInfo, StringIO(initFileRealData))
255
256     tapFileHandle = open(config['tapfile'], 'rb')
257     tapFileInfo = tarballHandle.gettarinfo(
258             arcname=os.path.join(config['release-name'], tapFileBase),
259             fileobj=tapFileHandle,
260         )
261     tapFileInfo.mode = 0644
262     tarballHandle.addfile(tapFileInfo, tapFileHandle)
263
264     tarballHandle.close()
265
266     log.msg(format="Created dummy source tarball %(tarballPath)r",
267             tarballPath=tarballPath)
268
269     # Create the spec file in the SPECS directory.
270     specName = "%s.spec" % (config['release-name'],)
271     specPath = os.path.join(buildDir, "SPECS", specName)
272     specHandle = open(specPath, "w")
273     specFileRealData = specFileData % {
274             'description': config['description'],
275             'rpm_file': config['rpmfile'],
276             'version': config['set-version'],
277             'tarfile_basename': tarballName,
278             'tap_file': tapFileBase,
279             'date': time.strftime('%a %b %d %Y', time.localtime(time.time())),
280             'maintainer': config['maintainer'],
281             'long_description': config['long_description'],
282         }
283     specHandle.write(specFileRealData)
284     specHandle.close()
285
286     log.msg(format="Created RPM spec file %(specPath)r",
287             specPath=specPath)
288
289     return specPath
290
291
292
293 def run(options=None):
294     #  parse options
295     try:
296         config = MyOptions()
297         config.parseOptions(options)
298     except usage.error, ue:
299          sys.exit("%s: %s" % (sys.argv[0], ue))
300
301     #  create RPM build environment
302     tmpDir = makeBuildDir()
303     specPath = setupBuildFiles(tmpDir, config)
304
305     #  build rpm
306     job = subprocess.Popen([
307             "rpmbuild",
308             "-vv",
309             "--define", "_topdir %s" % (tmpDir,),
310             "-ba", specPath,
311         ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
312     stdout, _ = job.communicate()
313
314     # If there was a problem, show people what it was.
315     if job.returncode != 0:
316         print stdout
317
318     #  copy the RPMs to the local directory
319     rpmPath = glob.glob(os.path.join(tmpDir, 'RPMS', 'noarch', '*'))[0]
320     srpmPath = glob.glob(os.path.join(tmpDir, 'SRPMS', '*'))[0]
321     if not config['quiet']:
322         print 'Writing "%s"...' % os.path.basename(rpmPath)
323     shutil.copy(rpmPath, '.')
324     if not config['quiet']:
325         print 'Writing "%s"...' % os.path.basename(srpmPath)
326     shutil.copy(srpmPath, '.')
327
328     #  remove the build directory
329     shutil.rmtree(tmpDir)
330
331     return [os.path.basename(rpmPath), os.path.basename(srpmPath)]