]> TLD Linux GIT Repositories - packages/rpm-build-tools.git/commitdiff
- PLD merge
authorMarcin Krol <hawk@tld-linux.org>
Sat, 27 Feb 2021 13:41:56 +0000 (14:41 +0100)
committerMarcin Krol <hawk@tld-linux.org>
Sat, 27 Feb 2021 13:41:56 +0000 (14:41 +0100)
builder.sh
rediff-patches.py [new file with mode: 0755]
relup.sh
rpm-build-tools.spec
sort-pkgs [new file with mode: 0755]

index bbeb418625bbeb9c5e97b839fa344a112441a999..a19da1207d111a72e70ecf92315418108f3452d0 100755 (executable)
@@ -38,9 +38,10 @@ APPDIR=$(d=$0; [ -L "$d" ] && d=$(readlink -f "$d"); dirname "$d")
 VERSION="v0.35"
 VERSIONSTRING="\
 Build package utility from PLD Linux Packages repository
-$VERSION (C) 1999-2016 Free Penguins".
+$VERSION (C) 1999-2020 Free Penguins".
 
-CLEAN_PATH="/bin:/usr/bin:/usr/sbin:/sbin:/usr/X11R6/bin"
+# Clean PATH without /usr/local or user paths
+CLEAN_PATH="/usr/sbin:/usr/bin:/sbin:/bin:/usr/X11R6/bin"
 
 # required rpm-build-macros
 RPM_MACROS_VER=1.534
@@ -496,6 +497,26 @@ Usage: builder [--all-branches] [-D|--debug] [-V|--version] [--short-version]  [
 "
 }
 
+is_rpmorg() {
+       local v
+
+       v=$(LC_ALL=C LANG=C rpm --version 2>&1)
+       v=${v#RPM version } # rpm 4
+       v=${v#rpm \(RPM\) } # rpm 5
+
+       case "$v" in
+               4.5|5.*)
+                       return 1
+                       ;;
+               4.*)
+                       return 0;
+                       ;;
+               *)
+                       echo "ERROR: unsupported RPM version $v" >&2
+                       exit 1
+       esac
+}
+
 # create tempfile. as secure as possible
 tempfile() {
        local prefix=builder.$PACKAGE_NAME${1:+.$1}
@@ -709,7 +730,8 @@ EOF
 %_sourcedir ./
 EOF
        fi
-       if rpm --version 2>&1 | grep -qE '5\.[0-9]+\.[0-9]+'; then
+       if ! is_rpmorg; then
+               local safe_macrofiles
                safe_macrofiles=$(rpm $TARGET_SWITCH --showrc | awk -F: '/^macrofiles/ { gsub(/^macrofiles[ \t]+:/, "", $0); print $0 } ')
                eval PATH=$CLEAN_PATH $RPMBUILD $TARGET_SWITCH --macros "$safe_macrofiles:$BUILDER_MACROS" $QUIET $RPMOPTS $RPMBUILDOPTS $BCOND $* 2>&1
        else
@@ -1079,7 +1101,10 @@ get_spec() {
                local _rev=$(get_pkgrev "$CVSTAG")
                echo "$_rev" | grep -q -E "^ERROR$" || CVSTAG="$_rev"
                if git rev-parse --verify -q "$CVSTAG" >/dev/null; then
-                       git checkout "$CVSTAG" --
+                       # checkout only if differs, so this will not trash git reflog
+                       if [ $(git rev-parse "$CVSTAG") != $(git rev-parse HEAD) ]; then
+                               git checkout "$CVSTAG" --
+                       fi
                elif git rev-parse --verify -q "refs/remotes/${REMOTE_PLD}/$CVSTAG"; then
                        git checkout -t "refs/remotes/${REMOTE_PLD}/$CVSTAG" > /dev/null
                fi
@@ -1386,6 +1411,7 @@ get_files() {
                                                ${GETURI} "$target" "$url"
                                        fi
 
+
                                        if [ -s "$target" ]; then
                                                cvsignore_df $target
                                        else
@@ -1847,7 +1873,7 @@ set_bconds_values() {
                without_*)
                        bcond=${opt#without_}
                        case "$BCOND" in
-                       *--without?${bcond}*)
+                       *--without?${bcond}\ *|*--without?${bcond})
                                AVAIL_BCONDS_WITHOUT="$AVAIL_BCONDS_WITHOUT <$bcond>"
                                ;;
                        *)
@@ -1858,7 +1884,7 @@ set_bconds_values() {
                with_*)
                        bcond=${opt#with_}
                        case "$BCOND" in
-                       *--with?${bcond}*)
+                       *--with?${bcond}\ *|*--with?${bcond})
                                AVAIL_BCONDS_WITH="$AVAIL_BCONDS_WITH <$bcond>"
                                ;;
                        *)
@@ -1915,7 +1941,7 @@ run_sub_builder() {
 # this requires following sudo rules:
 # - poldek --noask --caplookup -ug
 poldek_install() {
-       LANG=C $POLDEK_CMD --noask --caplookup --uniq -ug "$@"
+       LC_ALL=C LANG=C $POLDEK_CMD --noask --caplookup --uniq -ug "$@"
 }
 
 # install packages
@@ -2044,7 +2070,7 @@ _rpm_cnfl_check() {
                DEPS=$(cat)
        fi
 
-       LANG=C rpm -q --whatprovides $DEPS 2>/dev/null | awk '!/no package provides/ { print }'
+       LC_ALL=C LANG=C rpm -q --whatprovides $DEPS 2>/dev/null | awk '!/no package provides/ { print }'
 }
 
 # install deps via information from 'rpm-getdeps' or 'rpm --specsrpm'
diff --git a/rediff-patches.py b/rediff-patches.py
new file mode 100755 (executable)
index 0000000..42897f4
--- /dev/null
@@ -0,0 +1,169 @@
+#!/usr/bin/python3
+
+# rediff-patches.py name.spec
+
+import argparse
+import collections
+import logging
+import os
+import re
+import rpm
+import shutil
+import subprocess
+import sys
+import tempfile
+
+RPMBUILD_ISPATCH = (1<<1)
+
+def prepare_spec(r, patch_nr, before=False):
+    tempspec = tempfile.NamedTemporaryFile()
+    re_patch = re.compile(r'^%patch(?P<patch_number>\d+)\w*')
+    for line in r.parsed.split('\n'):
+        m = re_patch.match(line)
+        if m:
+            patch_number = int(m.group('patch_number'))
+            if patch_nr == patch_number:
+                if before:
+                    tempspec.write(b"exit 0\n# here was patch%d\n" % patch_nr)
+                else:
+                    line = re.sub(r'#.*', "", line)
+                    tempspec.write(b"%s\nexit 0\n" % line.encode('utf-8'))
+                continue
+        tempspec.write(b"%s\n" % line.encode('utf-8'))
+    tempspec.flush()
+    return tempspec
+
+def unpack(spec, appsourcedir, builddir):
+    cmd = [ 'rpmbuild', '-bp',
+           '--define',  '_builddir %s' % builddir,
+           '--define', '_specdir %s' % appsourcedir,
+           '--define', '_sourcedir %s' % appsourcedir,
+           '--define', '_enable_debug_packages 0',
+           '--define', '_default_patch_fuzz 2',
+           spec ]
+    logging.debug("running %s" % repr(cmd))
+    try:
+        res = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, check=True,
+                              env={'LC_ALL': 'C.UTF-8'}, timeout=600)
+    except subprocess.CalledProcessError as err:
+        logging.error("unpacking exited with status code %d." % err.returncode)
+        logging.error("STDOUT:")
+        if err.stdout:
+            for line in err.stdout.decode('utf-8').split("\n"):
+                logging.error(line)
+        logging.error("STDERR:")
+        if err.stderr:
+            for line in err.stderr.decode('utf-8').split("\n"):
+                logging.error(line)
+        raise
+    else:
+        logging.debug("unpacking exited with status code %d." % res.returncode)
+        logging.debug("STDOUT/STDERR:")
+        if res.stdout:
+            for line in res.stdout.decode('utf-8').split("\n"):
+                logging.debug(line)
+
+
+def diff(diffdir_org, diffdir, builddir, output):
+    diffdir_org = os.path.basename(diffdir_org)
+    diffdir = os.path.basename(diffdir)
+
+    with open(output, 'wt') as f:
+        cmd = [ 'diff', '-urNp', '-x', '*.orig', diffdir_org, diffdir ]
+        logging.debug("running %s" % repr(cmd))
+        try:
+            subprocess.check_call(cmd, cwd=builddir, stdout=f, stderr=sys.stderr,
+                                  env={'LC_ALL': 'C.UTF-8'}, timeout=600)
+        except subprocess.CalledProcessError as err:
+            if err.returncode != 1:
+                raise
+    logging.info("rediff generated as %s" % output)
+
+def diffstat(patch):
+    cmd = [ 'diffstat', patch ]
+    logging.info("running diffstat for: %s" % patch)
+    try:
+        subprocess.check_call(cmd, stdout=sys.stdout, stderr=sys.stderr,
+                              env={'LC_ALL': 'C.UTF-8'}, timeout=60)
+    except subprocess.CalledProcessError as err:
+        logging.error("running diffstat failed: %s" % err)
+    except FileNotFoundError as err:
+        logging.error("running diffstat failed: %s, install diffstat package?" % err)
+
+def main():
+    parser = parser = argparse.ArgumentParser(description='rediff patches to avoid fuzzy hunks')
+    parser.add_argument('spec', type=str, help='spec file name')
+    parser.add_argument('-p', '--patches', type=str, help='comma separated list of patch numbers to rediff')
+    parser.add_argument('-s', '--skip-patches', type=str, help='comma separated list of patch numbers to skip rediff')
+    parser.add_argument('-v', '--verbose', help='increase output verbosity', action='store_true')
+    args = parser.parse_args()
+
+    logging.basicConfig(level=logging.INFO)
+    rpm.setVerbosity(rpm.RPMLOG_ERR)
+
+    if args.verbose:
+            logging.basicConfig(level=logging.DEBUG)
+            rpm.setVerbosity(rpm.RPMLOG_DEBUG)
+
+    if args.patches:
+        args.patches = [int(x) for x in args.patches.split(',')]
+
+    if args.skip_patches:
+        args.skip_patches = [int(x) for x in args.skip_patches.split(',')]
+
+    specfile = args.spec
+    appsourcedir = os.path.dirname(os.path.abspath(specfile))
+
+    tempdir = tempfile.TemporaryDirectory(dir="/dev/shm")
+    topdir = tempdir.name
+    builddir = os.path.join(topdir, 'BUILD')
+
+    rpm.addMacro("_builddir", builddir)
+
+    r = rpm.spec(specfile)
+
+    patches = {}
+
+    for (name, nr, flags) in r.sources:
+        if flags & RPMBUILD_ISPATCH:
+            patches[nr] = name
+
+    applied_patches = collections.OrderedDict()
+    re_patch = re.compile(r'^%patch(?P<patch_number>\d+)\w*(?P<patch_args>.*)')
+    for line in r.parsed.split('\n'):
+        m = re_patch.match(line)
+        if not m:
+            continue
+        patch_nr = int(m.group('patch_number'))
+        patch_args = m.group('patch_args')
+        applied_patches[patch_nr] = patch_args
+
+    appbuilddir = rpm.expandMacro("%{_builddir}/%{?buildsubdir}")
+
+    for patch_nr in applied_patches.keys():
+        if args.patches and patch_nr not in args.patches:
+            continue
+        if args.skip_patches and patch_nr in args.skip_patches:
+            continue
+        patch_name = patches[patch_nr]
+        logging.info("*** patch %d: %s" % (patch_nr, patch_name))
+
+        tempspec = prepare_spec(r, patch_nr, before=True)
+        unpack(tempspec.name, appsourcedir, builddir)
+        tempspec.close()
+        os.rename(appbuilddir, appbuilddir + ".org")
+
+        tempspec = prepare_spec(r, patch_nr, before=False)
+        unpack(tempspec.name, appsourcedir, builddir)
+        tempspec.close()
+
+        diff(appbuilddir + ".org", appbuilddir, builddir, os.path.join(topdir, os.path.join(appsourcedir, patch_name + ".rediff")))
+
+        diffstat(os.path.join(topdir, os.path.join(appsourcedir, patch_name)))
+        diffstat(os.path.join(topdir, os.path.join(appsourcedir, patch_name + ".rediff")))
+
+        shutil.rmtree(builddir)
+    tempdir.cleanup()
+
+if __name__ == '__main__':
+    main()
index 7557ba619b1282596364914aa6d253ba8159fbea..8267436e1efc2c5cc295941189c01a0176365044 100755 (executable)
--- a/relup.sh
+++ b/relup.sh
@@ -8,12 +8,19 @@ set -e
 
 get_dump() {
        local specfile="$1"
-       if ! out=$(rpm --specfile "$specfile" --define 'prep %dump' -q 2>&1); then
-               echo >&2 "$out"
+       local rpm_dump
+       local success="y"
+       if [ -x /usr/bin/rpm-specdump ]; then
+               rpm_dump=$(rpm-specdump "$specfile" 2>&1) || success="n"
+       else
+               rpm_dump=$(rpm --specfile "$specfile" --define 'prep %dump' -q 2>&1) || success="n"
+       fi
+       if [ "$success" != "y" ]; then
+               echo >&2 "$rpm_dump"
                echo >&2 "You need icon files being present in SOURCES."
                exit 1
        fi
-       echo "$out"
+       echo "$rpm_dump"
 }
 
 usage="Usage:
@@ -38,7 +45,7 @@ get_release() {
        rel=$(awk '/^%define[   ]+_?rel[        ]+/{print $NF}' $specfile)
        if [ -z "$rel" ]; then
                dump=$(get_dump "$specfile")
-               rel=$(echo "$dump" | awk '/PACKAGE_RELEASE/{print $NF; exit}')
+               rel=$(echo "$dump" | awk '$2~/^(PACKAGE_)?RELEASE$/{print $NF; exit}')
        fi
        echo $rel
 }
index edf0a6c9ea73b5f7c950f1bbd3142f410e564f57..6b4485c449a2b64c88a8802f8db79f471446e13e 100644 (file)
@@ -6,7 +6,7 @@ Summary(ru.UTF-8):      Скрипты и утилиты, необходимые дл
 Summary(uk.UTF-8):     Скрипти та утиліти, необхідні для побудови пакетів
 Name:          rpm-build-tools
 Version:       4.9
-Release:       7
+Release:       12
 License:       GPL
 Group:         Applications/File
 Source0:       builder.sh
diff --git a/sort-pkgs b/sort-pkgs
new file mode 100755 (executable)
index 0000000..7b1fa41
--- /dev/null
+++ b/sort-pkgs
@@ -0,0 +1,80 @@
+#!/usr/bin/python3
+
+"""
+This script tries to set ordering in which packages ought to be sent to builders.
+Input: file with names of packages (without the .spec suffix). One package name per line.
+Output: sorted packages on stdout.
+
+If the script goes in a infinite loop, that means there is a cycle or other bug.
+"""
+
+import os
+import re
+import sys
+
+BR_PATTERN = re.compile('BuildRequires:\s+(.*?)(\s|$)')
+PACKAGE_PATTERN_WITH_N = re.compile('%package\s+-n\s+(.*)')
+PACKAGE_PATTERN = re.compile('%package\s+(.*)')
+
+DIR = os.getenv("HOME") + '/rpm/packages'
+
+BUILD_REQUIRES = {}
+PACKAGES = {}
+SPECS = {}
+VISITED = {}
+
+
+def parse_spec(name):
+    global PACKAGES, SPECS, BUILD_REQUIRES, VISITED
+    res = []
+    try:
+        with open(os.path.join(DIR, name, name + '.spec'), 'r') as f:
+            for line in f:
+                br = BR_PATTERN.match(line)
+                if br:
+                    p = br.group(1)
+                    res.append(p)
+                if line.startswith('%package'):
+                    pn = PACKAGE_PATTERN_WITH_N.match(line)
+                    if pn:
+                        package = pn.group(1)
+                        PACKAGES[package] = name
+                    else:
+                        pn = PACKAGE_PATTERN.match(line)
+                        if pn:
+                            ext = pn.group(1)
+                            if ext:
+                                package = name + '-' + ext
+                                PACKAGES[package] = name
+        BUILD_REQUIRES[name] = res[:]
+        PACKAGES[name] = name
+        SPECS[name] = True
+        VISITED[name] = False
+    except:
+        pass
+
+
+def print_spec(spec):
+    global PACKAGES, SPECS, BUILD_REQUIRES, VISITED
+
+    if not VISITED[spec]:
+        VISITED[spec] = True
+        for br in BUILD_REQUIRES[spec]:
+            name = PACKAGES.get(br, '')
+            if name in SPECS:
+                if not VISITED[name]:
+                    print_spec(name)
+        print(spec)
+
+
+if __name__ == "__main__":
+    if len(sys.argv) < 2:
+        print("Usage: %s filename" % sys.argv[0])
+        sys.exit(1)
+    with open(sys.argv[1], 'r') as f:
+        for line in f:
+            spec = line.rstrip()
+            parse_spec(spec)
+
+    for spec in SPECS:
+        print_spec(spec)