<feed xmlns='http://www.w3.org/2005/Atom'>
<title>git/refs.c, branch v1.8.2.2</title>
<subtitle>Mirror of https://git.kernel.org/pub/scm/git/git.git/
</subtitle>
<id>https://git.shady.money/git/atom?h=v1.8.2.2</id>
<link rel='self' href='https://git.shady.money/git/atom?h=v1.8.2.2'/>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/'/>
<updated>2013-04-03T16:18:01Z</updated>
<entry>
<title>Sync with 1.8.1 maintenance track</title>
<updated>2013-04-03T16:18:01Z</updated>
<author>
<name>Junio C Hamano</name>
<email>gitster@pobox.com</email>
</author>
<published>2013-04-03T16:18:01Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=92e0d916326de103e463f9ffcfcd99ec1f3a9dc0'/>
<id>urn:sha1:92e0d916326de103e463f9ffcfcd99ec1f3a9dc0</id>
<content type='text'>
* maint-1.8.1:
  Start preparing for 1.8.1.6
  git-tag(1): we tag HEAD by default
  Fix revision walk for commits with the same dates
  t2003: work around path mangling issue on Windows
  pack-refs: add fully-peeled trait
  pack-refs: write peeled entry for non-tags
  use parse_object_or_die instead of die("bad object")
  avoid segfaults on parse_object failure
  entry: fix filter lookup
  t2003: modernize style
  name-hash.c: fix endless loop with core.ignorecase=true
</content>
</entry>
<entry>
<title>Merge branch 'jk/fully-peeled-packed-ref' into maint-1.8.1</title>
<updated>2013-04-03T15:43:03Z</updated>
<author>
<name>Junio C Hamano</name>
<email>gitster@pobox.com</email>
</author>
<published>2013-04-03T15:43:03Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=f1ad05f3a524a8750533d8263ceb584a9e7ec573'/>
<id>urn:sha1:f1ad05f3a524a8750533d8263ceb584a9e7ec573</id>
<content type='text'>
* jk/fully-peeled-packed-ref:
  pack-refs: add fully-peeled trait
  pack-refs: write peeled entry for non-tags
  use parse_object_or_die instead of die("bad object")
  avoid segfaults on parse_object failure
</content>
</entry>
<entry>
<title>pack-refs: add fully-peeled trait</title>
<updated>2013-03-18T15:06:28Z</updated>
<author>
<name>Michael Haggerty</name>
<email>mhagger@alum.mit.edu</email>
</author>
<published>2013-03-18T11:37:32Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=c29c46fa2e21e608ce2e603649af5bf38e7969c2'/>
<id>urn:sha1:c29c46fa2e21e608ce2e603649af5bf38e7969c2</id>
<content type='text'>
Older versions of pack-refs did not write peel lines for
refs outside of refs/tags. This meant that on reading the
pack-refs file, we might set the REF_KNOWS_PEELED flag for
such a ref, even though we do not know anything about its
peeled value.

The previous commit updated the writer to always peel, no
matter what the ref is. That means that packed-refs files
written by newer versions of git are fine to be read by both
old and new versions of git. However, we still have the
problem of reading packed-refs files written by older
versions of git, or by other implementations which have not
yet learned the same trick.

The simplest fix would be to always unset the
REF_KNOWS_PEELED flag for refs outside of refs/tags that do
not have a peel line (if it has a peel line, we know it is
valid, but we cannot assume a missing peel line means
anything). But that loses an important optimization, as
upload-pack should not need to load the object pointed to by
refs/heads/foo to determine that it is not a tag.

Instead, we add a "fully-peeled" trait to the packed-refs
file. If it is set, we know that we can trust a missing peel
line to mean that a ref cannot be peeled. Otherwise, we fall
back to assuming nothing.

[commit message and tests by Jeff King &lt;peff@peff.net&gt;]

Signed-off-by: Michael Haggerty &lt;mhagger@alum.mit.edu&gt;
Signed-off-by: Jeff King &lt;peff@peff.net&gt;
Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>Merge branch 'jc/hidden-refs'</title>
<updated>2013-02-17T23:25:57Z</updated>
<author>
<name>Junio C Hamano</name>
<email>gitster@pobox.com</email>
</author>
<published>2013-02-17T23:25:57Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=ce735bf7fd66c6404e86e5a313f35abc0394b838'/>
<id>urn:sha1:ce735bf7fd66c6404e86e5a313f35abc0394b838</id>
<content type='text'>
Allow the server side to redact the refs/ namespace it shows to the
client.

Will merge to 'master'.

* jc/hidden-refs:
  upload/receive-pack: allow hiding ref hierarchies
  upload-pack: simplify request validation
  upload-pack: share more code
</content>
</entry>
<entry>
<title>upload/receive-pack: allow hiding ref hierarchies</title>
<updated>2013-02-07T21:48:47Z</updated>
<author>
<name>Junio C Hamano</name>
<email>gitster@pobox.com</email>
</author>
<published>2013-01-19T00:08:30Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=daebaa78137d59693a808c1f0bdec0ecb40fc12e'/>
<id>urn:sha1:daebaa78137d59693a808c1f0bdec0ecb40fc12e</id>
<content type='text'>
A repository may have refs that are only used for its internal
bookkeeping purposes that should not be exposed to the others that
come over the network.

Teach upload-pack to omit some refs from its initial advertisement
by paying attention to the uploadpack.hiderefs multi-valued
configuration variable.  Do the same to receive-pack via the
receive.hiderefs variable.  As a convenient short-hand, allow using
transfer.hiderefs to set the value to both of these variables.

Any ref that is under the hierarchies listed on the value of these
variable is excluded from responses to requests made by "ls-remote",
"fetch", etc. (for upload-pack) and "push" (for receive-pack).

Because these hidden refs do not count as OUR_REF, an attempt to
fetch objects at the tip of them will be rejected, and because these
refs do not get advertised, "git push :" will not see local branches
that have the same name as them as "matching" ones to be sent.

An attempt to update/delete these hidden refs with an explicit
refspec, e.g. "git push origin :refs/hidden/22", is rejected.  This
is not a new restriction.  To the pusher, it would appear that there
is no such ref, so its push request will conclude with "Now that I
sent you all the data, it is time for you to update the refs.  I saw
that the ref did not exist when I started pushing, and I want the
result to point at this commit".  The receiving end will apply the
compare-and-swap rule to this request and rejects the push with
"Well, your update request conflicts with somebody else; I see there
is such a ref.", which is the right thing to do. Otherwise a push to
a hidden ref will always be "the last one wins", which is not a good
default.

Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>Merge branch 'rs/clarify-entry-cmp-sslice'</title>
<updated>2013-01-24T05:19:06Z</updated>
<author>
<name>Junio C Hamano</name>
<email>gitster@pobox.com</email>
</author>
<published>2013-01-24T05:19:06Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=f12e49ae877ad0644b9b9939b7cb742da98691d2'/>
<id>urn:sha1:f12e49ae877ad0644b9b9939b7cb742da98691d2</id>
<content type='text'>
* rs/clarify-entry-cmp-sslice:
  refs: use strncmp() instead of strlen() and memcmp()
</content>
</entry>
<entry>
<title>refs: use strncmp() instead of strlen() and memcmp()</title>
<updated>2013-01-16T17:48:36Z</updated>
<author>
<name>René Scharfe</name>
<email>rene.scharfe@lsrfire.ath.cx</email>
</author>
<published>2013-01-16T01:08:16Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=c971ddfdcd319fb5cad95aa7047c54ebe6a22d1a'/>
<id>urn:sha1:c971ddfdcd319fb5cad95aa7047c54ebe6a22d1a</id>
<content type='text'>
Simplify ref_entry_cmp_sslice() by using strncmp() to compare the
length-limited key and a NUL-terminated entry.  While we're at it,
retain the const attribute of the input pointers.

Signed-off-by: Rene Scharfe &lt;rene.scharfe@lsrfire.ath.cx&gt;
Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>Merge branch 'jk/repack-ref-racefix' into maint</title>
<updated>2013-01-10T22:04:17Z</updated>
<author>
<name>Junio C Hamano</name>
<email>gitster@pobox.com</email>
</author>
<published>2013-01-10T22:04:17Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=f70eec840065ca598272979960073b1b50b5ad03'/>
<id>urn:sha1:f70eec840065ca598272979960073b1b50b5ad03</id>
<content type='text'>
* jk/repack-ref-racefix:
  refs: do not use cached refs in repack_without_ref
</content>
</entry>
<entry>
<title>Merge branch 'jk/repack-ref-racefix'</title>
<updated>2013-01-02T18:39:37Z</updated>
<author>
<name>Junio C Hamano</name>
<email>gitster@pobox.com</email>
</author>
<published>2013-01-02T18:39:36Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=229096a591cb1cd9b309feca0b786be0a0adbe04'/>
<id>urn:sha1:229096a591cb1cd9b309feca0b786be0a0adbe04</id>
<content type='text'>
"git pack-refs" that ran in parallel to another process that created
new refs had a nasty race.

* jk/repack-ref-racefix:
  refs: do not use cached refs in repack_without_ref
</content>
</entry>
<entry>
<title>refs: do not use cached refs in repack_without_ref</title>
<updated>2012-12-21T16:10:22Z</updated>
<author>
<name>Jeff King</name>
<email>peff@peff.net</email>
</author>
<published>2012-12-21T08:04:49Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=b3f1280ec740d8012d18e870a50a5ff76c4e3c42'/>
<id>urn:sha1:b3f1280ec740d8012d18e870a50a5ff76c4e3c42</id>
<content type='text'>
When we delete a ref that is packed, we rewrite the whole
packed-refs file and simply omit the ref that no longer
exists. However, we base the rewrite on whatever happens to
be in our refs cache, not what is necessarily on disk. That
opens us up to a race condition if another process is
simultaneously packing the refs, as we will overwrite their
newly-made pack-refs file with our potentially stale data,
losing commits.

You can demonstrate the race like this:

  # setup some repositories
  git init --bare parent &amp;&amp;
  (cd parent &amp;&amp; git config core.logallrefupdates true) &amp;&amp;
  git clone parent child &amp;&amp;
  (cd child &amp;&amp; git commit --allow-empty -m base)

  # in one terminal, repack the refs repeatedly
  cd parent &amp;&amp;
  while true; do
	git pack-refs --all
  done

  # in another terminal, simultaneously push updates to
  # master, and create and delete an unrelated ref
  cd child &amp;&amp;
  while true; do
	git push origin HEAD:newbranch &amp;&amp;
	git commit --allow-empty -m foo
	us=`git rev-parse master` &amp;&amp;
	git push origin master &amp;&amp;
	git push origin :newbranch &amp;&amp;
	them=`git --git-dir=../parent rev-parse master` &amp;&amp;
	if test "$them" != "$us"; then
		echo &gt;&amp;2 "$them" != "$us"
		exit 1
	fi
  done

In many cases the two processes will conflict over locking
the packed-refs file, and the deletion of newbranch will
simply fail.  But eventually you will hit the race, which
happens like this:

  1. We push a new commit to master. It is already packed
     (from the looping pack-refs call). We write the new
     value (let us call it B) to $GIT_DIR/refs/heads/master,
     but the old value (call it A) remains in the
     packed-refs file.

  2. We push the deletion of newbranch, spawning a
     receive-pack process. Receive-pack advertises all refs
     to the client, causing it to iterate over each ref; it
     caches the packed refs in memory, which points at the
     stale value A.

  3. Meanwhile, a separate pack-refs process is running. It
     runs to completion, updating the packed-refs file to
     point master at B, and deleting $GIT_DIR/refs/heads/master
     which also pointed at B.

  4. Back in the receive-pack process, we get the
     instruction to delete :newbranch. We take a lock on
     packed-refs (which works, as the other pack-refs
     process has already finished). We then rewrite the
     contents using the cached refs, which contain the stale
     value A.

The resulting packed-refs file points master once again at
A. The loose ref which would override it to point at B was
deleted (rightfully) in step 3. As a result, master now
points at A. The only trace that B ever existed in the
parent is in the reflog: the final entry will show master
moving from A to B, even though the ref still points at A
(so you can detect this race after the fact, because the
next reflog entry will move from A to C).

We can fix this by invalidating the packed-refs cache after
we have taken the lock. This means that we will re-read the
packed-refs file, and since we have the lock, we will be
sure that what we read will be atomically up-to-date when we
write (it may be out of date with respect to loose refs, but
that is OK, as loose refs take precedence).

Signed-off-by: Jeff King &lt;peff@peff.net&gt;
Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
</feed>
