<feed xmlns='http://www.w3.org/2005/Atom'>
<title>git/reachable.c, branch v2.6.2</title>
<subtitle>Mirror of https://git.kernel.org/pub/scm/git/git.git/
</subtitle>
<id>https://git.shady.money/git/atom?h=v2.6.2</id>
<link rel='self' href='https://git.shady.money/git/atom?h=v2.6.2'/>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/'/>
<updated>2015-05-25T19:19:34Z</updated>
<entry>
<title>add_one_ref(): rewrite to take an object_id argument</title>
<updated>2015-05-25T19:19:34Z</updated>
<author>
<name>Michael Haggerty</name>
<email>mhagger@alum.mit.edu</email>
</author>
<published>2015-05-25T18:39:00Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=635170f2bb34116441b562a93d3ce37ae4373ecc'/>
<id>urn:sha1:635170f2bb34116441b562a93d3ce37ae4373ecc</id>
<content type='text'>
Signed-off-by: Michael Haggerty &lt;mhagger@alum.mit.edu&gt;
Signed-off-by: brian m. carlson &lt;sandals@crustytoothpaste.net&gt;
Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>each_ref_fn: change to take an object_id parameter</title>
<updated>2015-05-25T19:19:27Z</updated>
<author>
<name>Michael Haggerty</name>
<email>mhagger@alum.mit.edu</email>
</author>
<published>2015-05-25T18:38:28Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=2b2a5be394bc67bed86bc009195c664dca740bd6'/>
<id>urn:sha1:2b2a5be394bc67bed86bc009195c664dca740bd6</id>
<content type='text'>
Change typedef each_ref_fn to take a "const struct object_id *oid"
parameter instead of "const unsigned char *sha1".

To aid this transition, implement an adapter that can be used to wrap
old-style functions matching the old typedef, which is now called
"each_ref_sha1_fn"), and make such functions callable via the new
interface. This requires the old function and its cb_data to be
wrapped in a "struct each_ref_fn_sha1_adapter", and that object to be
used as the cb_data for an adapter function, each_ref_fn_adapter().

This is an enormous diff, but most of it consists of simple,
mechanical changes to the sites that call any of the "for_each_ref"
family of functions. Subsequent to this change, the call sites can be
rewritten one by one to use the new interface.

Signed-off-by: Michael Haggerty &lt;mhagger@alum.mit.edu&gt;
Signed-off-by: brian m. carlson &lt;sandals@crustytoothpaste.net&gt;
Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>reachable: only mark local objects as recent</title>
<updated>2015-04-20T20:09:27Z</updated>
<author>
<name>Jeff King</name>
<email>peff@peff.net</email>
</author>
<published>2015-03-27T11:32:41Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=1385bb7ba39128de0a5bc4ff6e8a5ad03fc49205'/>
<id>urn:sha1:1385bb7ba39128de0a5bc4ff6e8a5ad03fc49205</id>
<content type='text'>
When pruning and repacking a repository that has an
alternate object store configured, we may traverse a large
number of objects in the alternate. This serves no purpose,
and may be expensive to do. A longer explanation is below.

Commits d3038d2 and abcb865 taught prune and pack-objects
(respectively) to treat "recent" objects as tips for
reachability, so that we keep whole chunks of history. They
built on the object traversal in 660c889 (sha1_file: add
for_each iterators for loose and packed objects,
2014-10-15), which covers both local and alternate objects.

In both cases, covering alternate objects is unnecessary, as
both commands can only drop objects from the local
repository. In the case of prune, we traverse only the local
object directory. And in the case of repacking, while we may
or may not include local objects in our pack, we will never
reach into the alternate with "repack -d". The "-l" option
is only a question of whether we are migrating objects from
the alternate into our repository, or leaving them
untouched.

It is possible that we may drop an object that is depended
upon by another object in the alternate. For example,
imagine two repositories, A and B, with A pointing to B as
an alternate. Now imagine a commit that is in B which
references a tree that is only in A. Traversing from recent
objects in B might prevent A from dropping that tree. But
this case isn't worth covering. Repo B should take
responsibility for its own objects. It would never have had
the commit in the first place if it did not also have the
tree, and assuming it is using the same "keep recent chunks
of history" scheme, then it would itself keep the tree, as
well.

So checking the alternate objects is not worth doing, and
come with a significant performance impact. In both cases,
we skip any recent objects that have already been marked
SEEN (i.e., that we know are already reachable for prune, or
included in the pack for a repack). So there is a slight
waste of time in opening the alternate packs at all, only to
notice that we have already considered each object. But much
worse, the alternate repository may have a large number of
objects that are not reachable from the local repository at
all, and we end up adding them to the traversal.

We can fix this by considering only local unseen objects.

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>reachable: use revision machinery's --indexed-objects code</title>
<updated>2014-10-19T22:07:07Z</updated>
<author>
<name>Jeff King</name>
<email>peff@peff.net</email>
</author>
<published>2014-10-17T00:44:30Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=1be111d88f526130dcf3b7c7ad0f5df17c6d2bae'/>
<id>urn:sha1:1be111d88f526130dcf3b7c7ad0f5df17c6d2bae</id>
<content type='text'>
This does the same thing as our custom code, so let's not
repeat ourselves.

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>pack-objects: match prune logic for discarding objects</title>
<updated>2014-10-16T17:10:43Z</updated>
<author>
<name>Jeff King</name>
<email>peff@peff.net</email>
</author>
<published>2014-10-15T22:42:09Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=abcb86553d3ec4afffa4e3963089dffe0559740e'/>
<id>urn:sha1:abcb86553d3ec4afffa4e3963089dffe0559740e</id>
<content type='text'>
A recent commit taught git-prune to keep non-recent objects
that are reachable from recent ones. However, pack-objects,
when loosening unreachable objects, tries to optimize out
the write in the case that the object will be immediately
pruned. It now gets this wrong, since its rule does not
reflect the new prune code (and this can be seen by running
t6501 with a strategically placed repack).

Let's teach pack-objects similar logic.

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>prune: keep objects reachable from recent objects</title>
<updated>2014-10-16T17:10:42Z</updated>
<author>
<name>Jeff King</name>
<email>peff@peff.net</email>
</author>
<published>2014-10-15T22:41:35Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=d3038d22f91aad9620bd8e6fc43fc67c16219738'/>
<id>urn:sha1:d3038d22f91aad9620bd8e6fc43fc67c16219738</id>
<content type='text'>
Our current strategy with prune is that an object falls into
one of three categories:

  1. Reachable (from ref tips, reflogs, index, etc).

  2. Not reachable, but recent (based on the --expire time).

  3. Not reachable and not recent.

We keep objects from (1) and (2), but prune objects in (3).
The point of (2) is that these objects may be part of an
in-progress operation that has not yet updated any refs.

However, it is not always the case that objects for an
in-progress operation will have a recent mtime. For example,
the object database may have an old copy of a blob (from an
abandoned operation, a branch that was deleted, etc). If we
create a new tree that points to it, a simultaneous prune
will leave our tree, but delete the blob. Referencing that
tree with a commit will then work (we check that the tree is
in the object database, but not that all of its referred
objects are), as will mentioning the commit in a ref. But
the resulting repo is corrupt; we are missing the blob
reachable from a ref.

One way to solve this is to be more thorough when
referencing a sha1: make sure that not only do we have that
sha1, but that we have objects it refers to, and so forth
recursively. The problem is that this is very expensive.
Creating a parent link would require traversing the entire
object graph!

Instead, this patch pushes the extra work onto prune, which
runs less frequently (and has to look at the whole object
graph anyway). It creates a new category of objects: objects
which are not recent, but which are reachable from a recent
object. We do not prune these objects, just like the
reachable and recent ones.

This lets us avoid the recursive check above, because if we
have an object, even if it is unreachable, we should have
its referent. We can make a simple inductive argument that
with this patch, this property holds (that there are no
objects with missing referents in the repository):

  0. When we have no objects, we have nothing to refer or be
     referred to, so the property holds.

  1. If we add objects to the repository, their direct
     referents must generally exist (e.g., if you create a
     tree, the blobs it references must exist; if you create
     a commit to point at the tree, the tree must exist).
     This is already the case before this patch. And it is
     not 100% foolproof (you can make bogus objects using
     `git hash-object`, for example), but it should be the
     case for normal usage.

     Therefore for any sequence of object additions, the
     property will continue to hold.

  2. If we remove objects from the repository, then we will
     not remove a child object (like a blob) if an object
     that refers to it is being kept. That is the part
     implemented by this patch.

     Note, however, that our reachability check and the
     actual pruning are not atomic. So it _is_ still
     possible to violate the property (e.g., an object
     becomes referenced just as we are deleting it). This
     patch is shooting for eliminating problems where the
     mtimes of dependent objects differ by hours or days,
     and one is dropped without the other. It does nothing
     to help with short races.

Naively, the simplest way to implement this would be to add
all recent objects as tips to the reachability traversal.
However, this does not perform well. In a recently-packed
repository, all reachable objects will also be recent, and
therefore we have to look at each object twice. This patch
instead performs the reachability traversal, then follows up
with a second traversal for recent objects, skipping any
that have already been marked.

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>reachable: mark index blobs as SEEN</title>
<updated>2014-10-16T17:10:40Z</updated>
<author>
<name>Jeff King</name>
<email>peff@peff.net</email>
</author>
<published>2014-10-15T22:40:37Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=3725427945657da052f2f833f5fd4616c949be3e'/>
<id>urn:sha1:3725427945657da052f2f833f5fd4616c949be3e</id>
<content type='text'>
When we mark all reachable objects for pruning, that
includes blobs mentioned by the index. However, we do not
mark these with the SEEN flag, as we do for objects that we
find by traversing (we also do not add them to the pending
list, but that is because there is nothing further to
traverse with them).

This doesn't cause any problems with prune, because it
checks only that the object exists in the global object
hash, and not its flags. However, let's mark these objects
to be consistent and avoid any later surprises.

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>reachable: reuse revision.c "add all reflogs" code</title>
<updated>2014-10-16T17:10:38Z</updated>
<author>
<name>Jeff King</name>
<email>peff@peff.net</email>
</author>
<published>2014-10-15T22:38:31Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=718ccc9731c4e98b123436c22c1cccf2beed5e29'/>
<id>urn:sha1:718ccc9731c4e98b123436c22c1cccf2beed5e29</id>
<content type='text'>
We want to add all reflog entries as tips for finding
reachable objects. The revision machinery can already do
this (to support "rev-list --reflog"); we can reuse that
code.

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>reachable: use traverse_commit_list instead of custom walk</title>
<updated>2014-10-16T17:10:38Z</updated>
<author>
<name>Jeff King</name>
<email>peff@peff.net</email>
</author>
<published>2014-10-15T22:37:28Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=5f78a431ab222189b11a9233a5902db61aa32976'/>
<id>urn:sha1:5f78a431ab222189b11a9233a5902db61aa32976</id>
<content type='text'>
To find the set of reachable objects, we add a bunch of
possible sources to our rev_info, call prepare_revision_walk,
and then launch into a custom walker that handles each
object top. This is a subset of what traverse_commit_list
does, so we can just reuse that code (it can also handle
more complex cases like UNINTERESTING commits and pathspecs,
but we don't use those features).

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>reachable.c: add HEAD to reachability starting commits</title>
<updated>2014-09-03T17:47:44Z</updated>
<author>
<name>Max Kirillov</name>
<email>max@max630.net</email>
</author>
<published>2014-09-03T16:14:10Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=c40fdd01dd120c8c63da5e830ccdeb1518434bd6'/>
<id>urn:sha1:c40fdd01dd120c8c63da5e830ccdeb1518434bd6</id>
<content type='text'>
HEAD is not explicitly used as a starting commit for
calculating reachability, so if it's detached and reflogs
are disabled it may be pruned.

Add tests which demonstrate it. Test 'prune: prune former HEAD after checking
out branch' also reverts changes to repository.

Signed-off-by: Max Kirillov &lt;max@max630.net&gt;
Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
</feed>
