Skip to content

Commit 6246de9

Browse files
committed
Merge completed: resolve the conflict with the upstream
2 parents 8384a50 + a064dc2 commit 6246de9

File tree

16 files changed

+309
-30
lines changed

16 files changed

+309
-30
lines changed

PROJECTS.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,6 @@ These are good small projects to get started with libgit2.
2828
core Git command and add a missing command-line option. There are many
2929
gaps right now and this helps demonstrate how to use the library. Here
3030
are some specific ideas:
31-
* Add the `--minimal` flag to `examples/diff.c` since the `libgit2`
32-
diff API now has a flag to support it
33-
* Add the `--patience` flag to `examples/diff.c` since it is also now
34-
supported.
3531
* Fix the `examples/diff.c` implementation of the `-B`
3632
(a.k.a. `--break-rewrites`) command line option to actually look for
3733
the optional `[<n>][/<m>]` configuration values. There is an

examples/diff.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,10 @@ static void parse_opts(struct opts *o, int argc, char *argv[])
238238
o->diffopts.flags |= GIT_DIFF_INCLUDE_IGNORED;
239239
else if (!strcmp(a, "--untracked"))
240240
o->diffopts.flags |= GIT_DIFF_INCLUDE_UNTRACKED;
241+
else if (!strcmp(a, "--patience"))
242+
o->diffopts.flags |= GIT_DIFF_PATIENCE;
243+
else if (!strcmp(a, "--minimal"))
244+
o->diffopts.flags |= GIT_DIFF_MINIMAL;
241245
else if (!strcmp(a, "--numstat"))
242246
o->numstat = 1;
243247
else if (!strcmp(a, "--shortstat"))

include/git2/object.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "common.h"
1111
#include "types.h"
1212
#include "oid.h"
13+
#include "buffer.h"
1314

1415
/**
1516
* @file git2/object.h
@@ -103,6 +104,15 @@ GIT_EXTERN(int) git_object_lookup_bypath(
103104
*/
104105
GIT_EXTERN(const git_oid *) git_object_id(const git_object *obj);
105106

107+
/**
108+
* Get a short abbreviated OID string for the object
109+
*
110+
* @param out Buffer to write string into
111+
* @param obj The object to get an ID for
112+
* @return 0 on success, <0 for error
113+
*/
114+
GIT_EXTERN(int) git_object_short_id(git_buf *out, const git_object *obj);
115+
106116
/**
107117
* Get the object type of an object
108118
*

include/git2/odb.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,19 @@ GIT_EXTERN(int) git_odb_read_header(size_t *len_out, git_otype *type_out, git_od
158158
*/
159159
GIT_EXTERN(int) git_odb_exists(git_odb *db, const git_oid *id);
160160

161+
/**
162+
* Determine if objects can be found in the object database from a short OID.
163+
*
164+
* @param out The full OID of the found object if just one is found.
165+
* @param db The database to be searched for the given object.
166+
* @param short_id A prefix of the id of the object to read.
167+
* @param len The length of the prefix.
168+
* @return 0 if found, GIT_ENOTFOUND if not found, GIT_EAMBIGUOUS if multiple
169+
* matches were found, other value < 0 if there was a read error.
170+
*/
171+
GIT_EXTERN(int) git_odb_exists_prefix(
172+
git_oid *out, git_odb *db, const git_oid *short_id, size_t len);
173+
161174
/**
162175
* Refresh the object database to load newly added files.
163176
*

include/git2/sys/odb_backend.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,8 @@ struct git_odb_backend {
3535
int (* read)(
3636
void **, size_t *, git_otype *, git_odb_backend *, const git_oid *);
3737

38-
/* To find a unique object given a prefix
39-
* of its oid.
40-
* The oid given must be so that the
41-
* remaining (GIT_OID_HEXSZ - len)*4 bits
42-
* are 0s.
38+
/* To find a unique object given a prefix of its oid. The oid given
39+
* must be so that the remaining (GIT_OID_HEXSZ - len)*4 bits are 0s.
4340
*/
4441
int (* read_prefix)(
4542
git_oid *, void **, size_t *, git_otype *,
@@ -64,6 +61,9 @@ struct git_odb_backend {
6461
int (* exists)(
6562
git_odb_backend *, const git_oid *);
6663

64+
int (* exists_prefix)(
65+
git_oid *, git_odb_backend *, const git_oid *, size_t);
66+
6767
/**
6868
* If the backend implements a refreshing mechanism, it should be exposed
6969
* through this endpoint. Each call to `git_odb_refresh()` will invoke it.

src/object.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,3 +397,46 @@ int git_object_lookup_bypath(
397397
git_tree_free(tree);
398398
return error;
399399
}
400+
401+
int git_object_short_id(git_buf *out, const git_object *obj)
402+
{
403+
git_repository *repo;
404+
int len = GIT_ABBREV_DEFAULT, error;
405+
git_oid id = {{0}};
406+
git_odb *odb;
407+
408+
assert(out && obj);
409+
410+
git_buf_sanitize(out);
411+
repo = git_object_owner(obj);
412+
413+
if ((error = git_repository__cvar(&len, repo, GIT_CVAR_ABBREV)) < 0)
414+
return error;
415+
416+
if ((error = git_repository_odb(&odb, repo)) < 0)
417+
return error;
418+
419+
while (len < GIT_OID_HEXSZ) {
420+
/* set up short oid */
421+
memcpy(&id.id, &obj->cached.oid.id, (len + 1) / 2);
422+
if (len & 1)
423+
id.id[len / 2] &= 0xf0;
424+
425+
error = git_odb_exists_prefix(NULL, odb, &id, len);
426+
if (error != GIT_EAMBIGUOUS)
427+
break;
428+
429+
giterr_clear();
430+
len++;
431+
}
432+
433+
if (!error && !(error = git_buf_grow(out, len + 1))) {
434+
git_oid_tostr(out->ptr, len + 1, &id);
435+
out->size = len;
436+
}
437+
438+
git_odb_free(odb);
439+
440+
return error;
441+
}
442+

src/odb.c

Lines changed: 67 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,61 @@ int git_odb_exists(git_odb *db, const git_oid *id)
635635
return (int)found;
636636
}
637637

638+
int git_odb_exists_prefix(
639+
git_oid *out, git_odb *db, const git_oid *short_id, size_t len)
640+
{
641+
int error = GIT_ENOTFOUND, num_found = 0;
642+
size_t i;
643+
git_oid last_found = {{0}}, found;
644+
645+
assert(db && short_id);
646+
647+
if (len < GIT_OID_MINPREFIXLEN)
648+
return git_odb__error_ambiguous("prefix length too short");
649+
if (len > GIT_OID_HEXSZ)
650+
len = GIT_OID_HEXSZ;
651+
652+
if (len == GIT_OID_HEXSZ) {
653+
if (git_odb_exists(db, short_id)) {
654+
if (out)
655+
git_oid_cpy(out, short_id);
656+
return 0;
657+
} else {
658+
return git_odb__error_notfound("no match for id prefix", short_id);
659+
}
660+
}
661+
662+
for (i = 0; i < db->backends.length; ++i) {
663+
backend_internal *internal = git_vector_get(&db->backends, i);
664+
git_odb_backend *b = internal->backend;
665+
666+
if (!b->exists_prefix)
667+
continue;
668+
669+
error = b->exists_prefix(&found, b, short_id, len);
670+
if (error == GIT_ENOTFOUND || error == GIT_PASSTHROUGH)
671+
continue;
672+
if (error)
673+
return error;
674+
675+
/* make sure found item doesn't introduce ambiguity */
676+
if (num_found) {
677+
if (git_oid__cmp(&last_found, &found))
678+
return git_odb__error_ambiguous("multiple matches for prefix");
679+
} else {
680+
git_oid_cpy(&last_found, &found);
681+
num_found++;
682+
}
683+
}
684+
685+
if (!num_found)
686+
return git_odb__error_notfound("no match for id prefix", short_id);
687+
if (out)
688+
git_oid_cpy(out, &last_found);
689+
690+
return error;
691+
}
692+
638693
int git_odb_read_header(size_t *len_p, git_otype *type_p, git_odb *db, const git_oid *id)
639694
{
640695
int error;
@@ -745,7 +800,6 @@ int git_odb_read_prefix(
745800

746801
if (len < GIT_OID_MINPREFIXLEN)
747802
return git_odb__error_ambiguous("prefix length too short");
748-
749803
if (len > GIT_OID_HEXSZ)
750804
len = GIT_OID_HEXSZ;
751805

@@ -862,7 +916,7 @@ int git_odb_open_wstream(
862916
{
863917
size_t i, writes = 0;
864918
int error = GIT_ERROR;
865-
git_hash_ctx *ctx;
919+
git_hash_ctx *ctx = NULL;
866920

867921
assert(stream && db);
868922

@@ -883,22 +937,28 @@ int git_odb_open_wstream(
883937
}
884938
}
885939

886-
if (error == GIT_PASSTHROUGH)
887-
error = 0;
888-
if (error < 0 && !writes)
889-
error = git_odb__error_unsupported_in_backend("write object");
940+
if (error < 0) {
941+
if (error == GIT_PASSTHROUGH)
942+
error = 0;
943+
else if (!writes)
944+
error = git_odb__error_unsupported_in_backend("write object");
945+
946+
goto done;
947+
}
890948

891949
ctx = git__malloc(sizeof(git_hash_ctx));
892950
GITERR_CHECK_ALLOC(ctx);
893951

952+
if ((error = git_hash_ctx_init(ctx)) < 0)
953+
goto done;
894954

895-
git_hash_ctx_init(ctx);
896955
hash_header(ctx, size, type);
897956
(*stream)->hash_ctx = ctx;
898957

899958
(*stream)->declared_size = size;
900959
(*stream)->received_bytes = 0;
901960

961+
done:
902962
return error;
903963
}
904964

src/odb_loose.c

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -519,11 +519,11 @@ static int locate_object_short_oid(
519519
loose_locate_object_state state;
520520
int error;
521521

522-
/* prealloc memory for OBJ_DIR/xx/ */
523-
if (git_buf_grow(object_location, dir_len + 5) < 0)
522+
/* prealloc memory for OBJ_DIR/xx/xx..38x..xx */
523+
if (git_buf_grow(object_location, dir_len + 3 + GIT_OID_HEXSZ) < 0)
524524
return -1;
525525

526-
git_buf_sets(object_location, objects_dir);
526+
git_buf_set(object_location, objects_dir, dir_len);
527527
git_path_to_dir(object_location);
528528

529529
/* save adjusted position at end of dir so it can be restored later */
@@ -533,8 +533,9 @@ static int locate_object_short_oid(
533533
git_oid_fmt((char *)state.short_oid, short_oid);
534534

535535
/* Explore OBJ_DIR/xx/ where xx is the beginning of hex formatted short oid */
536-
if (git_buf_printf(object_location, "%.2s/", state.short_oid) < 0)
536+
if (git_buf_put(object_location, (char *)state.short_oid, 3) < 0)
537537
return -1;
538+
object_location->ptr[object_location->size - 1] = '/';
538539

539540
/* Check that directory exists */
540541
if (git_path_isdir(object_location->ptr) == false)
@@ -646,12 +647,9 @@ static int loose_backend__read_prefix(
646647
{
647648
int error = 0;
648649

649-
assert(len <= GIT_OID_HEXSZ);
650+
assert(len >= GIT_OID_MINPREFIXLEN && len <= GIT_OID_HEXSZ);
650651

651-
if (len < GIT_OID_MINPREFIXLEN)
652-
error = git_odb__error_ambiguous("prefix length too short");
653-
654-
else if (len == GIT_OID_HEXSZ) {
652+
if (len == GIT_OID_HEXSZ) {
655653
/* We can fall back to regular read method */
656654
error = loose_backend__read(buffer_p, len_p, type_p, backend, short_oid);
657655
if (!error)
@@ -691,6 +689,22 @@ static int loose_backend__exists(git_odb_backend *backend, const git_oid *oid)
691689
return !error;
692690
}
693691

692+
static int loose_backend__exists_prefix(
693+
git_oid *out, git_odb_backend *backend, const git_oid *short_id, size_t len)
694+
{
695+
git_buf object_path = GIT_BUF_INIT;
696+
int error;
697+
698+
assert(backend && out && short_id && len >= GIT_OID_MINPREFIXLEN);
699+
700+
error = locate_object_short_oid(
701+
&object_path, out, (loose_backend *)backend, short_id, len);
702+
703+
git_buf_free(&object_path);
704+
705+
return error;
706+
}
707+
694708
struct foreach_state {
695709
size_t dir_len;
696710
git_odb_foreach_cb cb;
@@ -939,6 +953,7 @@ int git_odb_backend_loose(
939953
backend->parent.read_header = &loose_backend__read_header;
940954
backend->parent.writestream = &loose_backend__stream;
941955
backend->parent.exists = &loose_backend__exists;
956+
backend->parent.exists_prefix = &loose_backend__exists_prefix;
942957
backend->parent.foreach = &loose_backend__foreach;
943958
backend->parent.free = &loose_backend__free;
944959

src/odb_pack.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,23 @@ static int pack_backend__exists(git_odb_backend *backend, const git_oid *oid)
493493
return pack_entry_find(&e, (struct pack_backend *)backend, oid) == 0;
494494
}
495495

496+
static int pack_backend__exists_prefix(
497+
git_oid *out, git_odb_backend *backend, const git_oid *short_id, size_t len)
498+
{
499+
int error;
500+
struct pack_backend *pb = (struct pack_backend *)backend;
501+
struct git_pack_entry e = {0};
502+
503+
error = pack_entry_find_prefix(&e, pb, short_id, len);
504+
505+
if (error == GIT_ENOTFOUND && !(error = pack_backend__refresh(backend)))
506+
error = pack_entry_find_prefix(&e, pb, short_id, len);
507+
508+
git_oid_cpy(out, &e.sha1);
509+
510+
return error;
511+
}
512+
496513
static int pack_backend__foreach(git_odb_backend *_backend, git_odb_foreach_cb cb, void *data)
497514
{
498515
int error;
@@ -612,6 +629,7 @@ static int pack_backend__alloc(struct pack_backend **out, size_t initial_size)
612629
backend->parent.read_prefix = &pack_backend__read_prefix;
613630
backend->parent.read_header = &pack_backend__read_header;
614631
backend->parent.exists = &pack_backend__exists;
632+
backend->parent.exists_prefix = &pack_backend__exists_prefix;
615633
backend->parent.refresh = &pack_backend__refresh;
616634
backend->parent.foreach = &pack_backend__foreach;
617635
backend->parent.writepack = &pack_backend__writepack;

src/path.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -853,6 +853,9 @@ int git_path_direach(
853853

854854
if ((dir = opendir(path->ptr)) == NULL) {
855855
giterr_set(GITERR_OS, "Failed to open directory '%s'", path->ptr);
856+
if (errno == ENOENT)
857+
return GIT_ENOTFOUND;
858+
856859
return -1;
857860
}
858861

0 commit comments

Comments
 (0)