I've been managing my UNIX $HOME repository with version control for almost two decades now (first under CVS, then with git). Once in a while, I find a little hack to make this work better.

Today, it's dconf/gsettings, or more specifically, Workrave that I want to put in git. I noticed my laptop was extremely annoying compared with my office workstation and realized I never figured out how to write Workrave's configuration to git. The reason is that its configuration is stored in dconf, a binary database format, but, blissfully, I had forgotten about this and tried to figure out where the heck its config was.

I was about to give up when I re-remembered this, when I figured I would just do a quick search ("dconf commit to git") and that brought me to Josh Triplett's Debconf 14 talk about this exact topic. The slides are... a little terse, but I could figure out the gist of it. The key is to change the DCONF_PROFILE environment to point to a new config file (say in your .bashrc):

export DCONF_PROFILE=$HOME/.config/dconf/profile

That file (~/.config/dconf/profile) should be created with the following content:

user-db:user
service-db:keyfile/user
  1. The first line is the default: store everything in this huge binary file.

  2. The second is the magic: it stores configuration in a precious text file, in .config/dconf/user.txt specifically.

Then the last step was to migrate config between the two. For that I need a third config file, a DCONF_PROFILE that has only the text database so settings are forcibly written there, say ~/.config/dconf/profile-edit:

service-db:keyfile/user

And then I can migrate my workrave configuration with:

gsettings list-recursively org.workrave | while read schema key val ; do DCONF_PROFILE=~/.config/dconf/profile-edit gsettings set "$schema" "$key" "$val" ; done

Of course, a bunch of those settings are garbage and do not differ from the default. Unfortuantely, there doesn't seem to be a way to tell gsettings to only list non-default settings, so I had to do things by hand from there, by comparing my generated config with:

DCONF_PROFILE=/dev/null gsettings list-recursively org.workrave

I finally ended up with the following user.txt, which is now my workrave config:

[org/workrave/timers/daily-limit]
snooze=1800
limit=25200

[org/workrave/timers/micro-pause]
auto-reset=10
snooze=150
limit=900

[org/workrave/timers/rest-break]
auto-reset=600
snooze=1800
limit=10800

[org/workrave/breaks/micro-pause]
max-preludes=0

That's a nice setup: "YOLO" settings end up in the binary database that I don't care about tracking in git, and a precious few snowflakes get tracked in a text file. Triplett also made a command to change settings in the text file, but I don't think I need to bother with that. It's more critical to copy settings between the two, in my experience, as I rarely have this moment: "oh I know exactly the key setting I want to change and i'll write it down". What actually happens is that I'm making a change in a GUI and later realize it should be synchronized over.

(It looks like Triplett does have a tool to do those diffs and transitions, but unfortunately git://joshtriplett.org/git/home doesn't respond at this time so I can't find that source code.)

(Update: that git repository can be downloaded with:

git clone https://joshtriplett.org/git/home

It looks like dconfc is designed to copy settings between the two databases. So my above loop would be more easily written as:

dconf dump /org/workrave/ | DCONF_PROFILE=~/.config/dconf/profile-edit dconf load /org/workrave/

Certainly simplifies things. dconfd is also nice although it relies on the above dconfe script which makes it (IMHO) needlessly hard to deploy.)

Now if only Firefox bookmarks were reasonable again...

Created . Edited .