rubygems/rubygems.org — pull request #597 by jagthedrummer (2013-09-05 19:02:16+00:00)
Title: Show full dependency tree for Versions (ported from gemlou.pe)

This PR contains the initial port of the gemlou.pe dependency tree functionality into rubygems.org. It's meant to be a starting point for discussion of this feature. Questions/suggestions/criticisms are welcome.

### Background

A RailsConf I gave a lightning talk about my GemLoupe project (https://www.gemlou.pe/), which allows you to see the full dependency tree (not just direct dependencies) of any gem on rubygems.org. @qrush asked if I'd be interested in porting the dependency tree feature directly into rubygems.org. (Sorry for the delay, Nick.)

### Approach

To calculate the full dependency tree for a `Version` I'm writing a very simple `Gemfile` containing one gem into a tmp directory then shelling out to a simple script that runs Bundler and resolves the dependencies for that gem. I had to resort to shelling out to get outside of the Bundler context that is already in place inside the running app.

Part of the delay in submitting this PR is that I had looked into trying to resolve the dep tree entirely within the rubygems.org application (without Bundler, using the DB data), but then realized that I would need to duplicate much of the resolver functionality that is built into Bundler. I finally decided that it was better to port in the functionality that I already had working in GemLoupe and get some feedback from everyone about the merits of the current approach. It does introduce a weird circular dependency from rubygems.org -> Bundler -> rubygems.org, but it also means that if the Bundler resolver method changed in the future (however unlikely) the trees calculated for rubygems.org would automatically be up to date.

I'd love to hear any thoughts that anybody has about this approach.

### See it in action

After checking out this branch you can run something like this in a console to prepare the dependency tree for a given version.

```ruby
version = Version.find(xxx)
version.prep_tree
```

Then when you visit the page for that version you should see something like this:

![Dependency Tree Example](http://production.octolabs.com.s3.amazonaws.com/uploads/10/Screen_Shot_2013-09-05_at_1.39.29_PM.png)

### Issues

Currently I'm storing the dependency tree information as JSON in a `text` column. Some trees can get very large (Rails for instance), so I'm not sure if this is the best way to go.

I don't have everything wired up to automatically generate a tree when a new version is pushed. I think it should probably be handled asynchronously in a `DelayedJob`. Maybe queued up in the `after_write` method of `Pusher`?

The visual style of the dep tree could certainly use some work. I'm no designer, so I'd love to get someone with a better eye to take a look at that. My goal was to make it easy to see where the big "heavy" gems are in a tree.