Subject: [alpine-devel] recursive apk info

From: Dubiousjim <[email-masked]>
Date: Mon, 2 Dec 2013 23:48:14 -0500

I think there is currently no way to get apk info to recurse when
reporting dependencies or (installed) reverse dependencies. The switches
--depends and --rdepends just report a single layer. So I wrote the
following awk wrapper to get the recursive info occasionally. It's slow,
but presumably one won't need this very often.

#!/bin/sh

# We can't use a shebang of /usr/bin/awk -f, because awk may be implemented by gawk, which
# will handle an ARGV[1] of -D itself, rather than passing to this script.

usage() {
  echo "Usage: $0 -D/-R packages..." >&2
  exit 2
}

if [ $# -lt 2 ]; then usage
else
  case $1 in
  -D|-R) true;;
  --depends|--rdepends) true;;
  -r) true;; # deprecated form of -R
  *) usage;;
  esac
fi

awk -f - -- "$@" << EOF

#!/usr/bin/awk -f

function whoowns(f,   path, line) {
  f = substr(f, 4)
  #printf("who owns <%s>?\n", f)
  # TODO: grep output of `ldconfig -p`?
  if (system("test -f /lib/" f) == 0) path = "/lib/" f
  else if (system("test -f /usr/lib/" f) == 0) path = "/usr/lib/" f;
  if (path != "") {
    "apk info -Wq " path | getline line
    close("apk info -Wq " path)
    if (line != "" && line !~ /^ERROR:/) {
      return line
    }
  }
  printf("Couldn't find %s.\n", f) > "/dev/stderr"
  exit 1
}

function enqueue(f, v) {
  sub(/[<>]?=.*/, "", f)
  if (infocmd == "apk info -R ")
    sub(/-[^-]+-r[0-9]+$/, "", f)
  if (!(f in stored)) {
    queue[nextq] = f
    nextq++
    # v is 0 for initial arguments, 1 for dependencies
    stored[f] = v
  }
}

function readone(f,   line, rc) {
  #printf("running readone(%s)\n", f)
  rc = 1
  if (infocmd f | getline line) {
    # we read until first blank line
    rc = 0
    while ((infocmd f | getline line)>0 && line) {
      #printf("read: %s\n", line)
      if (line ~ /^so:/) line = whoowns(line)
      enqueue(line, 1)
    }
  }
  close(infocmd f)
  return rc
}

BEGIN {
  # globals: infocmd nextq queue[] stored[] i
    infocmd = "apk info " ARGV[1] " "
    nextq=1
    for (i=2; i<ARGC; i++) {
      enqueue(ARGV[i], 0)
    }
    #printf("ARGC=%d nextq=%d\n", ARGC, nextq)
    i=1
    while (i<nextq) {
      if (readone(queue[i])!=0) exit 1;
      i++
    }
    for (i in stored)
      if (stored[i]>0) print i | "sort"
    close("sort")
    exit 0
}

EOF

-- 
[email-masked]

---
Unsubscribe:  [email-masked]
Help:         [email-masked]
---

---

From: Dubiousjim <[email-masked]>
Date: Tue, 3 Dec 2013 07:17:04 -0500

Some fixes/tweaks...

#!/bin/sh

usage() {

awk -f - -- "$@" << "EOF"
#!/usr/bin/awk -f

  # TODO: grep output of ldconfig -p?

function enqueue(f, v) {
  if (infocmd ~ /^apk info (-[Rr]|--r)/)
    sub(/-[^-]+-r[0-9]+$/, "", f)
  else
    sub(/[<>]?=.*/, "", f)
  if (!(f in stored)) {
    queue[nextq++] = f
    # v is 0 for initial arguments, 1 for dependencies
    stored[f] = v
  }
}

function readone(f,   line, rc) {
  rc = 1
  if (infocmd f | getline line) {
    # we read until first blank line
    rc = 0
    while ((infocmd f | getline line)>0 && line) {
      if (line ~ /^so:/) line = whoowns(substr(line, 4))
      enqueue(line, 1)
    }
  }
  close(infocmd f)
  if (rc != 0) {
    printf("No info for %s.\n", f) > "/dev/stderr"
    exit 1
  }
}

BEGIN {
    while (i<nextq)
      readone(queue[i++])

EOF

-- 
[email-masked]

---