[#6728] Perform trac ticket import directly, not over http
Signed-off-by: Tim Van Steenburgh <tvansteenburgh@gmail.com>
diff --git a/Allura/allura/scripts/trac_export.py b/Allura/allura/scripts/trac_export.py
index f54e8bc..b269544 100644
--- a/Allura/allura/scripts/trac_export.py
+++ b/Allura/allura/scripts/trac_export.py
@@ -273,18 +273,24 @@
return json.JSONEncoder.default(self, obj)
-def main():
- options, args = parse_options()
- ex = TracExport(args[0], start_id=options.start_id,
- verbose=options.verbose, do_attachments=options.do_attachments)
- # Implement iterator sequence limiting using islice()
- doc = [t for t in islice(ex, options.limit)]
+def export(url, start_id=1, verbose=False, do_attachments=True,
+ only_tickets=False, limit=None):
+ ex = TracExport(url, start_id=start_id,
+ verbose=verbose, do_attachments=do_attachments)
- if not options.only_tickets:
+ doc = [t for t in islice(ex, limit)]
+
+ if not only_tickets:
doc = {
'class': 'PROJECT',
'trackers': {'default': {'artifacts': doc}}
}
+ return doc
+
+
+def main():
+ options, args = parse_options()
+ doc = export(args[0], **vars(options))
out_file = sys.stdout
if options.out_filename:
diff --git a/ForgeImporters/forgeimporters/trac/tests/test_tickets.py b/ForgeImporters/forgeimporters/trac/tests/test_tickets.py
index 298b09e..73f9352 100644
--- a/ForgeImporters/forgeimporters/trac/tests/test_tickets.py
+++ b/ForgeImporters/forgeimporters/trac/tests/test_tickets.py
@@ -36,15 +36,9 @@
@patch('forgeimporters.trac.tickets.session')
@patch('forgeimporters.trac.tickets.g')
@patch('forgeimporters.trac.tickets.AuditLog')
- @patch('forgeimporters.trac.tickets.import_tracker')
- @patch('forgeimporters.trac.tickets.AlluraImportApiClient')
- @patch('forgeimporters.trac.tickets.datetime')
- @patch('forgeimporters.trac.tickets.ApiTicket')
- @patch('forgeimporters.trac.tickets.TracExport')
- def test_import_tool(self, TracExport, ApiTicket, dt, ApiClient, import_tracker, AuditLog, g, session):
- from datetime import datetime, timedelta
- now = datetime.utcnow()
- dt.utcnow.return_value = now
+ @patch('forgeimporters.trac.tickets.ImportSupport')
+ @patch('forgeimporters.trac.tickets.export')
+ def test_import_tool(self, export, ImportSupport, AuditLog, g, session):
user_map = {"orig_user":"new_user"}
importer = TracTicketImporter()
app = Mock(name='ForgeTrackerApp')
@@ -54,13 +48,13 @@
project = Mock(name='Project', shortname='myproject')
project.install_app.return_value = app
user = Mock(name='User', _id='id')
- with patch.dict('forgeimporters.trac.tickets.config', {'base_url': 'foo'}):
- res = importer.import_tool(project, user,
- mount_point='bugs',
- mount_label='Bugs',
- trac_url='http://example.com/trac/url',
- user_map=json.dumps(user_map),
- )
+ export.return_value = []
+ res = importer.import_tool(project, user,
+ mount_point='bugs',
+ mount_label='Bugs',
+ trac_url='http://example.com/trac/url',
+ user_map=json.dumps(user_map),
+ )
self.assertEqual(res, app)
project.install_app.assert_called_once_with(
'Tickets', mount_point='bugs', mount_label='Bugs',
@@ -70,19 +64,14 @@
'source': 'Trac',
'trac_url': 'http://example.com/trac/url/',
})
- TracExport.return_value = []
- TracExport.assert_called_once_with('http://example.com/trac/url/')
- ApiTicket.assert_called_once_with(
- user_id=user._id,
- capabilities={"import": ["Projects", "myproject"]},
- expires=now + timedelta(minutes=60))
- api_client = ApiClient.return_value
- import_tracker.assert_called_once_with(
- api_client, 'myproject', 'bugs', {
+ export.assert_called_once_with('http://example.com/trac/url/')
+ ImportSupport.return_value.perform_import.assert_called_once_with(
+ json.dumps(export.return_value),
+ json.dumps({
"user_map": user_map,
"usernames_match": False,
- }, '[]',
- validate=False)
+ }),
+ )
AuditLog.log.assert_called_once_with(
'import tool bugs from http://example.com/trac/url/',
project=project, user=user, url='foo')
@@ -90,14 +79,14 @@
@patch('forgeimporters.trac.tickets.session')
@patch('forgeimporters.trac.tickets.h')
- @patch('forgeimporters.trac.tickets.TracExport')
- def test_import_tool_failure(self, TracExport, h, session):
+ @patch('forgeimporters.trac.tickets.export')
+ def test_import_tool_failure(self, export, h, session):
importer = TracTicketImporter()
app = Mock(name='ForgeTrackerApp')
project = Mock(name='Project', shortname='myproject')
project.install_app.return_value = app
user = Mock(name='User', _id='id')
- TracExport.side_effect = ValueError
+ export.side_effect = ValueError
self.assertRaises(ValueError, importer.import_tool, project, user,
mount_point='bugs',
diff --git a/ForgeImporters/forgeimporters/trac/tickets.py b/ForgeImporters/forgeimporters/trac/tickets.py
index 6b2600a..cae010b 100644
--- a/ForgeImporters/forgeimporters/trac/tickets.py
+++ b/ForgeImporters/forgeimporters/trac/tickets.py
@@ -15,10 +15,6 @@
# specific language governing permissions and limitations
# under the License.
-from datetime import (
- datetime,
- timedelta,
- )
import json
from formencode import validators as fev
@@ -27,7 +23,6 @@
from pylons import tmpl_context as c
from pylons import app_globals as g
from tg import (
- config,
expose,
flash,
redirect,
@@ -40,12 +35,11 @@
from allura.controllers import BaseController
from allura.lib.decorators import require_post, task
-from allura.lib.import_api import AlluraImportApiClient
from allura.lib import validators as v
from allura.lib import helpers as h
-from allura.model import ApiTicket, AuditLog
+from allura.model import AuditLog
from allura.scripts.trac_export import (
- TracExport,
+ export,
DateJSONEncoder,
)
@@ -55,7 +49,7 @@
ImportErrorHandler,
)
from forgetracker.tracker_main import ForgeTrackerApp
-from forgetracker.scripts.import_tracker import import_tracker
+from forgetracker.import_support import ImportSupport
@task(notifications_disabled=True)
@@ -131,19 +125,14 @@
session(app.config).flush(app.config)
session(app.globals).flush(app.globals)
try:
- export = [ticket for ticket in TracExport(trac_url)]
- export_string = json.dumps(export, cls=DateJSONEncoder)
- api_ticket = ApiTicket(user_id=user._id,
- capabilities={"import": ["Projects", project.shortname]},
- expires=datetime.utcnow() + timedelta(minutes=60))
- session(api_ticket).flush(api_ticket)
- cli = AlluraImportApiClient(config['base_url'], api_ticket.api_key,
- api_ticket.secret_key, verbose=True, retry=False)
- import_tracker(cli, project.shortname, mount_point, {
- 'user_map': json.loads(user_map) if user_map else {},
- 'usernames_match': self.usernames_match(trac_url),
- },
- export_string, validate=False)
+ with h.push_config(c, app=app):
+ ImportSupport().perform_import(
+ json.dumps(export(trac_url), cls=DateJSONEncoder),
+ json.dumps({
+ 'user_map': json.loads(user_map) if user_map else {},
+ 'usernames_match': self.usernames_match(trac_url),
+ }),
+ )
AuditLog.log(
'import tool %s from %s' % (
app.config.options.mount_point,
diff --git a/ForgeTracker/forgetracker/import_support.py b/ForgeTracker/forgetracker/import_support.py
index 381e711..1dc466c 100644
--- a/ForgeTracker/forgetracker/import_support.py
+++ b/ForgeTracker/forgetracker/import_support.py
@@ -24,12 +24,12 @@
# Non-stdlib imports
from pylons import tmpl_context as c
-from allura.lib import helpers as h
-
from ming.orm.ormsession import ThreadLocalORMSession
# Pyforge-specific imports
from allura import model as M
+from allura.lib import helpers as h
+from allura.lib.plugin import ImportIdConverter
# Local imports
from forgetracker import model as TM
@@ -230,7 +230,7 @@
app_config_id=c.app.config._id,
custom_fields=dict(),
ticket_num=ticket_num,
- import_id=c.api_token.api_key)
+ import_id=ImportIdConverter.get().expand(ticket_dict['id'], c.app))
ticket.update(remapped)
return ticket
@@ -289,7 +289,6 @@
h.really_unicode(comment_dict['submitter']), text)
comment = thread.post(text=text, timestamp=ts)
comment.author_id = author_id
- comment.import_id = c.api_token.api_key
def make_attachment(self, org_ticket_id, ticket_id, att_dict):
if att_dict['size'] > self.ATTACHMENT_SIZE_LIMIT:
@@ -375,8 +374,6 @@
self.errors.append('Only single tracker import is supported')
return self.errors, self.warnings
- log.info('Import id: %s', c.api_token.api_key)
-
artifacts = project_doc['trackers'][tracker_names[0]]['artifacts']
if self.option('create_users'):