Managing references

I thought more about how the proposed methods would be used and here is what makes sense to me.

When an object is read from a forge (Get), it contains references to other objects. The GetReferences method returns all these references so that they can be stored in memory and used later, for instance when mirroring. The references may be relative to the object they contain (for instance when they are about a user) or absolute (for instance when they are about an issue that exists in another project). The SetReferences will walk the forge hierarchy to store the reference where it belongs.

When mirroring, an object is Get and SetReferences(GetReferences()). But the identifiers (issue number for instance) it contains are meaningful in the context of the originating forge: they need to be translated into the corresponding identifiers in the destination forge.

The first time around, these identifiers do not exist and should be set to 0 because the object will be created. The identifiers created when the object is created in the destination forge are collected and stored in a map in the originating forge. When the originating forge is F3, they are stored in a _identifiers.json file.

The second time around the identifiers map returned by GetIDMap (which reads from _identifiers.json when the originating forge is F3) are used to substitute the identifiers from the originating forge before the object is upsert in the destination forge. This is required for the object identifier itself but also for all the references it contains. For mirroring, the object from the originating forge is transformed into the F3 in memory representation and contains the identifiers relative to the originating forge. The RemapReferences function is responsible for modifying the F3 in memory representation (and not the originating forge objects) using the relevant identifier map for each of them. The modified F3 in memory representation is then given in argument to Upsert: all its references are now relative to the destination forge.

The order in which objects are inserted matters. If an object is inserted after all the objects it references, RemapReferences will be able to remap all identifiers effectively. To guarantee that order, mirroring is required to first mirror all the references before mirroring the object. Note that there may be circular references but they only happen when extracted from a text (for instance an issue comment can reference an issue comment that has a back reference to the same comment) but avoid them can be left for later.