git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: How to check new commit availability without full fetch?

From
Nicolas Pitre <nico@fluxnic.net>
Date
Jan 11, 2010, 20:52 UTC
Message-ID
<alpine.LFD.2.00.1001111501360.10143@xanadu.home>
In-Reply-To
<7vmy0kjvms.fsf@alter.siamese.dyndns.org>
On Mon, 11 Jan 2010, Junio C Hamano wrote:
Show 24 quoted lines
> Ahh, you are right.  It walks from objects the remote side told us are at
> the tip, and stops at what we know are complete (i.e. reachable from our
> tip of objects); immediately after --dry-run slurped objects, the next
> fetch will prove everything is locally available and complete before going
> over the network.
> 
> But either I am very confused or the use of fields from "struct ref" is
> unintuitive in this codepath.
> 
> Why does it feed ref->old_sha1?  We are feeding _their_ tip commits to:
> 
>     rev-list --objects --stdin --not --all
> 
> and expecting it to report failure when some of their tip commits lead to
> what we don't have yet.  The reason why we have old_sha1[] vs new_sha1[]
> is because we want to report what changed from what, and also to protect
> us from simultaneous updates by doing compare-and-swap using the value we
> read from our refs when we started in old_sha1[], so I would have expected
> that ref_map elements would have _their_ commits on the new_sha1[] side,
> but apparently that is not what is happening, and it has been this way for
> a long time.  The use of old_sha1[] came from 4191c35 (git-fetch: avoid
> local fetching from alternate (again), 2007-11-11), so it is a lot more
> likely that I am confused than the code is wrong and nobody noticed so
> far.

Very confusing indeed. I first discovered about quickfetch() myself when I fixed shallow clone leading to commit 86386829.

If old_sha1[] was our refs then quickfetch() would always succeed and we'd never fetch anything.

> What am I missing?

Digging a bit, it looks like get_remote_heads() is storing the remote's heads into old_sha1. And so is performed in get_refs_from_bundle(), and in insert_packed_refs() from get_refs_via_rsync(), etc.

Looking at the struct ref definition, we can see:
struct ref {
        struct ref *next;
        unsigned char old_sha1[20];
        unsigned char new_sha1[20];
        [...]
        struct ref *peer_ref; /* when renaming */
        [...]
};

And apparently store_updated_refs() ends up using that peer_ref like this:

        for (rm = ref_map; rm; rm = rm->next) {
                struct ref *ref = NULL;
                if (rm->peer_ref) {
                        ref = xcalloc(1, sizeof(*ref) + strlen(rm->peer_ref->name) + 1);
                        strcpy(ref->name, rm->peer_ref->name);
                        hashcpy(ref->old_sha1, rm->peer_ref->old_sha1);
                        hashcpy(ref->new_sha1, rm->old_sha1);
                        ref->force = rm->peer_ref->force;
                }

So.... Doesn't this all look like a total mess of needless (and even leaked in this case) allocations and duplications, besides being completely unintuitive? Both hashcpy() above certainly throw my sense of logic aside...

Nicolas
Previous: Junio C HamanoNext: Andreas Schwab
Message 19 of 20 in “How to check new commit availability without full fetch?”
  1. Leo RazoumovJan 10, 2010
  2. Nicolas PitreJan 10, 2010
  3. Junio C HamanoJan 10, 2010
  4. Nicolas PitreJan 10, 2010
  5. Leo RazoumovJan 11, 2010
  6. Tay Ray ChuanJan 11, 2010
  7. Junio C HamanoJan 11, 2010
  8. Michael WittenJan 11, 2010
  9. Junio C HamanoJan 11, 2010
  10. Nicolas PitreJan 11, 2010
  11. Leo RazoumovJan 11, 2010
  12. Nicolas PitreJan 11, 2010
  13. Leo RazoumovJan 11, 2010
  14. Dmitry PotapovJan 11, 2010
  15. Robin RosenbergJan 11, 2010
  16. Junio C HamanoJan 11, 2010
  17. Nicolas PitreJan 11, 2010
  18. Junio C HamanoJan 11, 2010
  19. Nicolas PitreJan 11, 2010
  20. Andreas SchwabJan 11, 2010

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.