Merging from trunk to a branch

You created a branch in subversion, and while you were working on it, trunk progressed. You now want to include the trunk updates in your branch. What should you do? Maybe merge from trunk into your branch?

svn merge ${url}/trunk branches/mybranch

Nope! This isn’t it. Think about the simple case: branch out, edit the branch, merge back. What does ‘merge’ mean in this case? If I understand correctly, it means replaying on trunk all the changes you made to your branch.

What happens when you run the above command then? You replay all the changes you made to trunk, on top of your branch. Once that is done, what happens when you want to merge your branch back to trunk? One of the changes to be replayed is the merge you did, but it contains changes that have already been made on trunk, and the merge does not work.

How to do it properly then? What you probably meant to do, is to have your branch as if you started your branch-work on the newer trunk. Let’s first consider the simple case, where you branch out and then merge back.

svn cp ${url}/trunk ${url}/branches/mybranch
svn update
...editing your branch...
svn commit -m "edits to my branch"
svn merge ${url}/branches/mybranch trunk
svn commit -m "merging mybranch back to trunk"

That works. And it cannot really be more complex than that. Maybe if you’re a subversion whiz, but I’m not, so I like to stick to simple scenarios I can understand.

Let’s try to accommodate an updated trunk into the above workflow. It starts as usual:

svn cp ${url}/trunk ${url}/branches/mybranch
svn update
...editing your branch...
svn commit -m "edits to my branch"

So far so good. Let’s say there are some updates to trunk we want to see in our branch. You would think: “Why didn’t I start working on my branch later, I would have all the updates already in my branch!”. It turns out, you can do that! You can create an new branch from the new trunk, and then replay all the changes from your branch on top of it. The result? You still have your changes in a separate branch, and you have the updates to trunk too.

svn status
# Make sure this returns nothing ‒ your working copy is clean.
svn cp ${url}/trunk ${url}/branches/mybranch2
svn update
svn merge ${url}/branches/mybranch branches/mybranch2
# There is potential for code conflicts here, you need to resolve them.
svn commit -m "Replaying changes made to mybranch onto mybranch2."
svn rm ${url}/branches/mybranch
# Let's go to the original branch name.
svn mv ${url}/branches/mybranch2 ${url}/branches/mybranch
svn update

Your branch is now updated and looks as if you’ve started to work on it using the new trunk. You can use the regular merging procedure.

svn merge ${url}/branches/mybranch trunk
svn commit -m "merging mybranch back to trunk"

Your changes are now merged back to trunk.

Bridge and ipv6 autoconfiguration

“There’s no sound”, said my missus.

Few minutes before, as usual, I picked up my 17-inch laptop and placed it on the second desk, where it can face the room. I don’t really like dragging the armchair every time I want to watch a video together, but the flat isn’t big enough to arrange a place with a permanent setup. (I also don’t own a TV and I’m proud of it.)

This time there was indeed no sound.

“Wait a minute”, I said and opened Gnome Terminal. At my place, there is only one set of speakers connected to one computer, and shared over the local area network. After a while I figured out that mplayer had trouble contacting PulseAudio server. The server wouldn’t respond.

I tried playing sound from a different machine – it worked. So it’s not the server. Next test:

maciej@quince ~ $ ping -c 1 leon
PING leon.home.blizinski.pl (192.168.1.3) 56(84) bytes of data.
64 bytes from leon.home.blizinski.pl (192.168.1.3): icmp_seq=1 ttl=64 time=0.165 ms

— leon.home.blizinski.pl ping statistics —
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.165/0.165/0.165/0.000 ms

Next test…

maciej@quince ~ $ telnet leon 4713
Trying 2001:
660:952::20a:e4ff:fe28:a3cf...

Timeout. And… ah. I forgot I was running native IPv6 in my LAN. I tried connecting over IPv4, it worked. I’ve set ${PULSE_SERVER} to the IPv4 address of the PulseAudio server and happily watched the movie together with my missus.

But… what’s going on? Running ping6 ipv6.google.com gives good results – there are answers. But when I ran ping6 leon, I got no answer. How can ping work for an external host but not for a host in my LAN?

After more poking at the machine, I’ve found out that the response packets (ACK) over IPv6 are in fact coming to the slave eth0 interface, but never to the bridge interface, br0.

Then I’ve noticed that IPv6 routing is wrong! There are two routes:

2001:660:952::/64 dev eth0
2001:660:952::/64 dev br0

Packets should leave through br0, not eth0. First idea, restart the bridge. However, the wrong route stayed there even after interface restart. It made me think what happens when I stop the bridge.

Well, eth0 goes back from slave state into a normal state, and then… it’s autoconfigured. That means, it gets a route assigned to it. When the bridge is being started, eth0 becomes a slave of br0, but there probably is no mechanism to remove the route which was assigned during eth0’s autoconfiguration.

A quick ad-hoc fix is:

ip -6 route del 2001:660:952::/64 dev eth0

A permanent solution would be better, but I happen to be lazy.

UPDATE 2009-02-01: Jeroen Massar from SixXS offered a better workaround:
put in /etc/sysctl.conf:
net.ipv6.conf.eth0.accept_ra = 0

When talking about this problem, the conversation usually goes like this:
– I have this problem with IPv6 autoconfiguration… (yada yada)
– What distribution are you using?
– Gentoo.
– (laughter)

Well, turns out, they were right. I tried this config on Ubuntu:

maciej@ubuntu-vbox:~$ cat /etc/network/interfaces
auto lo
iface lo inet loopback
 
iface br0 inet dhcp
bridge_ports eth0
 
auto eth0
auto br0

After “/etc/init.d/network restart”, the surplus route was there. But after a reboot, it wasn’t there any more. Ubuntu/Debian somehow handles this case.

Ctrl key not working in VNC

Continuing my series of short tech notes for future generations.

The problem: ctrl key not working in VNC session. xev command doesn’t show any events coming after pressing ctrl key.

Cause: You’re using Gnome, aren’t you? Gnome has a feature that allows to locate the pointer: if you press and release ctrl key, it will show a small animation around your pointer. Unfortunately, it interferes with vncviewer.

Solution: Few websites, including BBC, offer a fix: System → Preferences → Mouse → Cursors tab…

Problem with the solution: Oh noes! Cursor tab is not there! I can’t change the setting!

Solution to the problem with the solution: Use gconf-editor to change the setting: Applications → System Tools → Configuration Editor. Press CTRL+F. Type: “pointer”. Tick “search also in key names” and press “Find”. Click /desktop/gnome/peripherals/mouse/locate_pointer. Untick the checkbox next to it, on the top right pane.

NAS won’t play? Wrap it with aoss!

I like to watch video on one laptop, while speakers are connected to the other; I don’t like the cable hanging in midair between the tables, begging to be pulled by someone when passing. I used to solve this by NAS, the Network Audio Server, an ancient, but still usable project that allows you to send audio through network and play from one computer to another. The problem is that I couldn’t lately get it to work. I’ve solved this yesterday, so here you go, back to the tradition of blogging my tech notes.

  • problem: nasd (the NAS daemon) would interfere with other applications, or other applications with nasd
  • symptoms: nasd won’t play, or Firefox won’t play, or music won’t play
  • how to discover: applications complain about /dev/dsp being busy
  • cause: nasd uses OSS, the deprecated “open sound system”, instead of ALSA, and OSS drivers often don’t allow applications to share sound output
  • solution: make NAS (and other applications, too) use alsa by using aoss wrapper

In Ubuntu:

  1. sudo apt-get install alsa-oss
  2. sudo gedit /usr/bin/start-nas
  3. Replace:
    nice -n -10 /usr/bin/nasd -b "$@"
    with:
    nice -n -10 aoss /usr/bin/nasd -b "$@"
    As for Firefox, follow these short instructions.

What happens now is, that the aoss wrapper hijacks calls to /dev/dsp made by NAS and handles them by using Alsa. The main interesting difference between OSS and ALSA is that in most OSS drivers, the sound output /dev/dsp cannot be shared among applications. For instance, having Firefox open might mean that Flash application is keeping the sound device open, even though it isn’t playing anything at the moment. And keeping /dev/dsp open means that no other application is allowed to play sound.

So far, I’ve watched one video using this setup, and the audio wasn’t perfect; I could hear clicks quite often. But I’m fine with that. If it annoys me, I’ll consider switching over to Pulse Audio.

UPDATE 2008-03-30:
I’ve switched to PulseAudio a couple weeks ago and I have to say it’s the best audio system I’ve ever used. The only strange thing I had to do was installing a library for Flash Player 9 that would make it able to use Pulse Audio. I have two computers transparently using a single set of speakers. Best setup ever.