View Issue Details

IDProjectCategoryView StatusLast Update
0015739mantisbtplug-inspublic2014-01-01 22:12
Reporterthraxisp Assigned To 
PrioritynormalSeverityminorReproducibilityalways
Status feedbackResolutionopen 
Product Version1.2.14 
Summary0015739: Improvements for plugin ImportExportXml to support import from Bugzilla
Description

Issue 0012013 provides a number of enhancements for the XML import. Unfortunately it is targeted for the non-functional 1.3.x branch.

Improvements needed:

  • add translation for XML export from other trackers to Mantis
  • record creation is hardcoded for "now"
  • add processing for date fields
Additional Information

A patch will follow shortly

Tagspatch
Attached Files
mantis_bug_15739.txt (42,521 bytes)   
From 4f27dd5ff54fd5f26a560028fe71c69de6de32b7 Mon Sep 17 00:00:00 2001
From: Glenn Henshaw <thraxisp@logicaloutcome.ca>
Date: Sun, 28 Apr 2013 22:01:09 -0400
Subject: backport XML importer improvements
 fix bug/ bugnote add to allow for setting dates directly
 updates to XML importer to:
   - add more fields
   - allow for translation between fields in the XML imported and Mantis fields
 add XSLT translation from Bugzilla export to Mantis
   - translate using xsltproc bugzilla2mantis.xslt bugzilla.xml > mantis.xml

---
 core/bug_api.php                                  |   16 +-
 core/bugnote_api.php                              |   17 +-
 core/file_api.php                                 |    6 +-
 plugins/XmlImportExport/ImportXml.php             |   47 +++-
 plugins/XmlImportExport/ImportXml/Interface.php   |    6 +-
 plugins/XmlImportExport/ImportXml/Issue.php       |  264 +++++++++++++++++++--
 plugins/XmlImportExport/ImportXml/Mapper.php      |   12 +-
 plugins/XmlImportExport/ImportXml/Translation.php |   71 ++++++
 plugins/XmlImportExport/XmlImportExport.php       |   14 +-
 plugins/XmlImportExport/bugzilla2mantis.xslt      |  225 ++++++++++++++++++
 plugins/XmlImportExport/pages/export.php          |   91 +++++++-
 plugins/XmlImportExport/pages/import.php          |    4 +-
 plugins/XmlImportExport/pages/import_action.php   |    4 +-
 13 files changed, 705 insertions(+), 72 deletions(-)
 mode change 100644 => 100755 plugins/XmlImportExport/ImportXml.php
 mode change 100644 => 100755 plugins/XmlImportExport/ImportXml/Interface.php
 mode change 100644 => 100755 plugins/XmlImportExport/ImportXml/Mapper.php
 create mode 100755 plugins/XmlImportExport/ImportXml/Translation.php
 mode change 100644 => 100755 plugins/XmlImportExport/XmlImportExport.php
 create mode 100644 plugins/XmlImportExport/bugzilla2mantis.xslt
 mode change 100644 => 100755 plugins/XmlImportExport/mantis.dtd
 mode change 100644 => 100755 plugins/XmlImportExport/pages/export.php
 mode change 100644 => 100755 plugins/XmlImportExport/pages/import.php
 mode change 100644 => 100755 plugins/XmlImportExport/pages/import_action.php

diff --git a/core/bug_api.php b/core/bug_api.php
index 06bc514..fca372b 100644
--- a/core/bug_api.php
+++ b/core/bug_api.php
@@ -1,5 +1,4 @@
 <?php
-# MantisBT - a php based bugtracking system
 
 # MantisBT is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -302,8 +301,15 @@ class BugData {
 
 		# check due_date format
 		if( is_blank( $this->due_date ) ) {
-			$this_due_date = date_get_null();
+			$this->due_date = date_get_null();
+		}
+		# check date submitted and last modified
+		if( is_blank( $this->date_submitted ) ) {
+			$this->date_submitted = db_now();
 		}
+		if( is_blank( $this->last_updated ) ) {
+			$this->last_updated = db_now();
+ 		}
 
 		$t_bug_table = db_get_table( 'mantis_bug_table' );
 		$t_bug_text_table = db_get_table( 'mantis_bug_text_table' );
@@ -366,7 +372,7 @@ class BugData {
 					      " . db_param() . ',' . db_param() . ',' . db_param() . ',' . db_param() . ",
 					      " . db_param() . ',' . db_param() . ',' . db_param() . ',' . db_param() . ')';
 
-		db_query_bound( $query, Array( $this->project_id, $this->reporter_id, $this->handler_id, $this->duplicate_id, $this->priority, $this->severity, $this->reproducibility, $t_status, $this->resolution, $this->projection, $this->category_id, db_now(), db_now(), $this->eta, $t_text_id, $this->os, $this->os_build, $this->platform, $this->version, $this->build, $this->profile_id, $this->summary, $this->view_state, $this->sponsorship_total, $this->sticky, $this->fixed_in_version, $this->target_version, $this->due_date ) );
+		db_query_bound( $query, Array( $this->project_id, $this->reporter_id, $this->handler_id, $this->duplicate_id, $this->priority, $this->severity, $this->reproducibility, $t_status, $this->resolution, $this->projection, $this->category_id, $this->date_submitted, $this->last_updated, $this->eta, $t_text_id, $this->os, $this->os_build, $this->platform, $this->version, $this->build, $this->profile_id, $this->summary, $this->view_state, $this->sponsorship_total, $this->sticky, $this->fixed_in_version, $this->target_version, $this->due_date ) );
 
 		$this->id = db_insert_id( $t_bug_table );
 
@@ -831,8 +837,8 @@ function bug_is_readonly( $p_bug_id ) {
  * @uses config_api.php
  */
 function bug_is_resolved( $p_bug_id ) {
-	$t_bug = bug_get( $p_bug_id );
-	return( $t_bug->status >= config_get( 'bug_resolved_status_threshold', null, null, $t_bug->project_id ) );
+	$t_status = bug_get_field( $p_bug_id, 'status' );
+	return( $t_status >= config_get( 'bug_resolved_status_threshold' ) );
 }
 
 /**
diff --git a/core/bugnote_api.php b/core/bugnote_api.php
index 13147ce..99bb694 100644
--- a/core/bugnote_api.php
+++ b/core/bugnote_api.php
@@ -121,13 +121,19 @@ function bugnote_is_user_reporter( $p_bugnote_id, $p_user_id ) {
  * @param string $p_attr
  * @param int $p_user_id user id
  * @param bool $p_send_email generate email?
+ * @param int $p_date_submitted date submitted (defaults to now())
+ * @param int $p_last_modified last modification date (defaults to now())
+ * @param bool $p_skip_bug_update skip bug last modification update (useful when importing bugs/bugnotes)
  * @return false|int false or indicating bugnote id added
  * @access public
  */
-function bugnote_add( $p_bug_id, $p_bugnote_text, $p_time_tracking = '0:00', $p_private = false, $p_type = BUGNOTE, $p_attr = '', $p_user_id = null, $p_send_email = TRUE, $p_log_history = TRUE) {
+function bugnote_add( $p_bug_id, $p_bugnote_text, $p_time_tracking = '0:00', $p_private = false, $p_type = BUGNOTE, $p_attr = '', $p_user_id = null, $p_send_email = TRUE, $p_log_history = TRUE, $p_date_submitted = 0, $p_last_modified = 0, $p_skip_bug_update = FALSE ) {
 	$c_bug_id = db_prepare_int( $p_bug_id );
 	$c_time_tracking = helper_duration_to_minutes( $p_time_tracking );
+	$c_private = db_prepare_bool( $p_private );
 	$c_type = db_prepare_int( $p_type );
+	$c_date_submitted = $p_date_submitted <= 0 ? db_now() : db_prepare_int( $p_date_submitted );
+	$c_last_modified = $p_last_modified <= 0 ? db_now() : db_prepare_int( $p_last_modified );
 
 	if( REMINDER !== $p_type ) {
 		# Check if this is a time-tracking note
@@ -179,17 +185,18 @@ function bugnote_add( $p_bug_id, $p_bugnote_text, $p_time_tracking = '0:00', $p_
 				(bug_id, reporter_id, bugnote_text_id, view_state, date_submitted, last_modified, note_type, note_attr, time_tracking )
 			VALUES
 				(" . db_param() . ', ' . db_param() . ',' . db_param() . ', ' . db_param() . ', ' . db_param() . ',' . db_param() . ', ' . db_param() . ', ' . db_param() . ', ' . db_param() . ' )';
-	db_query_bound( $query, Array( $c_bug_id, $c_user_id, $t_bugnote_text_id, $t_view_state, db_now(), db_now(), $c_type, $p_attr, $c_time_tracking ) );
+	db_query_bound( $query, Array( $c_bug_id, $c_user_id, $t_bugnote_text_id, $t_view_state, $c_date_submitted, $c_last_modified, $c_type, $p_attr, $c_time_tracking ) );
 
 	# get bugnote id
 	$t_bugnote_id = db_insert_id( $t_bugnote_table );
 
 	# update bug last updated
-	bug_update_date( $p_bug_id );
+	if ( !$p_skip_bug_update ) {
+		bug_update_date( $p_bug_id );
+	}
 
 	# log new bug
-	if ( TRUE == $p_log_history)
-    	history_log_event_special( $p_bug_id, BUGNOTE_ADDED, bugnote_format_id( $t_bugnote_id ) );
+	history_log_event_special( $p_bug_id, BUGNOTE_ADDED, bugnote_format_id( $t_bugnote_id ) );
 
 	# if it was FEEDBACK its NEW_ now
 	if ( config_get( 'reassign_on_feedback' ) &&
diff --git a/core/file_api.php b/core/file_api.php
index 877ac61..3125ba7 100644
--- a/core/file_api.php
+++ b/core/file_api.php
@@ -633,7 +633,7 @@ function file_is_name_unique( $p_name, $p_bug_id, $p_table  = 'bug' ) {
  * @param integer $p_bug_id the bug id
  * @param array $p_file the uploaded file info, as retrieved from gpc_get_file()
  */
-function file_add( $p_bug_id, $p_file, $p_table = 'bug', $p_title = '', $p_desc = '', $p_user_id = null ) {
+function file_add( $p_bug_id, $p_file, $p_table = 'bug', $p_title = '', $p_desc = '', $p_user_id = null, $p_date_added = 0, $p_skip_bug_update = false ) {
 
 	file_ensure_uploaded( $p_file );
 	$t_file_name = $p_file['name'];
@@ -739,7 +739,9 @@ function file_add( $p_bug_id, $p_file, $p_table = 'bug', $p_title = '', $p_desc
 	if( 'bug' == $p_table ) {
 
 		# updated the last_updated date
-		$result = bug_update_date( $p_bug_id );
+		if ( !$p_skip_bug_update ) {
+			$result = bug_update_date( $p_bug_id );
+		}
 
 		# log new bug
 		history_log_event_special( $p_bug_id, FILE_ADDED, $t_file_name );
diff --git a/plugins/XmlImportExport/ImportXml.php b/plugins/XmlImportExport/ImportXml.php
old mode 100644
new mode 100755
index 98a724b..8ccba059
--- a/plugins/XmlImportExport/ImportXml.php
+++ b/plugins/XmlImportExport/ImportXml.php
@@ -1,6 +1,6 @@
 <?php
-# MantisBT - a php based bugtracking system
-# Copyright (C) 2002 - 2013  MantisBT Team - mantisbt-dev@lists.sourceforge.net
+# MantisBT - A PHP based bugtracking system
+# Copyright (C) 2002 - 2010  MantisBT Team - mantisbt-dev@lists.sourceforge.net
 # MantisBT 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 2 of the License, or
@@ -16,6 +16,7 @@
 
 require_once( 'ImportXml' . DIRECTORY_SEPARATOR . 'Mapper.php' );
 require_once( 'ImportXml' . DIRECTORY_SEPARATOR . 'Issue.php' );
+require_once( 'ImportXml' . DIRECTORY_SEPARATOR . 'Translation.php' );
 
 class SourceData {
 	public $version;
@@ -74,7 +75,8 @@ class ImportXML {
 	 */
 	public function import( ) {
 		// Read the <mantis> element and it's attributes
-		while( $this->reader_->read( ) && $this->reader_->name == 'mantis' ) {
+		$this->reader_->read( );
+		if ( $this->reader_->name == 'mantis' ) {
 			$this->source_->version = $this->reader_->getAttribute( 'version' );
 			$this->source_->urlbase = $this->reader_->getAttribute( 'urlbase' );
 			$this->source_->issuelink = $this->reader_->getAttribute( 'issuelink' );
@@ -92,33 +94,53 @@ class ImportXML {
 					/* element start */
 					$t_element_name = $this->reader_->localName;
 					$t_importer = $this->get_importer_object( $t_element_name );
+					echo "import " . $t_element_name . "\n";
 					if( !is_null( $t_importer ) ) {
 						$t_importer->process( $this->reader_ );
 						$t_importer->update_map( $this->itemsMap_ );
 					}
 					break;
 			}
-		}
+		} 
 
 		echo " Done\n";
 
+		// replace references in bug description and additional information
 		$importedIssues = $this->itemsMap_->getall( 'issue' );
 		printf( "Processing cross-references for %s issues...", count( $importedIssues ) );
 		foreach( $importedIssues as $oldId => $newId ) {
 			$bugData = bug_get( $newId, true );
 
 			$bugLinkRegexp = '/(^|[^\w])(' . preg_quote( $this->source_->issuelink, '/' ) . ')(\d+)\b/e';
-			$replacement = '"\\1" . $this->getReplacementString( "\\2", "\\3" )';
-
-			$bugData->description = preg_replace( $bugLinkRegexp, $replacement, $bugData->description );
-			$bugData->update( true, true );
-		}
+			// replace links in description
+			preg_match_all( $bugLinkRegexp, $bugData->description, $matches );
+			if ( is_array( $matches[3] && count( $matches[3] ) > 0 ) ) {
+				$content_replaced = true;
+				foreach ( $matches[3] as $old_id ) {
+					$bugData->description = str_replace( $this->source_->issuelink . $old_id, $this->getReplacementString( $this->source_->issuelink, $old_id ), $bugData->description);
+				}
+			}
+			// replace links in additional information
+			preg_match_all( $bugLinkRegexp, $bugData->additional_information, $matches );
+			if ( is_array( $matches[3] && count( $matches[3] ) > 0 ) ) {
+				$content_replaced = true;
+				foreach ( $matches[3] as $old_id ) {
+					$bugData->additional_information = str_replace( $this->source_->issuelink . $old_id, $this->getReplacementString( $this->source_->issuelink, $old_id ), $bugData->additional_information);
+				}
+			}
+			if ( $content_replaced ) {
+				// only update bug if necessary (otherwise last update date would be unnecessarily overwritten)
+				$bugData->update( true );
+			}
+ 		}
+		
+		// @todo: replace references within bugnotes
 		echo " Done\n";
 	}
 
 	/**
 	 * Compute and return the new link
- *
+	 *
 	 */
 	private function getReplacementString( $oldLinkTag, $oldId ) {
 		$linkTag = config_get( 'bug_link_tag' );
@@ -160,7 +182,10 @@ class ImportXML {
 		$importer = null;
 		switch( $p_element_name ) {
 			case 'issue':
-				$importer = new ImportXml_Issue( $this->keepCategory_, $this->defaultCategory_ );
+				$importer = new ImportXml_Issue( $this->keepCategory_, $this->defaultCategory_, $this->itemsMap_ );
+				break;
+			case 'translation':
+				$importer = new ImportXml_Translation( );
 				break;
 		}
 		return $importer;
diff --git a/plugins/XmlImportExport/ImportXml/Interface.php b/plugins/XmlImportExport/ImportXml/Interface.php
old mode 100644
new mode 100755
index 143e02f..5cf8a15
--- a/plugins/XmlImportExport/ImportXml/Interface.php
+++ b/plugins/XmlImportExport/ImportXml/Interface.php
@@ -1,5 +1,5 @@
 <?php
-# MantisBT - a php based bugtracking system
+# MantisBT - A PHP based bugtracking system
 # Copyright (C) 2002 - 2013  MantisBT Team - mantisbt-dev@lists.sourceforge.net
 # MantisBT is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -22,7 +22,7 @@ interface ImportXml_Interface {
 	  *
 	  * @param XMLreader $reader
 	  */
-	public function process( XMLreader $reader );
+	public function process( XMLreader$reader );
 
 	/**
 	  * Update the old_id => new_id conversion map
@@ -32,7 +32,7 @@ interface ImportXml_Interface {
 	  * Import Classes for items not needing this info can use an
 	  * empty implementation
 	  *
-	  * @param ImportXml_Mapper $mapper
+	  * @param Mapper $mapper
 	  */
 	public function update_map( ImportXml_Mapper $mapper );
 }
diff --git a/plugins/XmlImportExport/ImportXml/Issue.php b/plugins/XmlImportExport/ImportXml/Issue.php
index 264faae..d96e6d6 100644
--- a/plugins/XmlImportExport/ImportXml/Issue.php
+++ b/plugins/XmlImportExport/ImportXml/Issue.php
@@ -1,5 +1,5 @@
 <?php
-# MantisBT - a php based bugtracking system
+# MantisBT - A PHP based bugtracking system
 # Copyright (C) 2002 - 2013  MantisBT Team - mantisbt-dev@lists.sourceforge.net
 # MantisBT is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -14,9 +14,12 @@
 # You should have received a copy of the GNU General Public License
 # along with MantisBT.  If not, see <http://www.gnu.org/licenses/>.
 
-require_once( 'bug_api.php' );
-require_once( 'user_api.php' );
+$t_core_path = config_get( 'core_path' );
+require_once( $t_core_path.'bug_api.php' );
+require_once( $t_core_path.'user_api.php' );
+require_once( $t_core_path.'utility_api.php' );
 require_once( 'Interface.php' );
+require_once( 'Mapper.php' );
 
 class ImportXml_Issue implements ImportXml_Interface {
 
@@ -28,26 +31,50 @@ class ImportXml_Issue implements ImportXml_Interface {
 	// import Issues options
 	private $keepCategory_;
 	private $defaultCategory_;
+	private $textTranslation_;
 
-	public function __construct( $keepCategory, $defaultCategory ) {
+	public function __construct( $keepCategory, $defaultCategory, Mapper$translation ) {
 		$this->newbug_ = new BugData;
 		$this->keepCategory_ = $keepCategory;
 		$this->defaultCategory_ = $defaultCategory;
+		$this->textTranslation_ = $translation;
 	}
 
+	// verify that date is numeric, and translate if necessary
+	private function parseDate( $p_time )
+	{
+		$t_time = $p_time;
+		if ( !is_numeric($t_time) )
+		{
+			// not a number, parse as a date
+			$t_time_comps = strptime($t_time, "%F %T %z");
+			if ( false !== $t_time_comps )
+				$t_time = mktime( $t_time_comps['tm_hour'], $t_time_comps['tm_min'],
+							$t_time_comps['tm_sec'], 1 , 
+							$t_time_comps['tm_yday'] + 1, $t_time_comps['tm_year'] + 1900 ); 
+			else
+				$t_time = time();
+		}
+		//echo "date: " . $p_time . " = " . $t_time . "\n";
+		return $t_time;
+	}
+	
+	
 	// Read stream until current item finishes, processing
 	// the data found
 	public function process( XMLreader $reader ) {
-
 		//print "\nImportIssue process()\n";
 		$t_project_id = helper_get_current_project(); // TODO: category_get_id_by_name could work by default on current project
 		$userId = auth_get_current_user_id( );
+		$bugnotePtr = -1;
+		$cfPtr = -1;
 
 		$depth = $reader->depth;
 		while( $reader->read() &&
 				($reader->depth > $depth ||
 				 $reader->nodeType != XMLReader::END_ELEMENT)) {
 			if( $reader->nodeType == XMLReader::ELEMENT ) {
+				//echo "process " . $reader->localName . "\n";
 				switch( $reader->localName ) {
 					case 'reporter':
 						$t_old_id = $reader->getAttribute( 'id' );
@@ -68,19 +95,15 @@ class ImportXml_Issue implements ImportXml_Interface {
 					case 'category':
 						$this->newbug_->category_id = $this->defaultCategory_;
 
+						// TODO: if we port the import/export code to 1.1.x, this needs to be
+						//       improved to cope with the different cases (1.1 => 1.2, 1.2 => 1.1 etc)
 						if( version_compare( MANTIS_VERSION, '1.2', '>' ) === true ) {
 							$reader->read( );
 
 							if( $this->keepCategory_ ) {
-								# Check for the category's existence in the current project
-								# well as its parents (if any)
-								$t_projects_hierarchy = project_hierarchy_inheritance( $t_project_id );
-								foreach( $t_projects_hierarchy as $t_project ) {
-									$t_category_id = category_get_id_by_name( $reader->value, $t_project, false );
-									if( $t_category_id !== false ) {
-										$this->newbug_->category_id = $t_category_id;
-										break;
-									}
+								$t_category_id = category_get_id_by_name( $reader->value, $t_project_id );
+								if( $t_category_id !== false ) {
+									$this->newbug_->category_id = $t_category_id;
 								}
 							}
 
@@ -99,11 +122,27 @@ class ImportXml_Issue implements ImportXml_Interface {
 						$t_field = $reader->localName;
 						$t_id = $reader->getAttribute( 'id' );
 						$reader->read( );
-						$t_value = $reader->value;
-
-						// Here we assume ids have the same meaning in both installations
-						// TODO add a check for customized values
-						$this->newbug_->$t_field = $t_id;
+						$t_value = strtolower( trim( $reader->value ));
+						if ( (NULL === $t_id) && ("" != $t_value) )
+						{
+							// id wasn't set, use value to find result
+							// remap using provided translations
+							//echo "  got $t_value\n";
+							$t_value = $this->textTranslation_->getNewID( $t_field, $t_value );
+							//echo "  remapping $t_value\n";
+							
+							// reverse text from enum string
+							$t_enum = $t_field . '_enum_string';
+							$t_id = MantisEnum::getValue( config_get( $t_enum ), $t_value );
+							if (false !== $t_id)
+							{
+								$this->newbug_->$t_field = $t_id;
+							}
+							else
+							{
+								echo "failed to map \"$t_value\" in $t_enum\n";
+							}
+						}
 						break;
 
 					case 'id':
@@ -111,11 +150,131 @@ class ImportXml_Issue implements ImportXml_Interface {
 						$this->old_id_ = $reader->value;
 						break;
 
-					case 'project';
+					case 'project_id';
+						$reader->read( );
+						$t_project = $reader->value;
+						$t_project_id = project_get_id_by_name( $t_project );
+						// ignore original value, use current project
+						//echo "  map project \"$t_project\" to id $t_project_id\n";
+						$this->newbug_->project_id = $t_project_id;
+						break;
+					
+					case 'date_submitted':
+						$reader->read( );
+						$t_time = $this->parseDate( $reader->value );
+						$this->newbug_->date_submitted = $t_time;
+						break;
+
+					case 'last_updated':
+						$reader->read( );
+						$t_time = $this->parseDate( $reader->value );
+						$this->newbug_->last_updated = $t_time;
+						break;
 
-					// ignore original value, use current project
-					$this->newbug_->project_id = $t_project_id;
-					break;
+					case 'custom_fields':
+						// store custom fields
+						$depth_cf = $reader->depth;
+						while ( $reader->read() &&
+							  ( $reader->depth > $depth_cf ||
+							   $reader->nodeType != XMLReader::END_ELEMENT ) )
+						{
+							
+							if ( $reader->nodeType == XMLReader::ELEMENT ) {
+								switch ( $reader->localName ) {
+									case "custom_field":
+									case "custom_fields":
+										break;	
+									default:
+										$t_field = $reader->localName;
+										$reader->read( );
+										$t_value = $reader->value;
+										if (false !== $t_value) {
+											$cfPtr++;
+											$t_custom_fields[$cfPtr]->name = $t_field;
+											$t_custom_fields[$cfPtr]->value = $t_value;
+										}
+										break;
+								}
+							}
+						}
+						break;
+						
+					case 'bugnotes':
+						// ignore bugnote container for now
+						$bugnotePtr = -1;
+						break;
+
+					case 'bugnote':
+						// store bug notes
+						$depth_bn = $reader->depth;
+						while ( $reader->read() &&
+							  ( $reader->depth > $depth_bn ||
+							   $reader->nodeType != XMLReader::END_ELEMENT ) )
+						{
+							
+							if ( $reader->nodeType == XMLReader::ELEMENT ) {
+								if ($reader->localName == 'bugnote') {
+									$bugnotePtr++;
+									$t_bugnotes[$bugnotePtr]->date_submitted = 0;
+									$t_bugnotes[$bugnotePtr]->last_updated = 0;
+								}
+								switch ( $reader->localName ) {
+									case 'reporter':
+										$t_old_id = $reader->getAttribute( 'id' );
+										$reader->read( );
+										$t_bugnotes[$bugnotePtr]->reporter_id = $this->get_user_id( $reader->value, $userId );
+										break;
+
+									case 'view_state':
+										$t_old_id = $reader->getAttribute( 'id' );
+										$reader->read( );
+										$t_bugnotes[$bugnotePtr]->private = $t_old_id == VS_PRIVATE ? true : false;
+										break;
+
+									case 'date_submitted':
+										$reader->read( );
+										$t_time = $this->parseDate( $reader->value );
+										$t_bugnotes[$bugnotePtr]->date_submitted = $t_time;
+										break;
+
+									case 'last_updated':
+										$reader->read( );
+										$t_time = $this->parseDate( $reader->value );
+										$t_bugnotes[$bugnotePtr]->last_updated = $t_time;
+										break;
+
+									default:
+										$field = $reader->localName;
+										$reader->read( );
+										$t_bugnotes[$bugnotePtr]->$field = $reader->value;
+								}
+							}
+						}
+						break;
+						
+					case 'attachments':
+						// store attachments
+						$i = -1;
+						$depth_att = $reader->depth;
+						while ( $reader->read() &&
+							  ( $reader->depth > $depth_att ||
+							   $reader->nodeType != XMLReader::END_ELEMENT ) )
+						{
+							
+							if ( $reader->nodeType == XMLReader::ELEMENT ) {
+								if ($reader->localName == 'attachment') {
+									$i++;
+								}
+								switch ( $reader->localName ) {
+									default:
+										$field = $reader->localName;
+										$reader->read( );
+										$t_attachments[$i]->$field = $reader->value;
+								}
+							}
+						}
+						break;
+						
 				default:
 					$field = $reader->localName;
 
@@ -126,8 +285,57 @@ class ImportXml_Issue implements ImportXml_Interface {
 			}
 		}
 
+		// pre-save checks
+		if ( is_blank($this->newbug_->description) )
+			$this->newbug_->description = "see below";
+
 		// now save the new bug
+		//var_dump($this->newbug_);
 		$this->new_id_ = $this->newbug_->create();
+		echo "created bug " . $this->new_id_ . "\n";
+		
+		// add custom fields
+		var_dump($t_custom_fields);
+		if ( $this->new_id_ > 0 && is_array( $t_custom_fields ) && count( $t_custom_fields ) > 0 ) {
+			foreach ( $t_custom_fields as $t_custom_field) {
+				$t_custom_field_id = custom_field_get_id_from_name( $t_custom_field->name );
+				if ( custom_field_exists( $t_custom_field_id ) && custom_field_is_linked( $t_custom_field_id, $t_project_id ) ) {
+					custom_field_set_value( $t_custom_field_id, $this->new_id_, $t_custom_field->value );
+				}
+				else {
+					echo "CF $t_custom_field not linked to project\n";
+					//error_parameters( $t_custom_field->name, $t_custom_field_id );
+					//trigger_error( ERROR_CUSTOM_FIELD_NOT_LINKED_TO_PROJECT, ERROR );
+				}
+			}
+		}
+		
+		// add bugnotes
+		echo "  add " . count($t_bugnotes) . " notes\n";
+		if ( $this->new_id_ > 0 && is_array( $t_bugnotes ) && count( $t_bugnotes ) > 0 ) {
+			foreach ( $t_bugnotes as $t_bugnote) {
+				if ($t_bugnote->last_updated == 0)
+					$t_bugnote->last_updated = $t_bugnote->date_submitted;
+				bugnote_add( $this->new_id_, $t_bugnote->note, $t_bugnote->time_tracking, $t_bugnote->private, $t_bugnote->note_type, $t_bugnote_>note_attr, $t_bugnote->reporter_id, false, $t_bugnote->date_submitted, $t_bugnote->last_modified, true );
+			}
+		}
+		
+		// add attachments
+		if ( $this->new_id_ > 0 && is_array( $t_attachments ) && count( $t_attachments ) > 0 ) {
+			foreach ( $t_attachments as $t_attachment) {
+				// Create a temporary file in the temporary files directory using sys_get_temp_dir()
+				$temp_file_name = tempnam( sys_get_temp_dir(), 'MantisImport' );
+				file_put_contents( $temp_file_name, base64_decode( $t_attachment->content ) );
+				$file_data = array( 'name' 		=> $t_attachment->filename,
+									'type' 		=> $t_attachment->file_type,
+									'tmp_name' 	=> $temp_file_name,
+									'size' 		=> filesize( $temp_file_name ) );
+				// unfortunately we have no clue who has added the attachment (this could only be fetched from history -> feel free to implement this)
+				// also I have no clue where description should come from...
+				file_add( $this->new_id_, $file_data, 'bug', $t_attachment->title, $p_desc = '', $p_user_id = null, $t_attachment->date_added, true );
+				unlink( $temp_file_name );
+			}
+		}
 
 		//echo "\nnew bug: $this->new_id_\n";
 	}
@@ -155,9 +363,13 @@ class ImportXml_Issue implements ImportXml_Interface {
 	private function get_user_id( $username, $squash_userid = 0 ) {
 		$t_user_id = user_get_id_by_name( $username );
 		if( $t_user_id === false ) {
-
-			//not found
-			$t_user_id = $squash_userid;
+			// user not found by username -> check real name
+			// keep in mind that the setting config_get( 'show_realname' ) may differ between import and export system!
+			$t_user_id = user_get_id_by_realname( $username );
+			if ( $t_user_id === false ) {
+				//not found
+				$t_user_id = $squash_userid;
+			}
 		}
 		return $t_user_id;
 	}
diff --git a/plugins/XmlImportExport/ImportXml/Mapper.php b/plugins/XmlImportExport/ImportXml/Mapper.php
old mode 100644
new mode 100755
index e514dee..3fea5dc
--- a/plugins/XmlImportExport/ImportXml/Mapper.php
+++ b/plugins/XmlImportExport/ImportXml/Mapper.php
@@ -1,5 +1,5 @@
 <?php
-# MantisBT - a php based bugtracking system
+# MantisBT - A PHP based bugtracking system
 # Copyright (C) 2002 - 2013  MantisBT Team - mantisbt-dev@lists.sourceforge.net
 # MantisBT is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -21,7 +21,15 @@
   */
 class ImportXml_Mapper {
 	private $issue = array( );
-
+	private $eta = array( );
+	private $priority = array( );
+	private $projection = array( );
+	private $reproducibility = array( );
+	private $resolution = array( );
+	private $severity = array( );
+	private $status = array( );
+	private $view_state = array( );
+	
 	public function add( $type, $old, $new ) {
 		$this->{$type}[ $old ] = $new;
 	}
diff --git a/plugins/XmlImportExport/ImportXml/Translation.php b/plugins/XmlImportExport/ImportXml/Translation.php
new file mode 100755
index 0000000..c14caae
--- /dev/null
+++ b/plugins/XmlImportExport/ImportXml/Translation.php
@@ -0,0 +1,71 @@
+<?php
+# MantisBT - A PHP based bugtracking system
+# Copyright (C) 2002 - 2013  MantisBT Team - mantisbt-dev@lists.sourceforge.net
+# MantisBT 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 2 of the License, or
+# (at your option) any later version.
+#
+# MantisBT 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with MantisBT.  If not, see <http://www.gnu.org/licenses/>.
+
+require_once( 'Interface.php' );
+
+class ImportXml_Translation implements ImportXml_Interface {
+
+	private $translation_;
+	private $new_id_;
+
+	private $mapping_name_;
+	
+	private $valid_mappings = array(
+			"eta", 
+			"priority", 
+			"projection", 
+			"reproducibility", 
+			"resolution", 
+			"severity", 
+			"status", 
+			"view_state"
+		);
+
+	// Read stream until current item finishes, processing
+	// the data found
+	public function process( XMLreader $reader ) {
+
+		$this->mapping_name_ = $reader->getAttribute( 'name' );
+
+		if (in_array($this->mapping_name_, $this->valid_mappings))
+		{
+			echo "process translation for " . $this->mapping_name_ . "\n";
+			$depth = $reader->depth;
+			while( $reader->read() &&
+					($reader->depth > $depth ||
+					$reader->nodeType != XMLReader::END_ELEMENT)) {
+				if( $reader->nodeType == XMLReader::ELEMENT ) {
+					switch( $reader->localName ) {
+						case 'translate':
+							$t_id = $reader->getAttribute( 'id' );
+							$reader->read( );
+							$this->translation[$t_id] = $reader->value;
+							echo "   translate " . $t_id . " to " . $reader->value . "\n";
+							break;
+
+						default:
+							}
+						}
+					}
+			
+		}
+	}
+
+	public function update_map( ImportXml_Mapper $mapper ) {
+		foreach ($this->translation as $t_id => $t_value)
+			$mapper->add( $this->mapping_name_, $t_id, $t_value );
+	}
+}
diff --git a/plugins/XmlImportExport/XmlImportExport.php b/plugins/XmlImportExport/XmlImportExport.php
old mode 100644
new mode 100755
index c894de3..07905a5
--- a/plugins/XmlImportExport/XmlImportExport.php
+++ b/plugins/XmlImportExport/XmlImportExport.php
@@ -1,5 +1,5 @@
 <?php
-# MantisBT - a php based bugtracking system
+# MantisBT - A PHP based bugtracking system
 
 # MantisBT is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -19,7 +19,7 @@
  * @package MantisPlugin
  * @subpackage MantisPlugin
  * @copyright Copyright (C) 2000 - 2002  Kenzaburo Ito - kenito@300baud.org
- * @copyright Copyright (C) 2002 - 2013  MantisBT Team - mantisbt-dev@lists.sourceforge.net
+ * @copyright Copyright (C) 2002 - 2010  MantisBT Team - mantisbt-dev@lists.sourceforge.net
  * @link http://www.mantisbt.org
  */
 
@@ -69,14 +69,4 @@ class XmlImportExportPlugin extends MantisPlugin {
 	function export_issues_menu( ) {
 		return array( '<a href="' . plugin_page( 'export' ) . '">' . plugin_lang_get( 'export' ) . '</a>', );
 	}
-
-	function install() {
-		$result = extension_loaded("xmlreader") && extension_loaded("xmlwriter");
-		if ( ! $result ) {
-			#\todo returning false should trigger some error reporting, needs rethinking error_api
-			error_parameters( plugin_lang_get( 'error_no_xml' ) );
-			trigger_error( ERROR_PLUGIN_INSTALL_FAILED, ERROR );
-		}
-		return $result;
-	}
 }
diff --git a/plugins/XmlImportExport/bugzilla2mantis.xslt b/plugins/XmlImportExport/bugzilla2mantis.xslt
new file mode 100644
index 0000000..0366387
--- /dev/null
+++ b/plugins/XmlImportExport/bugzilla2mantis.xslt
@@ -0,0 +1,225 @@
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+ <xsl:output omit-xml-declaration="yes" indent="yes"/>
+
+ <xsl:template match="/*">
+  <mantis 
+      version="1.2.15dev" 
+      urlbase="http://localhost:10088/~thraxisp/mantisbt/" 
+      issuelink="#" 
+      notelink="~"
+      format="1">
+      <translation name="severity">
+          <translate id="enhancement">feature</translate>
+          <translate id="normal">minor</translate>
+          <translate id="critical">crash</translate>
+      </translation>
+      <translation name="priority">
+          <translate id="---">normal</translate>
+          <translate id="lowest">low</translate>
+      </translation>
+      <translation name="status">
+          <translate id="reopened">feedback</translate>
+      </translation>
+      <xsl:apply-templates/>
+  </mantis>
+ </xsl:template>
+
+ <xsl:template match="bug">
+  <issue>
+   <xsl:apply-templates/>
+  </issue> 
+ </xsl:template>
+
+ <xsl:template match="bug_id">
+  <bug>
+      <xsl:apply-templates/>
+  </bug>
+ </xsl:template>
+
+ <xsl:template match="short_desc">
+  <summary>
+      <xsl:value-of select="."/>
+  </summary>
+  <description>
+      <xsl:value-of select="../long_desc[1]/thetext"/>
+  </description>
+ </xsl:template>
+
+ <xsl:template match="creation_ts">
+  <date_submitted>
+      <xsl:apply-templates/>
+  </date_submitted>
+ </xsl:template>
+
+ <xsl:template match="delta_ts">
+  <last_updated>
+      <xsl:apply-templates/>
+  </last_updated>
+ </xsl:template>
+
+ <xsl:template match="product">
+  <project_id>
+      <xsl:apply-templates/>
+  </project_id>
+ </xsl:template>
+
+ <xsl:template match="priority">
+  <priority>
+      <xsl:apply-templates/>
+  </priority>
+ </xsl:template>
+
+ <xsl:template match="bug_severity">
+  <severity>
+      <xsl:apply-templates/>
+  </severity>
+ </xsl:template>
+
+ <xsl:template match="bug_status">
+  <status>
+      <xsl:apply-templates/>
+  </status>
+ </xsl:template>
+
+ <xsl:template match="resolution">
+  <resolution>
+      <xsl:apply-templates/>
+  </resolution>
+ </xsl:template>
+
+ <xsl:template match="component">
+  <category>
+      <xsl:apply-templates/>
+  </category>
+ </xsl:template>
+
+ <xsl:template match="version">
+  <version>
+      <xsl:apply-templates/>
+  </version>
+ </xsl:template>
+
+ <xsl:template match="target_milestone">
+  <target_version>
+      <xsl:apply-templates/>
+  </target_version>
+ </xsl:template>
+
+ <xsl:template match="reporter">
+  <reporter>
+      <xsl:value-of select="@name"/>
+  </reporter>
+ </xsl:template>
+
+ <xsl:template match="assigned_to">
+  <handler>
+      <xsl:value-of select="@name"/>
+  </handler>
+ </xsl:template>
+
+ <xsl:template match="assigned_to">
+  <handler>
+      <xsl:value-of select="@name"/>
+  </handler>
+ </xsl:template>
+
+ <xsl:template match="cc">
+ </xsl:template>
+
+ <xsl:template match="op_sys">
+ </xsl:template>
+
+ <xsl:template match="rep_platform">
+ </xsl:template>
+
+ <xsl:template match="keywords">
+ </xsl:template>
+
+ <xsl:template match="status_whiteboard">
+ </xsl:template>
+
+ <xsl:template match="group">
+ </xsl:template>
+
+ <xsl:template match="reporter_accessible">
+ </xsl:template>
+
+ <xsl:template match="cclist_accessible">
+ </xsl:template>
+
+ <xsl:template match="classification_id">
+ </xsl:template>
+
+ <xsl:template match="classification">
+ </xsl:template>
+
+ <xsl:template match="bug_file_loc">
+ </xsl:template>
+
+ <xsl:template match="everconfirmed">
+ </xsl:template>
+
+ <xsl:template match="estimated_time">
+ </xsl:template>
+
+ <xsl:template match="remaining_time">
+ </xsl:template>
+
+ <xsl:template match="actual_time">
+ </xsl:template>
+
+ <xsl:template match="token">
+ </xsl:template>
+
+ <xsl:template match="cf_revision">
+     <custom_fields>
+         <revision>
+             <xsl:apply-templates/>
+         </revision>
+     </custom_fields>
+ </xsl:template>
+
+ <xsl:template match="cf_iteration">
+     <custom_fields>
+         <iteration>
+             <xsl:apply-templates/>
+         </iteration>
+     </custom_fields>
+ </xsl:template>
+
+ <!-- attachments -->
+ <!--  drop  -->
+ <xsl:template match="attachment" />
+
+ <!-- bug notes -->
+ <!--  drop first note -->
+ <xsl:template match="long_desc[1]" />
+ <xsl:template match="long_desc">
+  <bugnote>
+      <xsl:apply-templates/>
+  </bugnote>
+ </xsl:template>
+
+ <xsl:template match="commentid">
+ </xsl:template>
+
+ <xsl:template match="who">
+  <reporter>
+      <xsl:value-of select="@name"/>
+  </reporter>
+ </xsl:template>
+
+ <xsl:template match="bug_when">
+  <date_submitted>
+      <xsl:apply-templates/>
+  </date_submitted>
+ </xsl:template>
+
+ <xsl:template match="thetext">
+  <note>
+      <xsl:apply-templates/>
+  </note>
+ </xsl:template>
+
+</xsl:stylesheet>
\ No newline at end of file
diff --git a/plugins/XmlImportExport/mantis.dtd b/plugins/XmlImportExport/mantis.dtd
old mode 100644
new mode 100755
diff --git a/plugins/XmlImportExport/pages/export.php b/plugins/XmlImportExport/pages/export.php
old mode 100644
new mode 100755
index 700a804..0eb024e
--- a/plugins/XmlImportExport/pages/export.php
+++ b/plugins/XmlImportExport/pages/export.php
@@ -1,6 +1,6 @@
 <?php
-# MantisBT - a php based bugtracking system
-# Copyright (C) 2002 - 2013  MantisBT Team - mantisbt-dev@lists.sourceforge.net
+# MantisBT - A PHP based bugtracking system
+# Copyright (C) 2002 - 2010  MantisBT Team - mantisbt-dev@lists.sourceforge.net
 # MantisBT 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 2 of the License, or
@@ -146,6 +146,93 @@ foreach( $t_result as $t_row ) {
 				$writer->writeElement( $t_element, $t_value );
 		}
 	}
+	
+	# fetch and export custom fields
+	$t_custom_fields = custom_field_get_all_linked_fields( $t_row->id );
+	if ( is_array( $t_custom_fields ) && count( $t_custom_fields ) > 0 ) {
+		$writer->startElement( 'custom_fields' );
+		foreach ( $t_custom_fields as $custom_field_name => $t_custom_field ) {
+			$writer->startElement( 'custom_field' );
+			# id
+			$writer->writeElement( 'id', custom_field_get_id_from_name( $custom_field_name ) );
+			# title
+			$writer->writeElement( 'name', $custom_field_name );
+			# filename
+			$writer->writeElement( 'type', $t_custom_field['type'] );
+			# filesize
+			$writer->writeElement( 'value', $t_custom_field['value'] );
+			# file_type
+			$writer->writeElement( 'access_level_r', $t_custom_field['access_level_r'] );
+			
+			$writer->endElement(); # custom_field
+		}
+		$writer->endElement(); # custom_fields
+	}
+	
+	# fetch and export bugnotes
+	$t_bugnotes = bugnote_get_all_bugnotes( $t_row->id );
+	if ( is_array( $t_bugnotes ) && count( $t_bugnotes ) > 0 ) {
+		$writer->startElement( 'bugnotes' );
+		foreach ( $t_bugnotes as $t_bugnote ) {
+			$writer->startElement( 'bugnote' );
+			# id
+			$writer->writeElement( 'id', $t_bugnote->id );
+			# reporter
+			$writer->startElement( 'reporter' );
+			$writer->writeAttribute( 'id', $t_bugnote->reporter_id );
+			$writer->text( user_get_name( $t_bugnote->reporter_id ) );
+			$writer->endElement( );
+			# bug note
+			$writer->writeElement( 'note', $t_bugnote->note );
+			# view state
+			$writer->startElement( 'view_state' );
+			$writer->writeAttribute( 'id', $t_bugnote->view_state );
+			$writer->text( get_enum_element( 'view_state', $t_bugnote->view_state ) );
+			$writer->endElement( );
+			# date submitted
+			$writer->writeElement( 'date_submitted', $t_bugnote->date_submitted );
+			# last modified
+			$writer->writeElement( 'last_modified', $t_bugnote->last_modified );
+			# note type
+			$writer->writeElement( 'note_type', $t_bugnote->note_type );
+			# note attr
+			$writer->writeElement( 'note_attr', $t_bugnote->note_attr );
+			# time tracking
+			$writer->writeElement( 'time_tracking', $t_bugnote->time_tracking );
+			
+			$writer->endElement(); # bugnote
+		}
+		$writer->endElement(); # bugnotes
+	}
+	
+	# fetch and export attachments
+	$t_attachments = bug_get_attachments( $t_row->id );
+	if ( is_array( $t_attachments ) && count( $t_attachments ) > 0 ) {
+		$writer->startElement( 'attachments' );
+		foreach ( $t_attachments as $t_attachment ) {
+			$writer->startElement( 'attachment' );
+			# id
+			$writer->writeElement( 'id', $t_attachment['id'] );
+			# title
+			$writer->writeElement( 'title', $t_attachment['title'] );
+			# filename
+			$writer->writeElement( 'filename', $t_attachment['filename'] );
+			# filesize
+			$writer->writeElement( 'filesize', $t_attachment['filesize'] );
+			# file_type
+			$writer->writeElement( 'file_type', $t_attachment['file_type'] );
+			# last added
+			$writer->writeElement( 'date_added',  $t_attachment['date_added'] );
+			# content
+			$content = file_get_content( $t_attachment['id'] );
+			
+			$writer->writeElement( 'content',  base64_encode( $content['content'] ) );
+			
+			$writer->endElement(); # attachment
+		}
+		$writer->endElement(); # bugnotes
+	}
+	
 	$writer->endElement(); # issue
 
 	// Save memory by clearing cache
diff --git a/plugins/XmlImportExport/pages/import.php b/plugins/XmlImportExport/pages/import.php
old mode 100644
new mode 100755
index 14fe63d..429c64e
--- a/plugins/XmlImportExport/pages/import.php
+++ b/plugins/XmlImportExport/pages/import.php
@@ -1,6 +1,6 @@
 <?php
-# MantisBT - a php based bugtracking system
-# Copyright (C) 2002 - 2013  MantisBT Team - mantisbt-dev@lists.sourceforge.net
+# MantisBT - A PHP based bugtracking system
+# Copyright (C) 2002 - 2010  MantisBT Team - mantisbt-dev@lists.sourceforge.net
 # MantisBT 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 2 of the License, or
diff --git a/plugins/XmlImportExport/pages/import_action.php b/plugins/XmlImportExport/pages/import_action.php
old mode 100644
new mode 100755
index 7ef387b..8966594
--- a/plugins/XmlImportExport/pages/import_action.php
+++ b/plugins/XmlImportExport/pages/import_action.php
@@ -1,6 +1,6 @@
 <?php
-# MantisBT - a php based bugtracking system
-# Copyright (C) 2002 - 2013  MantisBT Team - mantisbt-dev@lists.sourceforge.net
+# MantisBT - A PHP based bugtracking system
+# Copyright (C) 2002 - 2010  MantisBT Team - mantisbt-dev@lists.sourceforge.net
 # MantisBT 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 2 of the License, or
-- 
1.7.3.5

mantis_bug_15739.txt (42,521 bytes)   

Relationships

related to 0012013 closeddregad Improvements for plugin ImportExportXml (and required core changes) 

Activities

atrol

atrol

2013-04-27 18:30

developer   ~0036701

Removed assignment. dhx will not contribute to this issue in near future.

thraxisp

thraxisp

2013-04-28 22:27

reporter   ~0036725

Patch for 1.2.x added. Given the recent flux on the next version, I am unsure as to where else to port it to.

dregad

dregad

2013-04-29 06:25

developer   ~0036728

Hi Glenn,

Can you detail what this patch exactly is ?

  • backport of master (0012013)
  • new changes/fixes
  • both
thraxisp

thraxisp

2013-04-29 07:46

reporter   ~0036730

Both.
The additional core changes are to fix the problem where the new bug / bugnote is always created "now" rather than with the dates passed in.
New additions accommodate additional fields, date conversion and more flexible XML formatting. An XSLT file is provided to convert the Bugzilla export to a Mantis one.

dregad

dregad

2013-04-29 08:27

developer   ~0036731

In that case, I think it would be much better to have your patch split into distinct bits & pieces, reflecting

a) the back-ported stuff, either as

  • cherry-picks from master (if it's just a few commits), or
  • one big diff commit (in that case the commit message should reference the fixed issues)

b) the new features as distinct commits (as there are 3 "feature" bullets in your patch commit message)

This way, we clearly document what was done and also have traceability in the tracker on back-ported issues

After doing a), we would hopefully have identical code in both 1.2.x and master branches, so b) should be applicable cleanly (or with minor issues) on both sides

dregad

dregad

2013-04-29 08:47

developer   ~0036732

Did a quick comparison of the commits between 1.2.x and master; it's actually mainly just one issue (0012013) which has not been ported. The rest are either translation updates, or minor things not worth documenting indivudually.

Note that 0011563 is only in 1.2.x but it looks like a similar change was made in master so can probably be ignored