rugged 0.24.6.1 → 0.25.0b1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/rugged/rugged_repo.c +44 -36
- data/lib/rugged/version.rb +1 -1
- data/vendor/libgit2/CMakeLists.txt +10 -21
- data/vendor/libgit2/include/git2/checkout.h +0 -7
- data/vendor/libgit2/include/git2/commit.h +46 -0
- data/vendor/libgit2/include/git2/common.h +1 -16
- data/vendor/libgit2/include/git2/odb.h +47 -1
- data/vendor/libgit2/include/git2/version.h +2 -2
- data/vendor/libgit2/src/array.h +0 -40
- data/vendor/libgit2/src/blame.c +3 -8
- data/vendor/libgit2/src/blame_git.c +9 -20
- data/vendor/libgit2/src/checkout.c +5 -13
- data/vendor/libgit2/src/commit.c +132 -52
- data/vendor/libgit2/src/common.h +1 -1
- data/vendor/libgit2/src/config_cache.c +1 -2
- data/vendor/libgit2/src/config_file.c +20 -14
- data/vendor/libgit2/src/delta-apply.c +5 -36
- data/vendor/libgit2/src/delta-apply.h +0 -12
- data/vendor/libgit2/src/describe.c +1 -2
- data/vendor/libgit2/src/diff_tform.c +3 -5
- data/vendor/libgit2/src/filebuf.c +1 -6
- data/vendor/libgit2/src/global.c +8 -28
- data/vendor/libgit2/src/global.h +0 -1
- data/vendor/libgit2/src/ignore.c +19 -56
- data/vendor/libgit2/src/index.c +8 -27
- data/vendor/libgit2/src/indexer.c +7 -11
- data/vendor/libgit2/src/iterator.c +2 -2
- data/vendor/libgit2/src/merge.c +0 -1
- data/vendor/libgit2/src/mwindow.c +19 -8
- data/vendor/libgit2/src/mwindow.h +2 -1
- data/vendor/libgit2/src/object.c +6 -3
- data/vendor/libgit2/src/odb.c +188 -48
- data/vendor/libgit2/src/odb_loose.c +1 -1
- data/vendor/libgit2/src/odb_pack.c +3 -0
- data/vendor/libgit2/src/openssl_stream.c +27 -60
- data/vendor/libgit2/src/openssl_stream.h +0 -106
- data/vendor/libgit2/src/pack-objects.c +2 -4
- data/vendor/libgit2/src/pack.c +9 -5
- data/vendor/libgit2/src/posix.c +0 -7
- data/vendor/libgit2/src/posix.h +0 -1
- data/vendor/libgit2/src/push.c +6 -6
- data/vendor/libgit2/src/refdb_fs.c +0 -1
- data/vendor/libgit2/src/refs.c +0 -3
- data/vendor/libgit2/src/refspec.c +2 -4
- data/vendor/libgit2/src/remote.c +5 -15
- data/vendor/libgit2/src/repository.c +21 -29
- data/vendor/libgit2/src/settings.c +1 -23
- data/vendor/libgit2/src/stransport_stream.c +9 -15
- data/vendor/libgit2/src/submodule.c +2 -3
- data/vendor/libgit2/src/sysdir.c +47 -41
- data/vendor/libgit2/src/sysdir.h +5 -0
- data/vendor/libgit2/src/tag.c +2 -8
- data/vendor/libgit2/src/thread-utils.h +51 -5
- data/vendor/libgit2/src/transports/http.c +3 -3
- data/vendor/libgit2/src/transports/smart_pkt.c +4 -13
- data/vendor/libgit2/src/transports/smart_protocol.c +17 -61
- data/vendor/libgit2/src/tree.c +100 -83
- data/vendor/libgit2/src/tree.h +5 -4
- data/vendor/libgit2/src/unix/map.c +0 -5
- data/vendor/libgit2/src/util.c +3 -3
- data/vendor/libgit2/src/win32/map.c +5 -24
- data/vendor/libgit2/src/win32/precompiled.h +1 -1
- data/vendor/libgit2/src/win32/{thread.c → pthread.c} +80 -50
- data/vendor/libgit2/src/win32/pthread.h +92 -0
- data/vendor/libgit2/src/xdiff/xprepare.c +1 -2
- metadata +7 -8
- data/vendor/libgit2/src/unix/pthread.h +0 -54
- data/vendor/libgit2/src/win32/thread.h +0 -62
data/vendor/libgit2/src/tag.c
CHANGED
@@ -137,14 +137,8 @@ static int tag_parse(git_tag *tag, const char *buffer, const char *buffer_end)
|
|
137
137
|
|
138
138
|
tag->message = NULL;
|
139
139
|
if (buffer < buffer_end) {
|
140
|
-
|
141
|
-
|
142
|
-
search = strstr(buffer, "\n\n");
|
143
|
-
if (search)
|
144
|
-
buffer = search + 1;
|
145
|
-
else
|
146
|
-
return tag_error("tag contains no message");
|
147
|
-
}
|
140
|
+
if( *buffer != '\n' )
|
141
|
+
return tag_error("No new line before message");
|
148
142
|
|
149
143
|
text_len = buffer_end - ++buffer;
|
150
144
|
|
@@ -40,12 +40,58 @@ typedef git_atomic git_atomic_ssize;
|
|
40
40
|
|
41
41
|
#ifdef GIT_THREADS
|
42
42
|
|
43
|
-
#
|
44
|
-
|
45
|
-
|
46
|
-
|
43
|
+
#if !defined(GIT_WIN32)
|
44
|
+
|
45
|
+
typedef struct {
|
46
|
+
pthread_t thread;
|
47
|
+
} git_thread;
|
48
|
+
|
49
|
+
#define git_thread_create(git_thread_ptr, attr, start_routine, arg) \
|
50
|
+
pthread_create(&(git_thread_ptr)->thread, attr, start_routine, arg)
|
51
|
+
#define git_thread_join(git_thread_ptr, status) \
|
52
|
+
pthread_join((git_thread_ptr)->thread, status)
|
53
|
+
|
47
54
|
#endif
|
48
55
|
|
56
|
+
/* Pthreads Mutex */
|
57
|
+
#define git_mutex pthread_mutex_t
|
58
|
+
#define git_mutex_init(a) pthread_mutex_init(a, NULL)
|
59
|
+
#define git_mutex_lock(a) pthread_mutex_lock(a)
|
60
|
+
#define git_mutex_unlock(a) pthread_mutex_unlock(a)
|
61
|
+
#define git_mutex_free(a) pthread_mutex_destroy(a)
|
62
|
+
|
63
|
+
/* Pthreads condition vars */
|
64
|
+
#define git_cond pthread_cond_t
|
65
|
+
#define git_cond_init(c) pthread_cond_init(c, NULL)
|
66
|
+
#define git_cond_free(c) pthread_cond_destroy(c)
|
67
|
+
#define git_cond_wait(c, l) pthread_cond_wait(c, l)
|
68
|
+
#define git_cond_signal(c) pthread_cond_signal(c)
|
69
|
+
#define git_cond_broadcast(c) pthread_cond_broadcast(c)
|
70
|
+
|
71
|
+
/* Pthread (-ish) rwlock
|
72
|
+
*
|
73
|
+
* This differs from normal pthreads rwlocks in two ways:
|
74
|
+
* 1. Separate APIs for releasing read locks and write locks (as
|
75
|
+
* opposed to the pure POSIX API which only has one unlock fn)
|
76
|
+
* 2. You should not use recursive read locks (i.e. grabbing a read
|
77
|
+
* lock in a thread that already holds a read lock) because the
|
78
|
+
* Windows implementation doesn't support it
|
79
|
+
*/
|
80
|
+
#define git_rwlock pthread_rwlock_t
|
81
|
+
#define git_rwlock_init(a) pthread_rwlock_init(a, NULL)
|
82
|
+
#define git_rwlock_rdlock(a) pthread_rwlock_rdlock(a)
|
83
|
+
#define git_rwlock_rdunlock(a) pthread_rwlock_rdunlock(a)
|
84
|
+
#define git_rwlock_wrlock(a) pthread_rwlock_wrlock(a)
|
85
|
+
#define git_rwlock_wrunlock(a) pthread_rwlock_wrunlock(a)
|
86
|
+
#define git_rwlock_free(a) pthread_rwlock_destroy(a)
|
87
|
+
#define GIT_RWLOCK_STATIC_INIT PTHREAD_RWLOCK_INITIALIZER
|
88
|
+
|
89
|
+
#ifndef GIT_WIN32
|
90
|
+
#define pthread_rwlock_rdunlock pthread_rwlock_unlock
|
91
|
+
#define pthread_rwlock_wrunlock pthread_rwlock_unlock
|
92
|
+
#endif
|
93
|
+
|
94
|
+
|
49
95
|
GIT_INLINE(void) git_atomic_set(git_atomic *a, int val)
|
50
96
|
{
|
51
97
|
#if defined(GIT_WIN32)
|
@@ -132,7 +178,7 @@ GIT_INLINE(int64_t) git_atomic64_add(git_atomic64 *a, int64_t addend)
|
|
132
178
|
#else
|
133
179
|
|
134
180
|
#define git_thread unsigned int
|
135
|
-
#define git_thread_create(thread, start_routine, arg) 0
|
181
|
+
#define git_thread_create(thread, attr, start_routine, arg) 0
|
136
182
|
#define git_thread_join(id, status) (void)0
|
137
183
|
|
138
184
|
/* Pthreads Mutex */
|
@@ -114,7 +114,7 @@ static bool challenge_match(git_http_auth_scheme *scheme, void *data)
|
|
114
114
|
size_t scheme_len;
|
115
115
|
|
116
116
|
scheme_len = strlen(scheme_name);
|
117
|
-
return (
|
117
|
+
return (strncmp(challenge, scheme_name, scheme_len) == 0 &&
|
118
118
|
(challenge[scheme_len] == '\0' || challenge[scheme_len] == ' '));
|
119
119
|
}
|
120
120
|
|
@@ -569,7 +569,6 @@ static int http_connect(http_subtransport *t)
|
|
569
569
|
git_stream_close(t->io);
|
570
570
|
git_stream_free(t->io);
|
571
571
|
t->io = NULL;
|
572
|
-
t->connected = 0;
|
573
572
|
}
|
574
573
|
|
575
574
|
if (t->connection_data.use_ssl) {
|
@@ -602,12 +601,13 @@ static int http_connect(http_subtransport *t)
|
|
602
601
|
if ((!error || error == GIT_ECERTIFICATE) && t->owner->certificate_check_cb != NULL &&
|
603
602
|
git_stream_is_encrypted(t->io)) {
|
604
603
|
git_cert *cert;
|
605
|
-
int is_valid
|
604
|
+
int is_valid;
|
606
605
|
|
607
606
|
if ((error = git_stream_certificate(&cert, t->io)) < 0)
|
608
607
|
return error;
|
609
608
|
|
610
609
|
giterr_clear();
|
610
|
+
is_valid = error != GIT_ECERTIFICATE;
|
611
611
|
error = t->owner->certificate_check_cb(cert, is_valid, t->connection_data.host, t->owner->message_cb_payload);
|
612
612
|
|
613
613
|
if (error < 0) {
|
@@ -427,23 +427,14 @@ int git_pkt_parse_line(
|
|
427
427
|
if (bufflen > 0 && bufflen < (size_t)len)
|
428
428
|
return GIT_EBUFS;
|
429
429
|
|
430
|
-
/*
|
431
|
-
* The length has to be exactly 0 in case of a flush
|
432
|
-
* packet or greater than PKT_LEN_SIZE, as the decoded
|
433
|
-
* length includes its own encoded length of four bytes.
|
434
|
-
*/
|
435
|
-
if (len != 0 && len < PKT_LEN_SIZE)
|
436
|
-
return GIT_ERROR;
|
437
|
-
|
438
430
|
line += PKT_LEN_SIZE;
|
439
431
|
/*
|
440
|
-
*
|
441
|
-
*
|
442
|
-
* line, we should return an error upon hitting one.
|
432
|
+
* TODO: How do we deal with empty lines? Try again? with the next
|
433
|
+
* line?
|
443
434
|
*/
|
444
435
|
if (len == PKT_LEN_SIZE) {
|
445
|
-
|
446
|
-
return
|
436
|
+
*out = line;
|
437
|
+
return 0;
|
447
438
|
}
|
448
439
|
|
449
440
|
if (len == 0) { /* Flush pkt */
|
@@ -721,39 +721,18 @@ static int add_push_report_pkt(git_push *push, git_pkt *pkt)
|
|
721
721
|
return 0;
|
722
722
|
}
|
723
723
|
|
724
|
-
static int add_push_report_sideband_pkt(git_push *push, git_pkt_data *data_pkt
|
724
|
+
static int add_push_report_sideband_pkt(git_push *push, git_pkt_data *data_pkt)
|
725
725
|
{
|
726
726
|
git_pkt *pkt;
|
727
|
-
const char *line, *line_end;
|
728
|
-
size_t line_len;
|
727
|
+
const char *line = data_pkt->data, *line_end;
|
728
|
+
size_t line_len = data_pkt->len;
|
729
729
|
int error;
|
730
|
-
int reading_from_buf = data_pkt_buf->size > 0;
|
731
|
-
|
732
|
-
if (reading_from_buf) {
|
733
|
-
/* We had an existing partial packet, so add the new
|
734
|
-
* packet to the buffer and parse the whole thing */
|
735
|
-
git_buf_put(data_pkt_buf, data_pkt->data, data_pkt->len);
|
736
|
-
line = data_pkt_buf->ptr;
|
737
|
-
line_len = data_pkt_buf->size;
|
738
|
-
}
|
739
|
-
else {
|
740
|
-
line = data_pkt->data;
|
741
|
-
line_len = data_pkt->len;
|
742
|
-
}
|
743
730
|
|
744
731
|
while (line_len > 0) {
|
745
732
|
error = git_pkt_parse_line(&pkt, line, &line_end, line_len);
|
746
733
|
|
747
|
-
if (error
|
748
|
-
|
749
|
-
* across multiple sideband packets */
|
750
|
-
if (!reading_from_buf)
|
751
|
-
git_buf_put(data_pkt_buf, line, line_len);
|
752
|
-
error = 0;
|
753
|
-
goto done;
|
754
|
-
}
|
755
|
-
else if (error < 0)
|
756
|
-
goto done;
|
734
|
+
if (error < 0)
|
735
|
+
return error;
|
757
736
|
|
758
737
|
/* Advance in the buffer */
|
759
738
|
line_len -= (line_end - line);
|
@@ -764,15 +743,10 @@ static int add_push_report_sideband_pkt(git_push *push, git_pkt_data *data_pkt,
|
|
764
743
|
git_pkt_free(pkt);
|
765
744
|
|
766
745
|
if (error < 0 && error != GIT_ITEROVER)
|
767
|
-
|
746
|
+
return error;
|
768
747
|
}
|
769
748
|
|
770
|
-
|
771
|
-
|
772
|
-
done:
|
773
|
-
if (reading_from_buf)
|
774
|
-
git_buf_consume(data_pkt_buf, line_end);
|
775
|
-
return error;
|
749
|
+
return 0;
|
776
750
|
}
|
777
751
|
|
778
752
|
static int parse_report(transport_smart *transport, git_push *push)
|
@@ -781,7 +755,6 @@ static int parse_report(transport_smart *transport, git_push *push)
|
|
781
755
|
const char *line_end = NULL;
|
782
756
|
gitno_buffer *buf = &transport->buffer;
|
783
757
|
int error, recvd;
|
784
|
-
git_buf data_pkt_buf = GIT_BUF_INIT;
|
785
758
|
|
786
759
|
for (;;) {
|
787
760
|
if (buf->offset > 0)
|
@@ -790,21 +763,16 @@ static int parse_report(transport_smart *transport, git_push *push)
|
|
790
763
|
else
|
791
764
|
error = GIT_EBUFS;
|
792
765
|
|
793
|
-
if (error < 0 && error != GIT_EBUFS)
|
794
|
-
|
795
|
-
goto done;
|
796
|
-
}
|
766
|
+
if (error < 0 && error != GIT_EBUFS)
|
767
|
+
return -1;
|
797
768
|
|
798
769
|
if (error == GIT_EBUFS) {
|
799
|
-
if ((recvd = gitno_recv(buf)) < 0)
|
800
|
-
|
801
|
-
goto done;
|
802
|
-
}
|
770
|
+
if ((recvd = gitno_recv(buf)) < 0)
|
771
|
+
return recvd;
|
803
772
|
|
804
773
|
if (recvd == 0) {
|
805
774
|
giterr_set(GITERR_NET, "early EOF");
|
806
|
-
|
807
|
-
goto done;
|
775
|
+
return GIT_EEOF;
|
808
776
|
}
|
809
777
|
continue;
|
810
778
|
}
|
@@ -816,7 +784,7 @@ static int parse_report(transport_smart *transport, git_push *push)
|
|
816
784
|
switch (pkt->type) {
|
817
785
|
case GIT_PKT_DATA:
|
818
786
|
/* This is a sideband packet which contains other packets */
|
819
|
-
error = add_push_report_sideband_pkt(push, (git_pkt_data *)pkt
|
787
|
+
error = add_push_report_sideband_pkt(push, (git_pkt_data *)pkt);
|
820
788
|
break;
|
821
789
|
case GIT_PKT_ERR:
|
822
790
|
giterr_set(GITERR_NET, "report-status: Error reported: %s",
|
@@ -837,24 +805,12 @@ static int parse_report(transport_smart *transport, git_push *push)
|
|
837
805
|
git_pkt_free(pkt);
|
838
806
|
|
839
807
|
/* add_push_report_pkt returns GIT_ITEROVER when it receives a flush */
|
840
|
-
if (error == GIT_ITEROVER)
|
841
|
-
|
842
|
-
if (data_pkt_buf.size > 0) {
|
843
|
-
/* If there was data remaining in the pack data buffer,
|
844
|
-
* then the server sent a partial pkt-line */
|
845
|
-
giterr_set(GITERR_NET, "Incomplete pack data pkt-line");
|
846
|
-
error = GIT_ERROR;
|
847
|
-
}
|
848
|
-
goto done;
|
849
|
-
}
|
808
|
+
if (error == GIT_ITEROVER)
|
809
|
+
return 0;
|
850
810
|
|
851
|
-
if (error < 0)
|
852
|
-
|
853
|
-
}
|
811
|
+
if (error < 0)
|
812
|
+
return error;
|
854
813
|
}
|
855
|
-
done:
|
856
|
-
git_buf_free(&data_pkt_buf);
|
857
|
-
return error;
|
858
814
|
}
|
859
815
|
|
860
816
|
static int add_ref_from_push_spec(git_vector *refs, push_spec *push_spec)
|
data/vendor/libgit2/src/tree.c
CHANGED
@@ -45,7 +45,7 @@ GIT_INLINE(git_filemode_t) normalize_filemode(git_filemode_t filemode)
|
|
45
45
|
if (GIT_MODE_TYPE(filemode) == GIT_FILEMODE_COMMIT)
|
46
46
|
return GIT_FILEMODE_COMMIT;
|
47
47
|
|
48
|
-
/* 12XXXX means
|
48
|
+
/* 12XXXX means commit */
|
49
49
|
if (GIT_MODE_TYPE(filemode) == GIT_FILEMODE_LINK)
|
50
50
|
return GIT_FILEMODE_LINK;
|
51
51
|
|
@@ -85,10 +85,9 @@ int git_tree_entry_icmp(const git_tree_entry *e1, const git_tree_entry *e2)
|
|
85
85
|
}
|
86
86
|
|
87
87
|
/**
|
88
|
-
* Allocate
|
89
|
-
* store the filename and the id.
|
88
|
+
* Allocate either from the pool or from the system allocator
|
90
89
|
*/
|
91
|
-
static git_tree_entry *
|
90
|
+
static git_tree_entry *alloc_entry_base(git_pool *pool, const char *filename, size_t filename_len)
|
92
91
|
{
|
93
92
|
git_tree_entry *entry = NULL;
|
94
93
|
size_t tree_len;
|
@@ -96,32 +95,44 @@ static git_tree_entry *alloc_entry(const char *filename, size_t filename_len, co
|
|
96
95
|
TREE_ENTRY_CHECK_NAMELEN(filename_len);
|
97
96
|
|
98
97
|
if (GIT_ADD_SIZET_OVERFLOW(&tree_len, sizeof(git_tree_entry), filename_len) ||
|
99
|
-
GIT_ADD_SIZET_OVERFLOW(&tree_len, tree_len, 1)
|
100
|
-
GIT_ADD_SIZET_OVERFLOW(&tree_len, tree_len, GIT_OID_RAWSZ))
|
98
|
+
GIT_ADD_SIZET_OVERFLOW(&tree_len, tree_len, 1))
|
101
99
|
return NULL;
|
102
100
|
|
103
|
-
entry =
|
101
|
+
entry = pool ? git_pool_malloc(pool, tree_len) :
|
102
|
+
git__malloc(tree_len);
|
104
103
|
if (!entry)
|
105
104
|
return NULL;
|
106
105
|
|
107
|
-
|
108
|
-
|
109
|
-
|
106
|
+
memset(entry, 0x0, sizeof(git_tree_entry));
|
107
|
+
memcpy(entry->filename, filename, filename_len);
|
108
|
+
entry->filename[filename_len] = 0;
|
109
|
+
entry->filename_len = (uint16_t)filename_len;
|
110
110
|
|
111
|
-
|
112
|
-
|
113
|
-
entry->filename = filename_ptr;
|
111
|
+
return entry;
|
112
|
+
}
|
114
113
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
114
|
+
/**
|
115
|
+
* Allocate a tree entry, using the poolin the tree which owns
|
116
|
+
* it. This is useful when reading trees, so we don't allocate a ton
|
117
|
+
* of small strings but can use the pool.
|
118
|
+
*/
|
119
|
+
static git_tree_entry *alloc_entry_pooled(git_pool *pool, const char *filename, size_t filename_len)
|
120
|
+
{
|
121
|
+
git_tree_entry *entry = NULL;
|
119
122
|
|
120
|
-
entry
|
123
|
+
if (!(entry = alloc_entry_base(pool, filename, filename_len)))
|
124
|
+
return NULL;
|
125
|
+
|
126
|
+
entry->pooled = true;
|
121
127
|
|
122
128
|
return entry;
|
123
129
|
}
|
124
130
|
|
131
|
+
static git_tree_entry *alloc_entry(const char *filename)
|
132
|
+
{
|
133
|
+
return alloc_entry_base(NULL, filename, strlen(filename));
|
134
|
+
}
|
135
|
+
|
125
136
|
struct tree_key_search {
|
126
137
|
const char *filename;
|
127
138
|
uint16_t filename_len;
|
@@ -163,10 +174,7 @@ static int homing_search_cmp(const void *key, const void *array_member)
|
|
163
174
|
* around the area for our target file.
|
164
175
|
*/
|
165
176
|
static int tree_key_search(
|
166
|
-
size_t *at_pos,
|
167
|
-
const git_tree *tree,
|
168
|
-
const char *filename,
|
169
|
-
size_t filename_len)
|
177
|
+
size_t *at_pos, git_vector *entries, const char *filename, size_t filename_len)
|
170
178
|
{
|
171
179
|
struct tree_key_search ksearch;
|
172
180
|
const git_tree_entry *entry;
|
@@ -179,15 +187,13 @@ static int tree_key_search(
|
|
179
187
|
|
180
188
|
/* Initial homing search; find an entry on the tree with
|
181
189
|
* the same prefix as the filename we're looking for */
|
182
|
-
|
183
|
-
if (git_array_search(&homing,
|
184
|
-
tree->entries, &homing_search_cmp, &ksearch) < 0)
|
190
|
+
if (git_vector_bsearch2(&homing, entries, &homing_search_cmp, &ksearch) < 0)
|
185
191
|
return GIT_ENOTFOUND; /* just a signal error; not passed back to user */
|
186
192
|
|
187
193
|
/* We found a common prefix. Look forward as long as
|
188
194
|
* there are entries that share the common prefix */
|
189
|
-
for (i = homing; i <
|
190
|
-
entry =
|
195
|
+
for (i = homing; i < entries->length; ++i) {
|
196
|
+
entry = entries->contents[i];
|
191
197
|
|
192
198
|
if (homing_search_cmp(&ksearch, entry) < 0)
|
193
199
|
break;
|
@@ -207,7 +213,7 @@ static int tree_key_search(
|
|
207
213
|
i = homing - 1;
|
208
214
|
|
209
215
|
do {
|
210
|
-
entry =
|
216
|
+
entry = entries->contents[i];
|
211
217
|
|
212
218
|
if (homing_search_cmp(&ksearch, entry) > 0)
|
213
219
|
break;
|
@@ -228,7 +234,7 @@ static int tree_key_search(
|
|
228
234
|
|
229
235
|
void git_tree_entry_free(git_tree_entry *entry)
|
230
236
|
{
|
231
|
-
if (entry == NULL)
|
237
|
+
if (entry == NULL || entry->pooled)
|
232
238
|
return;
|
233
239
|
|
234
240
|
git__free(entry);
|
@@ -236,26 +242,36 @@ void git_tree_entry_free(git_tree_entry *entry)
|
|
236
242
|
|
237
243
|
int git_tree_entry_dup(git_tree_entry **dest, const git_tree_entry *source)
|
238
244
|
{
|
239
|
-
|
245
|
+
size_t total_size;
|
246
|
+
git_tree_entry *copy;
|
240
247
|
|
241
248
|
assert(source);
|
242
249
|
|
243
|
-
|
244
|
-
|
245
|
-
return -1;
|
250
|
+
GITERR_CHECK_ALLOC_ADD(&total_size, sizeof(git_tree_entry), source->filename_len);
|
251
|
+
GITERR_CHECK_ALLOC_ADD(&total_size, total_size, 1);
|
246
252
|
|
247
|
-
|
253
|
+
copy = git__malloc(total_size);
|
254
|
+
GITERR_CHECK_ALLOC(copy);
|
248
255
|
|
249
|
-
|
256
|
+
memcpy(copy, source, total_size);
|
257
|
+
|
258
|
+
copy->pooled = 0;
|
259
|
+
|
260
|
+
*dest = copy;
|
250
261
|
return 0;
|
251
262
|
}
|
252
263
|
|
253
264
|
void git_tree__free(void *_tree)
|
254
265
|
{
|
255
266
|
git_tree *tree = _tree;
|
267
|
+
size_t i;
|
268
|
+
git_tree_entry *e;
|
269
|
+
|
270
|
+
git_vector_foreach(&tree->entries, i, e)
|
271
|
+
git_tree_entry_free(e);
|
256
272
|
|
257
|
-
|
258
|
-
|
273
|
+
git_vector_free(&tree->entries);
|
274
|
+
git_pool_clear(&tree->pool);
|
259
275
|
git__free(tree);
|
260
276
|
}
|
261
277
|
|
@@ -278,7 +294,7 @@ const char *git_tree_entry_name(const git_tree_entry *entry)
|
|
278
294
|
const git_oid *git_tree_entry_id(const git_tree_entry *entry)
|
279
295
|
{
|
280
296
|
assert(entry);
|
281
|
-
return entry->oid;
|
297
|
+
return &entry->oid;
|
282
298
|
}
|
283
299
|
|
284
300
|
git_otype git_tree_entry_type(const git_tree_entry *entry)
|
@@ -299,7 +315,7 @@ int git_tree_entry_to_object(
|
|
299
315
|
const git_tree_entry *entry)
|
300
316
|
{
|
301
317
|
assert(entry && object_out);
|
302
|
-
return git_object_lookup(object_out, repo, entry->oid, GIT_OBJ_ANY);
|
318
|
+
return git_object_lookup(object_out, repo, &entry->oid, GIT_OBJ_ANY);
|
303
319
|
}
|
304
320
|
|
305
321
|
static const git_tree_entry *entry_fromname(
|
@@ -307,10 +323,13 @@ static const git_tree_entry *entry_fromname(
|
|
307
323
|
{
|
308
324
|
size_t idx;
|
309
325
|
|
310
|
-
|
326
|
+
/* be safe when we cast away constness - i.e. don't trigger a sort */
|
327
|
+
assert(git_vector_is_sorted(&tree->entries));
|
328
|
+
|
329
|
+
if (tree_key_search(&idx, (git_vector *)&tree->entries, name, name_len) < 0)
|
311
330
|
return NULL;
|
312
331
|
|
313
|
-
return
|
332
|
+
return git_vector_get(&tree->entries, idx);
|
314
333
|
}
|
315
334
|
|
316
335
|
const git_tree_entry *git_tree_entry_byname(
|
@@ -325,7 +344,7 @@ const git_tree_entry *git_tree_entry_byindex(
|
|
325
344
|
const git_tree *tree, size_t idx)
|
326
345
|
{
|
327
346
|
assert(tree);
|
328
|
-
return
|
347
|
+
return git_vector_get(&tree->entries, idx);
|
329
348
|
}
|
330
349
|
|
331
350
|
const git_tree_entry *git_tree_entry_byid(
|
@@ -336,8 +355,8 @@ const git_tree_entry *git_tree_entry_byid(
|
|
336
355
|
|
337
356
|
assert(tree);
|
338
357
|
|
339
|
-
|
340
|
-
if (memcmp(&e->oid
|
358
|
+
git_vector_foreach(&tree->entries, i, e) {
|
359
|
+
if (memcmp(&e->oid.id, &id->id, sizeof(id->id)) == 0)
|
341
360
|
return e;
|
342
361
|
}
|
343
362
|
|
@@ -346,6 +365,7 @@ const git_tree_entry *git_tree_entry_byid(
|
|
346
365
|
|
347
366
|
int git_tree__prefix_position(const git_tree *tree, const char *path)
|
348
367
|
{
|
368
|
+
const git_vector *entries = &tree->entries;
|
349
369
|
struct tree_key_search ksearch;
|
350
370
|
size_t at_pos, path_len;
|
351
371
|
|
@@ -358,20 +378,21 @@ int git_tree__prefix_position(const git_tree *tree, const char *path)
|
|
358
378
|
ksearch.filename = path;
|
359
379
|
ksearch.filename_len = (uint16_t)path_len;
|
360
380
|
|
381
|
+
/* be safe when we cast away constness - i.e. don't trigger a sort */
|
382
|
+
assert(git_vector_is_sorted(&tree->entries));
|
383
|
+
|
361
384
|
/* Find tree entry with appropriate prefix */
|
362
|
-
|
363
|
-
&at_pos,
|
385
|
+
git_vector_bsearch2(
|
386
|
+
&at_pos, (git_vector *)entries, &homing_search_cmp, &ksearch);
|
364
387
|
|
365
|
-
for (; at_pos <
|
366
|
-
const git_tree_entry *entry =
|
388
|
+
for (; at_pos < entries->length; ++at_pos) {
|
389
|
+
const git_tree_entry *entry = entries->contents[at_pos];
|
367
390
|
if (homing_search_cmp(&ksearch, entry) < 0)
|
368
391
|
break;
|
369
392
|
}
|
370
393
|
|
371
394
|
for (; at_pos > 0; --at_pos) {
|
372
|
-
const git_tree_entry *entry =
|
373
|
-
git_array_get(tree->entries, at_pos - 1);
|
374
|
-
|
395
|
+
const git_tree_entry *entry = entries->contents[at_pos - 1];
|
375
396
|
if (homing_search_cmp(&ksearch, entry) > 0)
|
376
397
|
break;
|
377
398
|
}
|
@@ -382,7 +403,7 @@ int git_tree__prefix_position(const git_tree *tree, const char *path)
|
|
382
403
|
size_t git_tree_entrycount(const git_tree *tree)
|
383
404
|
{
|
384
405
|
assert(tree);
|
385
|
-
return tree->entries.
|
406
|
+
return tree->entries.length;
|
386
407
|
}
|
387
408
|
|
388
409
|
unsigned int git_treebuilder_entrycount(git_treebuilder *bld)
|
@@ -423,18 +444,13 @@ static int parse_mode(unsigned int *modep, const char *buffer, const char **buff
|
|
423
444
|
int git_tree__parse(void *_tree, git_odb_object *odb_obj)
|
424
445
|
{
|
425
446
|
git_tree *tree = _tree;
|
426
|
-
const char *buffer;
|
427
|
-
const char *buffer_end;
|
447
|
+
const char *buffer = git_odb_object_data(odb_obj);
|
448
|
+
const char *buffer_end = buffer + git_odb_object_size(odb_obj);
|
428
449
|
|
429
|
-
|
450
|
+
git_pool_init(&tree->pool, 1);
|
451
|
+
if (git_vector_init(&tree->entries, DEFAULT_TREE_SIZE, entry_sort_cmp) < 0)
|
430
452
|
return -1;
|
431
453
|
|
432
|
-
buffer = git_odb_object_data(tree->odb_obj);
|
433
|
-
buffer_end = buffer + git_odb_object_size(tree->odb_obj);
|
434
|
-
|
435
|
-
git_array_init_to_size(tree->entries, DEFAULT_TREE_SIZE);
|
436
|
-
GITERR_CHECK_ARRAY(tree->entries);
|
437
|
-
|
438
454
|
while (buffer < buffer_end) {
|
439
455
|
git_tree_entry *entry;
|
440
456
|
size_t filename_len;
|
@@ -447,27 +463,28 @@ int git_tree__parse(void *_tree, git_odb_object *odb_obj)
|
|
447
463
|
if ((nul = memchr(buffer, 0, buffer_end - buffer)) == NULL)
|
448
464
|
return tree_error("Failed to parse tree. Object is corrupted", NULL);
|
449
465
|
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
if ((buffer_end - (nul + 1)) < GIT_OID_RAWSZ)
|
454
|
-
return tree_error("Failed to parse tree. Can't parse OID", NULL);
|
455
|
-
|
456
|
-
/* Allocate the entry */
|
466
|
+
filename_len = nul - buffer;
|
467
|
+
/** Allocate the entry and store it in the entries vector */
|
457
468
|
{
|
458
|
-
entry =
|
469
|
+
entry = alloc_entry_pooled(&tree->pool, buffer, filename_len);
|
459
470
|
GITERR_CHECK_ALLOC(entry);
|
460
471
|
|
472
|
+
if (git_vector_insert(&tree->entries, entry) < 0)
|
473
|
+
return -1;
|
474
|
+
|
461
475
|
entry->attr = attr;
|
462
|
-
entry->filename_len = filename_len;
|
463
|
-
entry->filename = buffer;
|
464
|
-
entry->oid = (git_oid *) ((char *) buffer + filename_len + 1);
|
465
476
|
}
|
466
477
|
|
478
|
+
/* Advance to the ID just after the path */
|
467
479
|
buffer += filename_len + 1;
|
480
|
+
|
481
|
+
git_oid_fromraw(&entry->oid, (const unsigned char *)buffer);
|
468
482
|
buffer += GIT_OID_RAWSZ;
|
469
483
|
}
|
470
484
|
|
485
|
+
/* The tree is sorted by definition. Bad inputs give bad outputs */
|
486
|
+
tree->entries.flags |= GIT_VECTOR_SORTED;
|
487
|
+
|
471
488
|
return 0;
|
472
489
|
}
|
473
490
|
|
@@ -500,9 +517,10 @@ static int append_entry(
|
|
500
517
|
if (!valid_entry_name(bld->repo, filename))
|
501
518
|
return tree_error("Failed to insert entry. Invalid name for a tree entry", filename);
|
502
519
|
|
503
|
-
entry = alloc_entry(filename
|
520
|
+
entry = alloc_entry(filename);
|
504
521
|
GITERR_CHECK_ALLOC(entry);
|
505
522
|
|
523
|
+
git_oid_cpy(&entry->oid, id);
|
506
524
|
entry->attr = (uint16_t)filemode;
|
507
525
|
|
508
526
|
git_strmap_insert(bld->map, entry->filename, entry, error);
|
@@ -691,10 +709,10 @@ int git_treebuilder_new(
|
|
691
709
|
if (source != NULL) {
|
692
710
|
git_tree_entry *entry_src;
|
693
711
|
|
694
|
-
|
712
|
+
git_vector_foreach(&source->entries, i, entry_src) {
|
695
713
|
if (append_entry(
|
696
714
|
bld, entry_src->filename,
|
697
|
-
entry_src->oid,
|
715
|
+
&entry_src->oid,
|
698
716
|
entry_src->attr) < 0)
|
699
717
|
goto on_error;
|
700
718
|
}
|
@@ -746,9 +764,8 @@ int git_treebuilder_insert(
|
|
746
764
|
pos = git_strmap_lookup_index(bld->map, filename);
|
747
765
|
if (git_strmap_valid_index(bld->map, pos)) {
|
748
766
|
entry = git_strmap_value_at(bld->map, pos);
|
749
|
-
git_oid_cpy((git_oid *) entry->oid, id);
|
750
767
|
} else {
|
751
|
-
entry = alloc_entry(filename
|
768
|
+
entry = alloc_entry(filename);
|
752
769
|
GITERR_CHECK_ALLOC(entry);
|
753
770
|
|
754
771
|
git_strmap_insert(bld->map, entry->filename, entry, error);
|
@@ -760,6 +777,7 @@ int git_treebuilder_insert(
|
|
760
777
|
}
|
761
778
|
}
|
762
779
|
|
780
|
+
git_oid_cpy(&entry->oid, id);
|
763
781
|
entry->attr = filemode;
|
764
782
|
|
765
783
|
if (entry_out)
|
@@ -830,20 +848,19 @@ int git_treebuilder_write(git_oid *oid, git_treebuilder *bld)
|
|
830
848
|
|
831
849
|
git_buf_printf(&tree, "%o ", entry->attr);
|
832
850
|
git_buf_put(&tree, entry->filename, entry->filename_len + 1);
|
833
|
-
git_buf_put(&tree, (char *)entry->oid
|
851
|
+
git_buf_put(&tree, (char *)entry->oid.id, GIT_OID_RAWSZ);
|
834
852
|
|
835
853
|
if (git_buf_oom(&tree))
|
836
854
|
error = -1;
|
837
855
|
}
|
838
856
|
|
857
|
+
git_vector_free(&entries);
|
839
858
|
|
840
859
|
if (!error &&
|
841
860
|
!(error = git_repository_odb__weakptr(&odb, bld->repo)))
|
842
861
|
error = git_odb_write(oid, odb, tree.ptr, tree.size, GIT_OBJ_TREE);
|
843
862
|
|
844
863
|
git_buf_free(&tree);
|
845
|
-
git_vector_free(&entries);
|
846
|
-
|
847
864
|
return error;
|
848
865
|
}
|
849
866
|
|
@@ -943,7 +960,7 @@ int git_tree_entry_bypath(
|
|
943
960
|
return git_tree_entry_dup(entry_out, entry);
|
944
961
|
}
|
945
962
|
|
946
|
-
if (git_tree_lookup(&subtree, root->object.repo, entry->oid) < 0)
|
963
|
+
if (git_tree_lookup(&subtree, root->object.repo, &entry->oid) < 0)
|
947
964
|
return -1;
|
948
965
|
|
949
966
|
error = git_tree_entry_bypath(
|
@@ -967,7 +984,7 @@ static int tree_walk(
|
|
967
984
|
size_t i;
|
968
985
|
const git_tree_entry *entry;
|
969
986
|
|
970
|
-
|
987
|
+
git_vector_foreach(&tree->entries, i, entry) {
|
971
988
|
if (preorder) {
|
972
989
|
error = callback(path->ptr, entry, payload);
|
973
990
|
if (error < 0) { /* negative value stops iteration */
|
@@ -984,7 +1001,7 @@ static int tree_walk(
|
|
984
1001
|
git_tree *subtree;
|
985
1002
|
size_t path_len = git_buf_len(path);
|
986
1003
|
|
987
|
-
error = git_tree_lookup(&subtree, tree->object.repo, entry->oid);
|
1004
|
+
error = git_tree_lookup(&subtree, tree->object.repo, &entry->oid);
|
988
1005
|
if (error < 0)
|
989
1006
|
break;
|
990
1007
|
|