summaryrefslogtreecommitdiff
path: root/src/prtools/prfullpkg
blob: bbb8d732b6f2af4c9ba324d8a78f91be59050eda (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
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
#!/bin/bash

source /etc/makepkg.conf
source /etc/abs.conf
source /etc/libretools.conf
source /etc/libretools.d/prtools.conf

if [ -z $XDG_CONFIG_HOME ]; then # Avoid /libretools dir doesn't exist errors

    error "There's no XDG_CONFIG_HOME var set"; exit 1

elif [ -e $XDG_CONFIG_HOME/libretools/libretools.conf ]; then

    source $XDG_CONFIG_HOME/libretools/libretools.conf

fi


function usage {

    echo "cd to a dir containing a PKGBUILD and run:"
    echo "$0 [options]"
    printf "This script will check dependencies, build them if possible "
    printf "and stage the packages on it's repo."
    echo
    echo "OPTIONS:"
    echo " -h           : this message."
    echo " -a absdir    : set absdir as ABSROOT."
    echo " -b build_dir : use a fullpkg build_dir and only build."
    echo " -c           : check deps only, do not build."
    echo " -d build_dir : use this dir to build. Defaults to mktemp."
    echo " -n           : don't update pacman db."
    echo " -m max_level : check deps until this level"
    echo " -r \"command\" : use this instead of \"$FULLBUILDCMD\""
    echo
    exit 1

}

function remove_buildorder { # Removes a package from the buildorder
# $1 package name
# $2 buildorder file

  grep -Evw "${1}" ${2} > ${2}2
  mv -f ${2}2 ${2}

}

function guess_repo { # Get repo name. Asumes ${ABSROOT}/package/repo/PKGBUILD

    basename $(pwd)

}

function get_fullver { # return : full version spec, including epoch (if necessary), pkgver, pkgrel

#  usage : get_fullver( ${epoch:-0}, $pkgver, $pkgrel )

    if [[ $1 -eq 0 ]]; then
        # zero epoch case, don't include it in version
        echo $2-$3
    else
        echo $1:$2-$3
    fi

}

function cleanup {  # Cleans the build_dir.

    [ ! -d "${build_dir}" -o "${build_only}" = 'y' ] && return 0 # Do nothing or already cleaned.


    if [ $level -eq 0 ]; then   # Only do cleanup on level 0.
        msg "Cleaning up ${build_dir}"
        rm -rf "$build_dir/*"
    fi
}

function find_deps {  # Checks ABSROOT and look for target pkg deps. Adds them if not built or outdated.

    source PKGBUILD      ## Check this level.

    local repo=${repo:-$(guess_repo)}
    local pkgbase=${pkgbase:-${pkgname[0]}}
    local epoch=${epoch:-0}
    local fullver=$(get_fullver ${epoch} ${pkgver} ${pkgrel})

    if is_built "${pkgbase}" "${fullver}"; then
        exit 0  # pkg is built and updated
    fi

    echo "${level}:${pkgbase}" >> "${build_dir}/BUILDORDER"  # greater levels are built first

    if [ -d "${build_dir}/${pkgbase}" ]; then  # PKGBUILD is already there

        exit 0

    else  # Copy dir to build_dir

        mkdir ${build_dir}/${pkgbase}
        cp -r $(pwd)/* ${build_dir}/${pkgbase}

        echo "repo=$repo" > "${build_dir}/${pkgbase}/.INFO"  # to identify repo later
    fi

    msg2 "%${level}s${pkgbase}-${fullver}"  # current package plus a space for every level

    declare -i next_level=$level+1  ## Check next deps level.

    deps=$(echo "${depends[@]} ${makedepends[@]}" | \
           sed "s/[=<>]\+[^ ]\+//g" | \
           tr ' ' "\n" | \
           sort -u)  # All deps in separate line, only once, without version.

    for _dep in ${deps[@]}; do

        local found=false

        if [ -d "${ABSROOT}/${_dep}" ]; then  # ABSROOT/package/repo

            for _repo in ${REPOS[@]}; do  # Use PKGBUILD from repo in REPOS array order

                if [ -e "${ABSROOT}/${_dep}/${_repo}/PKGBUILD" ]; then

                    pushd "${ABSROOT}/${_dep}/${_repo}" > /dev/null
                    $0 -c -d ${build_dir} -l ${next_level}  # run this cmd on dep's PKGBUILD dir
                    [ $? -eq 20 ] && return 20  # probable circular deps
                    popd > /dev/null
                    local found=true
                    break 1  # found, go to next dep
                fi

            done

        else  # pkgsplit, needs guess

            for _repo in ${REPOS[@]}; do

                if _dir=($(find "$ABSROOT/" -type f \
                    -wholename "*/${_repo}/PKGBUILD" -print0 2>/dev/null | \
                    "xargs" -0 -e grep -HEw "pkgname=|pkgbase=|provides=" | \
                    grep -w "$_dep" 2>&1)) ;

                then

                    _dir=$(dirname $(echo $_dir | cut -d: -f1))
                    plain "guess for $_dep -> $_dir"

                    pushd "$_dir" > /dev/null
                    $0 -c -d ${build_dir} -l ${next_level}  # run this cmd on dep's PKGBUILD dir
                    [ $? -eq 20 ] && return 20  # probable circular dep
                    popd > /dev/null
                    local found=true
                    break 1 # found, go to next dep
                fi

            done

        fi

        if ( ${found} ); then
            continue 1  # go to next dep
        else
            echo "dep_not_found:$_dep" >> $build_dir/log
        fi

    done

    unset next_level dir
    # unset PKGBUILD variables
    unset pkgbase pkgname pkgver pkgrel epoch pkgdesc arch url license groups depends \
          makedepens checkdepends optdepends provides conflicts replaces backup \
          options install changelog source noextract md5sums build check package
}

function __build () {
    pushd ${build_dir}  > /dev/null

    build_packages=($(sort -gr $buildorder | cut -d: -f2)) # greater levels must be built first

    while [ ${#build_packages[@]} -ge 1 ]; do
        pushd $build_dir/${build_packages[0]} > /dev/null
        source PKGBUILD

        msg2 "${pkgbase:-${pkgname[0]}} $pkgver-$pkgrel"

        msg2 "Checking for non free deps"
        pkgbuild-check-nonfree || {
            if [ $? -eq 15 ]; then # this error means nonfree others means fail.

              echo "nonfree:$(basename $PWD)" >> $build_dir/log

              remove_buildorder "$(basename $PWD)" $buildorder # take out package from $buildorder

              continue # build next package
            fi
        }

        msg2 "Building $(basename $PWD)"

        $FULLBUILDCMD; r=$?  # this buildcmd is on libretools.conf

        case $r in

            0)  ## Succesfull build

                plain "The build was succesful."
                if source .INFO && [ -n $repo ]; then

                    if [ ! -z $HOOKLOCALRELEASE ]; then # Calls a local release script if it's used
                        find -name "*.pkg.tar.?z" -print0 | xargs -0 $HOOKLOCALRELEASE $repo
                    fi

                    librestage $repo || echo "unstaged:$(basename $PWD)" >> $build_dir/log

                    msg "Updating pacman db and packages"
                    sudo pacman -Sy || true

                fi

                echo "built:$(basename $PWD)" >> $build_dir/log
            ;;

            *)  ## Build failed
                error "There were errors while trying to build the package."
                echo "failed:$(basename $PWD)" >> $build_dir/log
            ;;
        esac

        remove_buildorder "${build_packages[0]}" $buildorder || true

        build_packages=($(sort -gr $buildorder | cut -d: -f2)) # which is next package?
        popd > /dev/null
    done

    pkgs=($(grep "nonfree:" $build_dir/log)) && {
        error "Those packages contain nonfree deps:"
        echo ${pkgs[@]} | tr " " "\n" | cut -d: -f2
    }

    pkgs=($(grep "built:" $build_dir/log)) && {
        msg "Those packages were built and staged:"
        echo ${pkgs[@]} | tr " " "\n" | cut -d: -f2
    }

    pkgs=($(grep "failed:" $build_dir/log)) && {
        error "Those packages failed to build:"
        echo ${pkgs[@]} | tr " " "\n" | cut -d: -f2
    }

    pkgs=($(grep "unstaged:" $build_dir/log)) && {
        error "Those packages couldn't be staged because of missing reponame:"
        echo ${pkgs[@]} | tr " " "\n" | cut -d: -f2
    }

    popd > /dev/null
}

function trap_exit { # End inmediately but print a useful message

  error "$@"
  warning "Leftover files left on $build_dir"

  exit 1
}

# Trap signals from makepkg
set -E
trap 'trap_exit "(prfullpkg:${level}) TERM signal caught. Exiting..."' TERM HUP QUIT
trap 'trap_exit "(prfullpkg:${level}) Aborted by user! Exiting..."' INT
trap 'trap_exit "(prfullpkg:${level}) An unknown error has occurred. Exiting..."' ERR

ban_file=$XDG_CONFIG_HOME/libretools/ban
force_build=""
level=0
noupdate='n'
build_only='n'
check_deps_only='n'
max_level=21

while getopts 'ha:b:cd:l:nm:r:' arg; do
    case $arg in
        h) usage ;;
        a) ABSROOT="$OPTARG" ;;
        b) build_only='y'
           build_dir="$OPTARG"
           if [ -z ${build_dir} ]; then
               usage
           fi
           if [ ! -r ${build_dir}/BUILDORDER ] ; then
               error "${build_dir}/BUILDORDER doesn't exist."
               exit 1
           fi;;
        c) check_deps_only='y' ;;
        d) build_dir="$OPTARG" ;;
        l) level=$OPTARG ;; # hidden option to know dep level.
        n) noupdate='y';;
        m) max_level=$OPTARG ;;
        r) FULLBUILDCMD="$OPTARG" ;;
    esac
done

if [ ${build_only} == 'n' ]; then

    [ ! -r PKGBUILD ] && {  # Check if we are actually on a build directory. Do this early.
        error "This isn't a build directory"
        usage
    }

    if [ ! -z "$HOOKPKGBUILDMOD" ]; then
        "$HOOKPKGBUILDMOD"
    fi

fi

if [ $level -eq 0 ]; then

    if [ ! -d ${build_dir} ]; then  # in case of custom -d option
        mkdir -p ${build_dir}
    else
        cleanup  # files already there can screw find_deps
    fi

    build_dir=${build_dir:-$(mktemp -d /tmp/fullpkg.XXXXXX)}  # use -d option or else mktemp

    touch ${build_dir}/{log,BUILDORDER} ${ban_file}  # make files for log and buildorder
    buildorder=${build_dir}/BUILDORDER

    if [ ${noupdate} = 'n' ]; then

        msg "Updating pacman db and packages"
        sudo pacman -Syu --noconfirm || true

    fi

    if [ ${build_only} == 'y' ]; then

        msg "Build Packages"

        __build

        exit 0

    fi

    msg "Checking dependencies"
fi

[ $level -ge $max_level ] && exit 20  # Probable circular deps

find_deps || {

    if [ $? -eq 20 ]; then  # Probable circular deps

       if [ $level -eq 0 ]; then  # Show error only on level 0
           error "Check for circular deps on $build_dir/BUILDORDER";
       fi

    fi
    exit 20  # Pass message 20
}

[ $check_deps_only = 'y' -o $level -gt 0 ] && exit 0  # only build on level 0

if [ $level -eq 0 -a -d $build_dir ]; then  # Sanity check

    if [  ! -w $ban_file -o ! -r $ban_file ]; then  # Check ban_file permisions

        chmod a+rw $ban_file || error "Ban file is not readable/writable ($ban_file)"

    else

        rsync -e ssh -aq $PARABOLAHOST:mips64el/ban >/dev/null 2>&1 || {

            warning "Failed to get ban list" && [ -r ${ban_file} ] && {  # use local copy if it exist

              search=$(cat ${ban_file} | tr "\n" "|")

              egrep -w "$search" ${buildorder} >> ${build_dir}/banned   # Keep track of banned files

              egrep -vw "$search" ${buildorder} > ${buildorder}2 # Take banned packages out of buildorder

              mv -f ${buildorder}2 ${buildorder}

              unset search
            }
        }
    fi
fi

msg "Building packages:"

__build  # Build the packages

echo
msg2 "Check if your system works fine and librerelease if it does"

exit 0