Merge branch 'jt/has_object'

A new helper function has_object() has been introduced to make it
easier to mark object existence checks that do and don't want to
trigger lazy fetches, and a few such checks are converted using it.

* jt/has_object:
  fsck: do not lazy fetch known non-promisor object
  pack-objects: no fetch when allow-{any,promisor}
  apply: do not lazy fetch when applying binary
  sha1-file: introduce no-lazy-fetch has_object()
This commit is contained in:
Junio C Hamano 2020-08-13 14:13:39 -07:00
commit d1a8a8979d
7 changed files with 62 additions and 10 deletions

View File

@ -270,15 +270,18 @@ So does `git bundle` (see linkgit:git-bundle[1]) when it creates a bundle.
This option specifies how missing objects are handled. This option specifies how missing objects are handled.
+ +
The form '--missing=error' requests that pack-objects stop with an error if The form '--missing=error' requests that pack-objects stop with an error if
a missing object is encountered. This is the default action. a missing object is encountered. If the repository is a partial clone, an
attempt to fetch missing objects will be made before declaring them missing.
This is the default action.
+ +
The form '--missing=allow-any' will allow object traversal to continue The form '--missing=allow-any' will allow object traversal to continue
if a missing object is encountered. Missing objects will silently be if a missing object is encountered. No fetch of a missing object will occur.
omitted from the results. Missing objects will silently be omitted from the results.
+ +
The form '--missing=allow-promisor' is like 'allow-any', but will only The form '--missing=allow-promisor' is like 'allow-any', but will only
allow object traversal to continue for EXPECTED promisor missing objects. allow object traversal to continue for EXPECTED promisor missing objects.
Unexpected missing object will raise an error. No fetch of a missing object will occur. An unexpected missing object will
raise an error.
--exclude-promisor-objects:: --exclude-promisor-objects::
Omit objects that are known to be in the promisor remote. (This Omit objects that are known to be in the promisor remote. (This

View File

@ -3178,7 +3178,7 @@ static int apply_binary(struct apply_state *state,
return 0; /* deletion patch */ return 0; /* deletion patch */
} }
if (has_object_file(&oid)) { if (has_object(the_repository, &oid, 0)) {
/* We already have the postimage */ /* We already have the postimage */
enum object_type type; enum object_type type;
unsigned long size; unsigned long size;

View File

@ -168,7 +168,7 @@ static int mark_object(struct object *obj, int type, void *data, struct fsck_opt
return 0; return 0;
if (!(obj->flags & HAS_OBJ)) { if (!(obj->flags & HAS_OBJ)) {
if (parent && !has_object_file(&obj->oid)) { if (parent && !has_object(the_repository, &obj->oid, 1)) {
printf_ln(_("broken link from %7s %s\n" printf_ln(_("broken link from %7s %s\n"
" to %7s %s"), " to %7s %s"),
printable_type(&parent->oid, parent->type), printable_type(&parent->oid, parent->type),

View File

@ -3048,7 +3048,7 @@ static void show_object__ma_allow_any(struct object *obj, const char *name, void
* Quietly ignore ALL missing objects. This avoids problems with * Quietly ignore ALL missing objects. This avoids problems with
* staging them now and getting an odd error later. * staging them now and getting an odd error later.
*/ */
if (!has_object_file(&obj->oid)) if (!has_object(the_repository, &obj->oid, 0))
return; return;
show_object(obj, name, data); show_object(obj, name, data);
@ -3062,7 +3062,7 @@ static void show_object__ma_allow_promisor(struct object *obj, const char *name,
* Quietly ignore EXPECTED missing objects. This avoids problems with * Quietly ignore EXPECTED missing objects. This avoids problems with
* staging them now and getting an odd error later. * staging them now and getting an odd error later.
*/ */
if (!has_object_file(&obj->oid) && is_promisor_object(&obj->oid)) if (!has_object(the_repository, &obj->oid, 0) && is_promisor_object(&obj->oid))
return; return;
show_object(obj, name, data); show_object(obj, name, data);

View File

@ -239,12 +239,33 @@ int read_loose_object(const char *path,
unsigned long *size, unsigned long *size,
void **contents); void **contents);
/* Retry packed storage after checking packed and loose storage */
#define HAS_OBJECT_RECHECK_PACKED 1
/*
* Returns 1 if the object exists. This function will not lazily fetch objects
* in a partial clone.
*/
int has_object(struct repository *r, const struct object_id *oid,
unsigned flags);
/*
* These macros and functions are deprecated. If checking existence for an
* object that is likely to be missing and/or whose absence is relatively
* inconsequential (or is consequential but the caller is prepared to handle
* it), use has_object(), which has better defaults (no lazy fetch in a partial
* clone and no rechecking of packed storage). In the unlikely event that a
* caller needs to assert existence of an object that it fully expects to
* exist, and wants to trigger a lazy fetch in a partial clone, use
* oid_object_info_extended() with a NULL struct object_info.
*
* These functions can be removed once all callers have migrated to
* has_object() and/or oid_object_info_extended().
*/
#ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS #ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS
#define has_sha1_file_with_flags(sha1, flags) repo_has_sha1_file_with_flags(the_repository, sha1, flags) #define has_sha1_file_with_flags(sha1, flags) repo_has_sha1_file_with_flags(the_repository, sha1, flags)
#define has_sha1_file(sha1) repo_has_sha1_file(the_repository, sha1) #define has_sha1_file(sha1) repo_has_sha1_file(the_repository, sha1)
#endif #endif
/* Same as the above, except for struct object_id. */
int repo_has_object_file(struct repository *r, const struct object_id *oid); int repo_has_object_file(struct repository *r, const struct object_id *oid);
int repo_has_object_file_with_flags(struct repository *r, int repo_has_object_file_with_flags(struct repository *r,
const struct object_id *oid, int flags); const struct object_id *oid, int flags);

View File

@ -1989,6 +1989,18 @@ int force_object_loose(const struct object_id *oid, time_t mtime)
return ret; return ret;
} }
int has_object(struct repository *r, const struct object_id *oid,
unsigned flags)
{
int quick = !(flags & HAS_OBJECT_RECHECK_PACKED);
unsigned object_info_flags = OBJECT_INFO_SKIP_FETCH_OBJECT |
(quick ? OBJECT_INFO_QUICK : 0);
if (!startup_info->have_repository)
return 0;
return oid_object_info_extended(r, oid, NULL, object_info_flags) >= 0;
}
int repo_has_object_file_with_flags(struct repository *r, int repo_has_object_file_with_flags(struct repository *r,
const struct object_id *oid, int flags) const struct object_id *oid, int flags)
{ {

View File

@ -1133,4 +1133,20 @@ test_expect_success 'am and .gitattibutes' '
) )
' '
test_expect_success 'apply binary blob in partial clone' '
printf "\\000" >binary &&
git add binary &&
git commit -m "binary blob" &&
git format-patch --stdout -m HEAD^ >patch &&
test_create_repo server &&
test_config -C server uploadpack.allowfilter 1 &&
test_config -C server uploadpack.allowanysha1inwant 1 &&
git clone --filter=blob:none "file://$(pwd)/server" client &&
test_when_finished "rm -rf client" &&
# Exercise to make sure that it works
git -C client am ../patch
'
test_done test_done