Index: release/views/project_release.views.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/project/release/views/project_release.views.inc,v
retrieving revision 1.4
diff -u -r1.4 project_release.views.inc
--- release/views/project_release.views.inc	8 Aug 2009 01:24:02 -0000	1.4
+++ release/views/project_release.views.inc	5 Nov 2009 20:57:21 -0000
@@ -20,6 +20,13 @@
   // have a group defined will go into this field by default.
   $data['project_release_nodes']['table']['group']  = t('Project release');
 
+  $data['project_release_nodes']['table']['base'] = array(
+    'field' => 'nid',
+    'title' => t('Project release'),
+    'help' => t('Project release information.'),
+    'weight' => -10,
+  );
+
   $data['project_release_nodes']['table']['join'] = array(
     'node' => array(
       'left_field' => 'nid',
Index: release/package-release-nodes.php
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/project/release/package-release-nodes.php,v
retrieving revision 1.50
diff -u -r1.50 package-release-nodes.php
--- release/package-release-nodes.php	18 Aug 2009 21:18:30 -0000	1.50
+++ release/package-release-nodes.php	5 Nov 2009 20:57:21 -0000
@@ -1,4 +1,3 @@
-#!/usr/bin/php
 <?php
 
 // $Id: package-release-nodes.php,v 1.50 2009/08/18 21:18:30 dww Exp $
@@ -22,29 +21,29 @@
 // The root of your Drupal installation, so we can properly bootstrap
 // Drupal. This should be the full path to the directory that holds
 // your index.php file, the "includes" subdirectory, etc.
-$drupal_root = '';
+$drupal_root = '/home/boombatower/software/drupal-6';
 
 // The name of your site. Required so that when we bootstrap Drupal in
 // this script, we find the right settings.php file in your sites folder.
 // For example, on drupal.org:
 // $site_name = 'drupal.org';
-$site_name = '';
+$site_name = 'pift.d6x.loc';
 
 // The CVSROOT for the repository this script will be packaging
 // releases from.  For example, on drupal.org:
 // $cvs_root = ':pserver:anonymous@cvs.drupal.org:/cvs/drupal';
-$cvs_root = '';
+$cvs_root = ':pserver:anonymous:anonymous@cvs.drupal.org:/cvs/drupal-contrib';
 
 // Root of the temporary directory where you want packages to be
 // made. Subdirectories will be created depending on the task.
-$tmp_root = '';
+$tmp_root = '/home/boombatower/download/build';
 
 // Location of the LICENSE.txt file you want included in all packages.
-$license = '';
+$license = '/home/boombatower/software/simpletest/CHANGELOG.txt';
 
 // Location of the INSTALL.txt file you want included in all
 // translation packages.
-$trans_install = '';
+$trans_install = '/home/boombatower/software/simpletest/CHANGELOG.txt';
 
 
 // ------------------------------------------------------------
@@ -58,7 +57,7 @@
 // "files/projects" directory of your root Drupal installation. If
 // that's not the case, you should customize these.
 $dest_root = $drupal_root;
-$dest_rel = 'files/projects';
+$dest_rel = 'sites/pift.d6x.loc/files/projects';
 
 // --------------
 // External tools
@@ -305,9 +304,9 @@
       }
     }
     if (!empty($fails)) {
-      wd_msg('ERROR: Failed to re-generate release history XML files for !num project(s)', array('!num' => $fails)); 
+      wd_msg('ERROR: Failed to re-generate release history XML files for !num project(s)', array('!num' => $fails));
     }
-    wd_msg('Done re-generating release history XML files for !num project(s)', array('!num' => $i)); 
+    wd_msg('Done re-generating release history XML files for !num project(s)', array('!num' => $i));
   }
 }
 
@@ -370,6 +369,12 @@
   global $cvs, $tar, $gzip, $rm, $ln;
   global $license, $trans_install;
 
+  // If project_info module exists then load package.inc.
+  static $project_info;
+  if (!isset($project_info) && ($project_info = module_exists('project_info'))) {
+    module_load_include('package.inc', 'project_info');
+  }
+
   $rid = 2;
   // Files to ignore when checking timestamps:
   $exclude = array('.', '..', 'LICENSE.txt');
@@ -417,7 +422,7 @@
     return false;
   }
 
-  // Fix any .info files
+  // Fix any .info files.
   foreach ($info_files as $file) {
     if (!fix_info_file_version($file, $uri, $version)) {
       wd_err("ERROR: Failed to update version in %file, aborting packaging", array('%file' => $file), $view_link);
@@ -425,6 +430,11 @@
     }
   }
 
+  // Allow project_info to process the module .info file.
+  if ($project_info) {
+    project_info_package_info_process_all($nid, $info_files, $uri, $version);
+  }
+
   // Link not copy, since we want to preserve the date...
   if (!drupal_exec("$ln -sf $license $uri/LICENSE.txt")) {
     return false;
@@ -569,7 +579,7 @@
           wd_err("ERROR: Unable to filter fuzzy strings and copying the translation files in %uri translation in version %version, not packaging", array('%uri' => $uri, '%version' => $version), $view_link);
           return FALSE;
         }
-      
+
         // Add file to package.
         $to_tar .= ' '. $target;
       }
Index: info/project_info.info
===================================================================
RCS file: info/project_info.info
diff -N info/project_info.info
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ info/project_info.info	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,6 @@
+; $Id$
+name = Project info
+description = Provides information related to projects, such as dependencies.
+package = Project
+dependencies[] = project_release
+core = 6.x
Index: info/views/project_info.views.inc
===================================================================
RCS file: info/views/project_info.views.inc
diff -N info/views/project_info.views.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ info/views/project_info.views.inc	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,140 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Provide views data definition.
+ */
+
+/**
+ * Implementation of hook_views_data()
+ */
+function project_info_views_data() {
+  $data = array();
+
+  // ----------------------------------------------------------------
+  // project_info_module table -- basic table information.
+
+  $data['project_info_module']['table']['group']  = t('Project info module');
+
+  $data['project_info_module']['table']['base'] = array(
+    'field' => 'module_id',
+    'title' => t('Project info module'),
+    'help' => t('The modules contained by a project release.'),
+    'weight' => -10,
+  );
+
+  $data['project_info_module']['table']['join'] = array(
+    'project_release_nodes' => array(
+      'left_field' => 'nid',
+      'field' => 'rid',
+    ),
+    'node' => array(
+      'left_field' => 'nid',
+      'field' => 'rid',
+    ),
+  );
+
+  $data['project_info_module']['module_id'] = array(
+    'title' => t('Module ID'),
+    'help' => t('Unique module ID.'),
+    'field' => array(
+      'handler' => 'views_handler_field_numeric',
+      'click sortable' => TRUE,
+    ),
+    'filter' => array(
+      'handler' => 'views_handler_filter_numeric',
+    ),
+    'sort' => array(
+      'handler' => 'views_handler_sort',
+    ),
+  );
+
+  $data['project_info_module']['rid'] = array(
+    'title' => t('Release ID'),
+    'help' => t('The {node}.nid of the project_release node.'),
+    'relationship' => array(
+      'help' => t('Add a relationship to gain access to more node data for releases.'),
+      'base' => 'project_release_nodes',
+      'handler' => 'views_handler_relationship',
+      'label' => t('Release node'),
+    ),
+  );
+
+  $data['project_info_module']['name'] = array(
+    'title' => t('Module name'),
+    'help' => t('Name of a module contained by the release.'),
+    'field' => array(
+      'handler' => 'views_handler_field',
+    ),
+    'filter' => array(
+      'handler' => 'views_handler_filter_string',
+    ),
+    'sort' => array(
+      'handler' => 'views_handler_sort',
+    ),
+  );
+
+
+  // ----------------------------------------------------------------
+  // project_info_dependency table -- basic table information.
+
+  $data['project_info_dependency']['table']['group']  = t('Project info dependency');
+
+  $data['project_info_dependency']['table']['base'] = array(
+    'field' => 'dependency_id',
+    'title' => t('Project info dependency'),
+    'help' => t('The dependencies of each project release.'),
+    'weight' => -9,
+  );
+
+  $data['project_info_dependency']['table']['join'] = array(
+    'project_release_nodes' => array(
+      'left_field' => 'nid',
+      'field' => 'rid',
+    ),
+    'node' => array(
+      'left_field' => 'nid',
+      'field' => 'rid',
+    ),
+  );
+
+  $data['project_info_dependency']['dependency_id'] = array(
+    'title' => t('Dependency ID'),
+    'help' => t('Unique dependency ID.'),
+    'field' => array(
+      'handler' => 'views_handler_field_numeric',
+      'click sortable' => TRUE,
+    ),
+    'filter' => array(
+      'handler' => 'views_handler_filter_numeric',
+    ),
+    'sort' => array(
+      'handler' => 'views_handler_sort',
+    ),
+  );
+
+  $data['project_info_dependency']['rid'] = array(
+    'title' => t('Release ID'),
+    'help' => t('The {node}.nid of the project_release node.'),
+    'relationship' => array(
+      'help' => t('Add a relationship to gain access to more node data for releases.'),
+      'base' => 'project_release_nodes',
+      'handler' => 'views_handler_relationship',
+      'label' => t('Release node'),
+    ),
+  );
+
+  $data['project_info_dependency']['module_id'] = array(
+    'title' => t('Dependency module'),
+    'help' => t('Reference to module that the release is dependent on.'),
+    'relationship' => array(
+      'help' => t('Add a relationship to gain access to more node data for releases.'),
+      'base' => 'project_info_module',
+      'handler' => 'views_handler_relationship',
+      'label' => t('dependency -> module'),
+    ),
+  );
+
+  return $data;
+}
Index: info/project_info.install
===================================================================
RCS file: info/project_info.install
diff -N info/project_info.install
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ info/project_info.install	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,93 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Provides schema for storing project information.
+ *
+ * @author Jimmy Berry ("boombatower", http://drupal.org/user/214218)
+ */
+
+/**
+ * Implementation of hook_schema().
+ */
+function project_info_schema() {
+  $schema = array();
+
+  $schema['project_info_module'] = array(
+    'description' => 'The modules contained by a project release.',
+    'fields' => array(
+      'module_id' => array(
+        'description' => 'Unique module ID.',
+        'type' => 'serial',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+      ),
+      'rid' => array(
+        'description' => 'The {node}.nid of the project_release node.',
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'name' => array(
+        'description' => 'Name of a module contained by the release.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+    ),
+    'primary key' => array('module_id'),
+    'indexes' => array(
+      'rid' => array('rid'),
+    ),
+  );
+
+  $schema['project_info_dependency'] = array(
+    'description' => 'The dependencies of each project release.',
+    'fields' => array(
+      'dependency_id' => array(
+        'description' => 'Unique dependency ID.',
+        'type' => 'serial',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+      ),
+      'rid' => array(
+        'description' => 'The {node}.nid of the project_release node.',
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'module_id' => array(
+        'description' => 'Reference to module that the release is dependent on.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+    ),
+    'primary key' => array('dependency_id'),
+    'indexes' => array(
+      'rid' => array('rid'),
+      'module_id' => array('module_id'),
+    ),
+  );
+
+  return $schema;
+}
+
+/**
+ * Implementation of hook_install().
+ */
+function project_info_install() {
+  drupal_install_schema('project_info');
+}
+
+/**
+ * Implementation of hook_uninstall().
+ */
+function project_info_uninstall() {
+  drupal_uninstall_schema('project_info');
+}
Index: info/views/project_info.views_default.inc
===================================================================
RCS file: info/views/project_info.views_default.inc
diff -N info/views/project_info.views_default.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ info/views/project_info.views_default.inc	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,329 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Contains default views on behalf of the project_info module.
+ */
+
+/**
+ * Implementation of hook_default_view_views().
+ */
+function project_info_views_default_views() {
+  // ----------------------------------------------------------------
+  // project_info_module
+
+  $view = new view;
+  $view->name = 'project_info_module';
+  $view->description = 'The modules contained by a project release.';
+  $view->tag = 'project_info';
+  $view->view_php = '';
+  $view->base_table = 'project_info_module';
+  $view->is_cacheable = FALSE;
+  $view->api_version = 2;
+  $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */
+  $handler = $view->new_display('default', 'Defaults', 'default');
+  $handler->override_option('relationships', array(
+    'rid' => array(
+      'label' => 'Release node',
+      'required' => 1,
+      'id' => 'rid',
+      'table' => 'project_info_module',
+      'field' => 'rid',
+      'relationship' => 'none',
+    ),
+  ));
+  $handler->override_option('fields', array(
+    'name' => array(
+      'label' => '',
+      'alter' => array(
+        'alter_text' => 0,
+        'text' => '',
+        'make_link' => 0,
+        'path' => '',
+        'link_class' => '',
+        'alt' => '',
+        'prefix' => '',
+        'suffix' => '',
+        'help' => '',
+        'trim' => 1,
+        'max_length' => '128',
+        'word_boundary' => 1,
+        'ellipsis' => 1,
+        'strip_tags' => 0,
+        'html' => 0,
+      ),
+      'exclude' => 0,
+      'id' => 'name',
+      'table' => 'project_info_module',
+      'field' => 'name',
+      'relationship' => 'none',
+    ),
+  ));
+  $handler->override_option('sorts', array(
+    'name' => array(
+      'order' => 'ASC',
+      'id' => 'name',
+      'table' => 'project_info_module',
+      'field' => 'name',
+      'relationship' => 'none',
+    ),
+  ));
+  $handler->override_option('arguments', array(
+    'pid' => array(
+      'default_action' => 'not found',
+      'style_plugin' => 'default_summary',
+      'style_options' => array(),
+      'wildcard' => 'all',
+      'wildcard_substitution' => 'All',
+      'title' => '',
+      'breadcrumb' => '',
+      'default_argument_type' => 'fixed',
+      'default_argument' => '',
+      'validate_type' => 'project_nid',
+      'validate_fail' => 'not found',
+      'break_phrase' => 0,
+      'not' => 0,
+      'id' => 'pid',
+      'table' => 'project_release_nodes',
+      'field' => 'pid',
+      'relationship' => 'rid',
+      'validate_user_argument_type' => 'uid',
+      'validate_user_roles' => array(
+        '2' => 0,
+      ),
+      'default_options_div_prefix' => '',
+      'default_argument_user' => 0,
+      'default_argument_fixed' => '',
+      'default_argument_php' => '',
+      'validate_argument_node_type' => array(
+        'project_project' => 0,
+        'project_release' => 0,
+        'project_issue' => 0,
+        'page' => 0,
+        'story' => 0,
+      ),
+      'validate_argument_node_access' => 0,
+      'validate_argument_nid_type' => 'nid',
+      'validate_argument_vocabulary' => array(
+        '1' => 0,
+        '2' => 0,
+        '3' => 0,
+      ),
+      'validate_argument_type' => 'tid',
+      'validate_argument_transform' => 0,
+      'validate_user_restrict_roles' => 0,
+      'validate_argument_project_term_vocabulary' => array(
+        '2' => 0,
+      ),
+      'validate_argument_project_term_argument_type' => 'tid',
+      'validate_argument_project_term_argument_action_top_without' => 'pass',
+      'validate_argument_project_term_argument_action_top_with' => 'pass',
+      'validate_argument_project_term_argument_action_child' => 'pass',
+      'validate_argument_php' => '',
+    ),
+  ));
+  $handler->override_option('access', array(
+    'type' => 'none',
+  ));
+  $handler->override_option('cache', array(
+    'type' => 'none',
+  ));
+  $handler->override_option('empty', '<em>The project does not contain any modules.</em>');
+  $handler->override_option('empty_format', '1');
+  $handler->override_option('use_pager', 'mini');
+  $handler->override_option('style_plugin', 'list');
+  $handler->override_option('style_options', array(
+    'grouping' => '',
+    'type' => 'ul',
+  ));
+
+  $views[$view->name] = $view;
+
+
+  // ----------------------------------------------------------------
+  // project_info_module
+
+  $view = new view;
+  $view->name = 'project_info_dependency';
+  $view->description = 'The dependencies of a project release.';
+  $view->tag = 'project_info';
+  $view->view_php = '';
+  $view->base_table = 'project_info_dependency';
+  $view->is_cacheable = FALSE;
+  $view->api_version = 2;
+  $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */
+  $handler = $view->new_display('default', 'Defaults', 'default');
+  $handler->override_option('relationships', array(
+    'rid' => array(
+      'label' => 'release -> dependency',
+      'required' => 1,
+      'id' => 'rid',
+      'table' => 'project_info_dependency',
+      'field' => 'rid',
+      'relationship' => 'none',
+    ),
+    'module_id' => array(
+      'label' => 'dependency -> module',
+      'required' => 1,
+      'id' => 'module_id',
+      'table' => 'project_info_dependency',
+      'field' => 'module_id',
+      'relationship' => 'none',
+    ),
+    'rid_1' => array(
+      'label' => 'dependency -> module -> release',
+      'required' => 1,
+      'id' => 'rid_1',
+      'table' => 'project_info_module',
+      'field' => 'rid',
+      'relationship' => 'module_id',
+    ),
+    'pid' => array(
+      'label' => 'dependency -> module -> release -> project',
+      'required' => 1,
+      'id' => 'pid',
+      'table' => 'project_release_nodes',
+      'field' => 'pid',
+      'relationship' => 'rid_1',
+    ),
+  ));
+  $handler->override_option('fields', array(
+    'uri' => array(
+      'label' => '',
+      'alter' => array(
+        'alter_text' => 0,
+        'text' => '',
+        'make_link' => 1,
+        'path' => 'project/[uri]',
+        'link_class' => '',
+        'alt' => '',
+        'prefix' => '',
+        'suffix' => '',
+        'help' => '',
+        'trim' => 0,
+        'max_length' => '',
+        'word_boundary' => 1,
+        'ellipsis' => 1,
+        'strip_tags' => 0,
+        'html' => 0,
+      ),
+      'link_to_node' => 0,
+      'exclude' => 1,
+      'id' => 'uri',
+      'table' => 'project_projects',
+      'field' => 'uri',
+      'relationship' => 'pid',
+    ),
+    'name' => array(
+      'label' => '',
+      'alter' => array(
+        'alter_text' => 0,
+        'text' => '',
+        'make_link' => 0,
+        'path' => '',
+        'link_class' => '',
+        'alt' => '',
+        'prefix' => '',
+        'suffix' => '',
+        'help' => '',
+        'trim' => 0,
+        'max_length' => '',
+        'word_boundary' => 1,
+        'ellipsis' => 1,
+        'strip_tags' => 0,
+        'html' => 0,
+      ),
+      'exclude' => 0,
+      'id' => 'name',
+      'table' => 'project_info_module',
+      'field' => 'name',
+      'relationship' => 'module_id',
+    ),
+  ));
+  $handler->override_option('sorts', array(
+    'uri' => array(
+      'order' => 'ASC',
+      'id' => 'uri',
+      'table' => 'project_projects',
+      'field' => 'uri',
+      'relationship' => 'pid',
+    ),
+  ));
+  $handler->override_option('arguments', array(
+    'pid' => array(
+      'default_action' => 'not found',
+      'style_plugin' => 'default_summary',
+      'style_options' => array(),
+      'wildcard' => 'all',
+      'wildcard_substitution' => 'All',
+      'title' => '',
+      'breadcrumb' => '',
+      'default_argument_type' => 'fixed',
+      'default_argument' => '',
+      'validate_type' => 'project_nid',
+      'validate_fail' => 'not found',
+      'break_phrase' => 0,
+      'not' => 0,
+      'id' => 'pid',
+      'table' => 'project_release_nodes',
+      'field' => 'pid',
+      'relationship' => 'rid',
+      'validate_user_argument_type' => 'uid',
+      'validate_user_roles' => array(
+        '2' => 0,
+      ),
+      'default_options_div_prefix' => '',
+      'default_argument_user' => 0,
+      'default_argument_fixed' => '',
+      'default_argument_php' => '',
+      'validate_argument_node_type' => array(
+        'project_project' => 0,
+        'project_release' => 0,
+        'project_issue' => 0,
+        'page' => 0,
+        'story' => 0,
+      ),
+      'validate_argument_node_access' => 0,
+      'validate_argument_nid_type' => 'nid',
+      'validate_argument_vocabulary' => array(
+        '1' => 0,
+        '2' => 0,
+        '3' => 0,
+      ),
+      'validate_argument_type' => 'tid',
+      'validate_argument_transform' => 0,
+      'validate_user_restrict_roles' => 0,
+      'validate_argument_project_term_vocabulary' => array(
+        '2' => 0,
+      ),
+      'validate_argument_project_term_argument_type' => 'tid',
+      'validate_argument_project_term_argument_action_top_without' => 'pass',
+      'validate_argument_project_term_argument_action_top_with' => 'pass',
+      'validate_argument_project_term_argument_action_child' => 'pass',
+      'validate_argument_php' => '',
+    ),
+  ));
+  $handler->override_option('access', array(
+    'type' => 'none',
+  ));
+  $handler->override_option('cache', array(
+    'type' => 'none',
+  ));
+  $handler->override_option('empty', '<em>The project does not have any dependencies.</em>');
+  $handler->override_option('empty_format', '1');
+  $handler->override_option('use_pager', 'mini');
+  $handler->override_option('style_plugin', 'list');
+  $handler->override_option('style_options', array(
+    'grouping' => 'uri',
+    'type' => 'ul',
+  ));
+  $handler->override_option('row_options', array(
+    'inline' => array(),
+    'separator' => '',
+  ));
+
+  $views[$view->name] = $view;
+
+  return $views;
+}
Index: info/project_info.legacy.inc
===================================================================
RCS file: info/project_info.legacy.inc
diff -N info/project_info.legacy.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ info/project_info.legacy.inc	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,260 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Parses legacy releases to build project_info tables.
+ *
+ * @author Jimmy Berry ("boombatower", http://drupal.org/user/214218)
+ */
+
+/**
+ * Directory to checkout modules during processing.
+ *
+ * The directory should be empty since it will be cleared before each checkout.
+ */
+define('PROJECT_INFO_LEGACY_DIRECTORY', '/home/boombatower/download/trash');
+
+/**
+ * Legacy parsing form.
+ *
+ * Provide a form to select the API versions that releases must be compatible
+ * with and initiate the batch process to perform the parsing.
+ */
+function project_info_legecy_form(&$form_state) {
+  $form = array();
+
+  $api_vid = _project_release_get_api_vid();
+  $form['filter'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Filter'),
+  );
+  $form['filter']['api'] = array(
+    '#type' => 'checkboxes',
+    '#title' => t('API'),
+    '#description' => t('Select the core API versions that releases must be compatible with.'),
+    '#options' => array(),
+    '#default_value' => array(),
+  );
+  $terms = project_release_get_api_taxonomy();
+  foreach ($terms as $term) {
+    $form['filter']['api']['#options'][$term->tid] = $term->name;
+
+    // Defaultly select
+    if (($major = array_shift(explode('.', $term->name, 2))) && $major >= PROJECT_INFO_MINIMUM_API) {
+      $form['filter']['api']['#default_value'][] = $term->tid;
+    }
+  }
+
+  $form['op'] = array(
+    '#type' => 'submit',
+    '#value' => t('Submit'),
+  );
+
+  return $form;
+}
+
+/**
+ * Ensure that the directory constant has been set.
+ */
+function project_info_legecy_form_validate($form, &$form_state) {
+  if (!PROJECT_INFO_LEGACY_DIRECTORY) {
+    form_set_error('op', t('The constant PROJECT_INFO_LEGACY_DIRECTORY must be set.'));
+  }
+}
+
+/**
+ * Start the batch to process legacy releases.
+ */
+function project_info_legecy_form_submit($form, &$form_state) {
+  $tids = array();
+  foreach ($form_state['values']['api'] as $tid => $selected) {
+    if ($selected) {
+      $tids[] = $tid;
+    }
+  }
+
+  $batch = array(
+    'title' => t('Processing releases'),
+    'operations' => array(
+      array('project_info_legacy_batch_operation_parse', array($tids)),
+      array('project_info_legacy_batch_operation_dependencies', array()),
+    ),
+    'finished' => 'project_info_legacy_batch_finished',
+    'init_message' => t('Determining releases to parse...'),
+    'file' => drupal_get_path('module', 'project_info') . '/project_info.legacy.inc',
+  );
+  batch_set($batch);
+}
+
+/**
+ * Parse the modules contained within a project and their dependencies.
+ */
+function project_info_legacy_batch_operation_parse(array $tids, &$context) {
+  if (!isset($context['sandbox']['max'])) {
+    // First iteration, initialize working values.
+    $context['sandbox']['max'] = project_info_legacy_releases($tids, 0, TRUE);
+    $context['sandbox']['release_id'] = 0;
+    $context['sandbox']['progress'] = 0;
+    $context['results']['dependencies'] = array();
+    $context['results']['count'] = 0;
+  }
+
+  // Load the package include that contains functions to save and parse data.
+  module_load_include('package.inc', 'project_info');
+
+  $releases = project_info_legacy_releases($tids, $context['sandbox']['release_id']);
+  foreach ($releases as $release) {
+    if (!($dependencies = project_info_legacy_process_release($release))) {
+      $context['results']['error'] = $release;
+      $context['finished'] = 1;
+      return;
+    }
+
+    $context['results']['dependencies'][$release['nid']] = $dependencies;
+
+    $context['sandbox']['release_id'] = $release['nid'];
+    $context['sandbox']['progress']++;
+    $context['results']['count']++;
+  }
+
+  $context['message'] = t('Last parsed %module release %tag.',
+    array('%module' => $release['uri'], '%tag' => $release['tag']));
+
+  $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
+}
+
+/**
+ * Determine dependencies of releases.
+ */
+function project_info_legacy_batch_operation_dependencies(&$context) {
+  if (!isset($context['sandbox']['max'])) {
+    $context['sandbox']['max'] = count($context['results']['dependencies']);
+    $context['sandbox']['progress'] = 0;
+  }
+
+  // Load the package include that contains functions to save and parse data.
+  module_load_include('package.inc', 'project_info');
+
+  $i = 0;
+  foreach ($context['results']['dependencies'] as $rid => $dependencies) {
+    project_info_package_info_process_dependencies($rid, $dependencies);
+
+    // Remove already processed releases.
+    unset($context['results']['dependencies'][$rid]);
+
+    $context['sandbox']['progress']++;
+
+    // Only process 20 releases in a single batch operation.
+    if ($i++ == 20) {
+      break;
+    }
+  }
+
+  $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
+}
+
+/**
+ * Display relevant finished message after batch run.
+ */
+function project_info_legacy_batch_finished($success, $results, $operations) {
+  if ($success && !isset($results['error'])) {
+    drupal_set_message(t('Processed @count release(s).', array('@count' => number_format($results['count']))));
+  }
+  else {
+    drupal_set_message(t('Failed to process @module release #@rid.',
+      array('@module' => $results['error']['uri'], '@rid' => $results['error']['nid'])), 'error');
+  }
+}
+
+/**
+ * Checkout a release and determine relevant information.
+ *
+ * Locate all .info files contained within the project, determine the names of
+ * the module(s) contained within the project and store the dependencies for
+ * later processing.
+ */
+function project_info_legacy_process_release(array $release) {
+  $directory_original = getcwd();
+
+  // Use legacy directory.
+  chdir(PROJECT_INFO_LEGACY_DIRECTORY);
+
+  // Clean directory.
+  exec('rm -r *');
+
+  // Checkout release.
+  $url = ':pserver:anonymous:anonymous@cvs.drupal.org:/cvs/drupal-contrib';
+  $branch = $release['tag'];
+  $module = 'contributions/modules/' . $release['uri'];
+  $directory = $release['uri'];
+  exec("cvs -z6 -Q -d$url checkout -d$directory -r $branch $module", $output, $status);
+
+  // Return to original directory.
+  chdir($directory_original);
+
+  // Check for CVS checkout failure.
+  if ($status != 0) {
+    return FALSE;
+  }
+
+  // Scan checkout for .info files and create a list in the same format that
+  // project release uses, so that standard API functions can be used.
+  $files = file_scan_directory(PROJECT_INFO_LEGACY_DIRECTORY . '/' . $directory, '\.info$');
+  $info_files = array();
+  $dependencies = array();
+  foreach ($files as $file) {
+    $info_files[] = $file->filename;
+
+    $info = drupal_parse_info_file($file->filename);
+    if (!empty($info['dependencies'])) {
+      $dependencies = array_merge($dependencies, $info['dependencies']);
+    }
+  }
+
+  // Clear previous records for the release.
+  project_info_package_list_clear($release['nid']);
+  project_info_package_dependency_clear($release['nid']);
+
+  // Store the list of modules contained by the project.
+  project_info_package_list_store($release['nid'], $info_files);
+
+  return array_unique($dependencies);
+}
+
+/**
+ * Select all 6.x or 7.x releases.
+ *
+ * Taxonomy term IDs 87 and 103 represent 6.x and 7.x releases.
+ *
+ * @return
+ *   List of release information: rid, project uri, and cvs directory.
+ */
+function project_info_legacy_releases(array $tids, $release_id, $count = FALSE) {
+  $sql = 'SELECT ' . ($count ? 'COUNT(r.nid)' : 'r.nid, r.tag, p.uri, cp.directory') . '
+    FROM {project_release_nodes} r
+    INNER JOIN {node} n
+      ON r.nid = n.nid
+    INNER JOIN {term_node} t
+      ON n.vid = t.vid
+    INNER JOIN {project_projects} p
+      ON r.pid = p.nid
+    INNER JOIN {cvs_projects} cp
+      ON p.nid = cp.nid
+    WHERE t.tid IN (' . db_placeholders($tids, 'int') . ')
+    AND r.nid > %d';
+
+  $args = array_merge($tids, array($release_id));
+
+  if ($count) {
+    return db_result(db_query($sql, $args));
+  }
+
+  $sql .= ' ORDER BY r.nid';
+  $result = db_query_range($sql, $args, 0, 10);
+  $releases = array();
+  while ($release = db_fetch_array($result)) {
+    $releases[] = $release;
+  }
+  return $releases;
+}
Index: info/project_info.package.inc
===================================================================
RCS file: info/project_info.package.inc
diff -N info/project_info.package.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ info/project_info.package.inc	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,163 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Provides information related to projects, such as dependencies.
+ *
+ * @author Jimmy Berry ("boombatower", http://drupal.org/user/214218)
+ */
+
+/**
+ * Parse Drupal info files for project information.
+ *
+ * @param $rid
+ *   The project release ID.
+ * @param $info_files
+ *   List of .info files to be processed.
+ * @param $uri
+ *   The short name of the project.
+ * @param $version
+ *   The version of the release being processed.
+ */
+function project_info_package_info_process_all($rid, array $info_files, $uri, $version) {
+  // Only process .info files for 6.x API and above.
+  if (($major = array_shift(explode('.', $version, 2))) && $major >= PROJECT_INFO_MINIMUM_API) {
+    // Clear previous records for the release.
+    project_info_package_list_clear($rid);
+    project_info_package_dependency_clear($rid);
+
+    // Store list of modules.
+    project_info_package_list_store($rid, $info_files);
+
+    // Store list of dependencies.
+    project_info_package_info_process($rid, $info_files);
+  }
+}
+
+/**
+ * Clear the list of modules for a release.
+ *
+ * @param $rid
+ *   The project release ID.
+ */
+function project_info_package_list_clear($rid) {
+  db_query('DELETE FROM {project_info_module} WHERE rid = %d', $rid);
+}
+
+/**
+ * Store the list of modules for a release.
+ *
+ * @param $rid
+ *   The project release ID.
+ * @param $info_files
+ *   List of .info files to be processed.
+ */
+function project_info_package_list_store($rid, array $info_files) {
+  foreach ($info_files as $file) {
+    $module = basename($file, '.info');
+
+    $info = array(
+      'rid' => $rid,
+      'name' => $module,
+    );
+    drupal_write_record('project_info_module', $info);
+  }
+}
+
+/**
+ * Clear the list of dependencies for a release.
+ *
+ * @param $rid
+ *   The project release ID.
+ */
+function project_info_package_dependency_clear($rid) {
+  db_query('DELETE FROM {project_info_dependency} WHERE rid = %d', $rid);
+}
+
+/**
+ * Determine and store the list of dependencies for a release.
+ *
+ * @param $rid
+ *   The project release ID.
+ * @param $info_files
+ *   List of .info files to be processed.
+ */
+function project_info_package_info_process($rid, array $info_files) {
+  foreach ($info_files as $file) {
+    $info = drupal_parse_info_file($file);
+
+    project_info_package_info_process_dependencies($rid, $info['dependencies']);
+  }
+}
+
+/**
+ * Store the list of dependencies for a release.
+ *
+ * @param $rid
+ *   The project release ID.
+ * @param $dependencies
+ *   List of dependencies.
+ */
+function project_info_package_info_process_dependencies($rid, array $dependencies) {
+  foreach ($dependencies as $dependency) {
+    if ($nid = project_get_nid_from_uri($dependency)) {
+      // Load the project and determine is core API version.
+      $project = node_load($nid);
+      list($api_version, $api_tid) = project_info_package_core_api($project);
+
+      // Cycle through the releases made by the project until a dev branch is
+      // found of the latest stable series that matches the core API.
+      $releases = project_release_get_releases($project, TRUE);
+      $best_release = NULL;
+      foreach ($releases as $release) {
+        list($api_version2, $api_tid2) = project_info_package_core_api($release);
+        if ($api_tid2 == $api_tid) {
+          if ($release->project_release['rebuild'] && $best_release &&
+            $release->project_release['version_major'] > $best_release->project_release['version_major']) {
+            $best_release = $release;
+          }
+        }
+      }
+
+      // Store the dependency if a best release was found.
+      if ($best_release) {
+        $result = db_query("SELECT module_id FROM {project_info_module}
+                            WHERE rid = %d
+                            AND name ='%s'", $best_release->nid, $dependency);
+        if ($module_id = db_result($result)) {
+          $info = array(
+            'rid' => $rid,
+            'module_id' => $module_id,
+          );
+          drupal_write_record('project_info_dependency', $info);
+        }
+      }
+    }
+  }
+}
+
+/**
+ * Attempt to determine the Drupal core API version.
+ *
+ * @param $node
+ *   Node object.
+ * @return
+ *   Core API version information in the format: array($api_version, $api_tid).
+ */
+function project_info_package_core_api($node) {
+  if (!empty($node->taxonomy)) {
+    // Relase API version vocabulary.
+    $api_vid = _project_release_get_api_vid();
+
+    foreach ($node->taxonomy as $tid => $term) {
+      if ($term->vid == $api_vid) {
+        $api_version = array_shift(explode('.', $term->name, 2));
+        $api_tid = $term->tid;
+
+        return array($api_version, $api_tid);
+      }
+    }
+  }
+  return array(NULL, NULL);
+}
Index: info/project_info.module
===================================================================
RCS file: info/project_info.module
diff -N info/project_info.module
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ info/project_info.module	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,139 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Provides information related to projects, such as dependencies.
+ *
+ * @author Jimmy Berry ("boombatower", http://drupal.org/user/214218)
+ */
+
+/**
+ * Minimum API compatibility to process.
+ */
+define('PROJECT_INFO_MINIMUM_API', 6);
+
+//module_load_include('legacy.inc', 'project_info');
+
+/**
+ * Implementation of hook_menu().
+ */
+function project_info_menu() {
+  $items = array();
+
+  $items['admin/project/project_info/legacy'] = array(
+    'title' => 'Parse legacy releases',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('project_info_legecy_form'),
+    'access arguments' => array('project_info legacy parse'),
+    'file' => 'project_info.legacy.inc',
+    'type' => MENU_CALLBACK,
+  );
+
+  return $items;
+}
+
+/**
+ * Implementation of hook_perm().
+ */
+function project_info_perm() {
+  return array(
+    'project_info legacy parse',
+  );
+}
+
+/**
+ * Implementation of hook_block().
+ */
+function project_info_block($op = 'list', $delta = 0, $edit = array()) {
+  if ($op == 'list') {
+    return array(
+      array('info' => t('Project info module list')),
+      array('info' => t('Project info dependency list')),
+    );
+  }
+  elseif ($op == 'view') {
+    if (arg(0) == 'node') {
+      switch ($delta) {
+        case 0:
+          return array(
+            'subject' => t('Modules'),
+            'content' => views_embed_view('project_info_module', 'default', arg(1)),
+          );
+        case 1:
+          return array(
+            'subject' => t('Dependencies'),
+            'content' => views_embed_view('project_info_dependency', 'default', arg(1)),
+          );
+      }
+    }
+  }
+}
+
+/**
+ * Implementation of hook_views_api().
+ */
+function project_info_views_api() {
+  return array(
+    'api' => 2,
+    'path' => drupal_get_path('module', 'project_info') . '/views',
+  );
+}
+
+/**
+ * Load the list of modules contained by a project release.
+ *
+ * @param $rid
+ *   Project release ID.
+ * @return
+ *   List of modules.
+ */
+function project_info_module_list_get($rid) {
+  $result = db_query('SELECT name FROM {project_info_module} WHERE rid = %d', $rid);
+  $modules = array();
+  while ($module = db_result($result)) {
+    $modules[] = $module;
+  }
+  return $modules;
+}
+
+/**
+ * Load a module.
+ *
+ * @param $module_id
+ *   Module ID to load.
+ * @return
+ *   Array of module information.
+ */
+function project_info_module_get($module_id) {
+  static $modules = array();
+
+  if (!isset($modules[$module_id])) {
+    $result = db_query('SELECT * FROM {project_info_module} WHERE module_id = %d', $module_id);
+    $modules[$module_id] = db_fetch_array($result);
+  }
+  return $modules[$module_id];
+}
+
+/**
+ * Recursively determine the list of dependencies of a release.
+ *
+ * @param $rid
+ *   Project release ID.
+ * @param $dependencies
+ *   (Optional) Array of already determined dependencies.
+ * @return
+ *   List of dependencies of the release.
+ */
+function project_info_dependency_list_get($rid, $dependencies = array()) {
+  $result = db_query('SELECT module_id FROM {project_info_dependency} WHERE rid = %d', $rid);
+  while ($module_id = db_result($result)) {
+    $module = project_info_module_get($module_id);
+
+    if (!in_array($module['rid'], $dependencies)) {
+      $dependencies[] = $module['rid'];
+      $dependencies = project_info_dependency_list_get($module['rid'], $dependencies);
+    }
+  }
+  return $dependencies;
+}
