For discussion of Alpine Linux development and developer support

1

[alpine-devel] recursive apk info

Dubiousjim
Details
Message ID
<20131203044814.GF29236@zen>
Sender timestamp
1386046094
DKIM signature
missing
Download raw message
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



-- 
dubiousjim@gmail.com


---
Unsubscribe:  alpine-devel+unsubscribe@lists.alpinelinux.org
Help:         alpine-devel+help@lists.alpinelinux.org
---
Dubiousjim
Details
Message ID
<20131203121703.GH29236@zen>
In-Reply-To
<20131203044814.GF29236@zen> (view parent)
Sender timestamp
1386073024
DKIM signature
missing
Download raw message
Some fixes/tweaks...



#!/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) {
  # 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) {
  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 {
  # globals: infocmd nextq queue[] stored[] i
    infocmd = "apk info " ARGV[1] " "
    nextq=1
    for (i=2; i<ARGC; i++) {
      enqueue(ARGV[i], 0)
    }
    i=1
    while (i<nextq)
      readone(queue[i++])
    for (i in stored)
      if (stored[i]>0) print i | "sort"
    close("sort")
    exit 0
}

EOF

-- 
dubiousjim@gmail.com


---
Unsubscribe:  alpine-devel+unsubscribe@lists.alpinelinux.org
Help:         alpine-devel+help@lists.alpinelinux.org
---