1#  Copyright (c) 2006 by Aurelien Foret <orelien@chez.com>
2#  Copyright (c) 2006-2018 Pacman Development Team <pacman-dev@archlinux.org>
3#
4#  This program is free software; you can redistribute it and/or modify
5#  it under the terms of the GNU General Public License as published by
6#  the Free Software Foundation; either version 2 of the License, or
7#  (at your option) any later version.
8#
9#  This program is distributed in the hope that it will be useful,
10#  but WITHOUT ANY WARRANTY; without even the implied warranty of
11#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12#  GNU General Public License for more details.
13#
14#  You should have received a copy of the GNU General Public License
15#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
17
18import os
19import re
20import hashlib
21
22import tap
23
24SELFPATH    = os.path.abspath(os.path.dirname(__file__))
25
26# ALPM
27PM_ROOT     = "/"
28PM_DBPATH   = "var/lib/pacman"
29PM_SYNCDBPATH = "var/lib/pacman/sync"
30PM_LOCK     = "var/lib/pacman/db.lck"
31PM_CACHEDIR = "var/cache/pacman/pkg"
32PM_EXT_PKG  = ".pkg.tar.gz"
33PM_HOOKDIR  = "etc/pacman.d/hooks"
34
35# Pacman
36PACCONF     = "etc/pacman.conf"
37
38# Pactest
39TMPDIR      = "tmp"
40SYNCREPO    = "var/pub"
41LOGFILE     = "var/log/pactest.log"
42
43verbose = 0
44
45def vprint(msg):
46    if verbose:
47        tap.diag(msg)
48
49#
50# Methods to generate files
51#
52
53def getfileinfo(filename):
54    data = {
55        'changed': False,
56        'isdir': False,
57        'islink': False,
58        'link': None,
59        'hasperms': False,
60        'perms': None,
61    }
62    if filename[-1] == "*":
63        data["changed"] = True
64        filename = filename.rstrip("*")
65    if filename.find(" -> ") != -1:
66        filename, link = filename.split(" -> ")
67        data["islink"] = True
68        data["link"] = link
69    elif filename.find("|") != -1:
70        filename, perms = filename.split("|")
71        data["hasperms"] = True
72        data["perms"] = int(perms, 8)
73    if filename[-1] == "/":
74        data["isdir"] = True
75
76    data["filename"] = filename
77    return data
78
79def mkfile(base, name, data=""):
80    info = getfileinfo(name)
81    filename = info["filename"]
82
83    path = os.path.join(base, filename)
84    if info["isdir"]:
85        if not os.path.isdir(path):
86            os.makedirs(path, 0o755)
87        return path
88
89    dir_path = os.path.dirname(path)
90    if dir_path and not os.path.isdir(dir_path):
91        os.makedirs(dir_path, 0o755)
92
93    if info["islink"]:
94        os.symlink(info["link"], path)
95    else:
96        writedata(path, data)
97
98    if info["perms"]:
99        os.chmod(path, info["perms"])
100
101    return path
102
103def writedata(filename, data):
104    if isinstance(data, list):
105        data = "\n".join(data)
106    fd = open(filename, "w")
107    if data:
108        fd.write(data)
109        if data[-1] != "\n":
110            fd.write("\n")
111    fd.close()
112
113def mkcfgfile(filename, root, option, db):
114    # Options
115    data = ["[options]"]
116    for key, value in option.items():
117        data.extend(["%s = %s" % (key, j) for j in value])
118
119    # Repositories
120    # sort by repo name so tests can predict repo order, rather than be
121    # subjects to the whims of python dict() ordering
122    for key in sorted(db.keys()):
123        if key != "local":
124            value = db[key]
125            data.append("[%s]\n" \
126                    "SigLevel = %s\n" \
127                    "Server = file://%s" \
128                     % (value.treename, value.getverify(), \
129                        os.path.join(root, SYNCREPO, value.treename)))
130            for optkey, optval in value.option.items():
131                data.extend(["%s = %s" % (optkey, j) for j in optval])
132
133    mkfile(root, filename, "\n".join(data))
134
135
136#
137# MD5 helpers
138#
139
140def getmd5sum(filename):
141    if not os.path.isfile(filename):
142        return ""
143    fd = open(filename, "rb")
144    checksum = hashlib.md5()
145    while 1:
146        block = fd.read(32 * 1024)
147        if not block:
148            break
149        checksum.update(block)
150    fd.close()
151    return checksum.hexdigest()
152
153def mkmd5sum(data):
154    checksum = hashlib.md5()
155    checksum.update("%s\n" % data)
156    return checksum.hexdigest()
157
158
159#
160# Miscellaneous
161#
162
163def which(filename, path=None):
164    if not path:
165        path = os.environ["PATH"].split(os.pathsep)
166    for p in path:
167        f = os.path.join(p, filename)
168        if os.access(f, os.F_OK):
169            return f
170    return None
171
172def grep(filename, pattern):
173    pat = re.compile(pattern)
174    myfile = open(filename, 'r')
175    for line in myfile:
176        if pat.search(line):
177            myfile.close()
178            return True
179    myfile.close()
180    return False
181
182def mkdir(path):
183    if os.path.isdir(path):
184        return
185    elif os.path.isfile(path):
186        raise OSError("'%s' already exists and is not a directory" % path)
187    os.makedirs(path, 0o755)
188