cvs diff: Diffing modules/cvslog Index: modules/cvslog/README.txt =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/cvslog/README.txt,v retrieving revision 1.3.2.1 diff -u -F^f -r1.3.2.1 README.txt --- modules/cvslog/README.txt 21 Jun 2006 22:57:07 -0000 1.3.2.1 +++ modules/cvslog/README.txt 16 Oct 2006 04:28:32 -0000 @@ -16,5 +16,10 @@ * Each commit message can be modified in a theme_cvs_entry($cvs) function, the parameter is an object containing user, timestamp, and message. +Site-specific customization: + * Parts of this code are very specific to how this module is used + on drupal.org. I'm trying to isolate as many of these + site-specific hacks as possible into the cvs_local.inc file. + Note that you must customize the xcvs/xcvs-config.php file if you wish to use those scripts on your site. See xcvs/README.txt for details. Index: modules/cvslog/cvs.install =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/cvslog/cvs.install,v retrieving revision 1.4.2.3 diff -u -F^f -r1.4.2.3 cvs.install --- modules/cvslog/cvs.install 18 Sep 2006 22:20:05 -0000 1.4.2.3 +++ modules/cvslog/cvs.install 16 Oct 2006 04:28:33 -0000 @@ -98,6 +98,7 @@ function cvs_install() { break; } + $ret[] = db_query("UPDATE {system} SET weight = 3 WHERE name = 'cvs'"); return $ret; } @@ -159,3 +160,9 @@ function cvs_update_3() { return $ret; } +function cvs_update_4() { + $ret = array(); + $ret[] = update_sql("UPDATE {system} SET weight = 3 WHERE name = 'cvs'"); + return $ret; +} + Index: modules/cvslog/cvs.module =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/cvslog/cvs.module,v retrieving revision 1.106.2.19 diff -u -F^f -r1.106.2.19 cvs.module --- modules/cvslog/cvs.module 18 Sep 2006 10:37:43 -0000 1.106.2.19 +++ modules/cvslog/cvs.module 16 Oct 2006 04:28:34 -0000 @@ -17,6 +17,11 @@ define('CVS_MESSAGE_ANON', 'The Concurrent Versioning System (CVS) is a software development tool available to volunteers with experience in software development, translation, themeing, or documentation who wish to participate in the Drupal project. To request access to the Drupal CVS repository you must create an account and login. Come back to this page after you have logged on.'); define('CVS_MESSAGE_AUTH', 'The Concurrent Versioning System (CVS) is a software development tool used to manage programs and files for the Drupal project. It is available to volunteers with experience in software development, translation, themeing, or documentation who wish to participate in the project. If you are an Open Source software developer, themer, translator, or documentation writer, you can use the form below to request access to Drupal\'s CVS repository. Note that there are two repositories, core and contributions. Access to the Drupal core repository is only available to a handful of people, and CVS access is not required to contribute patches to core. For that, you should submit an issue into the issue queue for Drupal core. You are also not allowed to commit patches to modules maintained by other people without obtaining permission from them to do so. Please do not duplicate modules that overlap with a significant portion of functionality with what you are proposing to write.'); +$path = drupal_get_path('module', 'cvs'); +if (file_exists("$path/cvs_local.inc")) { + require_once "$path/cvs_local.inc"; +} + /** * Implementation of hook_help(). */ @@ -384,38 +389,383 @@ function cvs_nodeapi(&$node, $op, $arg = */ function cvs_form_alter($form_id, &$form) { if ($form_id == 'project_project_node_form') { - $node = $form['#node']; - $result = db_query("SELECT rid, name FROM {cvs_repositories}"); - while ($repository = db_fetch_object($result)) { - $repositories[$repository->rid] = $repository->name; - } - $form['cvs_nodeapi'] = array( - '#type' => 'fieldset', - '#title' => t('CVS integration'), - '#collapsible' => TRUE, - '#collapsed' => $node->cvs_directory ? TRUE : FALSE, - ); - $projects_allowing_repo = explode(',', strtolower(variable_get('cvs_allow_repo_selection', ''))); - $allow_repo = in_array(strtolower($node->title), $projects_allowing_repo); - $default_repo = $node->cvs_repository ? $node->cvs_repository : variable_get('cvs_default_repo', ''); - if (!empty($repositories)) { - $form['cvs_nodeapi']['cvs_repository'] = array( - '#type' => 'select', - '#title' => t('Repository'), - '#default_value' => $default_repo, - '#options' => $allow_repo ? $repositories : array($default_repo => $repositories[$default_repo]), - '#description' => t("Specify the project's CVS repository."), - ); - } - $form['cvs_nodeapi']['cvs_directory'] = array( - '#type' => 'textfield', - '#title' => t('CVS directory'), - '#default_value' => $node->cvs_directory, - '#size' => 40, - '#maxlength' => 255, - '#description' => t("Specify the project's directory within the specified CVS repository. Directory names should start with a leading slash and end with a trailing slash, and must be unique for each project. For example: /modules/foo/, /themes/foo/ or /translations/foo/."), + cvs_alter_project_project_form($form); + return; + } + if ($form_id == 'project_release_node_form') { + if (function_exists('cvs_local_alter_project_release_form')) { + cvs_local_alter_project_release_form($form); + } + cvs_alter_project_release_form($form); + return; + } +} + +/** + * Alters the project_project node form to add CVS integration + * @see cvs_form_alter + */ +function cvs_alter_project_project_form(&$form) { + $node = $form['#node']; + $result = db_query("SELECT rid, name FROM {cvs_repositories}"); + while ($repository = db_fetch_object($result)) { + $repositories[$repository->rid] = $repository->name; + } + $form['cvs_nodeapi'] = array( + '#type' => 'fieldset', + '#title' => t('CVS integration'), + '#collapsible' => TRUE, + '#collapsed' => $node->cvs_directory ? TRUE : FALSE, + ); + $projects_allowing_repo = explode(',', strtolower(variable_get('cvs_allow_repo_selection', ''))); + $allow_repo = in_array(strtolower($node->title), $projects_allowing_repo); + $default_repo = $node->cvs_repository ? $node->cvs_repository : variable_get('cvs_default_repo', ''); + if (!empty($repositories)) { + $form['cvs_nodeapi']['cvs_repository'] = array( + '#type' => 'select', + '#title' => t('Repository'), + '#default_value' => $default_repo, + '#options' => $allow_repo ? $repositories : array($default_repo => $repositories[$default_repo]), + '#description' => t("Specify the project's CVS repository."), + ); + } + $form['cvs_nodeapi']['cvs_directory'] = array( + '#type' => 'textfield', + '#title' => t('CVS directory'), + '#default_value' => $node->cvs_directory, + '#size' => 40, + '#maxlength' => 255, + '#description' => t("Specify the project's directory within the specified CVS repository. Directory names should start with a leading slash and end with a trailing slash, and must be unique for each project. For example: /modules/foo/, /themes/foo/ or /translations/foo/."), + '#required' => TRUE, + ); +} + +/** + * Alters the project_release node to add build tag UI + * @see cvs_form_alter + */ +function cvs_alter_project_release_form(&$form) { + // If we're not adding it, call a separate method that just worries + // about how to alter the edit form, since the add form is so complex. + if (arg(1) != 'add') { + return cvs_alter_project_release_form_edit($form); + } + + $project = $form['project']['#value']; + if (!isset($project->releases)) { + // This project has no releases, nothing to alter + return; + } + + $fields = array('version_major', 'version_minor', 'version_patch'); + + if (isset($_POST['edit']['tag'])) { + $tag_name = $_POST['edit']['tag']; + // We have to validate this here, since we're getting called + // before a validate callback would be invoked... + if (!isset($tag_name)) { + form_set_error('tag', t('You have to select a valid CVS tag or branch.')); + } + $vid = _project_release_get_api_vid(); + if ($tag_name == 'HEAD') { + // Special case validation for the HEAD... + $tag->tag = 'HEAD'; + $tag->branch = 1; + $tag->nid = $project->nid; + $form['version'] = form_builder('project_release_node_form', $form['version']); + foreach ($fields as $field) { + $form_val = $form['version']['num'][$field]['#value']; + if (isset($form_val) && $form_val !== '') { + if (is_numeric($form_val) || $form_val == 'x') { + $version->$field = $form_val; + } + } + } + $form_val = $form['version']['num']['version_extra']['#value']; + if (isset($form_val) && $form_val !== '') { + $version->version_extra = check_plain($form_val); + } + // It'd be nice to just use form_builder() here, like we do with + // the rest of the version info. However, something about + // form_builder() screws up the usual taxonomy-related FAPI + // code, and when we finally hit hook_insert(), our taxonomy + // array is clobbered and the terms don't get saved. So, we just + // use very careful inspection of $_POST to figure out if the + // API selector has already been set and use that in our $version. + $needs_api_none = true; + if (isset($form['taxonomy'][$vid])) { + $post_val = $_POST['edit']['taxonomy'][$vid]; + if (isset($post_val)) { + if (is_numeric($post_val) && !empty($post_val) && db_result(db_query('SELECT COUNT(*) FROM {term_data} WHERE tid = %d AND vid = %d', $post_val, $vid))) { + $version->version_api_tid = $post_val; + $options[$post_val] = $form['taxonomy'][$vid]['#options'][$post_val]; + $form['taxonomy'][$vid]['#options'] = $options; + $form['taxonomy'][$vid]['#default_value'] = $post_val; + $needs_api_none = false; + } + } + if ($needs_api_none) { + $form['taxonomy'][$vid]['#options'] = array(0 => t('None')) + $form['taxonomy'][$vid]['#options']; + $form['taxonomy'][$vid]['#default_value'] = 0; + // Set required to false so we don't get an error as soon + // as we land on the page. We'll re-mark it required in + // pre_render(), and ensure we don't get "none"... + $form['taxonomy'][$vid]['#required'] = false; + } + } + if (function_exists('cvs_local_version_is_valid')) { + $version_is_valid = cvs_local_version_is_valid($version, $project); + } + else { + $version_is_valid = isset($version); + } + if ($version_is_valid) { + $version_str = project_release_get_version($version, $project); + unset($form['validate_version']); + } + else { + unset($version); + _cvs_alter_project_release_form_unset_all($form, false); + $elements = element_children($form['taxonomy']); + $found_it = false; + foreach ($elements as $element) { + if ($element != $vid) { + unset($form['taxonomy'][$element]); + } + else { + $found_it = true; + } + } + if (!$found_it) { + // If we're not leaving the API selection element, unset the + // whole thing so we don't leave an empty fieldset. + unset($form['taxonomy']); + } + } + } + else { + $query = db_query("SELECT * FROM {cvs_tags} WHERE nid = %d AND tag = '%s'", $project->nid, $tag_name); + $tag = db_fetch_object($query); + if (!$tag) { + form_set_error('tag', t('The tag you selected does not exist for this project.')); + } + $query = db_query("SELECT * FROM {project_release_nodes} WHERE pid = %d AND tag = '%s'", $project->nid, $tag_name); + if (db_num_rows($query)) { + form_set_error('tag', t('The tag or branch you have selected is already in use by another release')); + } + $version = cvs_get_version_from_tag($tag, $project); + $version_str = project_release_get_version($version, $project); + // Since we got the version info from the tag, we don't want to try + // try to validate the version field elements... + unset($form['validate_version']); + } + unset($form['tag']); + $tags[$tag_name] = $tag_name; + $form['cvs_tag'] = array('#weight' => -4); + $form['cvs_tag']['tag'] = array( + '#type' => 'select', + '#title' => t('CVS tag'), + '#options' => $tags, + '#default_value' => $tag->tag, '#required' => TRUE, ); + $form['cvs_tag']['rebuild'] = array( + '#type' => 'hidden', + '#value' => $tag->branch, + ); + $form['cvs_tag'] = form_builder('project_release_node_form', $form['cvs_tag']); + unset($form['version']['version']); + if (isset($version_str)) { + // Since this is the final page, turn this into a fieldset with + // all the nice float/clear goodness + $form['cvs_tag']['#type'] = 'fieldset'; + $form['cvs_tag']['#title'] = t('Release identification'); + $form['cvs_tag']['#prefix'] = '
'; + $form['cvs_tag']['#suffix'] = '
'; + $form['cvs_tag']['#description'] = t('Now that the CVS tag has been selected, these can not be modified.'); + + $form['cvs_tag']['version'] = array( + '#type' => 'textfield', + '#title' => 'Version string', + '#default_value' => $version_str, + '#attributes' => array('readonly' => true, 'style' => 'width:auto'), + '#required' => TRUE, + '#size' => 30, + '#maxlength' => 40, + ); + } + if (isset($version)) { + foreach (array_merge($fields, array('version_extra')) as $field) { + if (isset($version->$field)) { + $form['version']['num'][$field]['#type'] = 'hidden'; + $form['version']['num'][$field]['#value'] = $version->$field; + } + else { + unset($form['version']['num'][$field]); + } + } + if (isset($form['taxonomy'][$vid])) { + $tid = $version->version_api_tid; + $options[$tid] = $form['taxonomy'][$vid]['#options'][$tid]; + $form['taxonomy'][$vid]['#options'] = $options; + $form['taxonomy'][$vid]['#default_value'] = $tid; + } + unset($form['version']['num']['#type']); + unset($form['version']['num']['#title']); + unset($form['version']['num']['#prefix']); + unset($form['version']['num']['#suffix']); + $form['version'] = form_builder('project_release_node_form', $form['version']); + } + // We don't want body to be required unless we're done advancing with + // Next, or the body will be marked as an error as soon as we land + // on page 2. However, via pre_render() we always mark it as + // required so that it looks (and acts) like a required field. + if ($_POST['op'] == t('Next')) { + $form['body_filter']['body']['#required'] = FALSE; + $form['#pre_render'][] = 'cvs_project_release_form_pre_render'; + } + } + else { + // Rip out everything else that might be in this form... + _cvs_alter_project_release_form_unset_all($form, true); + unset($form['taxonomy']); + unset($form['validate_version']); + + // ... so we can add a tag selector. + $tags = array(); + if (!db_result(db_query("SELECT COUNT(*) FROM {project_release_nodes} p WHERE p.pid = %d AND p.tag = 'HEAD'", $project->nid))) { + $tags['Tags'] = array(); + $tags['Branches']['HEAD'] = 'HEAD'; + } + $result = db_query("SELECT c.nid, c.tag, c.branch FROM {cvs_tags} c LEFT JOIN {project_release_nodes} p ON c.nid = p.pid AND p.tag = c.tag WHERE c.nid = %d AND p.tag IS NULL ORDER BY c.tag DESC", $project->nid); + while ($tag = db_fetch_object($result)) { + $version = project_release_get_version(cvs_get_version_from_tag($tag, $project), $project); + if ($tag->branch) { + $tags['Branches'][$tag->tag] = $tag->tag .' ('. $version .')'; + } + else { + $tags['Tags'][$tag->tag] = $tag->tag .' ('. $version .')'; + } + } + if (!empty($tags)) { + unset($form['tag']); + $form['cvs_tag']['tag'] = array( + '#type' => 'select', + '#title' => t('CVS tag'), + '#options' => $tags, + '#weight' => -10, + '#required' => TRUE, + '#description' => t("Select the CVS tag (and therefore version number) for this release."), + ); + } + else { + // TODO: make this a setting or generate the text in some other way? + $err = t('ERROR: There are no CVS tags for this module that do not already have a release associated with them.'); + $err .= '

' . t('To create a release, you must first create either a new CVS tag on one of the existing branches for this project, or you must add a new CVS branch.'); + $err .= '

' . t('Once you have created a tag or branch that should be used for your new release, try pressing the %retry button to continue.', array('%retry' => theme('placeholder', t('Retry')))); + drupal_set_message($err); + $form['preview']['#value'] = t('Retry'); + } + } + + // Regardless of if we're on page #1 or #2, we want to remove the + // file selector, since if we're doing this via a CVS tag, the file + // will be filled in later by the packaging script. + // TODO (feature): it'd be nice if this was optional, so that some + // sites might want to still allow file attachments for releases... + unset($form['file']); +} + + +/** + * Alters the project_release node form during edits + * @see cvs_form_alter + */ +function cvs_alter_project_release_form_edit(&$form) { + global $user; + $release = $form['#node']; + if (user_access('administer projects')) { + $project = node_load($release->pid); + $tags = array(); + $tags[$release->tag] = $release->tag; + $tags['HEAD'] = 'HEAD'; + $result = db_query("SELECT c.nid, c.tag, c.branch FROM {cvs_tags} c LEFT JOIN {project_release_nodes} p ON c.nid = p.pid AND p.tag = c.tag WHERE c.nid = %d AND p.tag IS NULL AND c.branch = 1 ORDER BY c.tag DESC", $release->pid); + while ($tag = db_fetch_object($result)) { + $version = project_release_get_version(cvs_get_version_from_tag($tag, $project), $project); + $tags[$tag->tag] = $tag->tag .' ('. $version .')'; + } + } + else { + $tags[$release->tag] = $release->tag; + } + $form['cvs_tag'] = array( + '#type' => 'fieldset', + '#title' => t('Release identification'), + '#prefix' => '

', + '#suffix' => '
', + '#weight' => -4, + ); + $form['cvs_tag']['tag'] = array( + '#type' => 'select', + '#title' => t('CVS tag'), + '#options' => $tags, + '#required' => TRUE, + ); + $form['cvs_tag']['version'] = $form['version']['version']; + unset($form['version']['version']); + unset($form['tag']); +} + +/* + * Helper function to unset all the elements in the release node form + * that we don't want if we're on one of the preliminary pages to get + * the tag and/or version info before we present the final form. + * @see cvs_alter_project_release_form + */ +function _cvs_alter_project_release_form_unset_all(&$form, $unset_version) { + if ($unset_version) { + // Get rid of the form elements we don't want until we have a tag + unset($form['version']); + } + + // Get rid of all the node form elements, too, for page #1 + unset($form['attachments']); + unset($form['author']); + unset($form['body_filter']); + unset($form['comment_settings']); + unset($form['menu']); + unset($form['options']); + unset($form['path']); + + // Change preview to next and hide submit + $form['preview'] = array( + '#type' => 'button', + '#value' => t('Next'), + '#weight' => 19, + ); + $form['submit'] = array( + '#type' => 'value', + '#value' => 'hidden', + ); + $form['#redirect'] = FALSE; +} + +/** + * pre_render callback for the project_release node form. We use this + * to set the required form attribute back to TRUE on the body field, + * so that it appears with a nice little red star, even though it's + * not officially treated as a required field until they hit preview, + * so we avoid a validation error as soon as we first land on that page. + * @see cvs_alter_project_release_form + */ +function cvs_project_release_form_pre_render($form_id, &$form) { + if ($form_id == 'project_release_node_form') { + $form['body_filter']['body']['#required'] = TRUE; + $vid = _project_release_get_api_vid(); + $form['taxonomy'][$vid]['#required'] = TRUE; + if (function_exists('cvs_local_project_release_form_pre_render')) { + cvs_local_project_release_form_pre_render($form); + } } } Index: modules/cvslog/cvs_local.inc =================================================================== RCS file: modules/cvslog/cvs_local.inc diff -N modules/cvslog/cvs_local.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/cvslog/cvs_local.inc 16 Oct 2006 04:28:34 -0000 @@ -0,0 +1,159 @@ +tag); + $first = explode('-', $first_ver, 5); + $second = empty($second_ver) ? array() : explode('-', $second_ver); + + if ($project->nid == 3060) { + if ($first[1] >= 5) { + $version->version_major = $first[1]; + if (isset($first[2])) { + $version->version_patch = $first[2]; + $version->version_extra = _cvs_get_extra($first[3].$first[4]); + } + else { + $version->version_patch = 'x'; + $version->version_extra = 'dev'; + } + } + else { + if (isset($first[3])) { + // Looks like "DRUPAL-X-Y-Z". Ignore the 'DRUPAL' part in $first[0]. + $version->version_major = $first[1]; + $version->version_minor = $first[2]; + $version->version_patch = $first[3]; + $version->version_extra = _cvs_get_extra($first[4]); + } + else { + // Looks like "DRUPAL-X-Y", must be like "DRUPAL-4-7" (branch) + $version->version_major = $first[1]; + $version->version_minor = $first[2]; + $version->version_patch = 'x'; + $version->version_extra = 'dev'; + } + } + } + else { + // Contrib tags don't need any special cases + $version->version_major = $second[0] ? $second[0] : 0; + $version->version_patch = $tag->branch ? 'x' : $second[1]; + $version->version_extra = $tag->branch ? 'dev' : _cvs_get_extra($second[2]); + } + if ($tree = project_release_get_api_taxonomy()) { + // If we're using the compatibility taxonomy, find the right tid. + // For both core and contrib, it's set by what we saw before the '--', + // namely, the stuff in the $first array... + if (empty($first[2])) { + $target = "$first[1].x"; + } + else { + $target = "$first[1].$first[2].x"; + } + foreach ($tree as $i => $term) { + if ($term->name == $target) { + $version->version_api_tid = $term->tid; + break; + } + } + } + // TODO: add code to validate we parsed something reasonable, and ignore bad tags. + return $version; +} + +function _cvs_get_extra($str) { + return preg_replace('/[_-]/', '', strtolower($str)); +} + + +/** + * drupal.org specific customizations of the release node form + */ +function cvs_local_alter_project_release_form(&$form) { + $node = $form['#node']; + if (isset($node->tag)) { + $tag = $node->tag; + } + elseif (isset($_POST['edit']['tag'])) { + $tag = $_POST['edit']['tag']; + } + if (isset($tag) && $tag === 'HEAD') { + $form['version']['num']['#description'] = t('For releases being rebuilt from the trunk of the CVS repository (HEAD), you should probably use 0 for both the %major and %patch versions, to indicate that this is the initial version compatibile with the selected version of Drupal core. Furthermore, you should use "dev" in the %extra to indicate it is a development snapshot.', array('%major' => theme('placeholder', t('Major')), '%patch' => theme('placeholder', t('Patch-level')), '%extra' => theme('placeholder', t('Extra identifier')))); + unset($form['version']['num']['version_extra']['#description']); + } +} + +function cvs_local_project_release_form_pre_render(&$form) { + $form['version']['num']['version_major']['#required'] = TRUE; + $form['version']['num']['version_patch']['#required'] = TRUE; +} + +/** + * Decides if the given version object has enough information for + * us to move on to the next page. + */ +function cvs_local_version_is_valid($version, $project) { + if (!isset($version)) { + return false; + } + $is_valid = true; + if ($project->nid == 3060) { + // Core is obvious: we just need to ensure we've got major and patch. + // Everything else is optional. + if (!isset($version->version_major)) { + $is_valid = false; + form_set_error('version_major', t('Major version number is required.')); + } + elseif ($version->version_major >= 5 && isset($version->version_minor)) { + form_set_error('version_minor', t('You should not specify a minor version number if the major version is greater than or equal to 5.')); + $is_valid = false; + } + if (!isset($version->version_patch)) { + $is_valid = false; + form_set_error('version_patch', t('Patch-level version number is required.')); + } + } + else { + if (!isset($version->version_api_tid)) { + $is_valid = false; + $vid = _project_release_get_api_vid(); + if (isset($_POST['edit']['taxonomy'][$vid])) { + // We only want to flag an error if they've tried to advance + form_set_error($vid, t('You must select what version of Drupal core this release is compatible with.')); + } + } + if (!isset($version->version_major)) { + $is_valid = false; + form_set_error('version_major', t('Major version number is required.')); + } + if (!isset($version->version_patch)) { + $is_valid = false; + form_set_error('version_patch', t('Patch-level version number is required.')); + } + } + if ($is_valid) { + $version->pid = $project->nid; + if (project_release_exists($version)) { + // TODO: is there a better form element to mark with this error? + form_set_error('version_patch', t('This version already exists for this project.')); + $is_valid = false; + } + } + return $is_valid; +} + cvs diff: Diffing modules/cvslog/xcvs