A new version of Tools/scripts/plist

Martin Tournoij carpetsmoker at xs4all.nl
Mon Sep 10 01:46:20 PDT 2007


I've written a replacement for /ports/Tools/scripts/plist, the reason
this is a complete rewrite rather than an update is because I'm not
familair with ruby, and writing a new version in python was faster.

Problems/additions in this rewrite:
- Automaticlly replace the default PLIST_SUB values.

- Sensible sorting of the directory list, the current plist put
	directory's in ths order:
	share/someport/
	share/someport/adir/
	share/someport/adir/foobar
	Which is the reverse of what it should be.

- There are a number of directory's which are always created but
	should not be added to the pkg-plist, I have no idea where these
	directory's come from, see the comment on line 49 of my script.

I wrote this script for personal purposes, but why not let other
people benefit, maybe it can be placed in Tools/scripts? Either
replacing the current plist or alongside it.

Script is attached in this email, or you can view it online if you
like:
http://www.rwxrwxrwx.net/plist.py.txt

Regards,
Martin Tournoij
-------------- next part --------------
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
# -*- coding: utf-8 -*-
#
# $Carpetsmoker: ports/Scripts/plist.py,v 1.2 2007/09/10 08:02:53 carpetsmoker Exp $
#
# Make a pkg-plist.
# Maintained by Martin Tournoij <carpetsmoker at xs4all.nl>
#
# No boring license info, this file is released in public domain, feel
# free to do whatever you want with it (although eating it neither
# supported nor recommended).
#

import re, os, sys
from optparse import OptionParser

def GetMtree(mtree, prefix): #{{{
	''' Read mtree file 
	Arguments:
		mtree - Location to a mtree file
		prefix - prefixed to all entries (Should be a pathname)

	Returns a list.
	'''
	list = [ ]
	prev_prefix = ''
	mtree = open(mtree)
	
	# Skip entries which are unimportant to us.
	for line in mtree:
		if line[0] == '#' or line[0] == '/' or line == '.\n' or line == '\n':
			continue

		# Remove all flags, we don't need them.
		r = re.compile('\s+[\w\=]*$')
		line = r.sub('', line.lstrip())
		line = line.strip()

		if line == '..':
			(cur_prefix, a) = os.path.split(prev_prefix)
			prev_prefix = cur_prefix
		else:
			cur_prefix = os.path.join(prev_prefix, line)
			prev_prefix = cur_prefix
			list.append(cur_prefix)
	
	mtree.close()
	# XXX: This is a list of files that seem to be created always, but
	# how and where?
	# /etc/mtree/BSD.x11.dist lists some of the X11 related dirs, but
	# also many other dirs which are not created, and I can't find any
	# reference to the other files in either /etc/mtree/ or /ports/Mk/
	# We will add them manually for now.
	list.extend ([
		'include/X11',
		'include/X11/bitmaps',
		'lib/X11',
		'lib/X11/app-defaults',
		'lib/X11/fonts',
		'lib/X11/fonts/local',
		'share/locale/be',
		'share/locale/be/LC_MESSAGES',
		'share/locale/ca',
		'share/locale/ca/LC_MESSAGES',
		'share/locale/cs',
		'share/locale/cs/LC_MESSAGES',
		'share/locale/de_AT',
		'share/locale/de_AT/LC_MESSAGES',
		'share/locale/el',
		'share/locale/el/LC_MESSAGES',
		'share/locale/en_AU',
		'share/locale/en_AU/LC_MESSAGES',
		'share/locale/fa_IR',
		'share/locale/fa_IR/LC_MESSAGES',
		'share/locale/fi',
		'share/locale/fi/LC_MESSAGES',
		'share/locale/fr_FR',
		'share/locale/fr_FR/LC_MESSAGES',
		'share/locale/gl',
		'share/locale/gl/LC_MESSAGES',
		'share/locale/ko',
		'share/locale/ko/LC_MESSAGES',
		'share/locale/li',
		'share/locale/li/LC_MESSAGES',
		'share/locale/ne',
		'share/locale/ne/LC_MESSAGES',
		'share/locale/nn',
		'share/locale/nn/LC_MESSAGES',
		'share/locale/no',
		'share/locale/no/LC_MESSAGES',
		'share/locale/pl',
		'share/locale/pl/LC_MESSAGES',
		'share/locale/pt',
		'share/locale/pt/LC_MESSAGES',
		'share/locale/ro',
		'share/locale/ro/LC_MESSAGES',
		'share/locale/sk',
		'share/locale/sk/LC_MESSAGES',
		'share/locale/sl',
		'share/locale/sl/LC_MESSAGES',
		'share/locale/sr',
		'share/locale/sr/LC_MESSAGES',
		'share/locale/tg',
		'share/locale/tg/LC_MESSAGES',
		'share/locale/tk',
		'share/locale/tk/LC_MESSAGES',
		'share/locale/uk',
		'share/locale/uk/LC_MESSAGES',
		'share/locale/uz',
		'share/locale/uz/LC_MESSAGES',
		'share/locale/zh_CN',
		'share/locale/zh_CN/LC_MESSAGES',
		'share/locale/zh_TW',
		'share/locale/zh_TW/LC_MESSAGES',
		'share/pixmaps',
	])

	return list
#}}}
def GetTree(prefix, prev, d, f): #{{{
	''' Return recursive list of files and dirs
	
	Arguments:
		prefix - pathname to get the list of.
		prev, d, and f should not be given, or should be empty, they are
		used in overloading.

	Returns two lists, one with a list of dirs and the other a list of
	files.
	'''
	global opt

	for file in os.listdir(os.path.join(prefix, prev)):
		# Skip these files/dirs, they're added automatically
		if prev[:3] == 'man':
			continue
		if opt.noportdocs and prev.find('share/doc') != -1:
			continue

		path = os.path.join(prev, file)
		if os.path.isdir(os.path.join(prefix, path)):
			if CheckDir(path):
				d.append('@dirrm ' + path)
			GetTree(prefix, path, d, f)
		else:
			f.append(path)
	return d, f
#}}}
def CheckDir(path): #{{{
	''' Check if dir is in mtree
	
	Arguments:
		path - pathname to check
		
	Return False if it found the path in mtree, True if it didn't
	'''
	global mtree

	for m in mtree:
		if path == m:
			return False
		else:
			continue
	return True
#}}}
def ReplaceSub(path, dir=None): #{{{
	''' Replace paths with common PLIST_SUB values
	
	Arguments:
		path - pathname to do the substitution on
		dir - Set this to True if path is a dir
	
	Returns modified path
	'''
	global portname, prefix, opt

	plist_sub = {
		'%%PREFIX%%': prefix,
		'%%LOCALBASE%%': '/usr/local',
		'%%X11BASE%%': '/usr/X11R6',
		'%%DATADIR%%': os.path.join('share/', portname),
		'%%DOCSDIR%%': os.path.join('share/doc/', portname),
		'%%EXAMPLESDIR%%': os.path.join('share/examples/', portname),
		'%%WWWDIR%%': os.path.join('www', portname),
		'%%ETCDIR%%': os.path.join('etc', portname)
		}
	
	for replace, search in plist_sub.iteritems():
		path = path.replace(search, replace)

	if opt.portdocs:
		if dir:
			path = path.replace('@dirrm %%DOCSDIR%%', '%%PORTDOCS%%@dirrm %%DOCSDIR%%')
		else:
			path = path.replace('%%DOCSDIR%%', '%%PORTDOCS%%%%DOCSDIR%%')

	return path
# }}}

parser = OptionParser(usage='usage: %prog [options] prefix')
parser.add_option('-p', action='store', type='string', dest='portname',
	default=None, help='Port name, used to replace default PLIST_SUB values, no replacing will be done if it\'s empty.')
parser.add_option('-d', action='store_true', dest='portdocs',
	default=None, help='Prefix all entries in %%DOCSDIR%% with %%PORTDOCS%%, doesn\'t do anything if -p isn\'t specified or if -n is given.')
parser.add_option('-n', action='store_true', dest='noportdocs',
	default=None, help='Ignore all entries in %%DOCSDIR%%, usefull if you have PORTDOCS defined in your Makefile, doesn\'t do anything if -p isn\'t specified')

(opt, arg) = parser.parse_args()

try:
	prefix = arg[0]
except:
	parser.print_help()
	print 'Error: You must specify a prefix.'
	sys.exit(1)

if not os.path.exists(prefix):
	parser.print_help()
	print 'Error: The prefix"', prefix, '"doesn\'t exist.'
	sys.exit(1)

try:
	portname = opt.portname
except:
	portname = None

mtree = GetMtree('/etc/mtree/BSD.local.dist', prefix)
(dirlist, filelist) = GetTree(prefix, '', d = [ ], f = [ ])
dirlist.reverse()

for f in filelist:
	if portname:
		f = ReplaceSub(f)
	print f

for d in dirlist:
	if portname:
		d = ReplaceSub(d, True)
	print d


More information about the freebsd-ports mailing list