LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Slackware (https://www.linuxquestions.org/questions/slackware-14/)
-   -   package NAMING scheme (https://www.linuxquestions.org/questions/slackware-14/package-naming-scheme-4175479070/)

Skaperen 09-30-2013 09:17 AM

package NAMING scheme
 
I could not find a document that would confirm this, though I did see many examples by various individuals that contradicted this. But I'm basically interested in what is used by Slackware and maybe SBo. My purpose is so I can make a tool that will translate a package name with a version to a package name without a version, for matching a version-less reference.

The base version-less package name may have any number of "-" characters separating parts of the name. A version string is constructed that does not include any "-" characters. It is appended to the name separated by "-", followed by some kind of sequence number (what is this called, "packaging version"), also separated by "-".

I have seen package names with as many as 4 "-" separated parts before the version number, such as "font-adobe-utopia-100dpi".

So the following awk command could input the full versioned name and output the version-less name:
Code:

awk -F- '{m=NF-2;s="";for(i=1;i<m;++i){s=s "-" $i;};print substr(s,2);}'
Is this correct or do I need to know more about this than I figured so far?

NoStressHQ 09-30-2013 09:45 AM

Try using regular expressions instead of parsing the string with bare hands.

allend 09-30-2013 09:54 AM

If you google for slackware package naming convention, this is the top hit. http://www.slackware.com/~mozes/docs...esentation.pdf
Is this what you mean?
Code:

bash-4.2$ echo "icedtea-web-1.4-x86_64-2alien.txz" | rev | cut -d'-' -f4- | rev
icedtea-web


TommyC7 09-30-2013 10:01 AM

If I'm understanding this correctly, you're trying to get just the package name (or package name with version)?

I don't know a whole lot of awk, so I use this (for package name only):
Code:

rev | cut -f 4- -d "-" | rev
So if I wanted a list of installed packages without their version name:
Code:

ls -1 /var/log/packages | rev | cut -f 4- -d "-" | rev
Personally I'm not a huge fan of the whole: `rev | cut | rev' thing but I haven't figured out a way to do it without rev in shell so I've stuck with it.

If you want package names with version, you just need to change the field list to "3-" so it looks like:
Code:

ls -1 /var/log/packages | rev | cut -f 3- -d "-" | rev
You can of course, use the one with the package name and a version, then just take off the version with another `cut' probably.

Skaperen 09-30-2013 10:11 AM

Quote:

Originally Posted by NoStressHQ (Post 5037312)
Try using regular expressions instead of parsing the string with bare hands.

I could not figure out such an expression for this.

Didier Spaier 09-30-2013 10:15 AM

Why reinvent the wheel? Just have a look at functions package_base() and package_name() in /sbin/{install,remove,upgrade}pkg ;)

ERRATUM read pkgbase(), not package_base()

Skaperen 09-30-2013 10:18 AM

Quote:

Originally Posted by TommyC7 (Post 5037325)
If I'm understanding this correctly, you're trying to get just the package name (or package name with version)?

I don't know a whole lot of awk, so I use this (for package name only):
Code:

rev | cut -f 4- -d "-" | rev
So if I wanted a list of installed packages without their version name:
Code:

ls -1 /var/log/packages | rev | cut -f 4- -d "-" | rev
Personally I'm not a huge fan of the whole: `rev | cut | rev' thing but I haven't figured out a way to do it without rev in shell so I've stuck with it.

If you want package names with version, you just need to change the field list to "3-" so it looks like:
Code:

ls -1 /var/log/packages | rev | cut -f 3- -d "-" | rev
You can of course, use the one with the package name and a version, then just take off the version with another `cut' probably.

Actually, the "whole" 'rev | cut | rev' thing makes sense. For me "rev" just wasn't in my mental toolkit so I never thought to try it (I don't think I've ever used it for anything). I guess my background of lots of "by hand" parsing in C bent my mind in the direction of doing it "by hand" in shell with awk.

I was focused more on "is this really the naming scheme" (my google search just didn't come up with anything, perhaps because I did not use the term "convention"), rather than "how could one parse this" (I have no trouble with that ... I just do it by hand).

Skaperen 09-30-2013 10:25 AM

Quote:

Originally Posted by Didier Spaier (Post 5037336)
Why reinvent the wheel? Just have a look at functions package_base() and package_name() in /sbin/{install,remove,upgrade}pkg ;)

I didn't see "package_base()" in there. I did see "pkgbase()" but it's just removing the extension (not something I need ... at least not yet).

I did see "package_name()" but it seems to be more complex and I don't really follow it. Can the name scheme be described in English? (or French or German or Norwegian is OK)

gnashley 09-30-2013 10:32 AM

If you are using bash, then simply:
PKG=full-name-version-arch-build #(with or without *.txz)
echo NAME=${PKG%-*-*-*}
You are correct, the separator is the '-' character and fields should be viewed from right to left. In other words, if you have a version number(or arch or build) with a '-' in them, then installpkg will be confused. Names can have any number of '-' chars in them as you like.

Skaperen 09-30-2013 10:43 AM

Here is PART of what I am going to be doing with this. I want a search mechanism where an exact package can be found, rather than a prefix (that would be tempting but for what I'm doing would cause problems). If I did a prefix type search then "sysvinit" could match all of "sysvinit-2.88dsf-i486-3.txz" and "sysvinit-functions-8.53-i486-2.txz" and "sysvinit-scripts-2.0-noarch-15.txz". But I really want "sysvinit" to match "
sysvinit-2.88dsf-i486-3.txz". To get "sysvinit-functions-8.53-i486-2.txz" then "sysvinit-functions" should be used. This is because of the way I am building a list of packages that will be used to select package files for installation (it will also allow specifying the package with the version).

I don't need help on how this will be done. I was just looking for confirmation of the name scheme, that the last 3 parts separated by "-" are not part of the name itself.

Skaperen 09-30-2013 10:49 AM

Quote:

Originally Posted by gnashley (Post 5037347)
If you are using bash, then simply:
PKG=full-name-version-arch-build #(with or without *.txz)
echo NAME=${PKG%-*-*-*}
You are correct, the separator is the '-' character and fields should be viewed from right to left. In other words, if you have a version number(or arch or build) with a '-' in them, then installpkg will be confused. Names can have any number of '-' chars in them as you like.

At this point in my code development I'm taking the full file name and coming up with just the versionless name. See my awk script. See the "rev|cut|rev" method it seems most everyone else uses. Do you have something that would be better?

ruario 09-30-2013 11:00 AM

Quote:

Originally Posted by NoStressHQ (Post 5037312)
Try using regular expressions instead of parsing the string with bare hands.

Quote:

Originally Posted by Skaperen (Post 5037331)
I could not figure out such an expression for this.

Here it is as a possible regex:

Code:

$ ls /var/log/packages | sed -r 's/^([[:graph:]]+)(-[[:alnum:]\.\+_]+){3}$/\1/'
EDIT: P.S. I checked and it gives the same result as the earlier command with rev:

Code:

$ diff -s <(ls /var/log/packages | rev | cut -f 4- -d "-" | rev) <(ls /var/log/packages | sed -r 's/^([[:graph:]]+)(-[[:alnum:]\.\+_]+){3}$/\1/')
Files /dev/fd/63 and /dev/fd/62 are identical


GazL 09-30-2013 11:13 AM

This is what I use in one of my scripts. It generates a list of available packages using the following approach
Code:

gazl@ws1:~$ function reformat_available() {    sed -e 's:^\(.*/\)\(.*\)-\([^-]*\)-\([^-]*\)-\([0-9]\+\)\(.*\)\(\.t.z\)$:\2 \2-\3-\4-\5\6 \1\2-\3-\4-\5\6\7:'; }
gazl@ws1:~$ find /local/slackware/slackware64-current/slackware64/ -name "*.t?z" | sort | reformat_available

The output is formatted into 3 fields: base package name, versioned package name and the full filepath of the package on disk.

If you want to look-up a specific package it's just a case of tightening the grep using the appropriate anchors.
Code:

gazl@ws1:~$ find /local/slackware/slackware64-current/slackware64/ -name "*.t?z" | reformat_available | grep sysvinit
sysvinit-functions sysvinit-functions-8.53-x86_64-2 /local/slackware/slackware64-current/slackware64/a/sysvinit-functions-8.53-x86_64-2.txz
sysvinit-scripts sysvinit-scripts-2.0-noarch-15 /local/slackware/slackware64-current/slackware64/a/sysvinit-scripts-2.0-noarch-15.txz
sysvinit sysvinit-2.88dsf-x86_64-3 /local/slackware/slackware64-current/slackware64/a/sysvinit-2.88dsf-x86_64-3.txz
gazl@ws1:~$ find /local/slackware/slackware64-current/slackware64/ -name "*.t?z" | reformat_available | grep "^sysvinit "
sysvinit sysvinit-2.88dsf-x86_64-3 /local/slackware/slackware64-current/slackware64/a/sysvinit-2.88dsf-x86_64-3.txz
gazl@ws1:~$


Lennie 09-30-2013 11:43 AM

You need to store all candidates in an array, and loop through them until you find the package you want.
A simple example to illustrate it:
Code:

$ pkgs=$(find . -name "sysvinit*")
$ echo ${pkgs[@]}
./sysvinit-2.88dsf-x86_64-2 ./sysvinit-functions-8.53-x86_64-2 ./sysvinit-scripts-2.0-noarch-13
$ for i in ${pkgs[@]}; do
> i=${i##*/}
> i=${i%-*-*-*}
> echo $i
> if [[ "$i" == sysvinit ]]; then
> echo "found it: $i"
> fi
> done
sysvinit
found it: sysvinit
sysvinit-functions
sysvinit-scripts
$


Skaperen 09-30-2013 12:27 PM

Quote:

Originally Posted by GazL (Post 5037372)
This is what I use in one of my scripts. It generates a list of available packages using the following approach
Code:

gazl@ws1:~$ function reformat_available() {    sed -e 's:^\(.*/\)\(.*\)-\([^-]*\)-\([^-]*\)-\([0-9]\+\)\(.*\)\(\.t.z\)$:\2 \2-\3-\4-\5\6 \1\2-\3-\4-\5\6\7:'; }
gazl@ws1:~$ find /local/slackware/slackware64-current/slackware64/ -name "*.t?z" | sort | reformat_available

The output is formatted into 3 fields: base package name, versioned package name and the full filepath of the package on disk.

If you want to look-up a specific package it's just a case of tightening the grep using the appropriate anchors.
Code:

gazl@ws1:~$ find /local/slackware/slackware64-current/slackware64/ -name "*.t?z" | reformat_available | grep sysvinit
sysvinit-functions sysvinit-functions-8.53-x86_64-2 /local/slackware/slackware64-current/slackware64/a/sysvinit-functions-8.53-x86_64-2.txz
sysvinit-scripts sysvinit-scripts-2.0-noarch-15 /local/slackware/slackware64-current/slackware64/a/sysvinit-scripts-2.0-noarch-15.txz
sysvinit sysvinit-2.88dsf-x86_64-3 /local/slackware/slackware64-current/slackware64/a/sysvinit-2.88dsf-x86_64-3.txz
gazl@ws1:~$ find /local/slackware/slackware64-current/slackware64/ -name "*.t?z" | reformat_available | grep "^sysvinit "
sysvinit sysvinit-2.88dsf-x86_64-3 /local/slackware/slackware64-current/slackware64/a/sysvinit-2.88dsf-x86_64-3.txz
gazl@ws1:~$


This is very close to what I want to do. But this is going to be something that repeats the search for all packages from a given list. So my idea is to generate the list that maps the non-version basename and version basename to full path just once and store that in a file. Then I can run grep to do the search ... many times.

Skaperen 09-30-2013 12:30 PM

I may end up re-writing my code from Bash to Python. That will change things quite a bit. Then it will be easy to have the entire list of packages in a dictionary indexed by version and non-version base names giving full path.

GazL 09-30-2013 01:59 PM

I took a sequential approach using sorted input rather than go down that route. My script (it's a system update aid akin to slackpkg but with a different approach) offloads most the gruntwork to join, comm, and sort.

Code:

root@ws1:~# time slacklist upgrade install
/local/slackware/extras/packages/kernel-3.11.0-custom-none-x86_64-1_local.txz
/local/slackware/slackware64-current/slackware64/a/kernel-generic-3.10.12-x86_64-1.txz
/local/slackware/slackware64-current/slackware64/a/kernel-huge-3.10.12-x86_64-1.txz
/local/slackware/slackware64-current/slackware64/a/kernel-modules-3.10.12-x86_64-1.txz
/local/slackware/slackware64-current/slackware64/k/kernel-source-3.10.12-noarch-1.txz

real    0m0.157s
user    0m0.113s
sys    0m0.010s

0.157s elapsed to compare the packages installed on my system to those available on my local mirrors. Can't be bad.
Originally I used only bash internals to manipulate the data (along the lines of the example gnashley made earlier) and it was much slower than sorting and using join, comm and such.

I briefly considered recoding it in perl but what I have works so well I couldn't really see the point and it's nice having runtime requirements that are only bash + coreutils.

gnashley 10-01-2013 02:53 AM

Really, rev|cut|rev?, awk?? python??? What could be simpler than:
Code:

PKG='sysvinit-functions-8.53-x86_64-2.txz'
echo NAME=${PKG%-*-*-*}


Didier Spaier 10-01-2013 03:11 AM

Quote:

Originally Posted by gnashley (Post 5037804)
Really, rev|cut|rev?, awk?? python??? What could be simpler than:
Code:

PKG='sysvinit-functions-8.53-x86_64-2.txz'
echo NAME=${PKG%-*-*-*}


+1. And this should work with any POSIX compliant shell.

ponce 10-01-2013 03:51 AM

1 Attachment(s)
Quote:

Originally Posted by gnashley (Post 5037804)
Code:

PKG='sysvinit-functions-8.53-x86_64-2.txz'
echo NAME=${PKG%-*-*-*}


http://i.imgur.com/j74SykU.gif

GazL 10-01-2013 03:58 AM

Yep, gnashley's approach is what I normally use in these situations. Bash isn't very efficient when running these sort of manipulations but unless you're processing vast amounts of data it won't really matter.

Here's two different approaches to what I was doing above
Code:

gazl@ws1:~$ cat /tmp/testing.sh
#!/bin/bash

while read path
do
  pkgfile="${path##*/}"
  pkgver="${pkgfile%.t?z}"
  pkgbase="${pkgver%-*-*-*}"
  echo $pkgbase $pkgver $path
done < <( find /local/slackware/slackware64-current/slackware64 -name "*.t?z" | sort)

gazl@ws1:~$ time /tmp/testing.sh >/dev/null

real    0m0.077s
user    0m0.053s
sys    0m0.023s
gazl@ws1:~$ cat /tmp/testing2.sh
#!/bin/bash

function reformat_available()

  sed -e 's:^\(.*/\)\(.*\)-\([^-]*\)-\([^-]*\)-\([0-9]\+\)\(.*\)\(\.t.z\)$:\2 \2-\3-\4-\5\6 \1\2-\3-\4-\5\6\7:'
}

find /local/slackware/slackware64-current/slackware64/ -name "*.t?z" | sort | reformat_available
gazl@ws1:~$ time /tmp/testing2.sh >/dev/null

real    0m0.028s
user    0m0.027s
sys    0m0.000s
gazl@ws1:~$

As you can see, the sed version is much faster and uses less cpu -- though neither are slow enough for it to matter for such a small amount of input data. The reason I used sed in my script was because it was already using 'join','comm' and 'sort' so having an external dependency on sed really didn't make much difference ( plus it was a bit of an experiment ;) ).

P.S. Of course, the bash version is infinitely more readable than the sed/regex. :D

diwljina 10-01-2013 05:09 AM

Wrong post, didn't read the question right.

gnashley 10-01-2013 12:41 PM

"bash version is infinitely more readable than the sed/regex" in this case by a lot! But often it is the other way around.

Skaperen 10-02-2013 03:50 PM

Quote:

Originally Posted by gnashley (Post 5038099)
"bash version is infinitely more readable than the sed/regex" in this case by a lot! But often it is the other way around.

Indeed. But this was a new one for me. Glad you guys jumped in with it.

Didier Spaier 10-02-2013 04:31 PM

This one, found in pkgtool and copyright Patrick Volkerding, maybe hard to read but is super fast!
Code:

create_list_of_installed_packages()
{
        FILES=$(ls $ADM_DIR/packages)
      if [ -n "$FILES" ]; then
      cd $ADM_DIR/packages
      { grep '^PACKAGE DESCRIPTION:$' -Z -H -m1 -A1 $FILES; echo; } \
      | sed -n 'h;n;/\x00/{h;n;};x;s/  */ /g;s/ $//;s/[\"`$]/\\&/g
      s/\(.*\)\x00\([^:]*:\)\? *\(.*\)/ "\1" "\3" "View information about package \1" \\/;p' > $TMP/list_of_installed_packages \

      fi
}



All times are GMT -5. The time now is 10:59 AM.