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 $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 @@ + '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 @@ + '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 @@ +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', 'The project does not contain any modules.'); + $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', 'The project does not have any dependencies.'); + $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 @@ + '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 @@ += 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 @@ + '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; +}