notes on applying a merge changeset
Denys Duchier
duchier at ps.uni-sb.de
Thu Dec 29 01:55:19 GMT 2005
These notes are primarily for my own benefit, but I'd appreciate
feedback.
KINDS OF CHANGES IN A CHANGESET ENTRY
-------------------------------------
Each changeset entry stipulates 3 kinds of changes:
* what is changed in the topology (the tree structure)
* what is changed in the contents
* what is changed in the metadata
In each case, there are four possible kinds:
* delete
* create
* modify
* keep
Actually, in order to support changing the type of an entry, we may
want to admit a 4th value "typechange" as a new kind of "contents"
change.
topology_change_kind:
* delete: the id is in src but not in dst
* create: the id is in dst but not in src
* modify: the id is in both, and the entry is moved and/or renamed
* keep : the id is in both, and the entry is neither moved nor renamed
contents_change_kind:
* delete: there is contents associated with id in src, but not in dst
* create: there is contents associated with id in dst, but not is src
* modify: id is associated with different contents in src and dst
* keep : id is associated with the same contents in src and dst
metadata_change_kind:
* delete: there is metadata associated with id in src, but not in dst
* create: there is metadata associated with id in dst, but not in src
* modify: id is associated with different metadata in src and dst
* keep : id is associated with the same metadata in src and dst
change_kinds:
returns a triple of strings (topology,contents,metadata) describing
the changes in the respective dimensions.
PHASES OF APPLICATION OF A CHANGESET
------------------------------------
Application of a merge changeset happens in 2 phases:
* apply_into_limbo
* apply_from_limbo
For each entry:
T,C,M = self.change_kinds()
APPLY_INTO_LIMBO:
~~~~~~~~~~~~~~~~~
This phase considers changeset entries sorted bottom-up according to
the src tree (the this tree). For each entry:
if T=="delete": {DELETE ENTRY}
if C=="delete": {DELETE FILE (if present)}
if T=="modify": {MOVE FILE (if present) AND ENTRY INTO LIMBO}
APPLY FROM LIMBO:
~~~~~~~~~~~~~~~~~
This phase considers changeset entries sorted top-down according to
the dst tree (the other tree). For each entry:
if T=="modify": {MOVE FILE (if present) AND ENTRY FROM LIMBO}
if T=="create": {INSERT ENTRY}
if C=="create": {CREATE FILE IN PLACE}
if C=="modify": {MODIFY FILE IN PLACE / OR CREATE IF NOT PRESENT}
if M=="create": {APPLY TO ENTRY, ALSO TO FILE IF PRESENT}
if M=="modify": {APPLY TO ENTRY, ALSO TO FILE IF PRESENT}
There is currently code that attempts to preserve uncommited changes
in metadata (the exec flag). I think that all uncommited changes
should be "preserved". In other words: we should be merging into a
"working tree", not merely into a pristine checkout of a committed
revision.
I do not see why merging into a tree with uncommitted changes should
be ruled out. I understand that it may be desirable to warn the user
about possibly unintended consequences, but I don't think that the UI
should be dictating the library API.
Cheers,
--Denys
More information about the bazaar
mailing list