pactest: create packages in memory
[pacman-ng.git] / test / pacman / pmpkg.py
blob8e6d7c4343929610f32600f8c1fa8e19ae860caf
1 #! /usr/bin/python
3 # Copyright (c) 2006 by Aurelien Foret <orelien@chez.com>
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 import os
20 import tempfile
21 import stat
22 import shutil
23 from StringIO import StringIO
24 import tarfile
26 import util
28 class pmpkg(object):
29 """Package object.
31 Object holding data from an Arch Linux package.
32 """
34 def __init__(self, name, version = "1.0-1"):
35 self.path = "" #the path of the generated package
36 # desc
37 self.name = name
38 self.version = version
39 self.desc = ""
40 self.groups = []
41 self.url = ""
42 self.license = []
43 self.arch = ""
44 self.builddate = ""
45 self.installdate = ""
46 self.packager = ""
47 self.size = 0
48 self.csize = 0
49 self.isize = 0
50 self.reason = 0
51 self.md5sum = "" # sync only
52 self.pgpsig = "" # sync only
53 self.replaces = []
54 self.depends = []
55 self.optdepends = []
56 self.conflicts = []
57 self.provides = []
58 # files
59 self.files = []
60 self.backup = []
61 # install
62 self.install = {
63 "pre_install": "",
64 "post_install": "",
65 "pre_remove": "",
66 "post_remove": "",
67 "pre_upgrade": "",
68 "post_upgrade": "",
70 self.path = None
72 def __str__(self):
73 s = ["%s" % self.fullname()]
74 s.append("description: %s" % self.desc)
75 s.append("url: %s" % self.url)
76 s.append("files: %s" % " ".join(self.files))
77 s.append("reason: %d" % self.reason)
78 return "\n".join(s)
80 def fullname(self):
81 """Long name of a package.
83 Returns a string formatted as follows: "pkgname-pkgver".
84 """
85 return "%s-%s" % (self.name, self.version)
87 def filename(self):
88 """File name of a package, including its extension.
90 Returns a string formatted as follows: "pkgname-pkgver.PKG_EXT_PKG".
91 """
92 return "%s%s" % (self.fullname(), util.PM_EXT_PKG)
94 @staticmethod
95 def parse_filename(name):
96 filename = name
97 if filename[-1] == "*":
98 filename = filename.rstrip("*")
99 if filename.find(" -> ") != -1:
100 filename, extra = filename.split(" -> ")
101 elif filename.find("|") != -1:
102 filename, extra = filename.split("|")
103 return filename
105 def makepkg(self, path):
106 """Creates an Arch Linux package archive.
108 A package archive is generated in the location 'path', based on the data
109 from the object.
111 archive_files = []
113 # .PKGINFO
114 data = ["pkgname = %s" % self.name]
115 data.append("pkgver = %s" % self.version)
116 data.append("pkgdesc = %s" % self.desc)
117 data.append("url = %s" % self.url)
118 data.append("builddate = %s" % self.builddate)
119 data.append("packager = %s" % self.packager)
120 data.append("size = %s" % self.size)
121 if self.arch:
122 data.append("arch = %s" % self.arch)
123 for i in self.license:
124 data.append("license = %s" % i)
125 for i in self.replaces:
126 data.append("replaces = %s" % i)
127 for i in self.groups:
128 data.append("group = %s" % i)
129 for i in self.depends:
130 data.append("depend = %s" % i)
131 for i in self.optdepends:
132 data.append("optdepend = %s" % i)
133 for i in self.conflicts:
134 data.append("conflict = %s" % i)
135 for i in self.provides:
136 data.append("provides = %s" % i)
137 for i in self.backup:
138 data.append("backup = %s" % i)
139 data.append("\n")
140 archive_files.append((".PKGINFO", "\n".join(data)))
142 # .INSTALL
143 if any(self.install.values()):
144 archive_files.append((".INSTALL", self.installfile()))
146 self.path = os.path.join(path, self.filename())
147 util.mkdir(os.path.dirname(self.path))
149 # Generate package metadata
150 tar = tarfile.open(self.path, "w:gz")
151 for name, data in archive_files:
152 info = tarfile.TarInfo(name)
153 info.size = len(data)
154 tar.addfile(info, StringIO(data))
156 # Generate package file system
157 for name in self.files:
158 fileinfo = util.getfileinfo(name)
159 info = tarfile.TarInfo(fileinfo["filename"])
160 if fileinfo["hasperms"]:
161 info.mode = fileinfo["perms"]
162 if fileinfo["isdir"]:
163 info.type = tarfile.DIRTYPE
164 tar.addfile(info)
165 elif fileinfo["islink"]:
166 info.type = tarfile.SYMTYPE
167 info.linkname = fileinfo["link"]
168 tar.addfile(info)
169 else:
170 # TODO wow what a hack, adding a newline to match mkfile?
171 filedata = name + "\n"
172 info.size = len(filedata)
173 tar.addfile(info, StringIO(filedata))
175 tar.close()
177 def install_package(self, root):
178 """Install the package in the given root."""
179 for f in self.files:
180 util.mkfile(root, f, f)
181 path = os.path.join(root, f)
182 if os.path.isfile(path):
183 os.utime(path, (355, 355))
185 def full_filelist(self):
186 """Generate a list of package files.
188 Each path is decomposed to generate the list of all directories leading
189 to the file.
191 Example with 'usr/local/bin/dummy':
192 The resulting list will be:
193 usr/
194 usr/local/
195 usr/local/bin/
196 usr/local/bin/dummy
198 file_set = set()
199 for name in self.files:
200 name = self.parse_filename(name)
201 file_set.add(name)
202 while "/" in name:
203 name, tmp = name.rsplit("/", 1)
204 file_set.add(name + "/")
205 return sorted(file_set)
207 def local_backup_entries(self):
208 return ["%s\t%s" % (self.parse_filename(i), util.mkmd5sum(i)) for i in self.backup]
210 def installfile(self):
211 data = []
212 for key, value in self.install.iteritems():
213 if value:
214 data.append("%s() {\n%s\n}\n" % (key, value))
216 return "\n".join(data)
218 # vim: set ts=4 sw=4 et: