RE: dev-ruby/rails: File Collision Free Since September 2007!

I wrote earlier about our ebuilds for Rails being file collision free.

To get around having a blocker exposed to the user, rails had a post dependency on eselect-rails, meaning that eselect-rails would get merged AFTER rails. What I failed to remember, though, was that the eselect module was used during the merge of rails, so it had to be a build-time dependency, meaning it'd be pulled in before rails was merged.

This resulted in bug #191015.

Just changing it to DEPEND, and leaving the blockers in eselect-rails would have made annoying blockers, that would probably be a bit confusing for end-users.

So I did a bit of thinking about what really should block what. Versions less than 1.1.6-r2 are in SLOT=1 and install /usr/bin/rails. Versions 1.2.0, 1.2.1, 1.2.2, and 1.2.3 are in SLOT=2 and install /usr/bin/rails. So why not just make those versions block each other?

For less than 1.1.6-r2, we have:

DEPEND=">=dev-lang/ruby-1.8.2
        -snip-
        !~dev-ruby/rails-1.2.0
        !~dev-ruby/rails-1.2.1
        !=dev-ruby/rails-1.2.3"

And in 1.2.0, 1.2.1, 1.2.2, and 1.2.3, we have:

DEPEND=">=dev-lang/ruby-1.8.5
        -snip-
        !<dev-ruby/rails-1.1.6-r1"

I then removed the blockers in eselect-rails, so now it just depends on eselect.

So here are some use cases, and what happens you try to do emerge -u rails.

If you don't care about these, you can just skip down to the summary.

rails-1.1.6-r1 installed

/usr/bin/rails is from rails-1.1.6-r1

metaverse ~ # emerge -ptvu rails

These are the packages that would be merged, in reverse order:

Calculating dependencies... done!
[ebuild     U ] dev-ruby/rails-1.1.6-r2 [1.1.6-r1] USE="fastcgi mysql -doc -postgres -sqlite -sqlite3" 0 kB 
[ebuild  NS   ] dev-ruby/rails-1.2.3-r1  USE="fastcgi mysql -doc -postgres -sqlite -sqlite3" 0 kB 
[ebuild  N    ]  app-admin/eselect-rails-0.10  0 kB 

Total: 3 packages (1 upgrade, 1 new, 1 in new slot), Size of downloads: 0 kB

The version in SLOT=1 gets updated to the latest, and the version in the new slot gets brought in.

Version 1.2.3-r1 gets merged first. During its postinstall, it tries to update the /usr/bin/rails symlink, but it's a file at this point, so it ignores it.

Version 1.1.6-r2 gets merged next, then 1.1.6-r1 gets unmerged because it's in the same slot. This results in there being no /usr/bin/rails. When the postinstall runs, it sees this, and populates it to point use this version.

/usr/bin/rails is a symlink managed by eselect-rails, and points at /usr/bin/rails-1.1.6

rails-1.2.3 installed

/usr/bin/rails is from rails-1.2.3.

metaverse ~ # emerge -ptvu rails
These are the packages that would be merged, in reverse order:

Calculating dependencies... done!
[ebuild     U ] dev-ruby/rails-1.2.3-r1 [1.2.3] USE="fastcgi mysql -doc -postgres -sqlite -sqlite3" 0 kB 
[ebuild  N    ]  app-admin/eselect-rails-0.10  0 kB 

Total: 2 packages (1 upgrade, 1 new), Size of downloads: 0 kB

The version in SLOT=2 gets updated to the latest.

Version 1.2.3-r1 gets merged next, then 1.2.3 gets unmerged because it's in the same slot. This results in there being no /usr/bin/rails. When the postinstall runs, it sees this, and populates it to point use this version.

/usr/bin/rails is a symlink managed by eselect-rails, and points at /usr/bin/rails-1.2.3

rails-1.1.6-r1 and rails-1.2.3 installed

This can only happen if you don't have FEATURES="collision-protect" in your make.conf.

/usr/bin/rails ends up being from whichever version was last installed.

metaverse ~ # emerge -ptvu rails
These are the packages that would be merged, in reverse order:

Calculating dependencies... done!
[ebuild     U ] dev-ruby/rails-1.1.6-r2 [1.1.6-r1] USE="fastcgi mysql -doc -postgres -sqlite -sqlite3" 0 kB 
[ebuild     U ] dev-ruby/rails-1.2.3-r1 [1.2.3] USE="fastcgi mysql -doc -postgres -sqlite -sqlite3" 0 kB 
[ebuild  N    ]  app-admin/eselect-rails-0.10  0 kB 
[blocks B     ] =dev-ruby/rails-1.2.3 (is blocking dev-ruby/rails-1.1.6-r1)

Total: 3 packages (2 upgrades, 1 new, 1 block), Size of downloads: 0 kB

Now we have a blocker. What does it mean? It's saying that rails-1.2.3 is in the way of rails-1.1.6-r1. This is a little weird, because you'd think that since both versions are getting updated in such a way that would negate the blocker. It seems a bug has been filed about this very thing.

In the mean time, this is how you resolve this:

emerge -C =dev-ruby/rails-1.2.3

At this point, we only have rails-1.1.6-r1 installed, and it goes along like the first use case.

/usr/bin/rails is a symlink managed by eselect-rails, and points at /usr/bin/rails-1.1.6

If the old reversions have a file-collision, and now block each other, how did you test these use cases?

I disabled collision-protect on the command line, like:

FEATURES="-collision-protect" emerge ...

And I used the --nodeps command line argument for emerge, in order to ignore the dependencies, hence getting around the blockers.

The result is...

FEATURES="-collision-protect" emerge --nodeps =rails-1.2.3 =rails-1.1.6-r1

IMPORTANT This is not how you should get around blockers / file collisions. It really should only be used for testing and development.

Summary

The upgrade path ended up being a bit foobared for 1.1.6-r2 and 1.2.3-r1.

If you were seeing behavior described in bug #191015, I suggest doing:

metaverse ~ # emerge -C rails eselect-rails
metaverse ~ # emerge rails

If you see a blocker, that might look like:

Calculating dependencies... done!
[ebuild     U ] dev-ruby/rails-1.1.6-r2 [1.1.6-r1] USE="fastcgi mysql -doc -postgres -sqlite -sqlite3" 0 kB 
[ebuild     U ] dev-ruby/rails-1.2.3-r1 [1.2.3] USE="fastcgi mysql -doc -postgres -sqlite -sqlite3" 0 kB 
[ebuild  N    ]  app-admin/eselect-rails-0.10  0 kB 
[blocks B     ] =dev-ruby/rails-1.2.3 (is blocking dev-ruby/rails-1.1.6-r1)

You need to...

emerge -C =rails-1.2.3
September 04, 2007 at 01:11 Permalink Edit Destroy

dev-ruby/rails: File Collision Free Since September 2007!

For some time now, there has been a file collision between rails 1.1.x and rails 1.2.x, because it is a) slotted so both can be installed at the same time and b) both install /usr/bin/rails.

This issue has single handedly kept rails-1.2.3 from being stablized until now.

Since they are battling over /usr/bin/rails, it made sense for each slot to install versioned rails script, like /usr/bin/rails-1.2.3, and then use eselect to manage what /usr/bin/rails points at. This is a pretty common use case for using eselect.

Hans de Graaff, a fellow Gentoo Rubyist, did the initial work getting a new eselect module going. After reviewing and discussing it, we found a few issues that needed to be addressed. I took the torch and ran, and made sure most of the upgrade paths would worked properly.

So without further ado, I present you with dev-ruby/rails-1.1.6-r2 and dev-ruby/rails-1.2.3-r1.

These were barely committed, it might take a few hours to initially hit the mirrors.

Just 'emerge --u rails', and you'll get the updates.

Note the use of '-u'. This will ensure that both slots get updated at the same time (if they are installed) without an annoying blocker.

Thanks goes out to Hans de Graaff for his initial work and subsequent feedback, and Zack Medico for his initial post about sane upgrade paths with blockers, and subsequent help with figuring out how to get it to work with rails and eselect-rails.

September 01, 2007 at 01:39 Permalink Edit Destroy