X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?a=blobdiff_plain;ds=sidebyside;f=DESIGN;h=57f3191e23f1282d5b76fc75dd9084128071a52a;hb=3cef5f54091fb536fb77af9a33838a631fbf6738;hp=b7c677d51e5bd7c7e943214739cbae8cd135bd46;hpb=f188259a4c10646773fe0bbde14aadd419f341c9;p=topbloke.git diff --git a/DESIGN b/DESIGN index b7c677d..57f3191 100644 --- a/DESIGN +++ b/DESIGN @@ -17,9 +17,10 @@ Basic update algorithm: ii. For each source in the best order, do the following merge: (Our base has sources: - the branch for each direct dep - - the remote base) + - the remote base + - the topgit base, if this is a topgit import) - Find the common ancestor. + Find the (latest) common ancestor. Check for unwanted dependency removals. An unwanted dependency removal is @@ -30,14 +31,23 @@ Basic update algorithm: which have already occurred on our base; these will be reverted later.) For each unwanted dependency removal (ie for each such - branch), find the most recent commit which unwantedly removed - the dep from the source's actual included deps ("relevant - unwanted removal commit"). (Abort if any such commit is a - merge.) Select the earliest relevant unwanted removal commit - (from the set of relevant unwanted removal commits - corresponding to the unwanted dependency removals). - Merge from the ancestor of the relevant unwanted removal commit. - Merge from the relevant unwanted removal commit using -s ours. + branch), search as follows: + * An "unwanted removal commit" is a non-merge commit in the + history of the source, which removes the dep from the + actual included deps. + * But the search stops at any point where we would have to + traverse a commit where .topbloke/deps is empty (which + stops us looking into the hitory of non-topbloke-controlled + branches). This can be done with git-rev-list + --remove-empty. + * The the relevant unwanted removal commit for that dep is + the most recent unwanted removal commit, as defined. + Select the unwantedly removed dep whose relevant unwanted + removal commit is the earliest. Merge from the ancestor of + that relevant unwanted removal commit. Merge from the relevant + unwanted removal commit using -s ours. + + Now continue to the next unwanted dependency removal. (The purpose of this, and the result, is that the unwanted dependency removal has gone away. Doing things in this order @@ -48,8 +58,6 @@ Basic update algorithm: of a patch affected by an unwanted removal will benefit from that client's resolution of the situation.) - Now continue to the next unwanted dependency removal. - If there are no (more) unwanted dependency removals, merge from the source. @@ -79,12 +87,14 @@ Basic update algorithm: * Attempt to apply the appropriate diff to add (resp. remove) the contents of the relevant patch (adjusted appropriately for metadata, XXX??? particularly the actual inclusion list) + XXX if we want to add a dep we need to update the dep first * Go round again looking for another discrepancy. 3. Update our branch. Our branch has sources: - our base - the remote for our branch + - the topgit branch, if this is a topgit import For each source in the best order, do the merge. Double-check the actual dependency inclusions. In @@ -179,3 +189,52 @@ Unnecessary - instead, deal with leaf patches Operations like "go up the stack", goes towards leaf. Hopefully unique. "Down" the stack, uses a "conventional" linearisation Stack reordering op ? auto adjust deps + + +When merging, we need to DTRT with our metadata. +Do this by running write-tree/read-tree etc. ourselves ? +For a source we're merging from, we make a version where the +metadata we shouldn't be merging is removed ? +Or something. +Have discovered that specifying a custom merge driver for a file does +not have any effect if the three-way-merge looks trivial based +on looking at the file contents - at least, if you use git-merge. + +Only thing which knows how to do all the gitattributes stuff and +conflict markers and what have you is git-merge. (git-merge-tree does +too but the output format is unsuitable.) "git-merge-index +... git-merge-one-file" does not honour the merge drivers and is, +contrary to what the git docs seem to suggest but don't actually +state, not actualy used by git-merge. + +OK so here is a plan: + Use git-merge --no-commit + Perhaps on a HEAD, and/or against a tree, which have been massaged + to make the metadata suitable as input. + Filtering out the "merge was successful but we aren't committing" + message. Use a single pipe for stdout/stderr to get interleaving + right; the message from git-merge is not i18n'd. + Afterwards we: + Check for merge success in the index and compare to exit status + from git-merge (which is 1 if the merge failed). + Adjust the metadata. + Print appropriate big fat warnings if we have merge conflicts in our + metadata. + Commit, adjusting the parents of the new commit to the original + parents if we made the merge with special massaged parents. + We may still need to have custom merge drivers for metadata. + + +Strategies for each metadata file merge: + + in base/tip same patch's tip dep -> base base -> tip + + msg T textual merge rm from src not in src + deps T list merge rm from src not in src + deleted T std existence merge rm from src not in src + patch- BT must be same rm from src must be same + topgit- T must be same rm from src not in src + [^+]*- ?? textual merge rm from src rm from src + +included BT list merge rm from non-tb src list merge + +*- ?? textual merge rm from non-tb src textual merge + *[^-] ?? die, aborting all ops, if found in any tb src or branch