Lepiter Iceberg Integration Model
This pages provides details about how Lepiter is integrated with Iceberg.
Basic Model
We start from an Iceberg repository.
icebergRepository := IceRepository registry detect: [ :each | each name = 'test-repo-1' ].
The iceberg repository gets wrapped in a dedicated repository that is Lepiter-aware.
gtIcebergRepository := GtGitRepository fromIcebergRepository: icebergRepository.
The way the repository is aware of Lepiter is using a dedicated working copy, which is an instance of GtLepiterWorkingCopy
.
lepiterWorkingCopy := gtIcebergRepository lepiterWorkingCopy.
This working copy wraps a IceRepository
and its IceWorkingCopy
and adds extra functionality to work with Lepiter. For example, it knows how to return the list of Lepiter databases from the repository currently registered with the default instance of LeDatabasesRegistry
lepiterWorkingCopy databases
Creating diffs
We can directly as the working copy to do a diff with the reference commit. This diff contains both changes to Lepiter files from disk, and code changes done inside the image.
lepiterWorkingCopy diffToReferenceCommit.
We can also create the diff step by step. First we can define the source and the target commitish.
sourceCommitish := lepiterWorkingCopy. targetCommitish := lepiterWorkingCopy referenceCommit
The first step is to detect what types of changes are in the repo. For Lepiter we can have a GtLepiterLocalDatabaseChange
that indicates that a change was done in that database.
changes := sourceCommitish changesTo: targetCommitish.
This computes both code changes and Lepiter changes.
sourceCommitish lepiterChangesTo: targetCommitish.
sourceCommitish codeChangesTo: targetCommitish.
These changes are passed in IceDiff>>#buildForChanges:
to a IceChangeImporter
visitor.
diff := IceDiff from: sourceCommitish to: targetCommitish.
Steps for performing the diff
diff := IceDiff new sourceVersion: sourceCommitish; targetVersion: targetCommitish; yourself
leftTree := IceNode value: IceRootDefinition new. changes do: [ :aChange | aChange accept: (IceChangeImporter new version: sourceCommitish; diff: diff; parentNode: leftTree; yourself) ]. leftTree
rightTree := IceNode value: IceRootDefinition new. changes do: [ :change | change accept: (IceChangeImporter new version: targetCommitish; diff: diff; parentNode: rightTree; yourself) ]. rightTree
mergedTree := diff mergedTreeOf: leftTree with: rightTree.
tree := mergedTree select: [ :operation | operation hasChanges ].
diff instVarNamed: #tree put: tree. diff instVarNamed: #mergedTree put: mergedTree. diff
Commiting
icebergRepository index
icebergRepository index updateDiskWorkingCopy: diff
icebergRepository index updateIndex: diff
icebergRepository index addToGitIndex.
newCommit := icebergRepository commitIndexWithMessage: 'Example commit' andParents: (workingCopy workingCopyState referenceCommits reject: [ :each | each isNoCommit ]).
Swiching branches
targetBranch := icebergRepository branchNamed: 'master'. targetBranch checkout: ((GtGitIceCheckoutAlreadyLoadedContent new lepiterWorkingCopy: lepiterWorkingCopy) committish: targetBranch; yourself)
Merging
Merging follows the same steps as in Iceberg.
otherBranch := icebergRepository branchNamed: 'main'.
mergeAction := GtGitIceMerge new repository: gtIcebergRepository; mergeCommit: otherBranch commit; yourself
mergeAction calculateChanges
mergeTree := mergeAction instVarNamed: #mergeTree
gtIcebergRepository lepiterWorkingCopy loadLepiterChangesInWorkingCopyFrom: mergeTree
At this step the merge tree contains changes for all files between the two branches, including code and lepiter files. At this moment this tree is not Lepiter aware. So changes to Lepiter pages appear just as changes to files.
Step-by-step merge
leftCommit := icebergRepository headCommit. mergeCommit := otherBranch commit.
commonAncestor := leftCommit commonAncestorWith: mergeCommit.
Next we create diffs with the common ancestor.
sourceDiff := mergeCommit gtDiffTo: commonAncestor.
When creating this diff we compute the set of changes between two commits. These are going to be a list of IceChange
mergeCommit changesTo: commonAncestor
targetDiff := leftCommit diffTo: commonAncestor.