1 # -*- test-case-name: twisted.scripts.test.test_tap2rpm -*-
2 # Copyright (c) Twisted Matrix Laboratories.
3 # See LICENSE for details.
5 import sys, os, shutil, time, glob
9 from StringIO import StringIO
12 from twisted.python import usage, log, versions, deprecate
15 #################################
16 # data that goes in /etc/inittab
20 # Startup script for a Twisted service.
23 # description: Start-up script for the Twisted service "%(tap_file)s".
25 PATH=/usr/bin:/bin:/usr/sbin:/sbin
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
32 # load init function library
33 . /etc/init.d/functions
35 [ -r /etc/default/%(rpm_file)s ] && . /etc/default/%(rpm_file)s
37 # check for required files
38 if [ ! -x /usr/bin/twistd ]
40 echo "$0: Aborting, no /usr/bin/twistd found"
45 echo "$0: Aborting, no file $file found."
49 # set up run directory if necessary
50 if [ ! -d "${rundir}" ]
58 echo -n "Starting %(rpm_file)s: twistd"
62 --%(twistd_option)s=$file \\
68 echo -n "Stopping %(rpm_file)s: twistd"
69 kill `cat "${pidfile}"`
79 echo "Usage: ${0} {start|stop|restart|}" >&2
87 #######################################
88 # the data for creating the spec file
90 Summary: %(description)s
95 Group: Networking/Daemons
96 Source: %(tarfile_basename)s
97 BuildRoot: %%{_tmppath}/%%{name}-%%{version}-root
98 Requires: /usr/bin/twistd
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"
118 [ ! -z "$RPM_BUILD_ROOT" -a "$RPM_BUILD_ROOT" != '/' ] \
119 && rm -rf "$RPM_BUILD_ROOT"
122 /sbin/chkconfig --add %(rpm_file)s
123 /sbin/chkconfig --level 35 %(rpm_file)s
124 /etc/init.d/%(rpm_file)s start
127 /etc/init.d/%(rpm_file)s stop
128 /sbin/chkconfig --del %(rpm_file)s
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
136 * %(date)s %(maintainer)s
137 - Created by tap2rpm: %(rpm_file)s (%(version)s)
140 ###############################
141 class MyOptions(usage.Options):
142 optFlags = [['quiet', 'q']]
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'"],
156 compData = usage.Completions(
157 optActions={"type": usage.CompleteList(["tap", "xml", "source",
159 "rpmfile": usage.CompleteFiles("*.rpm")}
162 def postOptions(self):
164 Calculate the default values for certain command-line options.
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'],)
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'])
181 def opt_unsigned(self):
183 Generate an unsigned rather than a signed RPM. (DEPRECATED; unsigned
186 msg = deprecate.getDeprecationWarningString(
187 self.opt_unsigned, versions.Version("Twisted", 12, 1, 0))
188 warnings.warn(msg, category=DeprecationWarning, stacklevel=2)
190 # Maintain the -u short flag
203 ##########################
206 Set up the temporary directory for building RPMs.
208 Returns: buildDir, a randomly-named subdirectory of baseDir.
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'))
218 log.msg(format="Created RPM build structure in %(path)r",
224 def setupBuildFiles(buildDir, config):
226 Create files required to build an RPM in the build directory.
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")
233 sourceDirInfo = tarfile.TarInfo(config['release-name'])
234 sourceDirInfo.type = tarfile.DIRTYPE
235 sourceDirInfo.mode = 0755
236 tarballHandle.addfile(sourceDirInfo)
238 tapFileBase = os.path.basename(config['tapfile'])
240 initFileInfo = tarfile.TarInfo(
242 config['release-name'],
243 '%s.init' % config['rpmfile'],
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'],
253 initFileInfo.size = len(initFileRealData)
254 tarballHandle.addfile(initFileInfo, StringIO(initFileRealData))
256 tapFileHandle = open(config['tapfile'], 'rb')
257 tapFileInfo = tarballHandle.gettarinfo(
258 arcname=os.path.join(config['release-name'], tapFileBase),
259 fileobj=tapFileHandle,
261 tapFileInfo.mode = 0644
262 tarballHandle.addfile(tapFileInfo, tapFileHandle)
264 tarballHandle.close()
266 log.msg(format="Created dummy source tarball %(tarballPath)r",
267 tarballPath=tarballPath)
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'],
283 specHandle.write(specFileRealData)
286 log.msg(format="Created RPM spec file %(specPath)r",
293 def run(options=None):
297 config.parseOptions(options)
298 except usage.error, ue:
299 sys.exit("%s: %s" % (sys.argv[0], ue))
301 # create RPM build environment
302 tmpDir = makeBuildDir()
303 specPath = setupBuildFiles(tmpDir, config)
306 job = subprocess.Popen([
309 "--define", "_topdir %s" % (tmpDir,),
311 ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
312 stdout, _ = job.communicate()
314 # If there was a problem, show people what it was.
315 if job.returncode != 0:
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, '.')
328 # remove the build directory
329 shutil.rmtree(tmpDir)
331 return [os.path.basename(rpmPath), os.path.basename(srpmPath)]