Search Results: "ron"

25 July 2012

Diego Escalante Urrelo: A Coru a, d a uno

You can follow the latest GUADEC updates from @guadec and @diegoe.

Isa, Alejo, Laura, and Germ n stealing a mug.

GUADEC just started. Or at least, the arrangements for GUADEC.

The local team is hard at work at the GUADEC HQ of the Facultade de Inform tica, they are really working really hard to make sure that there is a proper wired network setup (yes, you read that right!), a great video setup to record all the talks and publish them as soon as possible and setting up the final details of rooms, info desk, accommodation

If you are staying at the Rialta, you can take the hourly bus to the Facultade (just ask the driver). The bus departs from the frontis of Block 3. Ask the driver to let you know when to get off the bus. He is aware of GUADEC so your gringo-spanish should suffice.

We will be holding a pre-registration party tonight at 21:00 (9pm) just outside the Rialta cafeteria. If you are already here drop by for the Queimada by Alejo, our galician wizard.

Vincent Sanders: A sad state of affairs

Surprisingly my previous post on my Debconf trip has gathered more queries over its title than anything else.

Mostly my blog titles are, if I can manage it, relevant quotes or book titles. For the last post I used the title of a collection of Mark Twain scripts surrounding his trip through Nicaragua in 1866.

I have not been able to read the publication myself beyond the quoted excerpts in more modern articles because, somehow, almost 150 years after the words were written the only access to these words is to buy a very expensive and rare 1940 publication.

This appears to stem from the fact the original Clements scripts were simply not published before 1940 and hence appear to gain copyright from that date (IANAL I might be wrong here is the source I used) and thanks to the US government effectively making copyrighted works published after 1922 be "protected" forever I may never read it at all.

Rather sad really, but if you do have a copy I could borrow...oh no that is probably illegal too? better just let the words fade to dust eh?

24 July 2012

Gunnar Wolf: Electronic voting: Talk delivered in Moquegua (Peru)

TitleElectronic voting: Talk delivered in Moquegua (Peru)
Publication TypeAudiovisual
Year of Publication2012
AuthorsWolf G
Date Published07/07/2012
CityMoquegua, Per
Full TextWhile we were at DebConf, all busy and in the organizing frenzy, I was supposed to deliver a talk in Moquegua, Per , on the evening of July 7. Of course, I was unable to attend. Nevertheless, I accepted, if the talk could be delivered as a pre-recorded video with a live Q&A session afterwards. And so it was.
The talk went quite smooth, and I think I will use bits of it. Video quality is far from great, but well... it was taken using nothing but a webcam and the laptop's integrated microphone. To my surprise, sound quality that's what matters! works quite well.
I mostly followed the attached presentation; the video is split in three parts to make it easier to download.
And yes, it's all in Spanish. Translations are, of course, welcome :)
AttachmentSize
Presentation slides (PDF)561.5 KB
Presentation video (1/3)76.57 MB
Presentation video (2/3)55.26 MB
Presentation video (3/3)137.46 MB

Gunnar Wolf: Ten theses in favor of free download of cultural goods on the Internet (by Enrique G. Gallegos)

This is one of the days where reading my everyday newspaper was worth more than just getting bitter at the news. I found this text in La Jornada, my usual newspaper. I liked it very much, and decided to translate it for a wider audience. Of course, if you can read Spanish, do yourself a favor and go to the original. It is not that the text is so easy to translate. And, after all, I'm not a native English writer. I'm trying to do a literal translation, even when disagreeing with the author. Ten theses in favor of free download of cultural goods on the Internet Enrique G. Gallegos Poet and philosopher. Currently a researcher in Universidad Aut noma Metropolitana-C
  1. Historical legacy. Criticists who promote the persecution of piracy and free downloads of cultural works from the Internet argue that the patrimonial rights have been wronged; they start off suposing that a cultural work is formed from a historical void, as if there was a "nothing" to begin with, and then a "something" appeared. Nothing more fallacious: All cultural products has its precedents, and thanks to these it generates part of its best forces.
  2. Opening towards the future. Human beings are projected into the future. As the main philosophies of the 20th century have explored, one of the singular characteristics of mankind is the ability to think and imagine the future. Products of culture are the best ways to think and project society, politics, love, hope, needs, failures A song, a poem, an essay, can trigger imaginary worlds with a transformative potential. To deny this to humanity with "patrimonial damage" as an argument is to mutilate man's temporal nature.
  3. Recognition of the present. Cultural works generate moments of reflection, criticism and pleasure; they can trigger actions demanding commitment, solidarity and strong indignation against injustice. If every cultural work is adscribed in some way to a historic tradition, and if cultural products anre necessary to imagine other possible worlds and open our future, it's not less true that they also allow us to recognize our present by making us more sensitive to others' ideas, sensations and emotions. Without culture, there is no present nor others' presence.
  4. Divulgation of the cultural heritage. If culture is "heritage of mankind", it should be also spread by any possible way. But not just spread, but actively sought for the biggest number of people to be able to effectively have access to it. In a potentially interconnected world, Internet is the most adequate world for it (despite its limitations). Therefore, penalizing free downloads means avoiding spreading it and restricting access to those groups who don't have enough economic resources.
  5. Preserving cultural heritage. If we agree that cultural works are heritage of mankind, we need to take every action needed to preserve them. But preserving culture does not only mean keeping the products in museums, galleries or never-polluted drawers; it rather means to keep them in the collective memory and in the flow of constant interpretations and appropiations. Said in other words, the genuine way to preserve culture is to allow universal access to cultural goods. That's why, holding that free copies and downloads of books, music, videos, etc. over the Internet are harmful, is an incompatible argument with the obligation to preserve cultural heritage.
  6. They are not goods. Cultural works are material and spiritual manifestations of mankind, concretions of its historicity; they are, also, expressions of emotions, ideas and projections of other lives and other worlds. That's why they cannot be equated to goods or inserted in patrimonialist logic. The market might want to cheat by giving a certain price to a painting by Orozco or auctioning a Baudelaire manuscript, but it will never be able to aprehend their true meaning as cultural works. And it's not that culture is not faluable, but taht its estimation criteria do not follow the rules of market, but those of the imponderable and unlimited.
  7. Price disproportion. Assuming we accept the possibility that intermediaries charge for the services they perform, the value of a book, record or movie should never exceed the daily wage of a worker or employee. But this ellection would only be one more option within the effective possibility that people opt to download or freely copy the cultural work. The final decision as to which media to go to should be a sovereign resolution of the culture-interested person.
  8. The principle of the most benefit. Even when copies and free downloads over Internet could generate a patrimonial "wrong" to third parties, the cultural benefit obtained by it will always be greater in as much that it carries out intensely the principle to foster, spread and access the cultural heritage of mankind. To think otherwise is to privilege the few over the many.
  9. The real evil is elsewhere. Murder, women- and children-trade, poverty and misery are the real evils that ache mankind. According to the United Nations, in 2010 there were 468 thousand murders in the world; the estimation is that 3500 million people live in poverty; in their 2009 inform, the UN found over 2400 victims of "people trade", kidnapped as sex slaves; in some regions in Africa, close to 30% of children suffer acute malnutrition and six people (between children and adults) die every day from hunger. That's why pretending that free download of cultural works is an evil is clearly a tricky and deceptive speech
  10. Against the intermediary-salesman. Culture does not need intermedieries that reduce cultural works to goods. Culture is too important to leavie it in the hands of salespeople that simplistly equate cultural goods with cakes. An intermediary of this kind will never understand the difference between a work of art and a disposable razor blade. What the world needs is more support from the government from every country to artists, creators and poets, as well as ensuring the conditions for the absolute mobility freedom for cultural works.

Sylvestre Ledru: News on Debian & clang

A couple week ago, during the last debconf (Debian Conference) in Managua/Nicaragua, I presented the latest developments about the inclusion of clang in the Debian architecture. To sum up (details are available in the slides and the video), the rebuild of the Debian archive with Clang 3.1 increased the number of failures from 8.8 to 12.1%. The main reason is that further checks have been added to clang. With Paul Tagliamonte as co-mentor and Alexander Pashaliyski as a GSoC student, we made great progress in bringing Clang as A new compiler in the Debian infrastructure. The various feedbacks that I had during Debconf were pretty good. It interests many people for reasons like Quality Assurance (more checks), performances, hackability or to decorrelate Debian and GCC. Build Debian with another compiler - Slides
Build Debian with another compiler - Video A nice resume of my talk has been made by Michael Larabel on Phoronix:
Decoupling GCC From Debian By Using LLVM/Clang

Wouter Verhelst: Runner scripts

Bert Desmet blogs about having to run a script more than once per minute, and using a runner script (started from cron) to do that. Unfortunately, his implementation contains a race condition:
if ! ps -p $(cat /path/to/runner.pid);
  then
    echo $$ > /path/to/runner.pid
If the script is accidentally started twice on approximately the same moment, chances are pretty high you'll see them both executing the ps call at approximately the same time, concluding that no other script is running, and then both executing the echo call at the same time. Result: your script will be running twice, yet you'll have only one pid file. Of course, if you do indeed run the script only from cron, and just once every 30 minutes, as in Bert's case, chances that you'll hit this race condition are pretty low. However, race conditions are bad, especially if they're easy to avoid.
set -o noclobber
if ! echo $$ > /var/run/runner.pid
then
  echo pidfile exists; exiting
  exit 0
fi
This code uses the noclobber shell option, which causes the shell to issue an error state if the file we try to overwrite with > already exists, and to do so in an atomic operation (so, no race condition there: either the file exists and we fail, or the file does not exist yet and we create it with our PID). Of course, that leaves out the check for is the other process running? Adding a second check for that is fairly complex to do right, as this cannot be done in an atomic operation; so it's usually better use exit traps to clean up the file:
set -o noclobber
if ! echo $$ > /var/run/runner.pid
then
  echo pidfile exists; exiting
  exit 0
fi
trap EXIT rm -f /var/run/runner.pid
This will fail if the system dies when the script is running, but then since we use /var/run (which is cleared on bootup, either because it's a tmpfs or because the initscripts clean it) this means the file should only ever be stale if some genius kills our process with kill -9 or kill -11.

Wouter Verhelst: DebConf 12 is over :(

As I write this, DebConf12 has actually been over for more than a week. Usually during DebConf, I'm a more proficient blogger than during other times of the year, since I'm not doing as much work that I have to remain quiet about at that time, which simply means I have more to blog about. Unfortunately, however, this year the server on which this blog runs managed to become unavailable on the second day of DebCamp, an issue that I could only fix once I was back in Belgium, which meant I haven't been able to blog as much as I would've wanted to. Anyway, all I can say is that both DebConf and DebCamp have been a huge success for me again, this year. I'd started the second rewrite of ipcfg a few weeks before DebCamp, and spent most of DebCamp whipping the basic framework into shape. It's nowhere near ready yet, but I'm confident it'll get further this time than it did before. During DebConf, I was also responsible for doing the group photo. I'd done that (together with Andrew McMillan) during DebConf8 before (if you look closely, you'll see me pressing the remote which actually triggers that picture), and I still like that picture. This time around, we didn't have a beach nearby (at least not as nearby as during DebConf8), so we had to do things slightly differently. Rather than doing one large picture, I took several pictures and used Hugin to stitch them together. Unfortunately however, some things did go wrong with the group photo. For starters, the weather wasn't very helpful, in that I noticed it was about to rain. As such, the main bunch of pictures were taken slightly before the announced time of 14:30, which meant that some people had missed it. To make matters worse, I had rushed to the group and handed the camera to someone else, so that I could gimp myself onto the picture too; but that meant that some people who were arriving as these pictures were being taken thought they were on the picture, when they really weren't. I've fixed most of these by just gimping them into the picture as well, but I might've missed some of them. If you're one of them, talk to me! Preferably now. If you're not one of them (or even if you are), hold off on doing things like printing it in large format or some such. I'll re-upload improved versions onto the same location once they're ready.

Sylvestre Ledru: News on Debian & clang

A couple week ago, during the last debconf (Debian Conference) in Managua/Nicaragua, I presented the latest developments about the inclusion of clang in the Debian architecture. To sum up (details are available in the slides and the video), the rebuild of the Debian archive with Clang 3.1 increased the number of failures from 8.8 to 12.1%. The main reason is that further checks have been added to clang. With Paul Tagliamonte as co-mentor and Alexander Pashaliyski as a GSoC student, we made great progress in bringing Clang as A new compiler in the Debian infrastructure. The various feedback that I had during Debconf were pretty good. It interests many people for reasons like Quality Assurance (more checks), performances, hackability or to decorrelate Debian and GCC. Build Debian with another compiler - Slides
Build Debian with another compiler - Video A nice resume of my talk has been made by Michael Larabel on Phoronix:
Decoupling GCC From Debian By Using LLVM/Clang

23 July 2012

Enrico Zini: Evolution's old odd mail folders to mbox

Evolution's old odd mail folders to mbox Something wrong happened in my dad's Evolution. It just would get stuck checking mail forever, with no useful diagnostic that I could find. Fun. Not. Anyway, I solved by resetting everything to factory defaults, moving away all gconf entries and .evolution/ files. Then it started to work again, of course then I needed to reconfigure it from scratch. It turned out however that some old mail was only archived locally, and in a kind of weird format that looks like this:
$ ls -la Enrico/
total 336
drwx------ 2 enrico enrico   4096 Jul 23 03:05 .
drwxr-xr-x 7 enrico enrico   4096 Jul 23 03:12 ..
-rw------- 1 enrico enrico   3230 Dec  4  2010 113.HEADER
-rw------- 1 enrico enrico  14521 Dec  4  2010 113.TEXT
-rw------- 1 enrico enrico   3209 Oct 22  2010 134.HEADER
-rw------- 1 enrico enrico   2937 Oct 22  2010 134.TEXT
-rw------- 1 enrico enrico   3116 Jun 27  2011 15.
-rw------- 1 enrico enrico   3678 Jun 27  2011 168.
-rw------- 1 enrico enrico     73 Apr 27  2009 22.1.MIME
-rw------- 1 enrico enrico   3199 Apr 27  2009 22.2
-rw------- 1 enrico enrico     88 Apr 27  2009 22.2.MIME
[...]
I couldn't even find the name of that mail folder layout, let alone conversion tools. So I had to sit down and waste my sunday break writing software to convert that to a mbox file. Here's the tool, may it save you the awful time I had today: http://anonscm.debian.org/gitweb/?p=users/enrico/evo2mbox.git Note: feel free to fork it, or send patches, but don't bother with feature requests. Evolution isn't and won't be a personal interest of mine. Anything that makes an afternoon at my parents more tiresome than a whole busy month of paid work, doesn't deserve to be. Luckily they now seem to have changed the local folder format to Maildir.

22 July 2012

Evgeni Golov: RC bugs 2012/29

RCBW report for 2012/29 (16.7.-22.7.) The motto for this week was:
shut up and take my patches!
(Don t take it personally, it s just a meme :P)

21 July 2012

Siegfried Gevatter: A gentle introduction to Zeitgeist s Python API

In this post I ll make a quick introduction by example on how to use Zeitgeist s Python API for good and profit. If you re interested in using Zeitgeist from C instead, see the libzeitgeist examples; to use it with C++/Qt, Trever s a web browser in 4 steps may be of interest. First things first In case you re not familiar with Zeitgeist, it may prove helpful to first read Mikkel s introduction to Zeitgeist post. If that s too much to read, just should know that Zeitgeist is an event log. Like the history in your browser, it keeps track of what websites you open at which point in time. It also keeps track of when you close them, and of what browser you used, since it s a system-wide service. Furthermore, it does the same for files, conversations, e-mails, and anything else you want to insert into it. So Zeitgeist is a database of events, and an event can be pretty much anything. But what does it look like? It s main attributes are the following: Additionally, each event has one or more subjects, which have the following attributes: Retrieving recent data Okay, so let s say you want to know the last song you ve listened to (if you have a Zeitgeist-enabled music player). It s a simple as:
from zeitgeist.client import ZeitgeistClient
from zeitgeist.datamodel import *
 
zeitgeist = ZeitgeistClient()
 
def on_events_received(events):
    if events:
        song = events[0]
        print "Last song: %s" % song.subjects[0].uri
    else:
        print "You haven't listened to any songs."
 
template = Event.new_for_values(subject_interpretation=Interpretation.AUDIO)
zeitgeist.find_events_for_template(template, on_events_received, num_events=1)
 
# Start a mainloop - note: the Qt mainloop also works
from gi.repository import GLib
GLib.MainLoop().run()
This may need some explaining. We start by importing the Zeitgeist client and some associated data structures (such as Event and Interpretation), and create an instance of the client. The ZeitgeistClient class is a wrapper around Zeitgeist s D-Bus API which not only makes it much nicer to use, but also makes it easy to install monitors (as we will see later) and provides convenient functionality such as automatic reconnection if the connection to the engine is lost. To query for the most recent song, we just need to create a template with the restrictions we want to impose and submit it to Zeitgeist using the find_events_for_template call. If you haven t read Mikkel s post yet, please do so, as it introduces the structure of events and subjects (in short: an event has a timestamp, some other properties, and one or more subjects representing the resources -files, websites, people - involved in the event). The Python API is inherently asynchronous (if for some reason you need a synchronous API, you may still use the lower level ZeitgeistDBusInterface class), so we need to define a callback function to handle the results we receive from the Zeitgeist engine. Finally, we need to create a main loop so the asynchronous functions can run.
Now this was a pretty simple example. Let s make it more interesting. One song isn t much, so let s get the 5 most recent songs. Also, now we want both songs and videos. The first part is pretty easy, we just need to change the num_events parameter. For the second extension, we have to change the event template. In fact, now we need two different event templates and the find_events_for_templates function, which takes an arbitrary number of event templates and ORs them. The result is as follows:
from zeitgeist.client import ZeitgeistClient
from zeitgeist.datamodel import *
 
zeitgeist = ZeitgeistClient()
 
def on_events_received(events):
    for event in events:
        print "- %s" % event.subjects[0].uri
 
tmpl1 = Event.new_for_values(subject_interpretation=Interpretation.AUDIO)
tmpl2 = Event.new_for_values(subject_interpretation=Interpretation.VIDEO)
zeitgeist.find_events_for_templates([tmpl1, tmpl2],
                                    on_events_received, num_events=5)
 
# Start a mainloop
from gi.repository import GLib
GLib.MainLoop().run()
This will work, but unless you re lucky you re likely to get some duplicate line. Why is this? Well, other than that you may have used the same file twice, don t forget that what you are requesting are actually events. If you ve started playing a given song, you probably also stopped playing it, so that s actually two of them (an AccessEvent and a LeaveEvent). Since this isn t what we want, we ll change the query a bit:
zeitgeist.find_events_for_templates(
    [tmpl1, tmpl2],
    on_events_received,
    num_events=5,
    result_type=ResultType.MostRecentSubjects,
    storage_state=StorageState.Available)
By requesting the most recent subjects, vs. the most recent events, we can filter out events with duplicate URI. See the ResultType documentation for other modes you can use. Note particularly the MostPopularSubjects result type. I also used the chance to introduce the storage_state parameter. This one will filter out events for files Zeitgeist knows aren t available (this mostly means online resources won t be shown if you don t have a network connnection; there s also support for handling external storage media, but because of problems with GIO this is currently disabled). Last but not least, the find_events_for_* methods also accept a timerange parameter. It defaults to TimeRange.until_now(), but you may change it to TimeRange.always() (if for some reason you re working with events in the future) or to any other time range of your choice. Here it s important to note that Zeitgeist s timestamps use millisecond precision.
For more advanced queries, you can use more complex combinations of events and subject templates. The rule to keep in mind here is that events are OR d and subjects are ANDed. Additionally, some field (actor, origin, mimetype, uri and current_uri) may be prefixed with an exclamation mark ( ! ) for NOT, or you may append an asterisc ( * ) to them for prefix search. You can even combine the two operators together. Here s an example of a template you could build:
subj1 = Subject.new_for_values(interpretation=Interpretation.SOURCE_CODE,
                               uri="file:///home/rainct/Development/*")
subj2 = Subject.new_for_values(uri="!file:///home/rainct/Development/zeitgeist/*")
tmpl1 = Event.new_for_values(interpretation=Interpretation.MODIFY_EVENT,
                             subjects=[subj1, subj2])
templates = [tmpl1]
In my case, this template would fetch a list of the source code files I modified most recently but excluding those related to the Zeitgeist project. Working with big sets of data In case you re trying to do something crazy, you may end up with a Zeitgeist query complaining that it exceeded the memory limit. You re not supposed to do that. Instead, we provide some methods for working with large collections of events.
from zeitgeist.client import ZeitgeistClient
from zeitgeist.datamodel import *
 
zeitgeist = ZeitgeistClient()
 
def on_events_received(events):
    for event in events:
        print '- %s' % event.subjects[0].uri
 
def on_ids_received(event_ids):
    print 'A total of %d source code files were found.' % len(event_ids)
    print 'Fetching the first 100...'
    zeitgeist.get_events(event_ids[:100], on_events_received)
 
tmpl = Event.new_for_values(subject_interpretation=Interpretation.SOURCE_CODE)
zeitgeist.find_event_ids_for_templates(
    [tmpl],
    on_ids_received,
    num_events=10000, # you can use 0 for "all events", but do you really need to?
    timerange=TimeRange.from_seconds_ago(3600*24*30*3),
    result_type=ResultType.MostPopularSubjects)
 
# Start a mainloop
from gi.repository import GLib
GLib.MainLoop().run()
And there you have the source code files you worked with during the last 3 months, ordered from most to least popular (popularity is measured counting the number of events; for more precision, maybe you could limit the results to events with interpretation AccessEvent). Why do we provide this mechanism instead of querying with a simple offset? Well, this avoids problems when the log changes (events are inserted or deleted). Have you ever been exploring the latest posts in some website, and as you change to the next page some of the results from the previous page show up again (because new posts have been added in the meantime)? With Zeitgeist this won t happen. Receiving information in real time At this point you re an expert at requesting all sorts of data from Zeitgeist, but now you want to show a list of the last kitten images you ve viewed, updated in real time. Don t worry, Zeitgeist can provide for this:
from zeitgeist.client import ZeitgeistClient
from zeitgeist.datamodel import *
 
zeitgeist = ZeitgeistClient()
 
def on_insert(time_range, events):
    # do awesome stuff with the events here
    print events
 
def on_delete(time_range, event_ids):
    # a previously inserted event was deleted
    print event_ids
 
templates = [Event.new_for_values(subject_uri='file:///home/user/kittens/*',
                                  subject_interpretation=Interpretation.IMAGE)]
zeitgeist.install_monitor(TimeRange.always(), templates, on_insert, on_delete)
 
# Start a mainloop
from gi.repository import GLib
GLib.MainLoop().run()
It s important to note that on_delete won t be called when an image is deleted (that d be a newly inserted event with interpretation=DELETE_EVENT); rather, it s called when a previously inserted event is deleted (for example, using the forget recent history option in Activity Log Manager). In case you re curious: for best performance, this doesn t actually use D-Bus signals. Instead, this little call will setup a D-Bus object behind the scenes and register it with the Zeitgeist engine, so it can notify said object when (and only when) an event of its interest is registered. To stop receiving notifications for a template, you ll need the save the object returned by the install_monitor call:
m = zeitgeist.install_monitor(TimeRange.always(), templates, on_insert, on_delete)
zeitgeist.remove_monitor(m)
Pro Tip: You can use the Zeitgeist Explorer GUI to quickly try out different queries (note: it s still work in progress, so much funcionality is missing, but it does work somewhat). Contextual awesomeness: finding related events By now you re familiar with retrieving events and keeping them up to date. Now it s time for a little secret:
import time
from zeitgeist.client import ZeitgeistClient
from zeitgeist.datamodel import *
 
zeitgeist = ZeitgeistClient()
 
def on_related_received(uris):
    print 'Related URIs:'
    for uri in uris:
        print ' - %s' % uri
 
query_templates = [Event.new_for_values(
    subject_interpretation=Interpretation.SOURCE_CODE,
    subject_uri='file:///home/rainct/Development/zeitgeist/*',
    subject_mimetype="text/x-vala")]
 
result_templates = [Event.new_for_values(
    subject_interpretation=Interpretation.WEBSITE,
    subject_manifestation=Manifestation.WEB_DATA_OBJECT)]
 
now = time.time()*1000
zeitgeist.find_related_uris_for_events(
    query_templates,
    on_related_received,
    time_range=TimeRange(now - 1000*3600*24*30*6, now),
    result_event_templates=result_templates,
    num_events=10)
 
# Start a mainloop
from gi.repository import GLib
GLib.MainLoop().run()
This little query example will return up to 10 websites I used at the same time as the Vala files inside my Zeitgeist directory, considering only data from the last 6 months. Nice, huh? This is an experimental feature, and it doesn t work well when operating on big inputs, so it s usually better to use the find_related_uris_for_uris variant (which replaces the first query_templates parameter with a list of URIs). Advanced searching: the FTS extension Some people think prefix searches aren t good enough for them, and this is why the Zeitgeist engine ships by default with a FTS (Full Text Search) extension. Using the methods provided by this extension you can perform more advanced queries against subjects current_uri and text properties (unlike the name may suggest, the FTS extension doesn t index the content of the files, but just the information in the event). This is exposed as zeitgeist_index_search in libzeitgeist (the C library), but unfortunately isn t currently available in the Python API. If you still need it, you ll have to fallback to pretty much using the D-Bus interface (you still get reconnection support, though). Here s an example:
from zeitgeist.client import ZeitgeistClient
from zeitgeist.datamodel import *
 
zeitgeist = ZeitgeistClient()
index = zeitgeist._iface.get_extension('Index', 'index/activity')
 
query            = 'hello' # search query
time_range       = TimeRange.always()
event_templates  = []
offset           = 0
num_events       = 10
result_type      = 100 # magic number for "relevancy" (ResultType.* also work)
 
def on_reply(events, num_estimated_matches):
    print 'Got %d out of ~%d results.' % (len(events), num_estimated_matches)
    events = map(Event, events)
    for event in events:
        print ' - %s' % event.subjects[0].uri
 
def on_error(exception):
    print 'Error from FTS:', exception
 
index.Search(query, time_range, event_templates,
             offset, num_events, result_type,
             reply_handler=on_reply, error_handler=on_error)
 
# Start a mainloop
from gi.repository import GLib
GLib.MainLoop().run()
The most interesting thing here is the query parameter. Quoting from the C documentation:
The default boolean operator is AND. Thus the query foo bar will
be interpreted as foo AND bar. To exclude a term from the result
set prepend it with a minus sign - eg foo -bar. Phrase queries
can be done by double quoting the string "foo is a bar". You can
truncate terms by appending a *.
There are a few keys you can prefix to a term or phrase to search
within a specific set of metadata. They are used like key:value.
The keys name and title search strictly within the text field of
the event subjects. The key app searches within the application
name or description that is found in the actor attribute of the
events. Lastly you can use the site key to search within the
domain name of the subject URIs.
You can also control the results with the boolean operators AND
and OR and you may use brackets, ( and ), to control the operator
precedence.
Modifying the log So far we ve only queried Zeitgeist for information, let s get a bit more active. You can delete events from Zeitgeist with the following query:
from zeitgeist.client import ZeitgeistClient
 
zeitgeist = ZeitgeistClient()
 
def on_deleted(timerange):
    print 'Deleted events going from %s to %s' % (timerange[0], timerange[1])
 
event_ids = [50] # put the IDs of the events you want to delete here
 
zeitgeist.delete_events(event_ids, on_deleted)
 
# Start a mainloop
from gi.repository import GLib
GLib.MainLoop().run()
The confirmation callback will receive a timerange going from the first to the last event. If no events were deleted (because they didn t exist), you ll get (-1, -1).
And now for the interesting part. If your application involves resources (files, websites, contacts, etc.) of any sort, you ll probably want to let Zeitgeist know that you re using them. It s time that you write a data-source! We start by registering the data-source. Here we go:
import time
from gi.repository import GLib
from zeitgeist.client import ZeitgeistClient
from zeitgeist.datamodel import *
 
zeitgeist = ZeitgeistClient()
 
def on_status_changed_callback(enabled):
    """ This method will be called whenever someone enables or disables
        the data-source. """
    if enabled:
        print 'Data-source enabled and ready to send events!'
    else:
        print 'Data-source disabled; don\'t send event, they\'ll be ignored.'
 
def register():
    # Always use the same unique_id. Name and description can change
    # freely.
    unique_id = 'com.example.your.data.source'
    name = 'user visible name (may be translated)'
    description = 'user visible description (may be translated)'
 
    # Describe what sort of events will be inserted (optional)
    subject_template = Subject()
    subject_template.interpretation = Interpretation.PLAIN_TEXT_DOCUMENT
    subject_template.manifestation = Manifestation.FILE_DATA_OBJECT
    templates = []
    for interp in (Interpretation.ACCESS_EVENT, Interpretation.LEAVE_EVENT):
        event_template = Event()
        event_template.interpretation = interp
        event_template.manifestation = Manifestation.USER_ACTIVITY
        event_template.append_subject(subject_template)
        templates.append(event_template)
 
    zeitgeist.register_data_source(unique_id, name, description, templates,
                                   on_status_changed_callback)
Once that s done (and if it is enabled), we are free to send our events:
def log(title, uri, opened):
    subject = Subject.new_for_values(
        uri=uri,
        interpretation=Interpretation.PLAIN_TEXT_DOCUMENT,
        manifestation=Manifestation.FILE_DATA_OBJECT,
        origin=GLib.path_get_dirname(uri),
        mimetype='text/plain',
        text=title)
    event = Event.new_for_values(
        timestamp=time.time()*1000,
        manifestation=Manifestation.USER_ACTIVITY,
        actor='application://your_application_name.desktop',
        subjects=[subject])
    if opened:
        event.interpretation = Interpretation.ACCESS_EVENT
    else:
        event.interpretation = Interpretation.LEAVE_EVENT
 
    def on_id_received(event_ids):
        print 'Logged %s (%d) with event id %d.' % (title, opened, event_ids[0])
 
    zeitgeist.insert_events([event], on_id_received)
 
if __name__ == '__main__':
    register()
 
    log('test.txt', 'file:///tmp/test.txt', opened=True)
    log('another_file.txt', 'file:///tmp/another_file.txt', opened=True)
    log('another_file.txt', 'file:///tmp/another_file.txt', opened=False)
    log('test.txt', 'file:///tmp/test.txt', opened=False)
 
    # Start a mainloop
    GLib.MainLoop().run()
If you don t know what interpretation and manifestation your subject should have, you can use the following utility methods:
from zeitgeist.mimetypes import *
 
print get_interpretation_for_mimetype('text/plain')
print get_manifestation_for_uri('file:///tmp/test.txt')
Event better, with Zeitgeist 0.9 you can just leave the subject (but not event!) interpretation and manifestation fields empty, and they ll be guessed the same way as if you used those utility methods. Pro Tip: You can examine all registered data-sources and toggle whether they are enabled or not using the zeitgeist-data-sources-gtk.py tool. Conclusion Wow, I m impressed if you ve got this far. By now you should have quite a good idea on how to use the Zeitgeist API, and I m looking forward to seeing what you do with it in your next awesome project. If you have any problem with Zeitgeist, feel free to visit us on IRC (#zeitgeist on irc.freenode.net), or join our mailing list. We ll also be at GUADEC next week, so if you re there make sure to say hi! In case you missed them, here are some useful links:
No comments
Siegfried-Angel Gevatter Pujals, 2012. Permalink License Post tags: ,
flattr this!

20 July 2012

Joey Hess: are there any gotchas with enabling the -threaded GHC runtime?

That's a seemingly simple question I started asking various people two weeks ago. I didn't get many useful answers, but now I have experience doing it myself, and so here's a blog post brain dump. I have been trying to convert git-annex to use GHC's threaded runtime, for a variety of reasons. Naively adding the -threaded option resulted in a git-annex command that seemed to randomly freeze, but only sometimes (and, infuriatingly, never when I straced it), and a test suite that froze at a random point almost every time I ran it. Not a good result, and lacking any knowledge about gotchas with using the threaded runtime, I was at a loss for a long time (most of DebConf) about how to fix it. I now know of at least three classes of problems that enabling the threaded runtime can turn up in programs that have been developed using the non-threaded runtime. accessing a MVar after forkprocess can hang MissingH has some code similar to this, which works ok with the non-threaded runtime:
forkProcess $ do
    debugM "about to run some command"
    executeFile ...
In the above example, debugM accesses a MVar. Doing that after forkProcess can result in a MVar deadlock, as it tries to access a MVar value, that is, apparently, not accessible to the forked process. (Bug report with test case) So, using System.Cmd.Utils from MissingH is asking for trouble. I switched all my code to the newer and, apparently, threaded runtime safe System.Process. forkProcess is a massively bad idea Even when not accessing a MVar after forkProcess, it's very unsafe to use. It's easy to miss the warning attached to forkProcess, when the code seems to work. But with the threaded runtime, I've found that most any call to forkProcess will sometimes succeed, and sometimes freeze the whole program. This might only happen around 1 time in 1000. Then you'll find this warning and do a lot of head-scratching about what it really means:
forkProcess comes with a giant warning: since any other running threads are not copied into the child process, it's easy to go wrong: e.g. by accessing some shared resource that was held by another thread in the parent.
The hangs I saw could be due to laziness issues deferring code to run after the forkProcess that you'd expect to have run before it ... or who knows what else. It's not clear to me that it's possible to use forkProcess safely in Haskell code. I think it's notable that System.Process runs the whole fork/exec in C code instead. unsafe FFI calls block According to most of the documentation you'll find in eg, the Haskell wiki, Real World Haskell, etc, the only difference between the safe and unsafe imports in the FFI is that unsafe is faster, and shouldn't be used for C code that calls back into Haskell code. But the documentation is out of date. Actually, if you're using the FFI, and the foreign function can block, you need to use safe. When using unsafe, a blocking foreign function can block all threads of the program. In my case, I was using kqueue to wait for changes to files, and this indeed blocked my whole program when linked with -threaded. Marking it safe fixed this. The details are well described in this paper: http://community.haskell.org/~simonmar/papers/conc-ffi.pdf Somewhat surprisingly, this blocking only happens when using the threaded runtime. If you're using the non-threaded runtime with unsafe blocking FFI functions, your other pseudo-threads won't be blocked. This is because the non-threaded runtime has an SIGALARM timer that interrupts (most) blocking system calls. This leads to other troubles of its own (like needing to restart interrupted FFI functions, or blocking the other pseudo-threads from running if the C code ignores SIGALARM), but that's offtopic for this post. summary Converting a large Haskell code base from the default, non-threaded runtime to the threaded runtime can be quite tricky. None of the problems are the sort of thing that Haskell helps to manage either. I will be developing new programs using the threaded runtime from the beginning from now on. By the way, don't take this post to say that threading in Haskell sucks. I've really been enjoying writing threaded Haskell code. The control Haskell gives over isolation of state to threads, and the excellent and wide-ranging suite of thread communications data types (MVar, Chan, QSemN, TMVar, SampleVar, etc) have made developing a complex threaded program something I feel comfortable doing for the first time, in any language.

John Goerzen: A Linux-Based RFID Thing Finder

Sometimes I have things nicely organized. Power adapters for radios in one drawer, for cameras in the next. And sometimes not so much. Sometimes I m not sure if things are in the basement or the attic. It seems like technology should be able to help solve this problem, but as far as I can tell, no such solution exists yet. So I m planning to build one. Here s my general idea. Feedback, of course, is welcome. Each item to be tracked can have an RFID tag of some sort attached to it. These tags can be read by an RFID reader at a distance of somewhere between 1ft and 1m in typical conditions. The reader could then act as a proximity alert to an object being searched for a you re close beep, for instance. That helps, but is only part of the battle. It doesn t help if you don t even know which room to look in. So the second part of the plan is that the RFID reader is constantly talking to an object database. Besides the obvious association between RFID tag IDs and object descriptions, the database will also capture background reads of RFID tags. Logged with accurate timestamps, we can then conjecture that RFID reads that occurred within a few seconds of each other are probably physically nearby. If boxes have RFID tags on them, then I can probably get a reasonable idea, down to a box or two, of which box that elusive book is in. If I further put tags on certain immovable physical locations in the house, such as every few feet along shelving, then these will also be captured in the background and hopefully associated with objects nearby, giving a good physical idea of where things are. What s more, the simple act of looking for things using the RFID reader would help keep the proximity tables up-to-date, since it could of course log the RFID tags it sees on the way. The only discipline required to keep this info current is to periodically hover nearby storage areas when moving things around. I like this concept a lot. That doesn t mean it s necessarily simple. Implementation requirements Software side I m envisioning the software being split into two components. One would run on an embedded system with the RFID reader. Its job is simple transmitting of scanned RFIDs to the server, receiving instructions from the server, and generating a tone if it s in search mode and the item being searched is nearby. On the server lies a database. The database would contain descriptions for the objects that are tagged (so that the tag ID can be looked up). It would also contain the timestamped scan logs. I envision a simple CGI-based frontend to it that is mobile-friendly, so a laptop, phone, tablet, etc. could be the user interface for the thing saving the cost of a display and input device by reusing what most people already have. This is the part I feel most qualified to work on already. Hardware The first question is what kind of RFID tags to use. Optimizing for cost per tag, the 800/900MHz UHF tags (EPC gen 2) seem ideal. I have found them in costs approaching $0.10 per tag when bought in rolls of 500 or 1000 Avery RFID labels. That s reasonable. The RFID reader is the more complicated part. UHF RFID readers are a lot more costly than their HF or LF counterparts. So far, the cheapest solution I have found started with a post about an Arduino UHF reader. It used a SolidDigi UHF reader board with UART interface for $177. That same board is also available with a USB interface at the same cost. There is also the need for an antenna. There is a small 5dBi one rated 0-50cm for $8, or a $100 8dBi version rated 1-6m designed for wall mounting. They sell these in kit form that include power adapter, USB cables, etc. as well. The kit with the small antenna runs $192, including reader board. Next is the compute platform. A DreamPlug might work for this at $160, though both the cost and the power consumption (5VDC 3A) are high. A Raspberry Pi seems perfect, though for whatever reason seem to be backordered by months everywhere and don t include wifi. The Pi is $35, and the USB wifi is another $30, plus a cheap SD card, so we re around $80 of computing. The running total of the project, then, is at least $272. Add on provisions for batteries, some sort of case, etc. and we re probably past the $300 mark. That s a lot cheaper than the $1000 for handheld RFID readers. The final item is tags. Bulk tags can be found in the $100 to $200 range, making the total cost of the project $400 to $500. Higher than I d like, but providing some valuable experience building something. Risks There are a few major risks to the project. First among them is read distance. If it s not long enough, the usefulness of the project will be low. Fortunately, $100 gets a more high-gain antenna and I d only be out the $8 if the cheaper one doesn t pan out. But that s something of a cold comfort, as it s another, well, $100. Having a bunch of RFID hardware can be used for all sorts of other interesting things, though, so it could perhaps be reused or repurposed. Another risk is that RFID collisions wouldn t be handled as intelligently as I d like, meaning that the read range required to be useful would activate so many tags that collision algorithms break down. I don t know enough about RFID collision algorithms to know if this is a serious councern.

Jamie McClelland: MySQL throwing the wrong error

I was running a routine CiviCRM installation when I was stopped by the error:
ERROR 1071 (42000) at line 2415: Specified key was too long; max key length is 1000 bytes
The line referred to a table that created two indexes. Each index combined a 512 byte varchar field with a 4 byte integer field (well below 1000 bytes). I then tried downloading the sql file to my local computer and it imported without a problem. So... I started the painstaking process of comparing the configurations on each computer. Eventually, I came to this setting that was causing the problem:
innodb_log_file_size = 268440000
In fact, it wasn't the setting causing the error. The error was caused because I added that setting without properly shutting down MySQL, removing /var/lib/mysql/iblogfile0 and /var/lib/mysql/iblogfile1 files and then restarting MySQL.

17 July 2012

Luciano Bello: there is no cabal.. but, what s a cabal?

In my long trip to Nicaragua I made progress in my reading: Quicksilver, by Neal Stephenson. In the Spanish edition the title is Azogue. But I m assuming that you are not a Spanish speaker. Here is a small fragment (in English) I found there:
You must remember that the planters are short-sighted. They re all desperate to get out of Jamaica they wake up every day expecting to find themselves, or their children, in the grip of some tropical fever. To import female Neegers would cost nearly as much as to import males, but the females cannot produce as much sugar particularly when they are breeding. Daniel had finally recognized this voice as belonging to Sir Richard Apthorp the second A in the CABAL.
It s a bit embarrassing when I discovered myself realizing where the word cabal comes from. And I m posting this as a head-up for everyone who know there is no cabal in Debian; but they don t know which is the origin of the word cabal. Stephenson changed the name of the historic cabal, a group of high councillers of King Charles II of England, Scotland and Ireland, in 1668. In the novel, they are: John Comstock (Earl of Epsom), Louis Anglesey (Duke of Gunfleet), Knott Bolstrood (Count Penistone), Sir Richard Apthorp and Hugh Lewis (Duke of Tweed). In the real world they had been:
Thomas Clifford, 1st Baron Clifford of Chudleigh (1630-1673). Henry Bennet, 1st Earl of Arlington (1618-1685). George Villiers, 2nd Duke of Buckingham (1628-1687). Anthony Ashley Cooper, 1st Baron Ashley of Wimborne St Giles (1621-1683). John Maitland, 1st Duke of Lauderdale (1616-1682).
This group shared the effective power in a royal council rather than the King.

16 July 2012

Tanguy Ortolo: MySQL save/restore: an example of what not to do

Database icon I had to play a bit with MySQL, saving and restoring databases with mysqldump and mysql. These two tools have one severe discrepancy, which I would like to comment here because I think it is an excellent example of what not to do when designing tools to be used together.Save mysqldump(1) is a database backup tool, that takes a MySQL database and prints the necessary SQL statements to restore it to a new server. It has one interesting option:
--default-character-set=charset_name Use charset_name as the default character set. See Section 10.5, Character Set Configuration . If no character set is specified, mysqldump uses utf8.
As you can see, it is quite modern in its default choice: if you do not specify which encoding you want to encode your database content into, it uses UTF-8. This way, it can save any database content, whatever characters it may contain. A more sensible choice may have been to use the LC_CTYPE environment variable. Restore mysql(1) is the command-line MySQL client, which can is used to restore such dumps. It has a similar option:
--default-character-set=charset_name Use charset_name as the default character set for the client and connection. A common issue that can occur when the operating system uses utf8 or another multi-byte character set is that output from the mysql client is formatted incorrectly, due to the fact that the MySQL client uses the latin1 character set by default. You can usually fix such issues by using this option to force the client to use the system character set instead.
As you can see, this utility is still has an antique design: if you do not specify a character set, it assumes you are giving it data encoded in latin-1. Discrepancy You can see the obvious discrepancy here: mysqldump encodes your database backups in UTF-8 by default, and mysql restores them as if they were encoded in latin-1. This way, when you have to restore your databases, if you thought you could do it without wondering, congratulations: voil , you have just fucked your databases up! And as an additional present, chances are high that this mistake is discreet enoughto be detected only after a while, when modifications have been done to the restored database and the original backups have been deleted. So, if you are dealing with MySQL databases, remember that you must take care of the encoding of your backups, because MySQL utilities will not by itself, or rather it will do just what should not be done. And if you are designing similar tools, please think, and if you want an example of what not to do, here is one!

Thorsten Glaser: Apache 2, https clients linked against GnuTLS, connection errors

I ve been debugging a weird problem at work after upgrading a complex system from lenny to wheezy, some https clients failed to connect: GNU wget and Debian s version of lynx(1) which is linked against libgnutls26 fail. NSS applications continue to work, as does cURL; wget and lynx on MirBSD (linked with OpenSSL of course) work. Even Debian s gnutls-cli tools from both gnutls26 and gnutls28 work. Huh. The error_log shows renegotiation problems, yet setting the new Apache 2 configuration option to use insecure renegotiation doesn t help either. (The option is a total #FAIL: its only other value is use secure TLSv1.x renegotiation , but I don t want/need SSL renegortiation at all, anyway.) Natureshadow told me this was a hot issue on Debianforum at the moment, yet, nobody had a clue or enough information to file a formal bugreport against (initially) apache2, as that s what changed. I tracked it down on a new VM with no configuration otherwise, and here are my findings so others don t run into it.

Tracking down the problem, this can be reduced to the following configuration (minimised, to show the problem) in /etc/apache2/sites-enabled/1one:

	<VirtualHost *:443>
		ServerName wiki-70.lan.tarent.de
		RedirectMatch permanent . https://evolvis-70.lan.tarent.de/
		SSLEngine on
		SSLCertificateFile /etc/ssl/W_lan_tarent_de.cer
		SSLCertificateKeyFile /etc/ssl/private/W_lan_tarent_de.key
		SSLCertificateChainFile /etc/ssl/godaddy.ca
	</VirtualHost>
 

Do not mind the actual content, this is a very stripped-down demo on a not-actually-set-up-yet box.

Same is valid for the companion configuration file /etc/apache2/sites-enabled/2two:

	NameVirtualHost *:443
	<VirtualHost *:443>
		ServerName evolvis-70.lan.tarent.de
		SSLEngine on
		# workaround for BEAST (CVE-2011-3389), short-term
		SSLCipherSuite RC4-SHA
		SSLCertificateFile /etc/ssl/W_lan_tarent_de.cer
		SSLCertificateKeyFile /etc/ssl/private/W_lan_tarent_de.key
		SSLCertificateChainFile /etc/ssl/godaddy.ca
		SSLProtocol TLSv1
	</VirtualHost>
 

Turns out the BEAST workaround was at fault here: the differing SSLCipherSuites between the vhosts (on the same Legacy IP / TCP Port tuple, as we use Wildcard SSL Certificates) made Apache 2 want to renegotiate, so either commenting it on 2two or, better, adding it to 1one helped. Interestingly enough, the SSLProtocol directive did not matter (in my tests). So, keep SSL settings synchronised between vhosts. In fact, those were already from include files, but 2two was from the Evolvis 5 generation, whereas we added to 1one an Include of the httpd.ssl1.inc file generated by the previous releases of EvolvisForge and had not switched those legacy vhosts to the new configuration, as everything worked on lenny. This wlog entry brought to you by the system administrators of tarent solutions GmbH and the Evolvis Project, based on FusionForge.

15 July 2012

Debian Med: Debian Med Bits: Report from LSM Geneva by Andreas Tille

In this report from LSM 2012 in Geneva I will report about
  1. Medical imaging using Debian
  2. Debian Med packaging workshop
  3. Integration of VistA into Debian
  4. Other interesting talks
Medical imaging using Debian There were about 10 attendees basically upstream developers of medical imaging software. The talk got some attention and the message to include even more medical imaging software into Debian was well percived. Thanks to Mathieu Malaterre there was some live demonstration which was way easier for him as a medical imaging expert than it would have been for me.
Debian Med packaging workshop Due to my advertising in the talk yesterday three students (two of them from one medical imaging project, one from an other project) attended the workshop. Thanks to Axel Beckert who helped me out surviving the challenge to walk on unexplored ground.

The idea of the workshop was to ask the attendees to name a package of their own and just package this. Because two of the attendees were upstream developers of CreaTools we decided to go on for packaging this. After circumeventing some pitfalls in the beginning it went rather smoothly and after about 2.5 hours we were able to commit some initial packaging to the Debian Med Git repository which comes quite close to a ready package (perhaps some split into a library and a development package needs to be done and for sure testing is needed).
Quoting Frederic Cervenansky, upstream of CreaTools
Thanks for your work. Your workshop was very interesting and didactic: a relevant discussion between Claire and me for the future of Creatools has emerged from the difficulties you encountered to package creatools. I will try, before the end of the month, to fully package creatools. And for sure, I will contact the debian-med mailing list.
Integration of VistA into Debian I had the good chance to directly address some issues of Claudio Zaugg the speaker in the talk Implementing open source Health Information Systems in Low- and Middle Income Countries a practical review directly before mine. It turned out that by using Debian packaged software might help simplifying the issues they had in supporting health care workers in Low- and Middle Income Countries.
My talk was partly repeating some basic ideas about Debian Med from the talk on Monday because the audience was completely different. Than I tried to explain in detail how we tried hard to establish good contacts to upstream developers and why this is essential to finalise the goal to include hospital information systems straight into Debian any by doing so open the doors of hospitals for large scale Debian installations.
There is also video recording of this talk. Other interesting talks OpenEMR, a multi-language free open source electronic health record for international use Just discussed the packaging of OpenEMR which is prepared for Debian Med as it can be seen on our tasks page. The contact to the creator of some inofficial package will be established to finalise this task.
OpenFovea : when open-source and biophysical research get married Just another target for Debian Med popped up in this talk to further enhance Debian Med in covering all issues of medical care on one hand and on the other hand helping upstream authors to distribute their code
more effectively.
Collaborative software development for nanoscale physics The talk would have fit very nicely into the Debian Science workshop at ESRF (European Synchrotron Radiation Facility) in Grenoble because it was about ETRF (European Theoretical Radiation Facility). At previous LSM events I had just talked with Yann and the work to include their software into Debian is on its way.
Free software and High Performance Computing This talk was not directly connected to my Debian work but I simply enjoyed to see how "two people" had a really entertaining talk about Top 500 computers. Vittoria, you made my last day at LSM.

14 July 2012

Don Armstrong: Debbugs: Control at Submit time

One of the features that I have been asked for multiple times is the ability to use control@bugs.debian.org commands at submit@bugs.debian.org time. I have now implemented this with the following syntax:
Package: foo
Version: 1.0-3
Control: retitle -1 this is the title
Control: severity -1 bleargh
Control: summary -1 0
Control: forward -1 http://bugs.debian.org/nnn
In short, you preface any control commands with Control:, -1 is the current bug, and the rest of each line is the control@ grammar you already know. This also now works for every kind of message to nnn@bugs.debian.org with the exception of messages received at nnn-done and nnn-forwarded. I don't know why you'd use it for anything else but submit@ messages, but hey, whatever works.

Don Armstrong: Debbugs: outlook command

Neil McGovern asked me to add an additional feature to the BTS to support tracking the current status of attempts at fixing a bug. In past releases, we've used the nice commenting feature of bts.turmzimmer.net to keep track of what is going on in a particular nasty RC bug, who is working on it, and what needs to be done next (or if everyone can just ignore the bug). This feature should probably have already been in the BTS to start with, but now it is. In addition to the existing summary feature, where you can nominate a message or text to be the summary for a bug, there is an outlook command, which tracks the current status of the bug, and behaves in exactly the same way:
outlook 12345 not good
outlook 54321 0
thanks
I'm totally stymied by #54321.
for example. I plan to include the outlook in the bugscan output in the future too, so it'll be easily accessible. (And possibly up-to-the-minute with some javascript-fu.)

Next.

Previous.