# replicator.py -- Python routines for replication daemon # Gareth Rees, Ravenbrook Limited, 2000-08-09 # $Id: //info.ravenbrook.com/project/p4dti/branch/2000-09-05/interface-debugging/replicator/replicator.py#1 $ # Perforce interface ---------------------------------------------------------- # The hostname and port number for the p4 server. p4_port = 'sandpiper.ravenbrook.com:1666' # The user to connect as. p4_user = 'gdr' # The p4 client to use. p4_client = 'p4dti-test' # TeamTrack interface --------------------------------------------------------- import teamtrack server = teamtrack.connect('joe', '', 'sandpiper.ravenbrook.com') # List of (p4 field, type, dt field) tuples. Each tuple is a field that # will be replicated into p4 from the DT. The type is of the p4 field. p4_from_teamtrack_fields = [ ( 'Description', 'text', 'DESCRIPTION' ) ] # Transform a TeamTrack case to a p4 job. def transform_teamtrack_to_p4(case, defaults, rid): job = defaults.copy() job['Job'] = case['P4DTI_' + rid + '_JOBNAME'] for field in p4_from_teamtrack_fields: job[field[0]] = case[field[2]] return job # recently_changed_teamtrack_cases(t, rid) returns a list of records from # the TS_CASES table which have changed since time t (seconds since # 1970-01-01 00:00:00 UTC) and which are due to be replicated by the # replicator with the given id. def recently_changed_teamtrack_cases(t, rid): query = "TS_LASTMODIFIEDDATE > %d AND TS_P4DTI_%s_JOBNAME <> ''" % (t, rid) return server.query(teamtrack.tables['CASES'], query) # Configuration --------------------------------------------------------------- # The replicator ID for this replicator. replicator_id = 'R0' # How long to sleep between polling the DT server (in seconds). poll_period = 10 # Additional window of time to look for changed DT issues (in seconds). poll_extra_window = 5 # Default values for required fields in p4 jobs. p4_default_fields = { 'Job' : 'new', 'Status' : 'open', 'User' : 'Administrator', 'Description' : 'replicated', } # transform_dt_to_p4(issue, defaults, rid) transforms the DT issue to a # p4 job, taking default values for p4 job fields from defaults. The # third argument is the replicator id. transform_dt_to_p4 = transform_teamtrack_to_p4 # recently_changed_dt_issues(t, rid) returns a list of DT issues that # have changed since time t (seconds since 1970-01-01 00:00:00 UTC) and # which are due to be replicated by the replicator with the given id. recently_changed_dt_issues = recently_changed_teamtrack_cases # Replicator ------------------------------------------------------------------ import regex, time error = 'p4dti replicator error' re = regex.compile('^Job \([a-z0-9]+\) created.$') # log(message, priority) does something appropriate with the message. def log(message, priority = None): print message # poll(t) polls the DT server and handles issues that have changed since # time t (seconds since 1970-01-01 00:00:00 UTC). def poll(t): log('Polling DT server for issues changed since %s UTC' % time.asctime(time.gmtime(t))) issues = recently_changed_dt_issues(t, replicator_id) log('%d issues have changed' % len(issues)) for issue in issues: # Replicate the issue to a p4 job. job = transform_dt_to_p4(issue, p4_default_fields, replicator_id) log('Transformed issue to %s' % `job`) results = p4.run(replicator_id, p4_port, p4_user, p4_client, 'job -i', [job]) # Did it work? if (len(results) == 0): raise error, 'No results from p4' elif (results[0]['code'] == 'error'): raise error, ('p4 error: %s' % results[0]['data']) else: log('p4 returned %s' % `results`) def replicator(): last_poll = 0 while 1==1: t = last_poll - poll_extra_window if (t < 0): t = 0 last_poll = time.time() poll(t) time.sleep(poll_period)