rugged 0.24.6.1 → 0.25.0b1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|