Subject: Re: [PATCH v2 0/8] Clarify commit-graph and grafts/replace/shallow incompatibilities

From: Derrick Stolee <[email-masked]>
Date: Mon, 20 Aug 2018 15:54:25 -0400

On 8/20/2018 3:37 PM, Stefan Beller wrote:
> On Mon, Aug 20, 2018 at 11:24 AM Derrick Stolee <[email-masked]> wrote:
>> One unresolved issue with the commit-graph feature is that it can cause
>> issues when combined with replace objects, commit grafts, or shallow
>> clones. These are not 100% incompatible, as one could be reasonably
>> successful writing a commit-graph after replacing some objects and not
>> have issues. The problems happen when commits that are already in the
>> commit-graph file are replaced, or when git is run with the
>> `--no-replace-objects` option; this can cause incorrect parents or
>> incorrect generation numbers. Similar things occur with commit grafts
>> and shallow clones, especially when running `git fetch --unshallow` in a
>> shallow repo.
>>
>> Instead of trying (and probably failing) to make these features work
>> together, default to making the commit-graph feature unavailable in these
>> situations. Create a new method 'commit_graph_compatible(r)' that checks
>> if the repository 'r' has any of these features enabled.
>>
>> CHANGES IN V2:
>>
>> * The first two commits regarding the ref iterators are unchanged, despite
>>    a lot of discussion on the subject [1].
>>
>> * I included Peff's changes in jk/core-use-replace-refs, changing the base
>>    commit for the series to 1689c22c1c328e9135ed51458e9f9a5d224c5057 (the merge
>>    that brought that topic into 'msater').
>>
>> * I fixed the tests for the interactions with the graft feature.
>>
>> Because of the change of base, it is hard to provide a side-by-side diff
>> from v1.
>>
>> Thanks,
>> -Stolee
>>
>> [1] https://public-inbox.org/git/CAGZ79kZ3PzqpGzXWcmxjzi98gA+LT2MBOf8KaA89hOa-Qig=[email-masked]/
>>      Stefan's response recommending we keep the first two commits.
>>
> After reviewing my own patches, I flipped again (Sorry!) and would
> rather not see my patches be merged, but the very original solution
> by you, that you proposed at [1]. That said, I will not insist on it, and
> if this is merged as is, we can fix it up later.
>
> With that said, I just read through the remaining patches, I think
> they are a valuable addition to Git and could be merged as-is.
>
> [1] https://github.com/gitgitgadget/git/pull/11/commits/300db80140dacc927db0d46c804ca0ef4dcc1be1
>
> Thanks,
> Stefan

Just to keep things on-list as possible, here is the patch for the 
commit linked above. It would replace patches 1 & 2 from this series.

Junio: I can send a v3 that includes this commit if you need it, or if 
there are other edits to be made in this series.

commit 300db80140dacc927db0d46c804ca0ef4dcc1be1
Author: Derrick Stolee <[email-masked]>
Date:   Fri Jul 20 15:39:06 2018 -0400

     replace-objects: use arbitrary repositories

     This is the smallest possible change that makes prepare_replace_objects
     work properly with arbitrary repositories. By supplying the repository
     as the cb_data, we do not need to modify any code in the ref iterator
     logic. We will likely want to do a full replacement of the ref iterator
     logic to provide a repository struct as a concrete parameter.

     Signed-off-by: Derrick Stolee <[email-masked]>

diff --git a/replace-object.c b/replace-object.c
index 801b5c1678..e99fcd1ff6 100644
--- a/replace-object.c
+++ b/replace-object.c
@@ -14,6 +14,7 @@ static int register_replace_ref(const char *refname,
         const char *slash = strrchr(refname, '/');
         const char *hash = slash ? slash + 1 : refname;
         struct replace_object *repl_obj = xmalloc(sizeof(*repl_obj));
+       struct repository *r = (struct repository *)cb_data;

         if (get_oid_hex(hash, &repl_obj->original.oid)) {
                 free(repl_obj);
@@ -25,7 +26,7 @@ static int register_replace_ref(const char *refname,
         oidcpy(&repl_obj->replacement, oid);

         /* Register new object */
-       if (oidmap_put(the_repository->objects->replace_map, repl_obj))
+       if (oidmap_put(r->objects->replace_map, repl_obj))
                 die("duplicate replace ref: %s", refname);

         return 0;
@@ -40,7 +41,7 @@ static void prepare_replace_object(struct repository *r)
                 xmalloc(sizeof(*r->objects->replace_map));
         oidmap_init(r->objects->replace_map, 0);

-       for_each_replace_ref(r, register_replace_ref, NULL);
+       for_each_replace_ref(r, register_replace_ref, r);
  }

  /* We allow "recursive" replacement. Only within reason, though */