aboutsummaryrefslogtreecommitdiff
blob: fa059efb38f9b0136641e81fe4b0b86e6ee6167a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#	vim:fileencoding=utf-8
# (c) 2011 Michał Górny <mgorny@gentoo.org>
# Released under the terms of the 2-clause BSD license.

import os, os.path

class EbuildRepository(object):
	"""
	A universal class to handle an ebuild repository in a PM-agnostic manner.

	>>> r = EbuildRepository('/usr/portage') # XXX: do not depend on path
	>>> r.repo_name # doctest: +ELLIPSIS
	'...'
	"""

	def __init__(self, path):
		"""
		Instantiate a new EbuildRepository. Read the repository name.

		@param path: path to the repository
		@type path: string
		@raise IOError: for repo_name file operations
		@raise ValueError: if repo_name contents are invalid
		"""
		self.path = path

		rnpath = os.path.join(path, 'profiles', 'repo_name')
		f = open(rnpath, 'r')
		self.repo_name = f.readline().strip()
		f.close()

		catspath = os.path.join(path, 'profiles', 'categories')
		try:
			f = open(catspath, 'r');
			self.categories = [l.strip() for l in f.readlines()]
			f.close()
		except IOError:
			self.categories = []

		if not self.repo_name:
			raise ValueError('Repository %s has invalid name.' % path)

	def get_category_from_path(self, fn):
		head = fn
		while head:
			head, tail = os.path.split(head)
		if tail in ('eclass', 'licenses', 'metadata', 'profiles'):
			return None
		return tail

	def write_files(self, files):
		"""
		Write files to the repository.
		
		@param files: a dict, as returned by L{library.case.TestCase.get_output_files()}
		@type files: dict(string -> stringifiable)
		"""
		newcats = set()
		for fn in files:
			cat = self.get_category_from_path(fn)
			if cat and cat not in self.categories:
				newcats.add(cat)

		self.add_categories(newcats, files)

		for fn, c in files.items():
			fp = os.path.join(self.path, fn)
			if not os.path.exists(os.path.dirname(fp)):
				os.makedirs(os.path.dirname(fp))
			f = open(fp, 'w')
			f.write(bytes(c))
			f.close()

	def remanifest(self, files, pm):
		"""
		Remanifest files in repository.

		@param files: filenames in the repository
		@type files: iterable(string)
		@param pm: the package manager instance
		@type pm: L{PackageManager}
		"""
		dirs = set()
		for fn in files:
			cat = self.get_category_from_path(fn)
			if cat:
				dirs.add(os.path.join(self.path, os.path.dirname(fn)))
		pm.remanifest(dirs)

	def add_categories(self, cats, files):
		"""
		Add categories in to profiles/categories. Update
		the profiles/categories file in C{files}.

		@param cats: categories to add
		@type cats: list(string)
		@param files: the files dict
		@type files: dict(string -> stringifiable)
		"""
		# XXX: profiles/categories can contain new categories already
		# and they may not be in self.categories
		self.categories.extend(cats)
		newcats = '\n'.join(self.categories)
		files[os.path.join('profiles', 'categories')] = newcats

class NewEbuildRepository(EbuildRepository):
	"""
	A subclass of EbuildRepository supporting creating a new repository
	for the test suite (i.e. not requiring repo_name to exist).
	"""

	def __init__(self, path, repo_name):
		"""
		Create a new ebuild repository in C{path}. Name it C{repo_name}.

		@param path: path to the repository
		@type path: string
		@param repo_name: the new repository name
		@type repo_name: string
		"""
		rnpath = os.path.join(path, 'profiles', 'repo_name')
		dirpath = os.path.dirname(rnpath)

		if not os.path.isdir(dirpath): # XXX: poor
			os.makedirs(dirpath)
		f = open(rnpath, 'w')
		f.write(repo_name)
		f.close()

		EbuildRepository.__init__(self, path)