diff --git a/Source/MantisSourcePlugin.class.php b/Source/MantisSourcePlugin.class.php index 35da316..07cb975 100644 --- a/Source/MantisSourcePlugin.class.php +++ b/Source/MantisSourcePlugin.class.php @@ -16,44 +16,24 @@ * @author John Reese */ abstract class MantisSourcePlugin extends MantisPlugin { - function hooks() { + public function hooks() { return array( - 'EVENT_SOURCE_GET_TYPES' => 'get_types', - - 'EVENT_SOURCE_SHOW_TYPE' => 'show_type', - 'EVENT_SOURCE_SHOW_CHANGESET' => 'show_changeset', - 'EVENT_SOURCE_SHOW_FILE' => 'show_file', - - 'EVENT_SOURCE_URL_REPO' => 'url_repo', - 'EVENT_SOURCE_URL_CHANGESET' => 'url_changeset', - 'EVENT_SOURCE_URL_FILE' => 'url_file', - 'EVENT_SOURCE_URL_FILE_DIFF' => 'url_diff', - - 'EVENT_SOURCE_UPDATE_REPO_FORM' => 'update_repo_form', - 'EVENT_SOURCE_UPDATE_REPO' => 'update_repo', - + 'EVENT_SOURCE_INTEGRATION' => 'integration', 'EVENT_SOURCE_PRECOMMIT' => 'precommit', - 'EVENT_SOURCE_COMMIT' => 'commit', - - 'EVENT_SOURCE_IMPORT_FULL' => 'import_full', - 'EVENT_SOURCE_IMPORT_LATEST' => 'import_latest', ); } /** - * Get a short, unique, lowercase string representing the plugin's source - * control type. - * @return string Source control type + * A short, unique, lowercase string representing the plugin's source control type. */ - abstract function get_types( $p_event ); + public $type = null; /** * Get a long, proper string representing the plugin's source control type. - * Should ignore any $p_type not matching the output from get_type() - * @param string Source control type + * Should be localized if possible. * @return string Source control name */ - abstract function show_type( $p_event, $p_type ); + abstract public function show_type(); /** * Get a string representing the given repository and changeset. @@ -61,7 +41,7 @@ * @param object Changeset * @return string Changeset string */ - abstract function show_changeset( $p_event, $p_repo, $p_changeset); + abstract public function show_changeset( $p_repo, $p_changeset); /** * Get a string representing a file for a given repository and changeset. @@ -70,7 +50,7 @@ * @param object File * @return string File string */ - abstract function show_file( $p_event, $p_repo, $p_changeset, $p_file ); + abstract public function show_file( $p_repo, $p_changeset, $p_file ); /** * Get a URL to a view of the repository at the given changeset. @@ -78,7 +58,7 @@ * @param object Changeset * @return string URL */ - abstract function url_repo( $p_event, $p_repo, $t_changeset=null ); + abstract public function url_repo( $p_repo, $t_changeset=null ); /** * Get a URL to a diff view of the given changeset. @@ -86,7 +66,7 @@ * @param object Changeset * @return string URL */ - abstract function url_changeset( $p_event, $p_repo, $p_changeset ); + abstract public function url_changeset( $p_repo, $p_changeset ); /** * Get a URL to a view of the given file at the given changeset. @@ -95,7 +75,7 @@ * @param object File * @return string URL */ - abstract function url_file( $p_event, $p_repo, $p_changeset, $p_file ); + abstract public function url_file( $p_repo, $p_changeset, $p_file ); /** * Get a URL to a diff view of the given file at the given changeset. @@ -104,16 +84,72 @@ * @param object File * @return string URL */ - abstract function url_diff( $p_event, $p_repo, $p_changeset, $p_file ); + abstract public function url_diff( $p_repo, $p_changeset, $p_file ); - function update_repo_form( $p_event, $p_repo ) {} - function update_repo( $p_event, $p_repo ) {} + /** + * Output form elements for custom repository data. + * @param object Repository + */ + public function update_repo_form( $p_repo ) {} - function precommit( $p_event ) {} - function commit( $p_event, $p_repo, $p_data ) {} + /** + * Process formelements for custom repository data. + * @param object Repository + */ + public function update_repo( $p_repo ) {} - function import_full( $p_event, $p_repo ) {} - function import_latest( $p_event, $p_repo ) {} + /** + * If necessary, check GPC inputs to determine if the checkin data + * is for a repository handled by this VCS type. + * @return array Array with "repo"=>Repository, "data"=>... + */ + public function precommit() {} + + /** + * Translate commit data to Changeset objects for the given repo. + * @param object Repository + * @param mixed Commit data + * @return array Changesets + */ + public function commit( $p_repo, $p_data ) {} + + /** + * Post-process changesets from checkin. + * @param object Repository + * @param array Changesets + */ + public function postcommit( $p_repo, $p_changesets ) {} + + /** + * Initiate an import of changeset data for the entire repository. + * @param object Repository + * @return array Changesets + */ + public function import_full( $p_repo ) {} + + /** + * Initiate an import of changeset data not yet imported. + * @param object Repository + * @return array Changesets + */ + public function import_latest( $p_repo ) {} + + /** + * Initialize contact with the integration framework. + * @return object The plugin object + */ + final public function integration( $p_event ) { + return $this; + } + + /** + * Post-process changesets from importing latest data. + * Not called after a full import. + * @param object Repository + * @param array Changesets + */ + public function postimport( $p_repo, $p_changesets ) {} + } /** @@ -129,39 +165,33 @@ $this->version = plugin_lang_get( 'version', 'Source' ); } - function get_types( $p_event ) { - return array('generic' => 'Generic'); + public $type = 'generic'; + + function show_type() { + return 'Generic'; } - function show_type( $p_event, $p_type ) { - if ( 'generic' == strtolower( $p_type ) ) { - return 'Generic'; - } - - return $p_type; - } - - function show_changeset( $p_event, $p_repo, $p_changeset ) { + function show_changeset( $p_repo, $p_changeset ) { return $p_repo->type . ' ' . $p_changeset->revision; } - function show_file( $p_event, $p_repo, $p_changeset, $p_file ) { + function show_file( $p_repo, $p_changeset, $p_file ) { return $p_file->filename . ' (' . $p_file->revision . ')'; } - function url_repo( $p_event, $p_repo, $t_changeset=null ) { + function url_repo( $p_repo, $t_changeset=null ) { return $p_repo->url; } - function url_changeset( $p_event, $p_repo, $p_changeset ) { + function url_changeset( $p_repo, $p_changeset ) { return $p_repo->url; } - function url_file( $p_event, $p_repo, $p_changeset, $p_file ) { + function url_file( $p_repo, $p_changeset, $p_file ) { return $p_repo->url; } - function url_diff( $p_event, $p_repo, $p_changeset, $p_file ) { + function url_diff( $p_repo, $p_changeset, $p_file ) { return $p_repo->url; } } diff --git a/Source/Source.API.php b/Source/Source.API.php index 4b1eb24..c2872ca 100644 --- a/Source/Source.API.php +++ b/Source/Source.API.php @@ -25,9 +25,6 @@ define( 'SOURCE_FIRST', 4 ); define( 'SOURCE_LAST', 5 ); -global $g_Source_cache_types; -$g_Source_cache_types = null; - function SourceType( $p_type ) { $t_types = SourceTypes(); @@ -39,25 +36,19 @@ } function SourceTypes() { - global $g_Source_cache_types; + static $s_types = null; - if ( is_null( $g_Source_cache_types ) ) { - $t_types = array(); + if ( is_null( $s_types ) ) { + $s_types = array(); - $t_raw_data = event_signal( 'EVENT_SOURCE_GET_TYPES' ); - foreach ( $t_raw_data as $t_plugin => $t_callbacks ) { - foreach ( $t_callbacks as $t_callback => $t_data ) { - foreach ( $t_data as $t_type => $t_name ) { - $t_types[$t_type] = $t_name; - } - } + foreach( SourceVCS::all() as $t_type => $t_vcs ) { + $s_types[ $t_type ] = $t_vcs->show_type(); } - asort( $t_types ); - $g_Source_cache_types = $t_types; + asort( $s_types ); } - return $g_Source_cache_types; + return $s_types; } /** @@ -394,8 +385,8 @@ $t_repo = SourceRepo::load( $t_changeset->repo_id ); - $t_url = event_signal( 'EVENT_SOURCE_URL_CHANGESET', array( $t_repo, $t_changeset ) ); - $t_name = event_signal( 'EVENT_SOURCE_SHOW_CHANGESET', array( $t_repo, $t_changeset ) ); + $t_url = $t_vcs->url_changeset( $t_repo, $t_changeset ); + $t_name = $t_vcs->show_changeset( $t_repo, $t_changeset ); if ( !is_blank( $t_url ) ) { $t_string = '' . $t_name . ''; @@ -406,6 +397,94 @@ } /** + * Object for handling registration and retrieval of VCS type extension plugins. + */ +class SourceVCS { + static private $cache = array(); + + /** + * Initialize the extension cache. + */ + static public function init() { + if ( is_array( self::$cache ) && !empty( self::$cache ) ) { + return; + } + + $t_raw_data = event_signal( 'EVENT_SOURCE_INTEGRATION' ); + foreach ( $t_raw_data as $t_plugin => $t_callbacks ) { + foreach ( $t_callbacks as $t_callback => $t_object ) { + if ( is_subclass_of( $t_object, 'MantisSourcePlugin' ) && + is_string( $t_object->type ) && !is_blank( $t_object->type ) ) { + $t_type = strtolower($t_object->type); + self::$cache[ $t_type ] = new SourceVCSWrapper( $t_object ); + } + } + } + } + + /** + * Retrieve an extension plugin that can handle the requested repo's VCS type. + * If the requested type is not available, the "generic" type will be returned. + * @param object Repository object + * @return object VCS plugin + */ + static public function repo( $p_repo ) { + return self::type( $p_repo->type ); + } + + /** + * Retrieve an extension plugin that can handle the requested VCS type. + * If the requested type is not available, the "generic" type will be returned. + * @param string VCS type + * @return object VCS plugin + */ + static public function type( $p_type ) { + $p_type = strtolower( $p_type ); + + if ( isset( self::$cache[ $p_type ] ) ) { + return self::$cache[ $p_type ]; + } else { + return self::$cache['generic']; + } + } + + /** + * Retrieve a list of all registered VCS types. + * @return array VCS plugins + */ + static public function all() { + return self::$cache; + } +} + +/** + * Class for wrapping VCS objects with plugin API calls + */ +class SourceVCSWrapper { + private $object; + private $basename; + + /** + * Build a wrapper around a VCS plugin object. + */ + function __construct( $p_object ) { + $this->object = $p_object; + $this->basename = $p_object->basename; + } + + /** + * Wrap method calls to the target object in plugin_push/pop calls. + */ + function __call( $p_method, $p_args ) { + plugin_push_current( $this->basename ); + $value = call_user_func_array( array( $this->object, $p_method ), $p_args ); + plugin_pop_current(); + + return $value; + } +} + +/** * Abstract source control repository data. */ class SourceRepo { @@ -804,6 +883,7 @@ $t_bugs_deleted = array_unique( array_diff( $this->__bugs, $this->bugs ) ); $this->load_repo(); + $t_vcs = SourceVCS::repo( $this->repo ); $t_user_id = (int)$p_user_id; if ( $t_user_id < 1 ) { @@ -823,7 +903,7 @@ foreach( $t_bugs_deleted as $t_bug_id ) { plugin_history_log( $t_bug_id, 'changeset_removed', - event_signal( 'EVENT_SOURCE_SHOW_CHANGESET', array( $this->repo, $this ) ), + $t_vcs->show_changeset( $this->repo, $this ), '', $t_user_id, 'Source' ); } } @@ -846,7 +926,7 @@ foreach( $t_bugs_added as $t_bug_id ) { plugin_history_log( $t_bug_id, 'changeset_attached', - event_signal( 'EVENT_SOURCE_SHOW_CHANGESET', array( $this->repo, $this ) ), + $t_vcs->show_changeset( $this->repo, $this ), '', $t_user_id, 'Source' ); } } diff --git a/Source/Source.ViewAPI.php b/Source/Source.ViewAPI.php index 70122e3..98bac02 100644 --- a/Source/Source.ViewAPI.php +++ b/Source/Source.ViewAPI.php @@ -32,6 +32,8 @@ foreach( $p_changesets as $t_changeset ) { $t_repo = $t_repos[ $t_changeset->repo_id ]; + $t_vcs = SourceVCS::repo( $t_repo ); + $t_changeset->load_files(); $t_author = Source_View_Author( $t_changeset, false ); @@ -42,7 +44,7 @@ name . ': ' : '' ) . - event_signal( 'EVENT_SOURCE_SHOW_CHANGESET', array( $t_repo, $t_changeset ) ) + $t_vcs->show_changeset( $t_repo, $t_changeset ) ) ?>
timestamp ) ?>
@@ -56,7 +58,7 @@
id, plugin_lang_get( 'details', 'Source' ) ); - if ( $t_url = event_signal( 'EVENT_SOURCE_URL_CHANGESET', array( $t_repo, $t_changeset ) ) ) { + if ( $t_url = $t_vcs->url_changeset( $t_repo, $t_changeset ) ) { print_bracket_link( $t_url, plugin_lang_get( 'diff', 'Source' ) ); } ?> @@ -66,13 +68,13 @@ files as $t_file ) { ?> - +show_file( $t_repo, $t_changeset, $t_file ) ) ?> url_diff( $t_repo, $t_changeset, $t_file ) ) { print_bracket_link( $t_url, plugin_lang_get( 'diff', 'Source' ) ); } - if ( $t_url = event_signal( 'EVENT_SOURCE_URL_FILE', array( $t_repo, $t_changeset, $t_file ) ) ) { + if ( $t_url = $t_vcs->url_file( $t_repo, $t_changeset, $t_file ) ) { print_bracket_link( $t_url, plugin_lang_get( 'file', 'Source' ) ); } ?> diff --git a/Source/Source.php b/Source/Source.php index ca3f773..784857e 100644 --- a/Source/Source.php +++ b/Source/Source.php @@ -18,6 +18,8 @@ * with the Mantis bug tracker software. */ class SourcePlugin extends MantisPlugin { + static $cache = array(); + function register() { $this->name = plugin_lang_get( 'title' ); $this->description = plugin_lang_get( 'description' ); @@ -71,33 +73,17 @@ function events() { return array( - 'EVENT_SOURCE_GET_TYPES' => EVENT_TYPE_DEFAULT, # Get a list of registered source control types + # Allow source integration plugins to announce themselves + 'EVENT_SOURCE_INTEGRATION' => EVENT_TYPE_DEFAULT, - 'EVENT_SOURCE_SHOW_TYPE' => EVENT_TYPE_FIRST, # Given a VCS type, return a long name (eg, svn -> Subversion) - 'EVENT_SOURCE_SHOW_CHANGESET' => EVENT_TYPE_FIRST, # Return an appropriate Type/Revision string for a given changeset - 'EVENT_SOURCE_SHOW_FILE' => EVENT_TYPE_FIRST, # Return an appropriate Filename/Revision string for a given changeset file - - 'EVENT_SOURCE_URL_REPO' => EVENT_TYPE_FIRST, # Return a URL to see data for the repository - 'EVENT_SOURCE_URL_CHANGESET' => EVENT_TYPE_FIRST, # Return a URL to see data for a single changeset - 'EVENT_SOURCE_URL_FILE' => EVENT_TYPE_FIRST, # Return a URL to see a given revision of a file - 'EVENT_SOURCE_URL_FILE_DIFF' => EVENT_TYPE_FIRST, # Return a URL to see a given revision's diff of a file - - 'EVENT_SOURCE_UPDATE_REPO_FORM' => EVENT_TYPE_FIRST, # Output HTML form elements for a repository update - 'EVENT_SOURCE_UPDATE_REPO' => EVENT_TYPE_FIRST, # Handle form data after submitting a repo update form - - 'EVENT_SOURCE_PRECOMMIT' => EVENT_TYPE_FIRST, # Allow plugins to try finding commit information before Source looks - 'EVENT_SOURCE_COMMIT' => EVENT_TYPE_FIRST, # Source control commit handling, passed commit details from checkin script - 'EVENT_SOURCE_POSTCOMMIT' => EVENT_TYPE_EXECUTE, # Allow processing of the newly-committed changesets - - 'EVENT_SOURCE_IMPORT_FULL' => EVENT_TYPE_FIRST, # Import an existing repository from scratch - 'EVENT_SOURCE_IMPORT_LATEST' => EVENT_TYPE_FIRST, # Import the latest changesets from a repository - 'EVENT_SOURCE_POSTIMPORT' => EVENT_TYPE_EXECUTE, # Allow processing of the newly-imported changesets + # Allow vcs plugins to pre-process commit data + 'EVENT_SOURCE_PRECOMMIT' => EVENT_TYPE_FIRST, ); } function hooks() { return array( - 'EVENT_PLUGIN_INIT' => 'post_init', + 'EVENT_CORE_READY' => 'core_ready', 'EVENT_LAYOUT_RESOURCES' => 'css', 'EVENT_MENU_MAIN' => 'menu_main', ); @@ -110,10 +96,15 @@ plugin_child( 'SourceIntegration' ); } - function post_init() { - # post-init register the generic source integration child plugin - # so that it always has lowest priority. + /** + * Register source integration plugins with the framework. + */ + function core_ready() { + # register the generic vcs type plugin_child( 'SourceGeneric' ); + + # initialize the vcs type cache + SourceVCS::init(); } function css() { diff --git a/Source/lang/strings_english.txt b/Source/lang/strings_english.txt index 11f662c..948371f 100644 --- a/Source/lang/strings_english.txt +++ b/Source/lang/strings_english.txt @@ -14,7 +14,7 @@ $s_plugin_Source_ = ''; $s_plugin_Source_title = 'Source Control Integration'; $s_plugin_Source_description = 'Source control integration using an abstract API to support any source control software.'; -$s_plugin_Source_version = '0.13'; +$s_plugin_Source_version = '0.14'; $s_plugin_Source_repository = 'Repository'; $s_plugin_Source_repositories = 'Repositories'; diff --git a/Source/pages/checkin.php b/Source/pages/checkin.php index 1fe15e8..e25be65 100644 --- a/Source/pages/checkin.php +++ b/Source/pages/checkin.php @@ -82,8 +82,10 @@ die( plugin_lang_get( 'invalid_repo' ) ); } +$t_vcs = SourceVCS::repo( $t_repo ); + # Let the plugins handle commit data -$t_changesets = event_signal( 'EVENT_SOURCE_COMMIT', array( $t_repo, $f_data ) ); +$t_changesets = $t_vcs->commit( $t_repo, $f_data ); # Changesets couldn't be loaded apparently if ( !is_array( $t_changesets ) ) { @@ -98,5 +100,5 @@ Source_Process_Changesets( $t_changesets ); # Allow plugins to handle commits afterwards -event_signal( 'EVENT_SOURCE_POSTCOMMIT', array( $t_repo, $t_changesets ) ); +$t_vcs->postcommit( $t_repo, $t_changesets ); diff --git a/Source/pages/index.php b/Source/pages/index.php index 1edc757..c757a5c 100644 --- a/Source/pages/index.php +++ b/Source/pages/index.php @@ -19,7 +19,6 @@ $t_title_span = $t_show_stats ? 2 : 1; $t_links_span = $t_show_stats ? 4 : 2; -$t_types = SourceTypes(); $t_repos = SourceRepo::load_all(); html_page_top1( plugin_lang_get( 'title' ) ); @@ -62,7 +61,6 @@ id, plugin_lang_get( 'changesets' ) ); - #print_bracket_link( event_signal( 'EVENT_SOURCE_URL_REPO', $t_repo ), plugin_lang_get( 'browse' ) ); if ( $t_can_manage ) { if ( preg_match( '/^Import \d+-\d+\d+/', $t_repo->name ) ) { print_bracket_link( plugin_page( 'repo_delete' ) . '&id=' . $t_repo->id . form_security_param( 'plugin_Source_repo_delete' ), plugin_lang_get( 'delete' ) ); @@ -96,7 +94,7 @@ diff --git a/Source/pages/list.php b/Source/pages/list.php index 0d4cdfd..a944dc5 100644 --- a/Source/pages/list.php +++ b/Source/pages/list.php @@ -20,6 +20,7 @@ $f_perpage = 25; $t_repo = SourceRepo::load( $f_repo_id ); +$t_vcs = SourceVCS::repo( $t_repo ); $t_type = SourceType($t_repo->type); $t_stats = $t_repo->stats( false ); @@ -39,7 +40,7 @@ if ( access_has_global_level( plugin_config_get( 'manage_threshold' ) ) ) { print_bracket_link( plugin_page( 'repo_manage_page' ) . '&id=' . $t_repo->id, plugin_lang_get( 'manage' ) ); } -if ( $t_url = event_signal( 'EVENT_SOURCE_URL_REPO', $t_repo ) ) { +if ( $t_url = $t_vcs->url_repo( $t_repo ) ) { print_bracket_link( $t_url, plugin_lang_get( 'browse' ) ); } print_bracket_link( plugin_page( 'index' ), plugin_lang_get( 'back' ) ); diff --git a/Source/pages/repo_import_full.php b/Source/pages/repo_import_full.php index 67830e6..fc936c0 100644 --- a/Source/pages/repo_import_full.php +++ b/Source/pages/repo_import_full.php @@ -17,6 +17,7 @@ $f_repo_id = gpc_get_string( 'id' ); $t_repo = SourceRepo::load( $f_repo_id ); +$t_vcs = SourceVCS::repo( $t_repo ); helper_ensure_confirmed( plugin_lang_get( 'ensure_import_full' ), plugin_lang_get( 'import_full' ) ); helper_begin_long_process(); @@ -35,7 +36,7 @@ while( true ) { # import the next batch of changesets - $t_changesets = event_signal( 'EVENT_SOURCE_IMPORT_FULL', array( $t_new_repo ) ); + $t_changesets = $t_vcs->import_full( $t_new_repo ); # check for errors if ( !is_array( $t_changesets ) ) { diff --git a/Source/pages/repo_import_latest.php b/Source/pages/repo_import_latest.php index 1eed510..77e1d62 100644 --- a/Source/pages/repo_import_latest.php +++ b/Source/pages/repo_import_latest.php @@ -77,6 +77,7 @@ $f_repo_id = gpc_get_string( 'id' ); $t_repo = SourceRepo::load( $f_repo_id ); +$t_vcs = SourceVCS::repo( $t_repo ); if ( !$t_remote ) { html_page_top1(); @@ -90,7 +91,7 @@ while( true ) { # import the next batch of changesets - $t_changesets = event_signal( 'EVENT_SOURCE_IMPORT_LATEST', array( $t_repo ) ); + $t_changesets = $t_vcs->import_latest( $t_repo ); # check for errors if ( !is_array( $t_changesets ) ) { @@ -106,7 +107,7 @@ Source_Process_Changesets( $t_changesets ); # let plugins process this batch of changesets - event_signal( 'EVENT_SOURCE_POSTIMPORT', array( $t_repo, $t_changesets ) ); + $t_vcs->postimport( $t_repo, $t_changesets ); } # only display results when the user is initiating the import diff --git a/Source/pages/repo_update.php b/Source/pages/repo_update.php index fbdfa86..419ba39 100644 --- a/Source/pages/repo_update.php +++ b/Source/pages/repo_update.php @@ -19,12 +19,13 @@ $f_repo_url = gpc_get_string( 'repo_url' ); $t_repo = SourceRepo::load( $f_repo_id ); +$t_vcs = SourceVCS::repo( $t_repo ); $t_type = SourceType($t_repo->type); $t_repo->name = $f_repo_name; $t_repo->url = $f_repo_url; -$t_updated_repo = event_signal( 'EVENT_SOURCE_UPDATE_REPO', array( $t_repo ) ); +$t_updated_repo = $t_vcs->update_repo( $t_repo ); if ( !is_null( $t_updated_repo ) ) { $t_updated_repo->save(); diff --git a/Source/pages/repo_update_page.php b/Source/pages/repo_update_page.php index 06b4680..656dd03 100644 --- a/Source/pages/repo_update_page.php +++ b/Source/pages/repo_update_page.php @@ -16,6 +16,7 @@ $f_repo_id = gpc_get_int( 'id' ); $t_repo = SourceRepo::load( $f_repo_id ); +$t_vcs = SourceVCS::repo( $t_repo ); $t_type = SourceType($t_repo->type); html_page_top1( plugin_lang_get( 'title' ) ); @@ -48,7 +49,7 @@ - +update_repo_form( $t_repo ) ?> diff --git a/Source/pages/view.php b/Source/pages/view.php index 14f8ad5..3a6a83b 100644 --- a/Source/pages/view.php +++ b/Source/pages/view.php @@ -46,6 +46,7 @@ $t_changeset_parent = null; } +$t_vcs = SourceVCS::repo( $t_repo ); $t_type = SourceType($t_repo->type); $t_use_porting = plugin_config_get( 'enable_porting' ); @@ -69,10 +70,10 @@ - + - +> - +
name ), ': ', event_signal( 'EVENT_SOURCE_SHOW_CHANGESET', array( $t_repo, $t_changeset ) ) ?>name ), ': ', $t_vcs->show_changeset( $t_repo, $t_changeset ) ?> url_changeset( $t_repo, $t_changeset ) ) { print_bracket_link( $t_url, plugin_lang_get( 'diff', 'Source' ) ); } print_bracket_link( plugin_page( 'list' ) . '&id=' . $t_repo->id . '&offset=' . $f_offset, "Back to Repository" ); @@ -96,7 +97,7 @@ branch ) ?> timestamp ) ?>id, event_signal( 'EVENT_SOURCE_SHOW_CHANGESET', array( $t_repo, $t_changeset_parent ) ) ); } ?>id, $t_vcs->show_changeset( $t_repo, $t_changeset_parent ) ); } ?>
show_file( $t_repo, $t_changeset, $t_file ) ) ?> - - + url_diff( $t_repo, $t_changeset, $t_file ), plugin_lang_get( 'diff', 'Source' ) ) ?> + url_file( $t_repo, $t_changeset, $t_file ), plugin_lang_get( 'file', 'Source' ) ) ?>