Monthly Archive for March, 2004

Embedding Lua interpreter into RPM

I’ve recently committed into the RPM CVS HEAD the internal support for Lua scripts.

Please, notice that this is experimental stuff.

Why embedding Lua in RPM?

  • Many scripts execute simple operations which in an internal interpreter require no forking at all
  • Internal scripts reduce or eliminate external dependencies related to script slots
  • Internal scripts operate even under unfriendly situations like stripped chroots (anyone said installers?)
  • Internal scripts in Lua are really fast
  • Syntax errors in internal scripts are detected at package building time

How it works?

Just use -p <lua> in any script slot (%pre, %post, etc).

For example:

%pre -p <lua>
print("Wow! It really works!")

What is accessible from Lua?

The standard Lua library, the posix module (basic system access, by Luiz Henrique de Figueiredo and Claudio Terra), and the rex module (regular expressions, by Reuben Thomas).

Macro support

Support for Lua macros was also introduced. It means that one can create custom content using Lua macros anywhere.

For example:

%{lua: print("Requires: hello-world > 1.0") }

More additions to APT-RPM Lua interface

The APT-RPM Lua interface is constantly being improved. This time, the following functions were added:

pkgid() and verid()

Return a unique integer identifying a package or a version.

verpkg()

Returns the parent package of some given version.

verdeplist()

Returns a list of dependencies for a given package, including complete information about it.

These new functions were introduced to give support for something which is frequently asked by APT-RPM users: the ability to discover which installed packages are not required by any other installed package.

Here is a script using these functions to list these packages. This script will be called list-nodeps, and will be available in the contrib/ directory of the next APT-RPM release.

-- Collect dependencies from installed packages
deplist = {}
verlist = {}
for i, pkg in ipairs(pkglist()) do
    ver = pkgvercur(pkg)
    if ver then
        table.insert(verlist, ver)
        for i, dep in ipairs(verdeplist(ver)) do
            for i, depver in ipairs(dep.verlist) do
                deplist[verid(depver)] = true
            end
        end
    end
end

-- Now list all versions which are not dependencies
for i, ver in ipairs(verlist) do
    if not deplist[verid(ver)] then
        name = pkgname(verpkg(ver))
        if name ~= "gpg-pubkey" then
            -- Print package name and version without epoch
            -- (rpm -e friendly ;-) .
            print(name.."-"..string.gsub(verstr(ver), "^%d+:", ""))
        end
    end
end

More information about the introduced functions is available in https://moin.conectiva.com.br/AptRpm/Scripting

New KDE frontend for APT-RPM

Here is a screenshot of Kynaptic, a new experiment I’m working on. This is a KDE-based frontend for APT-RPM and APT. Kynaptic is based on Synaptic, and shares the same base code on top of the APT library.

On the right side you see a new toy: the interactive search dialog. This should definetly improve the user experience while looking for packages, and could eventually be ported to Synaptic itself.

Another interesting point is that during the development process of Kynaptic I’m also cleaning up the Synaptic code, something I had in my mind for some time already.

APT-RPM article now in portuguese

I’ve translated to portuguese (pt_BR) the APT-RPM article I wrote for LWN. It’s available in printed media on Revista do Linux #50, and also on the LinuxIT site.

Toy interpreter for Linear Algebra

While working with Linear Algebra, I’ve decided to build a toy interpreter in C to play around. This was a quite interesting experiment for myself, since it was the first time I’ve built a complete (with tokenizer, compiler, and interpreter) and auto-suficient (no external dependencies, no additional tools) interpreter from the ground.

The interpreter is currently 1076 lines long, and is based on a tokenizer for the grammar, a compiler which creates a list of trees of expressions, an interpreter for the generated structure, and two modules for symbol maintenance and matrix operations.

Here is a quick example:

a = 2*3+4/2
print(a)

b = [1,2,3|4,5,6]
c = [1,2,3|4,5,6]
print((b+c)/2)
print(trans(b))

d = [1,0|-2,3|5,4|0,1]
e = [0,6,1|3,8,-2]
print(d*e)

f = [1,2|3,4]
print(det(f))
f = [2,3,4|-5,5,6|7,8,9]
print(det(f))
f = [1,-4,2,-2|4,7,-3,5|3,0,8,0|-5,-1,6,9]
print(det(f))

And here is the output:

8
[ 1, 2, 3 | 4, 5, 6 ]
[ 1, 4 | 2, 5 | 3, 6 ]
[ 0, 6, 1 | 9, 12, -8 | 12, 62, -3 | 3, 8, -2 ]
-2
-45
2042

New RPM transaction locking

Last week I’ve worked with Jeff Johnson to fix a small RPM issue which was bothering us for quite some time. Until this change, RPM was accepting two transactions to be run at the same time but, unfortunately, this might put the database in an inconsistent state, and some headers might get lost while restoring it with –rebuilddb.

Our fix was rather simple, based on fcntl() locking while transactions are being committed to the system. This should be enough, protecting databases while the issue is not fixed The Right Way (the time consuming one ;-) ).

Developers of applications linked with RPM should not worry about additional errors, since the current behavior is to wait for the lock to be released while entering in the transaction committing function.