State of the F3 implementation

A few notes from messages posted in the chatroom.

The migration API in Gitea is just one interface, which is simple. But the structure of a forge is hierarchical and this leads to an implementation that is complex because it tries to flatten the hierarchy. Which leads to contorted code, for instance when dealing with a review within a pull request within a project. Or an asset within a release within a project. Or a reaction within a comment within an issue within a project.

With the refactor the migration will walk the hierarchy instead, starting with ForgeProject, looping on the PullRequests data member, down to each ForgePullRequest, looping on the Comments data member, down to each PullRequestComment.

and the concrete implementation, for a Gitea comments implements List/Get/Put/Delete with almost no boilerplate code, which should help with maintenance.

and most importantly, the implementor for a given forge does not have to deal with generics whatsoever. There is quite a bit of generic code in the refactor, which helps keep everything as DRY as humanly possible. It is difficult to read for someone who’s not used to it but contained in a few files (such as F3 beans). The refactor also helps in this area: the type parameters in the previous implementation grew as new types were added and that led to very hairy code, extremely difficult to maintain, refactor or work with.

1 Like

The mirror logic is implemented, as follows:

func (o *Container) Mirror(other ContainerInterface) {
	for _, otherElement := range other.List() {
		element := o.Upsert(other.ToFormat(otherElement))

And each container is responsible for calling the Mirror method on each of its data members, for instance Issues do this:

func (o *ForgeIssue) Mirror(other common.ContainerElementInterface) {
	c := other.(*ForgeIssue)

At the highest level, a F3 instance is mirrored from a Gitea instance like so:

1 Like