rugged 0.24.6.1 → 0.25.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (213) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +1 -1
  3. data/ext/rugged/extconf.rb +9 -2
  4. data/ext/rugged/rugged.c +85 -21
  5. data/ext/rugged/rugged.h +7 -21
  6. data/ext/rugged/rugged_backend.c +3 -20
  7. data/ext/rugged/rugged_blame.c +7 -24
  8. data/ext/rugged/rugged_blob.c +136 -59
  9. data/ext/rugged/rugged_branch.c +3 -20
  10. data/ext/rugged/rugged_branch_collection.c +3 -20
  11. data/ext/rugged/rugged_commit.c +251 -101
  12. data/ext/rugged/rugged_config.c +3 -20
  13. data/ext/rugged/rugged_cred.c +3 -20
  14. data/ext/rugged/rugged_diff.c +3 -20
  15. data/ext/rugged/rugged_diff_delta.c +3 -20
  16. data/ext/rugged/rugged_diff_hunk.c +3 -20
  17. data/ext/rugged/rugged_diff_line.c +3 -20
  18. data/ext/rugged/rugged_index.c +46 -229
  19. data/ext/rugged/rugged_note.c +3 -20
  20. data/ext/rugged/rugged_object.c +3 -20
  21. data/ext/rugged/rugged_patch.c +192 -34
  22. data/ext/rugged/rugged_rebase.c +90 -48
  23. data/ext/rugged/rugged_reference.c +4 -21
  24. data/ext/rugged/rugged_reference_collection.c +3 -20
  25. data/ext/rugged/rugged_remote.c +70 -42
  26. data/ext/rugged/rugged_remote_collection.c +3 -20
  27. data/ext/rugged/rugged_repo.c +50 -59
  28. data/ext/rugged/rugged_revwalk.c +4 -21
  29. data/ext/rugged/rugged_settings.c +3 -20
  30. data/ext/rugged/rugged_signature.c +3 -20
  31. data/ext/rugged/rugged_submodule.c +4 -21
  32. data/ext/rugged/rugged_submodule_collection.c +3 -20
  33. data/ext/rugged/rugged_tag.c +3 -20
  34. data/ext/rugged/rugged_tag_collection.c +3 -20
  35. data/ext/rugged/rugged_tree.c +189 -184
  36. data/lib/rugged/attributes.rb +5 -0
  37. data/lib/rugged/blob.rb +5 -0
  38. data/lib/rugged/branch.rb +6 -1
  39. data/lib/rugged/commit.rb +5 -0
  40. data/lib/rugged/console.rb +5 -0
  41. data/lib/rugged/credentials.rb +5 -0
  42. data/lib/rugged/diff/delta.rb +5 -0
  43. data/lib/rugged/diff/hunk.rb +5 -0
  44. data/lib/rugged/diff/line.rb +5 -0
  45. data/lib/rugged/diff.rb +5 -0
  46. data/lib/rugged/index.rb +120 -0
  47. data/lib/rugged/object.rb +5 -0
  48. data/lib/rugged/patch.rb +5 -0
  49. data/lib/rugged/reference.rb +5 -0
  50. data/lib/rugged/remote.rb +5 -0
  51. data/lib/rugged/repository.rb +9 -4
  52. data/lib/rugged/submodule_collection.rb +5 -0
  53. data/lib/rugged/tag.rb +5 -0
  54. data/lib/rugged/tree.rb +156 -1
  55. data/lib/rugged/version.rb +6 -1
  56. data/lib/rugged/walker.rb +5 -0
  57. data/lib/rugged.rb +5 -0
  58. data/vendor/libgit2/CMakeLists.txt +12 -2
  59. data/vendor/libgit2/include/git2/blob.h +39 -28
  60. data/vendor/libgit2/include/git2/commit.h +76 -0
  61. data/vendor/libgit2/include/git2/common.h +21 -1
  62. data/vendor/libgit2/include/git2/describe.h +5 -2
  63. data/vendor/libgit2/include/git2/diff.h +62 -7
  64. data/vendor/libgit2/include/git2/errors.h +2 -1
  65. data/vendor/libgit2/include/git2/index.h +25 -0
  66. data/vendor/libgit2/include/git2/merge.h +10 -1
  67. data/vendor/libgit2/include/git2/odb.h +47 -1
  68. data/vendor/libgit2/include/git2/pack.h +4 -4
  69. data/vendor/libgit2/include/git2/patch.h +1 -1
  70. data/vendor/libgit2/include/git2/proxy.h +92 -0
  71. data/vendor/libgit2/include/git2/refs.h +11 -0
  72. data/vendor/libgit2/include/git2/remote.h +21 -8
  73. data/vendor/libgit2/include/git2/repository.h +20 -1
  74. data/vendor/libgit2/include/git2/revwalk.h +4 -6
  75. data/vendor/libgit2/include/git2/signature.h +13 -0
  76. data/vendor/libgit2/include/git2/submodule.h +11 -3
  77. data/vendor/libgit2/include/git2/sys/merge.h +177 -0
  78. data/vendor/libgit2/include/git2/sys/odb_backend.h +11 -0
  79. data/vendor/libgit2/include/git2/sys/remote.h +16 -0
  80. data/vendor/libgit2/include/git2/sys/stream.h +2 -1
  81. data/vendor/libgit2/include/git2/sys/time.h +31 -0
  82. data/vendor/libgit2/include/git2/sys/transport.h +3 -1
  83. data/vendor/libgit2/include/git2/tag.h +9 -0
  84. data/vendor/libgit2/include/git2/transaction.h +9 -0
  85. data/vendor/libgit2/include/git2/tree.h +55 -0
  86. data/vendor/libgit2/include/git2/version.h +4 -4
  87. data/vendor/libgit2/include/git2.h +1 -0
  88. data/vendor/libgit2/src/annotated_commit.c +99 -80
  89. data/vendor/libgit2/src/annotated_commit.h +5 -2
  90. data/vendor/libgit2/src/apply.c +377 -0
  91. data/vendor/libgit2/src/apply.h +21 -0
  92. data/vendor/libgit2/src/array.h +0 -1
  93. data/vendor/libgit2/src/blob.c +71 -39
  94. data/vendor/libgit2/src/branch.c +7 -5
  95. data/vendor/libgit2/src/buffer.c +252 -20
  96. data/vendor/libgit2/src/buffer.h +8 -0
  97. data/vendor/libgit2/src/checkout.c +69 -42
  98. data/vendor/libgit2/src/clone.c +0 -8
  99. data/vendor/libgit2/src/commit.c +193 -49
  100. data/vendor/libgit2/src/commit_list.c +8 -3
  101. data/vendor/libgit2/src/commit_list.h +1 -0
  102. data/vendor/libgit2/src/common.h +2 -1
  103. data/vendor/libgit2/src/config.c +3 -3
  104. data/vendor/libgit2/src/config_file.c +20 -10
  105. data/vendor/libgit2/src/crlf.c +1 -0
  106. data/vendor/libgit2/src/curl_stream.c +106 -6
  107. data/vendor/libgit2/src/delta.c +238 -62
  108. data/vendor/libgit2/src/delta.h +79 -58
  109. data/vendor/libgit2/src/describe.c +1 -1
  110. data/vendor/libgit2/src/diff.c +32 -1554
  111. data/vendor/libgit2/src/diff.h +14 -122
  112. data/vendor/libgit2/src/diff_driver.c +4 -6
  113. data/vendor/libgit2/src/diff_file.c +3 -0
  114. data/vendor/libgit2/src/diff_generate.c +1613 -0
  115. data/vendor/libgit2/src/diff_generate.h +123 -0
  116. data/vendor/libgit2/src/diff_parse.c +101 -0
  117. data/vendor/libgit2/src/diff_parse.h +18 -0
  118. data/vendor/libgit2/src/diff_print.c +263 -144
  119. data/vendor/libgit2/src/diff_stats.c +21 -12
  120. data/vendor/libgit2/src/diff_tform.c +1 -0
  121. data/vendor/libgit2/src/diff_tform.h +22 -0
  122. data/vendor/libgit2/src/diff_xdiff.c +9 -9
  123. data/vendor/libgit2/src/diff_xdiff.h +5 -5
  124. data/vendor/libgit2/src/fetchhead.c +8 -8
  125. data/vendor/libgit2/src/filebuf.c +6 -1
  126. data/vendor/libgit2/src/filebuf.h +1 -0
  127. data/vendor/libgit2/src/fileops.c +22 -1
  128. data/vendor/libgit2/src/fileops.h +8 -2
  129. data/vendor/libgit2/src/fnmatch.c +18 -5
  130. data/vendor/libgit2/src/global.c +21 -4
  131. data/vendor/libgit2/src/global.h +6 -0
  132. data/vendor/libgit2/src/graph.c +1 -1
  133. data/vendor/libgit2/src/index.c +159 -46
  134. data/vendor/libgit2/src/index.h +2 -0
  135. data/vendor/libgit2/src/iterator.c +1573 -1468
  136. data/vendor/libgit2/src/iterator.h +52 -69
  137. data/vendor/libgit2/src/merge.c +163 -64
  138. data/vendor/libgit2/src/merge.h +61 -2
  139. data/vendor/libgit2/src/merge_driver.c +397 -0
  140. data/vendor/libgit2/src/merge_driver.h +60 -0
  141. data/vendor/libgit2/src/merge_file.c +11 -49
  142. data/vendor/libgit2/src/netops.c +12 -10
  143. data/vendor/libgit2/src/object_api.c +19 -1
  144. data/vendor/libgit2/src/odb.c +228 -52
  145. data/vendor/libgit2/src/odb_loose.c +19 -1
  146. data/vendor/libgit2/src/odb_mempack.c +1 -1
  147. data/vendor/libgit2/src/odb_pack.c +27 -1
  148. data/vendor/libgit2/src/openssl_stream.c +4 -5
  149. data/vendor/libgit2/src/pack-objects.c +105 -76
  150. data/vendor/libgit2/src/pack-objects.h +13 -12
  151. data/vendor/libgit2/src/pack.c +16 -10
  152. data/vendor/libgit2/src/pack.h +2 -0
  153. data/vendor/libgit2/src/patch.c +216 -0
  154. data/vendor/libgit2/src/patch.h +66 -0
  155. data/vendor/libgit2/src/{diff_patch.c → patch_generate.c} +203 -376
  156. data/vendor/libgit2/src/patch_generate.h +68 -0
  157. data/vendor/libgit2/src/patch_parse.c +1159 -0
  158. data/vendor/libgit2/src/patch_parse.h +56 -0
  159. data/vendor/libgit2/src/path.c +38 -2
  160. data/vendor/libgit2/src/path.h +18 -0
  161. data/vendor/libgit2/src/pathspec.c +1 -1
  162. data/vendor/libgit2/src/pool.h +5 -0
  163. data/vendor/libgit2/src/pqueue.c +12 -5
  164. data/vendor/libgit2/src/pqueue.h +1 -0
  165. data/vendor/libgit2/src/proxy.c +32 -0
  166. data/vendor/libgit2/src/proxy.h +14 -0
  167. data/vendor/libgit2/src/push.c +1 -1
  168. data/vendor/libgit2/src/rebase.c +63 -36
  169. data/vendor/libgit2/src/refdb.c +4 -2
  170. data/vendor/libgit2/src/refdb_fs.c +82 -54
  171. data/vendor/libgit2/src/refs.c +13 -1
  172. data/vendor/libgit2/src/remote.c +20 -81
  173. data/vendor/libgit2/src/repository.c +212 -29
  174. data/vendor/libgit2/src/reset.c +1 -1
  175. data/vendor/libgit2/src/revparse.c +1 -1
  176. data/vendor/libgit2/src/revwalk.c +260 -184
  177. data/vendor/libgit2/src/settings.c +11 -3
  178. data/vendor/libgit2/src/signature.c +27 -2
  179. data/vendor/libgit2/src/sortedcache.c +14 -5
  180. data/vendor/libgit2/src/stash.c +1 -0
  181. data/vendor/libgit2/src/status.c +1 -0
  182. data/vendor/libgit2/src/stransport_stream.c +4 -2
  183. data/vendor/libgit2/src/stream.h +2 -2
  184. data/vendor/libgit2/src/submodule.c +16 -4
  185. data/vendor/libgit2/src/sysdir.c +1 -1
  186. data/vendor/libgit2/src/transport.c +3 -5
  187. data/vendor/libgit2/src/transports/http.c +38 -13
  188. data/vendor/libgit2/src/transports/local.c +4 -1
  189. data/vendor/libgit2/src/transports/smart.c +6 -0
  190. data/vendor/libgit2/src/transports/smart.h +1 -0
  191. data/vendor/libgit2/src/transports/smart_pkt.c +5 -13
  192. data/vendor/libgit2/src/transports/smart_protocol.c +22 -7
  193. data/vendor/libgit2/src/transports/winhttp.c +144 -11
  194. data/vendor/libgit2/src/tree.c +267 -2
  195. data/vendor/libgit2/src/unix/posix.h +10 -0
  196. data/vendor/libgit2/src/unix/pthread.h +2 -0
  197. data/vendor/libgit2/src/util.c +25 -2
  198. data/vendor/libgit2/src/util.h +10 -0
  199. data/vendor/libgit2/src/varint.c +44 -0
  200. data/vendor/libgit2/src/varint.h +15 -0
  201. data/vendor/libgit2/src/vector.c +58 -0
  202. data/vendor/libgit2/src/vector.h +8 -0
  203. data/vendor/libgit2/src/win32/posix.h +3 -0
  204. data/vendor/libgit2/src/win32/thread.c +18 -0
  205. data/vendor/libgit2/src/win32/thread.h +2 -0
  206. data/vendor/libgit2/src/win32/w32_util.h +1 -1
  207. data/vendor/libgit2/src/zstream.c +37 -8
  208. data/vendor/libgit2/src/zstream.h +8 -1
  209. metadata +100 -82
  210. data/vendor/libgit2/Makefile.embed +0 -60
  211. data/vendor/libgit2/src/delta-apply.c +0 -166
  212. data/vendor/libgit2/src/delta-apply.h +0 -62
  213. data/vendor/libgit2/src/diff_patch.h +0 -83
@@ -917,7 +917,7 @@ int git_tree_entry_bypath(
917
917
 
918
918
  if (entry == NULL) {
919
919
  giterr_set(GITERR_TREE,
920
- "the path '%.*s' does not exist in the given tree", filename_len, path);
920
+ "the path '%.*s' does not exist in the given tree", (int) filename_len, path);
921
921
  return GIT_ENOTFOUND;
922
922
  }
923
923
 
@@ -927,7 +927,7 @@ int git_tree_entry_bypath(
927
927
  * then this entry *must* be a tree */
928
928
  if (!git_tree_entry__is_tree(entry)) {
929
929
  giterr_set(GITERR_TREE,
930
- "the path '%.*s' exists but is not a tree", filename_len, path);
930
+ "the path '%.*s' exists but is not a tree", (int) filename_len, path);
931
931
  return GIT_ENOTFOUND;
932
932
  }
933
933
 
@@ -1039,3 +1039,268 @@ int git_tree_walk(
1039
1039
  return error;
1040
1040
  }
1041
1041
 
1042
+ static int compare_entries(const void *_a, const void *_b)
1043
+ {
1044
+ const git_tree_update *a = (git_tree_update *) _a;
1045
+ const git_tree_update *b = (git_tree_update *) _b;
1046
+
1047
+ return strcmp(a->path, b->path);
1048
+ }
1049
+
1050
+ static int on_dup_entry(void **old, void *new)
1051
+ {
1052
+ GIT_UNUSED(old); GIT_UNUSED(new);
1053
+
1054
+ giterr_set(GITERR_TREE, "duplicate entries given for update");
1055
+ return -1;
1056
+ }
1057
+
1058
+ /*
1059
+ * We keep the previous tree and the new one at each level of the
1060
+ * stack. When we leave a level we're done with that tree and we can
1061
+ * write it out to the odb.
1062
+ */
1063
+ typedef struct {
1064
+ git_treebuilder *bld;
1065
+ git_tree *tree;
1066
+ char *name;
1067
+ } tree_stack_entry;
1068
+
1069
+ /** Count how many slashes (i.e. path components) there are in this string */
1070
+ GIT_INLINE(size_t) count_slashes(const char *path)
1071
+ {
1072
+ size_t count = 0;
1073
+ const char *slash;
1074
+
1075
+ while ((slash = strchr(path, '/')) != NULL) {
1076
+ count++;
1077
+ path = slash + 1;
1078
+ }
1079
+
1080
+ return count;
1081
+ }
1082
+
1083
+ static bool next_component(git_buf *out, const char *in)
1084
+ {
1085
+ const char *slash = strchr(in, '/');
1086
+
1087
+ git_buf_clear(out);
1088
+
1089
+ if (slash)
1090
+ git_buf_put(out, in, slash - in);
1091
+
1092
+ return !!slash;
1093
+ }
1094
+
1095
+ static int create_popped_tree(tree_stack_entry *current, tree_stack_entry *popped, git_buf *component)
1096
+ {
1097
+ int error;
1098
+ git_oid new_tree;
1099
+
1100
+ git_tree_free(popped->tree);
1101
+
1102
+ /* If the tree would be empty, remove it from the one higher up */
1103
+ if (git_treebuilder_entrycount(popped->bld) == 0) {
1104
+ git_treebuilder_free(popped->bld);
1105
+ error = git_treebuilder_remove(current->bld, popped->name);
1106
+ git__free(popped->name);
1107
+ return error;
1108
+ }
1109
+
1110
+ error = git_treebuilder_write(&new_tree, popped->bld);
1111
+ git_treebuilder_free(popped->bld);
1112
+
1113
+ if (error < 0) {
1114
+ git__free(popped->name);
1115
+ return error;
1116
+ }
1117
+
1118
+ /* We've written out the tree, now we have to put the new value into its parent */
1119
+ git_buf_clear(component);
1120
+ git_buf_puts(component, popped->name);
1121
+ git__free(popped->name);
1122
+
1123
+ GITERR_CHECK_ALLOC(component->ptr);
1124
+
1125
+ /* Error out if this would create a D/F conflict in this update */
1126
+ if (current->tree) {
1127
+ const git_tree_entry *to_replace;
1128
+ to_replace = git_tree_entry_byname(current->tree, component->ptr);
1129
+ if (to_replace && git_tree_entry_type(to_replace) != GIT_OBJ_TREE) {
1130
+ giterr_set(GITERR_TREE, "D/F conflict when updating tree");
1131
+ return -1;
1132
+ }
1133
+ }
1134
+
1135
+ return git_treebuilder_insert(NULL, current->bld, component->ptr, &new_tree, GIT_FILEMODE_TREE);
1136
+ }
1137
+
1138
+ int git_tree_create_updated(git_oid *out, git_repository *repo, git_tree *baseline, size_t nupdates, const git_tree_update *updates)
1139
+ {
1140
+ git_array_t(tree_stack_entry) stack = GIT_ARRAY_INIT;
1141
+ tree_stack_entry *root_elem;
1142
+ git_vector entries;
1143
+ int error;
1144
+ size_t i;
1145
+ git_buf component = GIT_BUF_INIT;
1146
+
1147
+ if ((error = git_vector_init(&entries, nupdates, compare_entries)) < 0)
1148
+ return error;
1149
+
1150
+ /* Sort the entries for treversal */
1151
+ for (i = 0 ; i < nupdates; i++) {
1152
+ if ((error = git_vector_insert_sorted(&entries, (void *) &updates[i], on_dup_entry)) < 0)
1153
+ goto cleanup;
1154
+ }
1155
+
1156
+ root_elem = git_array_alloc(stack);
1157
+ GITERR_CHECK_ALLOC(root_elem);
1158
+ memset(root_elem, 0, sizeof(*root_elem));
1159
+
1160
+ if (baseline && (error = git_tree_dup(&root_elem->tree, baseline)) < 0)
1161
+ goto cleanup;
1162
+
1163
+ if ((error = git_treebuilder_new(&root_elem->bld, repo, root_elem->tree)) < 0)
1164
+ goto cleanup;
1165
+
1166
+ for (i = 0; i < nupdates; i++) {
1167
+ const git_tree_update *last_update = i == 0 ? NULL : git_vector_get(&entries, i-1);
1168
+ const git_tree_update *update = git_vector_get(&entries, i);
1169
+ size_t common_prefix = 0, steps_up, j;
1170
+ const char *path;
1171
+
1172
+ /* Figure out how much we need to change from the previous tree */
1173
+ if (last_update)
1174
+ common_prefix = git_path_common_dirlen(last_update->path, update->path);
1175
+
1176
+ /*
1177
+ * The entries are sorted, so when we find we're no
1178
+ * longer in the same directory, we need to abandon
1179
+ * the old tree (steps up) and dive down to the next
1180
+ * one.
1181
+ */
1182
+ steps_up = last_update == NULL ? 0 : count_slashes(&last_update->path[common_prefix]);
1183
+
1184
+ for (j = 0; j < steps_up; j++) {
1185
+ tree_stack_entry *current, *popped = git_array_pop(stack);
1186
+ assert(popped);
1187
+
1188
+ current = git_array_last(stack);
1189
+ assert(current);
1190
+
1191
+ if ((error = create_popped_tree(current, popped, &component)) < 0)
1192
+ goto cleanup;
1193
+ }
1194
+
1195
+ /* Now that we've created the trees we popped from the stack, let's go back down */
1196
+ path = &update->path[common_prefix];
1197
+ while (next_component(&component, path)) {
1198
+ tree_stack_entry *last, *new_entry;
1199
+ const git_tree_entry *entry;
1200
+
1201
+ last = git_array_last(stack);
1202
+ entry = last->tree ? git_tree_entry_byname(last->tree, component.ptr) : NULL;
1203
+ if (!entry)
1204
+ entry = treebuilder_get(last->bld, component.ptr);
1205
+
1206
+ if (entry && git_tree_entry_type(entry) != GIT_OBJ_TREE) {
1207
+ giterr_set(GITERR_TREE, "D/F conflict when updating tree");
1208
+ error = -1;
1209
+ goto cleanup;
1210
+ }
1211
+
1212
+ new_entry = git_array_alloc(stack);
1213
+ GITERR_CHECK_ALLOC(new_entry);
1214
+ memset(new_entry, 0, sizeof(*new_entry));
1215
+
1216
+ new_entry->tree = NULL;
1217
+ if (entry && (error = git_tree_lookup(&new_entry->tree, repo, git_tree_entry_id(entry))) < 0)
1218
+ goto cleanup;
1219
+
1220
+ if ((error = git_treebuilder_new(&new_entry->bld, repo, new_entry->tree)) < 0)
1221
+ goto cleanup;
1222
+
1223
+ new_entry->name = git__strdup(component.ptr);
1224
+ GITERR_CHECK_ALLOC(new_entry->name);
1225
+
1226
+ /* Get to the start of the next component */
1227
+ path += component.size + 1;
1228
+ }
1229
+
1230
+ /* After all that, we're finally at the place where we want to perform the update */
1231
+ switch (update->action) {
1232
+ case GIT_TREE_UPDATE_UPSERT:
1233
+ {
1234
+ /* Make sure we're replacing something of the same type */
1235
+ tree_stack_entry *last = git_array_last(stack);
1236
+ char *basename = git_path_basename(update->path);
1237
+ const git_tree_entry *e = git_treebuilder_get(last->bld, basename);
1238
+ if (e && git_tree_entry_type(e) != git_object__type_from_filemode(update->filemode)) {
1239
+ git__free(basename);
1240
+ giterr_set(GITERR_TREE, "Cannot replace '%s' with '%s' at '%s'",
1241
+ git_object_type2string(git_tree_entry_type(e)),
1242
+ git_object_type2string(git_object__type_from_filemode(update->filemode)),
1243
+ update->path);
1244
+ error = -1;
1245
+ goto cleanup;
1246
+ }
1247
+
1248
+ error = git_treebuilder_insert(NULL, last->bld, basename, &update->id, update->filemode);
1249
+ git__free(basename);
1250
+ break;
1251
+ }
1252
+ case GIT_TREE_UPDATE_REMOVE:
1253
+ {
1254
+ char *basename = git_path_basename(update->path);
1255
+ error = git_treebuilder_remove(git_array_last(stack)->bld, basename);
1256
+ git__free(basename);
1257
+ break;
1258
+ }
1259
+ default:
1260
+ giterr_set(GITERR_TREE, "unkown action for update");
1261
+ error = -1;
1262
+ goto cleanup;
1263
+ }
1264
+
1265
+ if (error < 0)
1266
+ goto cleanup;
1267
+ }
1268
+
1269
+ /* We're done, go up the stack again and write out the tree */
1270
+ {
1271
+ tree_stack_entry *current = NULL, *popped = NULL;
1272
+ while ((popped = git_array_pop(stack)) != NULL) {
1273
+ current = git_array_last(stack);
1274
+ /* We've reached the top, current is the root tree */
1275
+ if (!current)
1276
+ break;
1277
+
1278
+ if ((error = create_popped_tree(current, popped, &component)) < 0)
1279
+ goto cleanup;
1280
+ }
1281
+
1282
+ /* Write out the root tree */
1283
+ git__free(popped->name);
1284
+ git_tree_free(popped->tree);
1285
+
1286
+ error = git_treebuilder_write(out, popped->bld);
1287
+ git_treebuilder_free(popped->bld);
1288
+ if (error < 0)
1289
+ goto cleanup;
1290
+ }
1291
+
1292
+ cleanup:
1293
+ {
1294
+ tree_stack_entry *e;
1295
+ while ((e = git_array_pop(stack)) != NULL) {
1296
+ git_treebuilder_free(e->bld);
1297
+ git_tree_free(e->tree);
1298
+ git__free(e->name);
1299
+ }
1300
+ }
1301
+
1302
+ git_buf_free(&component);
1303
+ git_array_clear(stack);
1304
+ git_vector_free(&entries);
1305
+ return error;
1306
+ }
@@ -80,4 +80,14 @@ GIT_INLINE(int) p_futimes(int f, const struct p_timeval t[2])
80
80
  # define p_futimes futimes
81
81
  #endif
82
82
 
83
+ #ifdef HAVE_REGCOMP_L
84
+ #include <xlocale.h>
85
+ GIT_INLINE(int) p_regcomp(regex_t *preg, const char *pattern, int cflags)
86
+ {
87
+ return regcomp_l(preg, pattern, cflags, (locale_t) 0);
88
+ }
89
+ #else
90
+ # define p_regcomp regcomp
91
+ #endif
92
+
83
93
  #endif
@@ -17,6 +17,8 @@ typedef struct {
17
17
  pthread_create(&(git_thread_ptr)->thread, NULL, start_routine, arg)
18
18
  #define git_thread_join(git_thread_ptr, status) \
19
19
  pthread_join((git_thread_ptr)->thread, status)
20
+ #define git_thread_currentid() ((size_t)(pthread_self()))
21
+ #define git_thread_exit(retval) pthread_exit(retval)
20
22
 
21
23
  /* Git Mutex */
22
24
  #define git_mutex pthread_mutex_t
@@ -65,6 +65,12 @@ int git_strarray_copy(git_strarray *tgt, const git_strarray *src)
65
65
  }
66
66
 
67
67
  int git__strtol64(int64_t *result, const char *nptr, const char **endptr, int base)
68
+ {
69
+
70
+ return git__strntol64(result, nptr, (size_t)-1, endptr, base);
71
+ }
72
+
73
+ int git__strntol64(int64_t *result, const char *nptr, size_t nptr_len, const char **endptr, int base)
68
74
  {
69
75
  const char *p;
70
76
  int64_t n, nn;
@@ -111,7 +117,7 @@ int git__strtol64(int64_t *result, const char *nptr, const char **endptr, int ba
111
117
  /*
112
118
  * Non-empty sequence of digits
113
119
  */
114
- for (;; p++,ndig++) {
120
+ for (; nptr_len > 0; p++,ndig++,nptr_len--) {
115
121
  c = *p;
116
122
  v = base;
117
123
  if ('0'<=c && c<='9')
@@ -147,12 +153,18 @@ Return:
147
153
  }
148
154
 
149
155
  int git__strtol32(int32_t *result, const char *nptr, const char **endptr, int base)
156
+ {
157
+
158
+ return git__strntol32(result, nptr, (size_t)-1, endptr, base);
159
+ }
160
+
161
+ int git__strntol32(int32_t *result, const char *nptr, size_t nptr_len, const char **endptr, int base)
150
162
  {
151
163
  int error;
152
164
  int32_t tmp_int;
153
165
  int64_t tmp_long;
154
166
 
155
- if ((error = git__strtol64(&tmp_long, nptr, endptr, base)) < 0)
167
+ if ((error = git__strntol64(&tmp_long, nptr, nptr_len, endptr, base)) < 0)
156
168
  return error;
157
169
 
158
170
  tmp_int = tmp_long & 0xFFFFFFFF;
@@ -321,6 +333,12 @@ char *git__strsep(char **end, const char *sep)
321
333
  return NULL;
322
334
  }
323
335
 
336
+ size_t git__linenlen(const char *buffer, size_t buffer_len)
337
+ {
338
+ char *nl = memchr(buffer, '\n', buffer_len);
339
+ return nl ? (size_t)(nl - buffer) + 1 : buffer_len;
340
+ }
341
+
324
342
  void git__hexdump(const char *buffer, size_t len)
325
343
  {
326
344
  static const size_t LINE_WIDTH = 16;
@@ -765,6 +783,11 @@ int git__utf8_iterate(const uint8_t *str, int str_len, int32_t *dst)
765
783
  return length;
766
784
  }
767
785
 
786
+ double git_time_monotonic(void)
787
+ {
788
+ return git__timer();
789
+ }
790
+
768
791
  #ifdef GIT_WIN32
769
792
  int git__getenv(git_buf *out, const char *name)
770
793
  {
@@ -263,7 +263,10 @@ GIT_INLINE(int) git__signum(int val)
263
263
  }
264
264
 
265
265
  extern int git__strtol32(int32_t *n, const char *buff, const char **end_buf, int base);
266
+ extern int git__strntol32(int32_t *n, const char *buff, size_t buff_len, const char **end_buf, int base);
266
267
  extern int git__strtol64(int64_t *n, const char *buff, const char **end_buf, int base);
268
+ extern int git__strntol64(int64_t *n, const char *buff, size_t buff_len, const char **end_buf, int base);
269
+
267
270
 
268
271
  extern void git__hexdump(const char *buffer, size_t n);
269
272
  extern uint32_t git__hash(const void *key, int len, uint32_t seed);
@@ -290,6 +293,8 @@ GIT_INLINE(int) git__tolower(int c)
290
293
  # define git__tolower(a) tolower(a)
291
294
  #endif
292
295
 
296
+ extern size_t git__linenlen(const char *buffer, size_t buffer_len);
297
+
293
298
  GIT_INLINE(const char *) git__next_line(const char *s)
294
299
  {
295
300
  while (*s && *s != '\n') s++;
@@ -466,6 +471,11 @@ GIT_INLINE(bool) git__iswildcard(int c)
466
471
  return (c == '*' || c == '?' || c == '[');
467
472
  }
468
473
 
474
+ GIT_INLINE(bool) git__isxdigit(int c)
475
+ {
476
+ return ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'));
477
+ }
478
+
469
479
  /*
470
480
  * Parse a string value as a boolean, just like Core Git does.
471
481
  *
@@ -0,0 +1,44 @@
1
+ /*
2
+ * Copyright (C) the libgit2 contributors. All rights reserved.
3
+ *
4
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
5
+ * a Linking Exception. For full terms see the included COPYING file.
6
+ */
7
+
8
+ #include "common.h"
9
+ #include "varint.h"
10
+
11
+ uintmax_t git_decode_varint(const unsigned char *bufp, size_t *varint_len)
12
+ {
13
+ const unsigned char *buf = bufp;
14
+ unsigned char c = *buf++;
15
+ uintmax_t val = c & 127;
16
+ while (c & 128) {
17
+ val += 1;
18
+ if (!val || MSB(val, 7)) {
19
+ /* This is not a valid varint_len, so it signals
20
+ the error */
21
+ *varint_len = 0;
22
+ return 0; /* overflow */
23
+ }
24
+ c = *buf++;
25
+ val = (val << 7) + (c & 127);
26
+ }
27
+ *varint_len = buf - bufp;
28
+ return val;
29
+ }
30
+
31
+ int git_encode_varint(unsigned char *buf, size_t bufsize, uintmax_t value)
32
+ {
33
+ unsigned char varint[16];
34
+ unsigned pos = sizeof(varint) - 1;
35
+ varint[pos] = value & 127;
36
+ while (value >>= 7)
37
+ varint[--pos] = 128 | (--value & 127);
38
+ if (buf) {
39
+ if (bufsize < pos)
40
+ return -1;
41
+ memcpy(buf, varint + pos, sizeof(varint) - pos);
42
+ }
43
+ return sizeof(varint) - pos;
44
+ }
@@ -0,0 +1,15 @@
1
+ /*
2
+ * Copyright (C) the libgit2 contributors. All rights reserved.
3
+ *
4
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
5
+ * a Linking Exception. For full terms see the included COPYING file.
6
+ */
7
+ #ifndef INCLUDE_varint_h__
8
+ #define INCLUDE_varint_h__
9
+
10
+ #include <stdint.h>
11
+
12
+ extern int git_encode_varint(unsigned char *, size_t, uintmax_t);
13
+ extern uintmax_t git_decode_varint(const unsigned char *, size_t *);
14
+
15
+ #endif
@@ -7,6 +7,7 @@
7
7
 
8
8
  #include "common.h"
9
9
  #include "vector.h"
10
+ #include "integer.h"
10
11
 
11
12
  /* In elements, not bytes */
12
13
  #define MIN_ALLOCSIZE 8
@@ -330,6 +331,47 @@ int git_vector_resize_to(git_vector *v, size_t new_length)
330
331
  return 0;
331
332
  }
332
333
 
334
+ int git_vector_insert_null(git_vector *v, size_t idx, size_t insert_len)
335
+ {
336
+ size_t new_length;
337
+
338
+ assert(insert_len > 0 && idx <= v->length);
339
+
340
+ GITERR_CHECK_ALLOC_ADD(&new_length, v->length, insert_len);
341
+
342
+ if (new_length > v->_alloc_size && resize_vector(v, new_length) < 0)
343
+ return -1;
344
+
345
+ memmove(&v->contents[idx + insert_len], &v->contents[idx],
346
+ sizeof(void *) * (v->length - idx));
347
+ memset(&v->contents[idx], 0, sizeof(void *) * insert_len);
348
+
349
+ v->length = new_length;
350
+ return 0;
351
+ }
352
+
353
+ int git_vector_remove_range(git_vector *v, size_t idx, size_t remove_len)
354
+ {
355
+ size_t new_length = v->length - remove_len;
356
+ size_t end_idx = 0;
357
+
358
+ assert(remove_len > 0);
359
+
360
+ if (git__add_sizet_overflow(&end_idx, idx, remove_len))
361
+ assert(0);
362
+
363
+ assert(end_idx <= v->length);
364
+
365
+ if (end_idx < v->length)
366
+ memmove(&v->contents[idx], &v->contents[end_idx],
367
+ sizeof(void *) * (v->length - end_idx));
368
+
369
+ memset(&v->contents[new_length], 0, sizeof(void *) * remove_len);
370
+
371
+ v->length = new_length;
372
+ return 0;
373
+ }
374
+
333
375
  int git_vector_set(void **old, git_vector *v, size_t position, void *value)
334
376
  {
335
377
  if (position + 1 > v->length) {
@@ -359,3 +401,19 @@ int git_vector_verify_sorted(const git_vector *v)
359
401
 
360
402
  return 0;
361
403
  }
404
+
405
+ void git_vector_reverse(git_vector *v)
406
+ {
407
+ size_t a, b;
408
+
409
+ a = 0;
410
+ b = v->length - 1;
411
+
412
+ while (a < b) {
413
+ void *tmp = v->contents[a];
414
+ v->contents[a] = v->contents[b];
415
+ v->contents[b] = tmp;
416
+ a++;
417
+ b--;
418
+ }
419
+ }
@@ -93,6 +93,9 @@ void git_vector_remove_matching(
93
93
  void *payload);
94
94
 
95
95
  int git_vector_resize_to(git_vector *v, size_t new_length);
96
+ int git_vector_insert_null(git_vector *v, size_t idx, size_t insert_len);
97
+ int git_vector_remove_range(git_vector *v, size_t idx, size_t remove_len);
98
+
96
99
  int git_vector_set(void **old, git_vector *v, size_t position, void *value);
97
100
 
98
101
  /** Check if vector is sorted */
@@ -115,4 +118,9 @@ GIT_INLINE(void) git_vector_set_cmp(git_vector *v, git_vector_cmp cmp)
115
118
  /* Just use this in tests, not for realz. returns -1 if not sorted */
116
119
  int git_vector_verify_sorted(const git_vector *v);
117
120
 
121
+ /**
122
+ * Reverse the vector in-place.
123
+ */
124
+ void git_vector_reverse(git_vector *v);
125
+
118
126
  #endif
@@ -57,4 +57,7 @@ extern int p_lstat_posixly(const char *filename, struct stat *buf);
57
57
  extern struct tm * p_localtime_r(const time_t *timer, struct tm *result);
58
58
  extern struct tm * p_gmtime_r(const time_t *timer, struct tm *result);
59
59
 
60
+ /* Use the bundled regcomp */
61
+ #define p_regcomp regcomp
62
+
60
63
  #endif
@@ -26,6 +26,9 @@ static DWORD WINAPI git_win32__threadproc(LPVOID lpParameter)
26
26
  {
27
27
  git_thread *thread = lpParameter;
28
28
 
29
+ /* Set the current thread for `git_thread_exit` */
30
+ GIT_GLOBAL->current_thread = thread;
31
+
29
32
  thread->result = thread->proc(thread->param);
30
33
 
31
34
  git__free_tls_data();
@@ -95,6 +98,21 @@ int git_thread_join(
95
98
  return 0;
96
99
  }
97
100
 
101
+ void git_thread_exit(void *value)
102
+ {
103
+ assert(GIT_GLOBAL->current_thread);
104
+ GIT_GLOBAL->current_thread->result = value;
105
+
106
+ git__free_tls_data();
107
+
108
+ ExitThread(CLEAN_THREAD_EXIT);
109
+ }
110
+
111
+ size_t git_thread_currentid(void)
112
+ {
113
+ return GetCurrentThreadId();
114
+ }
115
+
98
116
  int git_mutex_init(git_mutex *GIT_RESTRICT mutex)
99
117
  {
100
118
  InitializeCriticalSection(mutex);
@@ -41,6 +41,8 @@ int git_thread_create(git_thread *GIT_RESTRICT,
41
41
  void *(*) (void *),
42
42
  void *GIT_RESTRICT);
43
43
  int git_thread_join(git_thread *, void **);
44
+ size_t git_thread_currentid(void);
45
+ void git_thread_exit(void *);
44
46
 
45
47
  int git_mutex_init(git_mutex *GIT_RESTRICT mutex);
46
48
  int git_mutex_free(git_mutex *);
@@ -174,7 +174,7 @@ GIT_INLINE(int) git_win32__file_attribute_to_stat(
174
174
  /* st_size gets the UTF-8 length of the target name, in bytes,
175
175
  * not counting the NULL terminator */
176
176
  if ((st->st_size = git__utf16_to_8(NULL, 0, target)) < 0) {
177
- giterr_set(GITERR_OS, "Could not convert reparse point name for '%s'", path);
177
+ giterr_set(GITERR_OS, "Could not convert reparse point name for '%ls'", path);
178
178
  return -1;
179
179
  }
180
180
  }