Re: [PATCH RFC] parse_object: pass on the original sha1, not the replaced one
- From
Christian Couder <chriscool@tuxfamily.org>
- Date
- Aug 14, 2010, 02:03 UTC
- Message-ID
- <201008140403.33164.chriscool@tuxfamily.org>
- In-Reply-To
- <AANLkTinmJ0=VxFAaCXNjB2WAiPYHq3jXmRnzVoEiw_-f@mail.gmail.com>
On Friday 13 August 2010 11:02:40 Nguyen Thai Ngoc Duy wrote:
Show 31 quoted lines
> On Fri, Aug 13, 2010 at 1:59 PM, Christian Couder
>
> <chriscool@tuxfamily.org> wrote:
> > On Saturday 07 August 2010 06:03:05 Nguyen Thai Ngoc Duy wrote:
> >> On Thu, Aug 5, 2010 at 9:41 PM, Christian Couder
> >>
> >> <chriscool@tuxfamily.org> wrote:
> >> > It looks like parse_commit() is buggy regarding replaced objects. But
> >> > I am not sure how it should be fixed.
> >>
> >> It could be fixed the same way you did with parse_object(): replace
> >> read_sha1_file() with read_sha1_file_repl(). You would also need to
> >> fix parse_tree() and parse_tag(). But..
> >>
> >> > Anyway if you use parse_object(), then you don't need parse_commit().
> >> > So if possible you should use parse_object() instead of both
> >> > lookup_commit() and parse_commit().
> >>
> >> That's how those functions are used. For example, in
> >> traverse_commit_list(), lookup_*() may be called and uninteresting
> >> objects marked UNINTERESTING. Later on in process_{tree,blob,tag},
> >> parse_* may be called if their content is interesting.
> >>
> >> To me, the fix above will leave a gap when object->sha1 is the
> >> original sha1, until parse_*() is called. It just does not sound good.
> >
> > What do you think about adding a parse_commit_repl() function like the
> > patch below and then using it instead of parse_commit()?
>
> How do you plan to use this new function? #define parse_commit(c)
> parse_commit_repl(c) or use the new function explictly when needed?We have to use the new function explicitly instead of parse_commit() but I think in most cases we just need to change parse_commit(stuff) into parse_commit_repl(&stuff) and it will work.
> You are going to need parse_tree_repl() too
Yes, probably, I did not look at that yet.
> unless you declare > tree/blob replacement is not supported and make git-replace refuse > blob/tree replacement.
I think they should be supported as much as possible in the long run but it is not as important as supporting commits.
> Another thing to address is, there will be a duration between > lookup_commit() and parse_commit_repl(), where object.sha1 is the > original one. If it is saved elsewhere, troubles are ahead.
Yes, parse_commit_repl() may not be the only solution needed in some cases but I think it is good enough in most cases.
Show 39 quoted lines
> > ------- >8 ---------------------------------------------------
> >
> > diff --git a/commit.c b/commit.c
> > index 652c1ba..183a735 100644
> > --- a/commit.c
> > +++ b/commit.c
> > @@ -316,6 +316,50 @@ int parse_commit(struct commit *item)
> > return ret;
> > }
> >
> > +int parse_commit_repl(struct commit **commit)
> > +{
> > + enum object_type type;
> > + void *buffer;
> > + unsigned long size;
> > + int ret;
> > + const unsigned char *repl;
> > + struct commit *item = *commit;
> > +
> > + if (!item)
> > + return -1;
> > + if (item->object.parsed)
> > + return 0;
> > + buffer = read_sha1_file_repl(item->object.sha1, &type, &size,
> > &repl); + if (!buffer)
> > + return error("Could not read %s",
> > + sha1_to_hex(item->object.sha1));
> > +
> > + if (item->object.sha1 != repl) {
> > + struct commit *repl_item = lookup_commit(repl);
> > + if (!repl_item) {
> > + free(buffer);
> > + return error("Bad replacement %s for commit %s",
> > + sha1_to_hex(repl),
> > + sha1_to_hex(item->object.sha1));
> > + }
>
> You need to use lookup_object() instead here. lookup_commit() wil
> create new object if "repl" is not found.We are inside the "if (item->object.sha1 != repl)" block, so we know that we will have to do "*commit = repl_item" with a repl_item that is different from item. So we have to create the repl_item commit if it doesn't exist.
Thanks, Christian.