Newer
Older
Mantis_source-integration / SourceWebSVN / SourceWebSVN.php
@John Reese John Reese on 29 Jul 2008 8 KB Increment plugins to version 0.12
<?php
# Copyright (C) 2008	John Reese
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

if ( false === include_once( config_get( 'plugin_path' ) . 'Source/MantisSourcePlugin.class.php' ) ) {
	return;
}

class SourceWebSVNPlugin extends MantisSourcePlugin {
	function register() {
		$this->name = lang_get( 'plugin_SourceWebSVN_title' );
		$this->description = lang_get( 'plugin_SourceWebSVN_description' );

		$this->version = '0.12';
		$this->requires = array(
			'MantisCore' => '1.2.0',
			'Source' => '0.12',
		);

		$this->author = 'John Reese';
		$this->contact = 'jreese@leetcode.net';
		$this->url = 'http://leetcode.net';
	}

	function get_types( $p_event ) {
		return array( 'svn' => lang_get( 'plugin_SourceWebSVN_svn' ) );
	}

	function show_type( $p_event, $p_type ) {
		if ( 'svn' == $p_type ) {
			return lang_get( 'plugin_SourceWebSVN_svn' );
		}
	}

	function show_changeset( $p_event, $p_repo, $p_changeset ) {
		if ( 'svn' == $p_repo->type ) {
			return "$p_changeset->branch r$p_changeset->revision";
		}
	}

	function show_file( $p_event, $p_repo, $p_changeset, $p_file ) {
		if ( 'svn' == $p_repo->type ) {
			return $p_file->action . ' - ' . $p_file->filename;
		}
	}

	function url_repo( $p_event, $p_repo, $p_changeset=null ) {
		if ( 'svn' == $p_repo->type ) {
			$t_rev = '';
			$t_path = '';

			if ( !is_null( $p_changeset ) ) {
				$t_rev = '&rev=' . urlencode( $p_changeset->revision );
			}
			if ( !is_blank( $p_repo->info['websvn_path'] ) ) {
				$t_path = '&path=' . urlencode( $p_repo->info['websvn_path'] );
			}
			return $p_repo->info['websvn_url'] . 'listing.php?repname=' . urlencode( $p_repo->info['websvn_name'] ) . "$t_path$t_rev&sc=1";
		}
	}

	function url_changeset( $p_event, $p_repo, $p_changeset ) {
		if ( 'svn' == $p_repo->type ) {
			return $this->url_repo( $p_event, $p_repo, $p_changeset );
		}
	}

	function url_file( $p_event, $p_repo, $p_changeset, $p_file ) {
		if ( 'svn' == $p_repo->type ) {
			if ( $p_file->action == 'D' ) {
				return '';
			}
			return $p_repo->info['websvn_url'] . 'filedetails.php?repname=' . urlencode( $p_repo->info['websvn_name'] ) .
				'&rev=' . urlencode( $p_changeset->revision ) . '&path=' . urlencode( $p_file->filename ) . '&sc=1';
		}
	}

	function url_diff( $p_event, $p_repo, $p_changeset, $p_file ) {
		if ( 'svn' == $p_repo->type ) {
			if ( $p_file->action == 'D' || $p_file->action == 'A' ) {
				return '';
			}
			return $p_repo->info['websvn_url'] . 'diff.php?repname=' . urlencode( $p_repo->info['websvn_name'] ) .
				'&rev=' . urlencode( $p_changeset->revision ) . '&path=' . urlencode( $p_file->filename ) . '&sc=1';
		}
	}

	function update_repo_form( $p_event, $p_repo ) {
		if ( 'svn' != $p_repo->type ) {
			return;
		}

		$t_url = $t_name = '';
		if ( isset( $p_repo->info['websvn_url'] ) ) {
			$t_url = $p_repo->info['websvn_url'];
		}
		if ( isset( $p_repo->info['websvn_name'] ) ) {
			$t_name = $p_repo->info['websvn_name'];
		}
		if ( isset( $p_repo->info['websvn_path'] ) ) {
			$t_path = $p_repo->info['websvn_path'];
		}
		if ( isset( $p_repo->info['standard_repo'] ) ) {
			$t_branches = $p_repo->info['standard_repo'];
		}
?>
<tr <?php echo helper_alternate_class() ?>>
<td class="category"><?php echo lang_get( 'plugin_SourceWebSVN_websvn_url' ) ?></td>
<td><input name="websvn_url" maxlength="250" size="40" value="<?php echo string_attribute( $t_url ) ?>"/></td>
</tr>
<tr <?php echo helper_alternate_class() ?>>
<td class="category"><?php echo lang_get( 'plugin_SourceWebSVN_websvn_name' ) ?></td>
<td><input name="websvn_name" maxlength="250" size="40" value="<?php echo string_attribute( $t_name ) ?>"/></td>
</tr>
<tr <?php echo helper_alternate_class() ?>>
<td class="category"><?php echo lang_get( 'plugin_SourceWebSVN_websvn_path' ) ?></td>
<td><input name="websvn_path" maxlength="250" size="40" value="<?php echo string_attribute( $t_path ) ?>"/></td>
</tr>
<tr <?php echo helper_alternate_class() ?>>
<td class="category"><?php echo lang_get( 'plugin_SourceWebSVN_standard_repo' ) ?></td>
<td><input name="standard_repo" type="checkbox" <?php echo ($t_branches ? 'checked="checked"' : '') ?>/></td>
</tr>
<?php
	}

	function update_repo( $p_event, $p_repo ) {
		if (  'svn' != $p_repo->type ) {
			return;
		}

		$f_websvn_url = gpc_get_string( 'websvn_url' );
		$f_websvn_name = gpc_get_string( 'websvn_name' );
		$f_websvn_path = gpc_get_string( 'websvn_path' );
		$f_standard_repo = gpc_get_bool( 'standard_repo', false );

		$p_repo->info['websvn_url'] = $f_websvn_url;
		$p_repo->info['websvn_name'] = $f_websvn_name;
		$p_repo->info['websvn_path'] = $f_websvn_path;
		$p_repo->info['standard_repo'] = $f_standard_repo;

		return $p_repo;
	}

	function commit( $p_event, $p_repo, $p_data ) {
		if ( 'svn' != $p_repo->type ) {
			return null;
		}

		if ( preg_match( '/(\d+)/', $p_data, $p_matches ) ) {
			$t_url = $p_repo->url;
			$t_revision = $p_matches[1];
			$t_svnlog = explode( "\n", `svn log -v $t_url -r$t_revision` );

			if ( SourceChangeset::exists( $p_repo->id, $t_revision ) ) {
				echo "Revision $t_revision already committed!\n";
				return null;
			}

			return $this->process_svn_log( $p_repo, $t_svnlog );
		}

	}

	function import_full( $p_event, $p_repo ) {
		if ( 'svn' != $p_repo->type ) {
			return;
		}

		$this->check_svn();

		$t_url = $p_repo->url;
		$t_svnlog = explode( "\n", `svn log -v $t_url` );

		return $this->process_svn_log( $p_repo, $t_svnlog );
	}

	function import_latest( $p_event, $p_repo ) {
		if ( 'svn' != $p_repo->type ) {
			return;
		}

		$this->check_svn();

		$t_changeset_table = plugin_table( 'changeset', 'Source' );

		$t_max_query = "SELECT revision FROM $t_changeset_table
						WHERE repo_id=" . db_param() . '
						ORDER BY timestamp DESC';
		$t_db_revision = db_result( db_query_bound( $t_max_query, array( $p_repo->id ), 1 ) );

		$t_url = $p_repo->url;
		$t_rev = $t_db_revision + 1;
		$t_svnlog = explode( "\n", `svn log -v -r $t_rev:HEAD $t_url` );

		return $this->process_svn_log( $p_repo, $t_svnlog );
	}

	function check_svn() {
		if ( is_blank( `svn help` ) ) {
			trigger_error( ERROR_GENERIC, ERROR );
		}
	}

	function process_svn_log( $p_repo, $p_svnlog ) {
		$t_state = 0;
		$t_svnline = str_pad( '', 72, '-' );

		$t_changeset = null;
		$t_comments = '';
		$t_count = 0;

		foreach( $p_svnlog as $t_line ) {

			# starting state, do nothing
			if ( 0 == $t_state ) {
				if ( $t_line == $t_svnline ) {
					$t_state = 1;
				}

			# Changeset info
			} elseif ( 1 == $t_state && preg_match( '/^r([0-9]+) \| (\w+) \| ([0-9\-]+) ([0-9:]+)/', $t_line, $t_matches ) ) {
				if ( !is_null( $t_changeset ) ) {
					$t_changeset->bugs = Source_Parse_Buglinks( $t_changeset->message );
					$t_changeset->save();
				}

				$t_user_id = user_get_id_by_name( $t_matches[2] );
				$t_user_id = ( false === $t_user_id ? 0 : $t_user_id );

				$t_changeset = new SourceChangeset( $p_repo->id, $t_matches[1], '', $t_matches[3] . ' ' . $t_matches[4], $t_matches[2], '', $t_user_id );

				$t_state = 2;

			# Changed paths
			} elseif ( 2 == $t_state ) {
				if ( strlen( $t_line ) == 0 ) {
					$t_state = 3;
				} else {
					if ( preg_match( '/^\s+([a-zA-Z])\s+([\S]+)/', $t_line, $t_matches ) ) {
						switch( $t_matches[1] ) {
							case 'A': $t_action = 'add'; break;
							case 'D': $t_action = 'rm'; break;
							case 'M': $t_action = 'mod'; break;
							default: $t_action = $t_matches[1];
						}

						$t_file = new SourceFile( $t_changeset->id, '', $t_matches[2], $t_action );
						$t_changeset->files[] = $t_file;

						# Branch-checking
						if ( is_blank( $t_changeset->branch) ) {
							# Look for standard trunk/branches/tags information
							if ( $p_repo->info['standard_repo'] ) {
								if ( preg_match( '/\/(?:(trunk)|(?:branches|tags)\/([^\/]+))/', $t_file->filename, $t_matches ) ) {
									if ( 'trunk' == $t_matches[1] ) {
										$t_changeset->branch = 'trunk';
									} else {
										$t_changeset->branch = $t_matches[2];
									}
								}
							} else {
								if ( preg_match( '/\/([^\/]+)/', $t_file->filename, $t_matches ) ) {
									$t_changeset->branch = $t_matches[1];
								}
							}
						}
					}
				}

			# Changeset comments
			} elseif ( 3 == $t_state ) {
				if ( $t_line == $t_svnline ) {
					$t_state = 1;
				} else {
					if ( !is_blank($t_changeset->message) ) {
						$t_changeset->message .= "\n$t_line";
					} else {
						$t_changeset->message .= $t_line;
					}
				}

			# Should only happen at the end...
			} else {
				break;
			}
		}

		if ( !is_null( $t_changeset ) ) {
			$t_changeset->bugs = Source_Parse_Buglinks( $t_changeset->message );
			$t_changeset->save();
		}

		return true;
	}
}