#!/usr/bin/python # processes the Perforce Journal entries for keeping the meta-data # in sync with a special meta-data location in the depot. import Journal, listener, cutil, p4util, Setup # Field 6 value maps for db.revcx ADD_FILE = 0 EDIT_FILE = 1 DELETE_FILE = 2 INTEGRATE_FILE = 3 # integrate for add only? does this apply for other types? class ArchiveMetaChanges(listener.Listener): ''' Read changes to the Perforce meta-data, and update the depot files accordingly. Note that, with the spec repository, this is no longer needed. ''' def __init__(self): pass def isHandled(self, obj): return False def listen(self, obj): pass def noData(self, hadData): ''' Don't do anything on a no-data section. ''' pass def stoppedLoop(self): ''' No special code for ending the loop. ''' pass class RetrieveMetaChanges(listener.Listener): ''' Take note of depot meta-data files, and update the Perforce meta-data when those files change. Settings are stored in Setup.py, under: Setup.METADATASYNC ''' def __init__(self): pass def isHandled(self, obj): # Must be an update to the repository to push this change to # the P4 meta-data. # as far as I can tell, for db.revcx, the fields are: # 0: pv (always insert) # 1: 0 (version of the type of operation) # 2: db.revcx (database to update) # 3: XXX (changelist number) # 4: XXX (depot file to update) # 5: R (revision of the new file) # 6: M (type of change: see above) if len(obj.fields) > 5 \ and obj.fields[0] == 'pv' \ and obj.fields[2] == 'db.revcx': for path in Setup.METADATASYNC.updateP4.values(): if obj.fields[4].startswith(path): return True return False def listen(self, obj): for mdt, path in Setup.METADATASYNC.updateP4.items(): if obj.fields[4].startswith(path): self._processMetaData(mdt, obj.fields[4], obj.fields[6]) def noData(self, hadData): ''' Don't do anything on a no-data section. ''' pass def stoppedLoop(self): ''' No special code for ending the loop. ''' pass def _processMetaData(self, metaType, metaFile, operationType): # TODO: make this more dynamic so that users can, in the config file, # select different handlers for each meta-data type. That is, you could # have a custom protect package that assembles pieces of files to create # the real protect contents. if metaType == 'groups': if operationType == DELETE_FILE: self._groupDelete(metaFile) # edits, adds, and integrations should all act the same # does integrate a delete have the same code? else: self._groupUpdate(metaFile) elif metaType == 'labels': pass elif metaType == 'branches': pass elif metaType == 'clients': pass elif metaType == 'typemap': pass elif metaType == 'triggers': pass elif metaType == 'protect': pass else: cutil.log(cutil.ERR, ["Unsupported meta-data type: ", metaType]) def _groupUpdate(self, metaFile): ''' Update Perforce meta-data for the group described in this file. The steps simulate: p4 print -q [metaFile]#head | p4 group -i ''' p4c = p4util.createP4() spec = p4c.retrieve(metaFile) if spec is None: cutil.log(cutil.ERR, ["Could not retrieve depot file ", metaFile]) return if not p4c.updateGroup(spec): cutil.log(cutil.ERR, ["Could not update group from file ", metaFile]) def _groupDelete(self, metaFile): ''' Remove the group from Perforce meta-data. Not currently implemented. This should be a manual process. ''' cutil.log(cutil.INFO, ["Ignoring group delete for meta file ", metaFile]) pass