summaryrefslogtreecommitdiffstats
path: root/bm
blob: 7c0a6578f3216a7f49011a35b85ba0e16c875be1 (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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#!/usr/bin/python3
from BuildManager.optionparser import *
from BuildManager.build import *
from BuildManager import *
import fnmatch
import logging
import sys, os
import pwd

AUTHOR  = "Gustavo Niemeyer <niemeyer@conectiva.com>, papoteur <papoteur@mageialinux-online.org>"
VERSION = "3.6"

def passtrough(option, opt, val, parser):
    opts = parser.values
    if opt == "--define":
        assert option.nargs == 1
        opts.options.insert(0, opt)
        opts.options.insert(1, "'%s'" % parser.rargs[0].replace("'", r"\'"))
    else:
        opts.options.append(opt)
        for val in parser.rargs[:option.nargs]:
            opts.options.append("'%s'" % val.replace("'", r"\'"))
    del parser.rargs[:option.nargs]

def parse_options():
    workDir = os.getcwd()
    parser = OptionParser("%prog [OPTIONS] [<rpm dir>] [<spec file>] [<srpm file>]",
                          version="%prog "+VERSION)
    parser.add_option("-a", dest="mode", action="store_const", const="all",
                      help="do everything and build source and binary packages"
                           " (default)", default="all")
    parser.add_option("-u", dest="mode", action="store_const", const="unpack",
                      help="just unpack - default directory is \""+workDir+"\"")
    parser.add_option("-p", dest="mode", action="store_const", const="prep",
                      help="unpack and run %prep stage")
    parser.add_option("-r", dest="mode", action="store_const", const="generate_buildrequires",
                      help="unpack, run %prep and generate buildrequires")
    parser.add_option("-c", dest="mode", action="store_const", const="compile",
                      help="unpack, run %prep, and compile")
    parser.add_option("-i", dest="mode", action="store_const", const="install",
                      help="unpack, run %prep, compile and install"),
    parser.add_option("-s", dest="mode", action="store_const", const="source",
                      help="do everything and build source packages")
    parser.add_option("-b", dest="mode", action="store_const", const="binary",
                      help="do everything and build binary packages")
    parser.add_option("-l", dest="show_log", action="store_true",
                      help="show rpm output, besides copying to the log file")
    parser.add_option("-j", dest="parallel", metavar="N", type="int", default=1,
                      help="specify number of packages to build in parallel")
    parser.add_option("-o", dest="options", action="append",
                      metavar="OPT", default=[],
                      help="pass given parameters directly to rpm")
    parser.add_option("--unpack-dir", metavar="DIR", default=workDir,
                      help="specify directory where to unpack file(s)")
    parser.add_option("--build-log", metavar="FILE",
                      help="specify where to put the build log for each package")
    parser.add_option("--move-srpm", metavar="DIR",
                      help="move built srpm packages to given directory")
    parser.add_option("--move-rpm", metavar="DIR",
                      help="move built rpm packages to given directory")
    parser.add_option("--move-failed-srpm", metavar="DIR",
                      help="move original srpm packages to given directory, if failed")
    parser.add_option("--copy-failed-srpm", metavar="DIR",
                      help="copy original srpm packages to given directory, if failed")
    parser.add_option("--remove-failed-srpm", action="store_true",
                      help="remove original srpm packages, if failed")
    parser.add_option("--move-succeeded-srpm", metavar="DIR",
                      help="move original srpm packages to given directory, if succeeded")
    parser.add_option("--copy-succeeded-srpm", metavar="DIR",
                      help="copy original srpm packages to given directory, if succeeded")
    parser.add_option("--remove-succeeded-srpm", action="store_true",
                      help="remove original srpm packages, if succeeded")
    parser.add_option("--move-log", metavar="DIR",
                      help="move log files to given directory")
    parser.add_option("--move-failed-log", metavar="DIR",
                      help="move log files to given directory, if failed")
    parser.add_option("--filter-renew", metavar="DIR", action="append", default=[],
                      help="don't build packages if a newer version exists in given directory")
    parser.add_option("--filter-refresh", metavar="DIR", action="append", default=[],
                      help="only build packages if an older version exists in given directory")
    parser.add_option("--clean", action="store_true",
                      help="recursively remove directory used as topdir after the build process")
    parser.add_option("--clean-on-success", action="store_true",
                      help="same as --clean, but only remove if build has succeeded")
    parser.add_option("--ignore", metavar="PKGNAME", action="append", default=[],
                      help="ignore given package names (shell globbing allowed)")
    parser.add_option("--force-unpack", dest="forceunpack", action="store_true",
                      help="force unpacking regardless of rpm errors or warnings", default=False)

    # Passtrough options
    parser.add_option("--sign", action="callback", nargs=0, callback=passtrough,
                      help="pass this option to rpm")
    parser.add_option("--nodeps", action="callback", nargs=0, callback=passtrough,
                      help="pass this option to rpm")
    parser.add_option("--noclean", action="callback", nargs=0, callback=passtrough,
                      help="pass this option to rpm")
    parser.add_option("--debug", action="callback", nargs=0, callback=passtrough,
                      help="pass this option to rpm")
    parser.add_option("--short-circuit", action="callback", nargs=0, callback=passtrough,
                      help="pass this option to rpm")
    parser.add_option("--with", action="callback", nargs=1, callback=passtrough,
                      help="pass this option to rpm")
    parser.add_option("--without", action="callback", nargs=1, callback=passtrough,
                      help="pass this option to rpm")
    parser.add_option("--define", action="callback", nargs=1, callback=passtrough,
                      help="pass this option to rpm")
    parser.add_option("--target", action="callback", nargs=1, callback=passtrough,
                      help="pass this option to rpm")

    parser.add_option("--dryrun", dest="dryrun", action="store_true",
                      help="do not commit changes to the system")
    parser.add_option("--log", dest="loglevel", metavar="LEVEL",
                      help="set logging level to LEVEL (debug, info, "
                           "warning, error)", default="info")
    opts, args = parser.parse_args()
    opts.args = args

    if not opts.args:
        # Let's try to find a spec file by ourselves
        dir = os.getcwd()
        if dir[-6:] == "/SPECS":
            dir = "./"
        elif os.path.isdir("./SPECS"):
            dir = "./SPECS"
        else:
            while dir != "/":
                dir = os.path.dirname(dir)
                tmpdir = dir+"/SPECS"
                if os.path.isdir(tmpdir):
                    dir = tmpdir
                    break
            else:
                raise Error("couldn't guess SPECS directory")
        filelist = os.listdir(dir)
        for file in filelist[:]:
            if file[-5:] != ".spec":
                filelist.remove(file)
        if len(filelist) != 1:
            raise Error("couldn't guess spec file in "+dir)
        opts.args = [os.path.join(dir, filelist[0])]
    else:
        # Detect directories with a SPECS/ directory inside it
        for i in range(len(opts.args)):
            specsdir = os.path.join(opts.args[i]+"/SPECS")
            if os.path.isdir(specsdir):
                filelist = os.listdir(specsdir)
                for file in filelist[:]:
                    if file[-5:] != ".spec":
                        filelist.remove(file)
                if len(filelist) != 1:
                    raise Error("couldn't guess spec file in "+specsdir)
                opts.args[i] = os.path.join(specsdir, filelist[0])

        opts.filter_renew = [y for x in opts.filter_renew
                               for y in x.split()]
        opts.filter_refresh = [y for x in opts.filter_refresh
                                 for y in x.split()]

    for attr in ["unpack_dir", "move_srpm", "move_rpm",
                 "move_failed_srpm", "copy_failed_srpm",
                 "move_succeeded_srpm", "copy_succeeded_srpm",
                 "move_log", "move_failed_log",
                 "filter_renew", "filter_refresh"]:
        attrval = getattr(opts, attr)
        error = False
        if type(attrval) is list:
            for attrval in attrval:
                if attrval and not os.path.isdir(attrval):
                    error = True
                    break
        else:
            if attrval and not os.path.isdir(attrval):
                error = True
        if error:
            raise Error("value of --%s must be a directory" \
                         % attr.replace("_", "-"))

    old_ignore = opts.ignore
    opts.ignore = []
    for ignore in old_ignore:
        for item in ignore.split():
            opts.ignore.append(re.compile(fnmatch.translate(item)))

    return opts

def main():
    # Get the right $HOME, even when using sudo.
    if os.getuid() == 0:
        os.environ["HOME"] = pwd.getpwuid(0)[5]
    try:
        opts = parse_options()
        logger.setLevel(logging.getLevelName(opts.loglevel.upper()))
        logger.debug("starting bm")
        builder = PackageBuilder(opts)
        status = builder.run()
    except Error as e:
        logger.error(str(e))
        logger.debug("finishing bm with error")
        sys.exit(1)
    else:
        logger.debug("finishing bm")
        sys.exit(int(not status))

if __name__ == "__main__":
    main()

# vim:et:ts=4:sw=4