Thursday, October 3, 2013

The X.Org Foundation and the 501(c)(3) status

X.Org is not a single thing. One the one hand, X.Org is a collection of projects that provide a window system stack, most notably the X server, its drivers and Xlib. Some other tools are part of the X.Org software set (see the X11R7.7 katamari release). Additionally, there are projects that are more or less associated with X.Org but aren't necessarily X.Org (depends on who you ask, and it doesn't really matter anyway for this post). These projects include Mesa and Wayland. Let's call this the "Software".

On the other hand, X.Org is the X.Org Foundation, a non-profit corporation to help advance X.Org and related projects. Let's call this the "Foundation". Disclaimer upfront: I'm the current Secretary for the X.Org Foundation.

The Software and the Foundation are not the same thing, but they do share the name. The Foundation has zero technical influence over the development of the Software, it cannot direct roadmaps, it cannot decide on releases, it can't decide on technical features. The Foundation does have money it can provide to developers of the Software though. This is done indirectly, e.g. through financing developer conferences (XDC) and providing travel sponsorship for attendees. The Foundation backs the Endless Vacation of Code (think Google Summer of Code without specific start dates).

Generally, what happens with the Foundation doesn't really matter to the Software and that is by design. If the Foundation goes away, the worst thing that would happen to the Software is that funding for conferences would have to come from elsewhere. Think of the Foundation as being the rich auntie for the developers. You can ask her for money to travel, but she doesn't participate in day-to-day development work.

Recently, you may have read that the Foundation lost 501(c)(3) status (temporarily anyway). For the non-US readers, 501(c)(3) is US legalese for a non-profit organisation which allows for some donations to be tax-deductible. The loss of the 501(c)(3) status caused the usual internet outrage and insults towards the Foundation and the Software, so let's look at that in a bit more detail.

The X.Org Foundation structure

There is a link between the members of the Foundation and the Software: to become a member, you have to "i) be actively involved in the activities relating to the technologies of X.Org, as set forth in the Membership Agreement". So as long as you're hacking on X or you're otherwise affiliated, you can join and membership is free.

The day-to-day work of the Foundation are largely handled by the Board of Directors, 8 elected members in two-year terms, 4 of which are up for election every year. One treasurer, one secretary, pretty much standard stuff. The board has regular meetings, but if they get your blood pressure up you really need to see a doctor.

Gaining, losing and re-gaining 501(c)(3) status

The reason we even have that status is historical. Back a few years ago the old X Consortium got regular chunks money from large corporations (Sun, HP, to name a few). After the change to X.Org, setting that up for tax-deductible donations seemed like a good idea. Fast-forward a bit and with the help of the great people at the SFLC X.Org got 501(c)(3) status in 2012 (retroactively applied to 2009).

Something else happened while fast-forwarding: we never actually solicited or took any donations. The financial crisis had hit, so there wasn't that much money around and anyway we had enough money to run conferences for years to come. The closest thing to a donation we got was to allow interested parties to host beer bashes at our conferences.

So since 2005, we've been slow-burning through money and at the current rate we still have enough money for a couple of years of conferences and travel sponsorship. 501(c)(3) limits the ways how to spend the money (see Wikipedia), so we pretty much only spend it on conferences and travel.

So the summary: the Foundation is a 501(c)(3) that doesn't collect donations. But if we did, they'd be tax-deductible. As long as you're in the US, that is. Non-US people pretty much have nothing to gain either way since we're not registered in any other country and 501(c)(3) doesn't apply to other (any?) countries. (Correct me if I'm wrong. Also: don't listen to me for tax advice)

A couple of months ago 2013 we lost 501(c)(3) status. The reason we lost it: we didn't file the required tax forms. As said above, no donations means no income, so we never actually owed any taxes and we hadn't filed tax forms for years before we go the 501(c)(3) status. So the IRS removing our status was a bit of a surprise. I should also note that the Foundation is one step removed from from the IRS communication: the IRS contacts the SFLC who then contacts us.

Anyway, once again the great people at the SFLC helped us and we got the 501(c)(3) re-instated. So we're back to normal, not collecting tax-deductible donations. With the additional benefit of having learned to double-check tax forms from now on.

Summary

We had 501(c)(3) status but didn't collect donations. Then we lost it, and got it back, all the time not actually collecting donations. There was no money owed to the IRS. No doubt: It's embarrassing, it shouldn't have happened. But in reality it had zero effect.

So pack up the pitchforks, but keep them well oiled, I'm sure there's a reason to get them out soon again.

Final note: you may have heard that the Foundation is planning to join SPI. This is correct but still ongoing and I'll talk about that when it's actually done.

Wednesday, September 18, 2013

libevdev - creating uinput devices

This post describes how to create uinput devices through the new libevdev library. For more information about libevdev, please refer to the first post in this series.

What is uinput?

uinput is the kernel interface to create evdev devices that, for most purposes, look the same as real devices. This goes so far that around 80% (well, I'm guessing. actually, make this 83.45%) of all testing I do now is with emulated devices only. There are a few bits that can't be emulated, a few things that are different, but generally I found uinput devices to be close enough to the real thing. As the evdev interface, the uinput interface requires you to handle a few structs and ioctls, not necessarily in an obvious way. libevdev wraps that for you.

Creating a device

The simplest way to create a uinput device is to duplicate an existing device.

struct libevdev *dev;
struct libevdev_uinput *uidev;
int rc;

rc = libevdev_new_from_fd(fd, &dev);
if (rc < 0)
     handle_error();

rc = libevdev_uinput_create_from_device(dev,
                                        LIBEVDEV_UINPUT_OPEN_MANAGED,
                                        &uidev);
if (rc < 0)
     handle_error();
/* don't need the source device anymore */
libevdev_free(dev);

libevdev_uinput_write_event(uidev, EV_REL, REL_X, -1);
libevdev_uinput_write_event(uidev, EV_REL, REL_Y, 1);
libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0);
libevdev_uinput_destroy(uidev);

The above code will create a device from a fd, duplicate that device as a uinput device and then post a x/y relative event through that uinput device. Because we opened the uinput device as LIBEVDEV_UINPUT_OPEN_MANAGED, libevdev will handle access to the /dev/uinput node.

Duplicating devices is useful, but a more likely use-case is to create a device from scratch:

int fd;

dev = libevdev_new();
libevdev_set_name(dev, "my device");
libevdev_enable_event_type(dev, EV_REL);
libevdev_enable_event_code(dev, EV_REL, REL_X);
libevdev_enable_event_code(dev, EV_REL, REL_Y);
libevdev_enable_event_type(dev, EV_KEY);
libevdev_enable_event_code(dev, EV_KEY, BTN_LEFT);
libevdev_enable_event_code(dev, EV_KEY, BTN_MIDDLE);
libevdev_enable_event_code(dev, EV_KEY, BTN_RIGHT);

fd = open("/dev/uinput", O_RDWR);

rc = libevdev_uinput_create_from_device(dev, fd, &uidev);
if (rc < 0)
     handle_error();

/* don't need the source device anymore */
libevdev_free(dev);

... do something

libevdev_uinput_destroy(uidev);
close(fd);

This time we created a blank device, set a few bits and created a uinput device from that. The result should be a device that looks like a normal three-button mouse to most of the stack.

As you can see, because this time we opened /dev/uinput ourselves, we need to close it ourselves too. libevdev won't touch the fd unless it's in LIBEVDEV_UINPUT_OPEN_MANAGED mode. Note that you can only ever have one active uinput device per fd, and closing the fd will destroy the uinput device (but won't free the memory, you'll still have to call libevdev_uinput_destroy).

Accessing uinput devices

We just created a uinput device, but how do we actually use it? Well, as shown above events are just written to the device directly. But sometimes we have to create a device and re-open it through libevdev.

int fd;
struct libevdev *dev;
const char *devnode;

devnode = libevdev_uinput_get_devnode(uidev);
fd = open(devnode, O_RDWR|O_NONBLOCK);
rc = libevdev_new_from_fd(fd, &dev);
if (rc < 0)
   handle_error();

Voila. That's all there is to it to complete the circle. You can now use that device to create a uinput device again, and so on, and so forth.

A word of warning: the kernel does not (yet) provide an ioctl to get the device number from a newly created uinput device. libevdev has to guess what the device is going to be. In some cases, this guess may come up with the wrong device. This can happen if you create multiple uinput devices with the same name at the same time. So, don't do that. Either change the name, or delay creation so that the timestamp (one-second resolution!) differs for each device.

libevdev - accessing and modifying devices

This post describes how to change the appearance of a device through the new libevdev library. For more information about libevdev, please refer to the previous post on libevdev.

Changing a device

So you have a device but for some reason it doesn't exactly reflect what you actually need. This can happen for broken devices that export random axes, or it can happen if the software stack needs certain bits that the device doesn't actually provide. The code below is C-style pseudocode, don't expect to be able to directly take and compile it.

struct libevdev *dev;
int rc;

rc = libevdev_new_from_fd(fd, &dev));
if (rc < 0)
     handle_error();

/* broken device, shouldn't have ABS_RX */
if (libevdev_has_event_code(dev, EV_ABS, ABS_RX))
    libevdev_disable_event_code(dev, EV_ABS, ABS_RX));

/* will never return a ABS_RX event now */
rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev);

if (!libevdev_has_event_code(dev, EV_ABS, ABS_PRESSURE)) {
    struct input_absinfo abs;
    abs.minimum = 0;
    abs.maximum = 100;
    abs.resolution = 1;
    abs.fuzz = abs.flat = 0;
    libevdev_enable_event_code(dev, EV_ABS, ABS_PRESSURE, &abs);
}

Simple enough - we've disabled ABS_RX, so we'll never get an event from this instance. Note that this is a local change only, so anyone else reading the device will still receive ABS_RX events. Likewise, we enabled ABS_PRESSURE so that future calls to libevdev_has_event_code will return true, including the axis range we've provided. This too is a local change only and won't affect anyone else. For obvious reasons, enabling a bit on the device doesn't actually make the device generate events of that type. Otherwise, the HW industry would be out of business quickly.

For local changes, libevdev provides setters for almost every field. I won't go into more details here, the API should be obvious enough so that e.g. changing the device name is straightforward.

Modifying the kernel device

A few calls can actually modify the kernel device, so that other readers of the device will see modified data.

if (libevdev_has_event_code(dev, EV_ABS, ABS_PRESSURE))
     rc = libevdev_kernel_set_abs_info(dev, ABS_PRESSURE, &abs));

This call would actually change the axis ranges on the device. A future reader of the device would thus see the new range. Note that the kernel won't enable the bits as you upload the new data, so you can't actually create new axes on the device, only modify existing ones.

Modifying LEDs

A slightly more common scenario is toggling LEDs on a device:

if (libevdev_has_event_code(dev, EV_LED, LED_NUML))
   rc = libevdev_set_led_value(dev, LED_NUML, LIBEVDEV_LED_ON);

/* for the lazy: */
rc = libevdev_set_led_values(dev, LED_NUML, LIBEVDEV_LED_ON,
                                  LED_CAPSL, LIBEVDEV_LED_OFF,
                                  LED_SCROLLL, LIBEVDEV_LED_ON,
                                  -1);

Again, this shouldn't need much explanation. The first call toggles a single LED, the second call toggles multiple LEDs in one go.

libevdev - handling input events

This post describes how to read input events from the kernel through the new libevdev library.

What is libevdev?

libevdev is a wrapper library to access /dev/input/eventX devices and provide their events through a C API. It buffers the device and is essentially a read(2) on steriods. Instead of read(2) on the file descriptor, you'd call libevdev_next_event() to fetch the next event that is waiting on the fd. And the buffering allows a process to access device data easily.

Why use a library though? The kernel interface is relatively simple, but it has a few pitfalls. For one, device data is accessed through ioctl(2) and can cause weird bugs [1]. Second, not all events work in the same way. e.g. EVIOCGABS doesn't work the same for multi-touch axes, simply because the slot protocol has different semantics than the normal EV_ABS protocol. EV_REP has different handling as EV_ABS, EV_SYN is a special case anyway, etc. libevdev tries to avoid having to think about the differences and does sanity checks for the various calls.

Repositories and documentation

Status of libevdev

libevdev is currently in version 0.4, and the current API is expected stable. That is, we don't foresee any changes unless we discover some severe bug. If that is the case, I will update the blog post here.

Example code

The code snippets below are in C-style pseudocode. You won't be able to just take them and compile them, but look at libevdev-events for a real tool that does almost everything described below.

Initializing a device

The first step to get a device is to open it. That is not actually handled by libevdev directly, rather it expects an already opened file descriptor. The reason is simple: reading /dev/input/event devices usually requires root and the process accessing the device may not have these permissions. In weston for example, the fd is passed from the suid weston-launch binary. Ok, enough talk, let's see some code:

struct libevdev *dev;
int fd;
int rc;

fd = open("/dev/input/event0", O_RDONLY|O_NONBLOCK);
if (fd < 0)
   fprintf(stderr, "error: %d %s\n", errno, strerror(errno));
rc = libevdev_new_from_fd(fd, &dev);
if (rc < 0)
   fprintf(stderr, "error: %d %s\n", -rc, strerror(-rc));

Fairly straightforward. Open a new device from the file descriptor and initialize it. On error, the return value is a negative errno.

printf("Device: %s\n", libevdev_get_name(dev));
printf("vendor: %x product: %x\n",
       libevdev_get_id_vendor(dev),
       libevdev_get_id_product(dev));

if (libevdev_has_event_type(dev, EV_REL) &&
    libevdev_has_event_code(dev, EV_REL, REL_X) &&
    libevdev_has_event_code(dev, EV_REL, REL_Y) &&
    libevdev_has_event_code(dev, EV_KEY, BTN_LEFT) &&
    libevdev_has_event_code(dev, EV_KEY, BTN_MIDDLE) &&
    libevdev_has_event_code(dev, EV_KEY, BTN_RIGHT))
    printf("Looks like we got ourselves a mouse\n");

libevdev_free(dev);
close(fd);

Getting information about the device is done by simply calling the various getters. And checking the device for functionality is done by checking the various event codes we care about. Note that the above code checks for the EV_REL event type first, then for the actual axes bits. This is just for completeness, it is not necessary. Checking for an event code also checks for the event type so we can skip libevdev_has_event_type(). Both approaches are allowed of course, whichever makes you feel more comfortable about the code.

Finally, cleaning up: Because we don't handle the fd in libevdev, we just use it, you'll have to close that separately.

Ok, the gist of how to access a device should be clear. Let's move on to reading events from the device

Reading events

In the standard case, we just want to get the next event and process it.

struct input_event ev;

rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev);
if (rc < 0) {
    if (rc != -EAGAIN)
        fprintf(stderr, "error: %d %s\n", -rc, strerror(-rc));
else if (rc == LIBEVDEV_READ_STATUS_SYNC)
    handle_syn_dropped(dev);
else if (rc == LIBEVDEV_READ_STATUS_SUCCESS)
    print("We have an event!\n%d (%s) %s (%d) value %d\n",
          ev.type, libevdev_event_type_get_name(ev.type),
          ev.code, libevdev_event_code_get_name(ev.type, ev.code),
          ev.value);

The error handling should be clear by now: negative errno means something has gone wrong. Except -EAGAIN, wich indicates that there are no events to read at the moment. A return value of LIBEVDEV_READ_STATUS_SYNC is special, it signals a SYN_DROPPED event which I'll describe later.

A return value of LIBEVDEV_READ_STATUS_SUCCESS means success, so we know we have an event and we can print it. libevdev provides some helper functions to print the string value of an event type or code. The code above could, for example print something like this:

We have an event!
2 (EV_REL) 0 (REL_X) value -1

As you can see, all this effort just to read the same thing off the kernel device that you would've otherwise with a read(2) call. But wait! There's more!

Event buffering

libevdev buffers events internally and always tries to read the maximum number of events off the kernel device. So when you call libevdev_next_event, libevdev may read 50 events off the fd (or whatever is available) and only give you the first. On the next call, it will simply give you the second event of those first 50, but try to read more again to keep the kernel buffer as empty as possible.

Whenever you request an event, libevdev will update its internal state to match the current device state so the client doesn't have to. So if you need to keep track of button states, you can rely on libevdev:

if (!libevdev_has_event_code(dev, EV_KEY, BTN_LEFT))
        return;

if (libevdev_get_event_value(dev, EV_KEY, BTN_LEFT) == 0)
   printf("Button is up\n");
else
   printf("Button is down\n");

/* BTN_LEFT event happens */

rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev))
...

if (libevdev_get_event_value(dev, EV_KEY, BTN_LEFT) == 0)
   printf("Button is up\n");
else
   printf("Button is down\n");

If no button is pressed, then pressed before the next event is read, this snippet would print "Button is up" and "Button is down". Fairly obvious, I think.

Important to point out is that the device state is always the state as seen by the client, i.e. if the client would keep track of the device state based on the events libevdev hands to it, libevdev and the client would always have the same state. Why is this important? libevdev reads multiple events off the wire whenever a client calls libevdev_next_event, but these events do not update the state of the device until passed to the client. So again, since libevdev reflects the state as seen by the client, the client doesn't need to keep track of the state itself. Winners all 'round.

SYN_DROPPED device syncing

A EV_SYN/SYN_DROPPED event is relatively recent (kernel 2.6.39). If a device sends events faster than userspace can read it, eventually the kernel buffers are full and the kernel drops events. When it does so, it sends a EV_SYN/SYN_DROPPED event to notify userspace. The userspace process then needs to stop what it's doing, re-sync the device (i.e. query all axis, key, LED, etc. values), update the internal state accordingly and then it can start reading events again.

libevdev handles all this for you. In the example code above, you saw that a return value of LIBEVDEV_READ_STATUS_SYNC signals a SYN_DROPPED event and we called handle_syn_dropped(). This function is actually incredibly easy:

void handle_syn_dropped(struct libevdev *dev) {
    struct input_event ev;
    int rc = LIBEVDEV_READ_STATUS_SYNC;

    while (rc == LIBEVDEV_READ_STATUS_SYNC) {
        rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_SYNC, &ev);
        if (rc < 0) {
            if (rc != -EAGAIN)
                fprintf(stderr, "error %d (%s)\n", -rc, strerror(-rc));
            return;
        }

        printf("State change since SYN_DROPPED for %s %s value %d\n",
                libevdev_event_type_get_name(ev.type),
                libevdev_event_code_get_name(ev.type, ev.code),
                ev.value);
    }
}

You notice there is almost no difference to the normal event loop. A different read flag, and instead of an rc of 0, we're now expecting an rc of LIBEVDEV_READ_STATUS_SYNC. libevdev will give us events that all reflect the state change since the SYN_DROPPED so we can update the client accordingly. Once the device is fully synced, libevdev_next_event returns -EAGAIN to indicate there are no more events to sync. The client can go back to reading events normally with LIBEVDEV_READ_FLAG_NORMAL.

This is a lot simpler than having to ioctl the device and calculating the state manually.

The state handling is the same as described above. Even though libevdev knows that there are e.g. a few button events waiting in the sync queue it will not update the client-visible state until it passed the respective event to you.

Finally: you don't have to sync the device after a SYN_DROPPED event. You can chose to keep reading with LIBEVDEV_READ_FLAG_NORMAL as if nothing happened. If you do so, libevdev will drop the sync event queue, update the internal state to match the sync status and pass you the next real event. So even if you didn't get that button down event because you dropped the sync, libevdev_get_event_value(dev, EV_KEY, BTN_LEFT) will now return 1 to reflect the state of the device. So libevdev's device state still matches what the client would otherwise see (had it processed all events).

This is a base overview of how libevdev works. In the next post, I'll show how to manipulate the device.

[1] look the kernel source, drivers/input/evdev.c:handle_eviocgbit, supplying the wrong size was common enough to warrant a warning in the kernel.

Friday, September 13, 2013

git-branch-tools: creating patch sets

git-branch-tools is my little repo for git scripts to make a few things easier. I first talked about it here. The repository is available on https://github.com/whot/git-branch-tools, the latest addition is git patch-set. I used to create git patch sets with just git format-patch, but too often I found some minor change on the last review and had to re-generate it. So ended up with multiple patch files in the directory, or worse, a combination of old and new ones in danger of being sent by git send-email later. git-patch-set fixes this for me:
$> git patch-set HEAD~2
patches/patches-201309130933-HEAD~2/0001-test-provide-wrapper-for-fetching-the-devnode-from-a.patch
patches/patches-201309130933-HEAD~2/0002-wrap-EVIOCSCLOCKID-into-an-API-call.patch
So my patches are in the $GIT_DIR/patches/ directory, named after the current date + time and the refs used for the list. This makes them identifiable and sortable (to some degree anyway). And, to make things easier, $GIT_DIR/patches/latest is a symlink to the latest patch set, so usually the workflow is
$> git patch-set HEAD~2
patches/patches-201309130933-HEAD~2/0001-test-provide-wrapper-for-fetching-the-devnode-from-a.patch
patches/patches-201309130933-HEAD~2/0002-wrap-EVIOCSCLOCKID-into-an-API-call.patch
$> git send-email patches/latest/*.patch
That's not all though. I've added two hooks, pre-patch-set and post-patch-set to be run before/after the actual patch generation.
$> cat .git/hooks/pre-patch-set
#!/bin/bash -e
echo "running make check"
make check
$> git patch-set HEAD~2
running make check
Making check in doc
doxygen libevdev.doxygen
Making check in libevdev
make  check-am
make[2]: Nothing to be done for `check-am'.
Making check in tools
make[1]: Nothing to be done for `check'.
Making check in test
make  check-TESTS check-local
PASS: test-libevdev
make[4]: Nothing to be done for `all'.
============================================================================
Testsuite summary for libevdev 0.3
============================================================================
# TOTAL: 1
# PASS:  1
# SKIP:  0
# XFAIL: 0
# FAIL:  0
# XPASS: 0
# ERROR: 0
============================================================================
  GEN      gcov-report.txt
========== coverage report ========
libevdev-uinput.c: total lines: 172 not tested: 28 (83%)
libevdev.c: total lines: 689 not tested: 78 (88%)
========== =============== ========
patches/patches-2013091309:33-HEAD~2/0001-test-provide-wrapper-for-fetching-the-devnode-from-a.patch
patches/patches-2013091309:33-HEAD~2/0002-wrap-EVIOCSCLOCKID-into-an-API-call.patch
I've been using that script for quite a while now and it did make sending patch sets a bit easier. Plus, now I'm not in danger of sending out patch sets that don't pass make check :)

Wednesday, April 17, 2013

CVE-2013-1940: VT-switched servers receive input from hot-plugged devices

Rather by accident, Dave Airlie and I found a minor security issue in the X server last week (read the story here) This issue has been assigned CVE-2013-1940 and is now publicly available. The corresponding bug reports are here: https://bugs.freedesktop.org/63353 and https://bugzilla.redhat.com/950438.

X servers receive notifications from HAL/udev about new input devices, even when you vt-switched to the tty or another server. Input devices added while the server is not the owner of the vt will be added but not enabled, so events from such devices are ignored. On vt-switch back, the device is enabled and the fd is added to the select set used by the server. Future events will trigger a SIGIO and will be processed as expected

evdev holds the fd open between PreInit and enabling the device. If the device is hot-plugged while the server is vt-switched away events accumulate on the fd. evdev calls xf86FlushInput() to discard these events but a bug in that function made it essentially a noop for evdev devices. Thus, once the server is the VT owner again, events from that device are still on the fd and are processed whenever the next event comes along on that device.

Reproducer is fairly simple: open a text editor, vt-switch, hotplug a keyboard, type something on that keyboard, vt-switch back and the events will be replayed on the existing server.

This issue is now fixed upstream and I have released xserver 1.13.4 and xserver 1.14.1. It is of relatively low impact but the fix is easy so I recommend to patch your X servers.

Monday, March 4, 2013

git branch-tools: some helpers for managing git branches

I'm using a lot of branches. Almost one per feature or bug, and they add up quickly. Why I'm doing this doesn't matter for this post, but I found it to be a good workflow. The problem with that is of course that after a while I forget which branch was for what, or what branch I worked on three weeks ago. So I started hacking up some git helpers.

I pushed them to https://github.com/whot/git-branch-tools today, feel free to use them or improve on them.

Archiving branches

Some branches are not actively developed anymore but should still be preserved for posterity. These branches are clogging up the branch view.

git archive-branch mybranch
moves mybranch to archive/2013/mybranch and tags the current top commit with a message about the branch history. An example git branch output would look like this now:
  ...
  archive/2013/touch-test-libtool-linker-issues
  archive/2013/two-screen-coordinates
  archive/2013/wrong-signal-logging-merge
  archive/2013/xi2-protocol-tests
  archive/2013/xi21-confine-to
  archive/2013/xorg-conf-init-cleanup
  attic
  bugfix/xts-segfault
  devel
  fedora-17-branch
  fedora-rawhide-branch
  for-keith
  high-keycodes
  master
  memleak
* next
  ...

Showing recent branches

Working on many branches can mean you forget which branch you worked on last week, or the week before.

git recent-branches
lists the various branches checked out over the history, including the date and last commit date on that branch. Example:
next                                 4 hours ago    last commit 6 days ago
server-1.13-branch                   4 hours ago    last commit 2 weeks ago
touch-grab-race-condition-56578-v2   3 days ago     last commit 3 days ago
touch-grab-race-condition-56578      4 days ago     last commit 6 days ago      †
bug/xts-segfaults                    6 days ago     last commit 6 days ago      †
master                               6 days ago     last commit 3 weeks ago
for-keith                            10 days ago    last commit 2 weeks ago
memleak                              13 days ago    last commit 2 weeks ago
The output above shows the branch name, last time that branch was checked out, last commit time and a marker that shows up if this branch doesn't exist anymore. There are a few more flags you can pass in too, including git log flags, so play around with it.

Better branch descriptions

Can't remember what branch "fix-race-condition" was? Me neither. That's what

git branch-description [branchname] [upstream]
will tell you. If upstream is given, it'll also show you what has been merged into upstream already (by patch, not by commit). Example again:
:: whot@yabbi:~/xorg/xserver (next)> git-branch-description touch-grab-race-condition-56578-v2
Branch       touch-grab-race-condition-56578-v2
Branched:    Thu Feb 14 11:05:48 2013 -0800
Last commit: Fri Mar 1 16:37:49 2013 +1000

Fixes for https://bugs.freedesktop.org/show_bug.cgi?id=56578, second attempt

============================ Unmerged commits =============================
Commits on touch-grab-race-condition-56578-v2 not in next:
68b937046f278d53de14b586dbf7fd5aa7367f59 Xi: return !Success from DeliverTouchEmulatedEvent if we didn't deliver
f8baab8ac32e5abb31bcd1bb4f74e82d40208221 Xi: use a temp variable for the new listener
9cbb956765c7b4f1572ab2100f46504bf6313330 dix: don't set non-exisiting flags on touch events
2a5b3f2f2293f4a428142fffdb1b6e8ffbbb5db0 dix: fix a comment
76e8756545951d7f13ca84a4bd24fe5f367c5de2 Xi: compress two if statements with the same body
61b06226a43839ed75126f9c54d47bc440285e21 dix: update coords for touch events in PlayReleasedEvents
bd1a5423bbb02a349991a52f4997e830a0dc1992 Xi: add a comment to make a condition a bit clearer
78b26498085a7589e1f4d9ac3c21b69dc3227f87 Xi: not having an ownership mask does not mean automatic acceptance
c7271c7e05cdbeb35a3558223f9c2d6544504c4c dix: don't prepend an activated passive grab to the listeners
71ee72c97e459ef76984e6da64e5dab0ce6e4465 Xi: if we delivered a TouchEnd to a passive grab, end it
9b6966187fd0e6fb7ad3c2c1073456d96e3adab0 Xi: if a pointer grabbing listener gets the touch end, the touch is over
5afef18196ce70faec3e94379c3e6d3767660c4a FIXME: Xi: fix lookup in ActivateEarlyAccept
3784283be1f482a0f039f2eb790c0c8c2cc4bedb Xi: update the core listener state if we delivered the event
3570ef1244c87aef92db97df6e2b921529ffb75a Xi: if a passive async grab is activated from an emulated touch, accept
9bef901d8e28d48f43da3167219b02ad1dba27d8 Xi: save state for early acceptance
7d51022becd5af124896817030a10eedf7f1783a Xi: when punting to a new owner, always create TouchEnd events
4775cdb0d9a2513edcf27a9c4c1916e8213c397b Xi: use public.processInputProc to replay the touch history
431b128b9138af7a208b63d4eb5b917d94c08129 Xi: Don't emit a TouchEnd event to a frozen device
4126d64f6a40d5568b2d1412d519325c02786c9a dix: AllowSome is equivalent to TouchAccept
33421e91a52be91d7121c7c2146ff7bb53bea638 dix: move EmitTouchEnd to touch.c
54f8884aef275b15f2c42e3350e2b4968124af01 dix: XAllowEvents() on a touch event means accepting it

Commits on touch-grab-race-condition-56578-v2 already merged to next:

================================= Activity =================================
e7b4b83 HEAD@{5 hours ago}: checkout: moving from touch-grab-race-condition-56578-v2 to server-1.13-branch
9cbb956 HEAD@{3 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to 9cbb956
d58ddeb HEAD@{3 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to d58ddeb
7c3968b HEAD@{3 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to 7c3968b
a354dd8 HEAD@{3 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to a354dd8
fdf4869 HEAD@{3 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to fdf4869
82be6b2 HEAD@{3 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to 82be6b2
82be6b2 HEAD@{3 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to 82be6b2
68b9370 HEAD@{3 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to 68b9370
151eff1 HEAD@{3 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to 151eff1
57fa0b9 HEAD@{3 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to 57fa0b9
b43e866 HEAD@{3 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to b43e866
ef6a120 HEAD@{3 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to ef6a120
9064294 HEAD@{3 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to 90642948cc78834d95f7a3bddaac7ff77b68ed7e
9064294 HEAD@{3 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to 90642948cc78834d95f7a3bddaac7ff77b68ed7e
6513e0e HEAD@{3 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to 6513e0e
0d60ba6 HEAD@{3 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to 0d60ba6
dd23302 HEAD@{4 days ago}: checkout: moving from f21354da571dcd39ae1423388298d5c61d3e736d to touch-grab-race-condition-56578-v2
f21354d HEAD@{4 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to f21354da571dcd39ae1423388298d5c61d3e736d
0d60ba6 HEAD@{4 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to 0d60ba6
ae2cac9 HEAD@{4 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to ae2cac99a75917d6c4d34b8aa4aeaec0b5d32da7
c2b3d37 HEAD@{4 days ago}: checkout: moving from d75925b9fb8b24c8134b5082294e82abf83294af to touch-grab-race-condition-56578-v2
0d60ba6 HEAD@{4 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to 0d60ba683e7e95049c01ac5dba48a2f5fd80d9b9
c2b3d37 HEAD@{4 days ago}: checkout: moving from 0d60ba683e7e95049c01ac5dba48a2f5fd80d9b9 to touch-grab-race-condition-56578-v2
0d60ba6 HEAD@{4 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to 0d60ba683e7e95049c01ac5dba48a2f5fd80d9b9
0d60ba6 HEAD@{4 days ago}: checkout: moving from 90642948cc78834d95f7a3bddaac7ff77b68ed7e to touch-grab-race-condition-56578-v2
9064294 HEAD@{4 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to 90642948cc78834d95f7a3bddaac7ff77b68ed7e
8e5adb4 HEAD@{4 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to 8e5adb4ef8bafa2a3188e69409e2908f80288311
033b932 HEAD@{4 days ago}: checkout: moving from touch-grab-race-condition-56578 to touch-grab-race-condition-56578-v2

And install the git-post-checkout-nagging-hook as your .git/hooks/post-checkout to make sure you get reminded to set the branch description.