rugged 0.23.0b1 → 0.23.0b2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/ext/rugged/rugged_note.c +7 -2
  3. data/ext/rugged/rugged_revwalk.c +321 -145
  4. data/lib/rugged/version.rb +1 -1
  5. data/vendor/libgit2/CMakeLists.txt +83 -8
  6. data/vendor/libgit2/cmake/Modules/FindCoreFoundation.cmake +9 -0
  7. data/vendor/libgit2/cmake/Modules/FindIconv.cmake +0 -3
  8. data/vendor/libgit2/cmake/Modules/FindSecurity.cmake +9 -0
  9. data/vendor/libgit2/deps/winhttp/urlmon.h +45 -0
  10. data/vendor/libgit2/deps/winhttp/winhttp.def +29 -0
  11. data/vendor/libgit2/deps/winhttp/winhttp.h +592 -0
  12. data/vendor/libgit2/deps/winhttp/winhttp64.def +29 -0
  13. data/vendor/libgit2/include/git2/diff.h +6 -1
  14. data/vendor/libgit2/include/git2/index.h +1 -1
  15. data/vendor/libgit2/include/git2/merge.h +2 -1
  16. data/vendor/libgit2/include/git2/notes.h +2 -2
  17. data/vendor/libgit2/include/git2/pack.h +12 -0
  18. data/vendor/libgit2/include/git2/push.h +30 -0
  19. data/vendor/libgit2/include/git2/rebase.h +36 -16
  20. data/vendor/libgit2/include/git2/remote.h +6 -0
  21. data/vendor/libgit2/include/git2/reset.h +2 -2
  22. data/vendor/libgit2/include/git2/revwalk.h +10 -8
  23. data/vendor/libgit2/include/git2/submodule.h +16 -0
  24. data/vendor/libgit2/include/git2/sys/transport.h +12 -4
  25. data/vendor/libgit2/include/git2/types.h +1 -0
  26. data/vendor/libgit2/src/attr.c +3 -3
  27. data/vendor/libgit2/src/attr_file.c +24 -3
  28. data/vendor/libgit2/src/attr_file.h +3 -1
  29. data/vendor/libgit2/src/checkout.c +31 -7
  30. data/vendor/libgit2/src/config.c +5 -6
  31. data/vendor/libgit2/src/config_file.c +533 -469
  32. data/vendor/libgit2/src/describe.c +1 -1
  33. data/vendor/libgit2/src/diff.c +20 -10
  34. data/vendor/libgit2/src/diff_driver.c +1 -1
  35. data/vendor/libgit2/src/diff_tform.c +8 -2
  36. data/vendor/libgit2/src/filter.c +6 -3
  37. data/vendor/libgit2/src/global.c +17 -15
  38. data/vendor/libgit2/src/global.h +3 -1
  39. data/vendor/libgit2/src/ignore.c +48 -8
  40. data/vendor/libgit2/src/ignore.h +1 -1
  41. data/vendor/libgit2/src/index.c +12 -8
  42. data/vendor/libgit2/src/iterator.c +133 -12
  43. data/vendor/libgit2/src/netops.h +2 -2
  44. data/vendor/libgit2/src/notes.c +40 -21
  45. data/vendor/libgit2/src/openssl_stream.c +5 -1
  46. data/vendor/libgit2/src/pack-objects.c +36 -0
  47. data/vendor/libgit2/src/path.c +277 -140
  48. data/vendor/libgit2/src/path.h +132 -60
  49. data/vendor/libgit2/src/posix.h +0 -1
  50. data/vendor/libgit2/src/push.c +43 -4
  51. data/vendor/libgit2/src/push.h +8 -1
  52. data/vendor/libgit2/src/rebase.c +139 -119
  53. data/vendor/libgit2/src/reflog.c +1 -1
  54. data/vendor/libgit2/src/refs.c +3 -5
  55. data/vendor/libgit2/src/remote.c +6 -5
  56. data/vendor/libgit2/src/repository.c +7 -3
  57. data/vendor/libgit2/src/reset.c +3 -3
  58. data/vendor/libgit2/src/revwalk.c +26 -2
  59. data/vendor/libgit2/src/settings.c +3 -3
  60. data/vendor/libgit2/src/stransport_stream.c +249 -0
  61. data/vendor/libgit2/src/stransport_stream.h +14 -0
  62. data/vendor/libgit2/src/submodule.c +26 -2
  63. data/vendor/libgit2/src/tls_stream.c +28 -0
  64. data/vendor/libgit2/src/tls_stream.h +21 -0
  65. data/vendor/libgit2/src/transport.c +4 -4
  66. data/vendor/libgit2/src/transports/git.c +4 -1
  67. data/vendor/libgit2/src/transports/http.c +6 -4
  68. data/vendor/libgit2/src/transports/local.c +2 -1
  69. data/vendor/libgit2/src/transports/smart.c +1 -1
  70. data/vendor/libgit2/src/transports/ssh.c +5 -1
  71. data/vendor/libgit2/src/transports/winhttp.c +30 -23
  72. data/vendor/libgit2/src/tree.c +2 -2
  73. data/vendor/libgit2/src/unix/posix.h +1 -0
  74. data/vendor/libgit2/src/util.h +117 -0
  75. data/vendor/libgit2/src/win32/buffer.c +55 -0
  76. data/vendor/libgit2/src/win32/buffer.h +18 -0
  77. data/vendor/libgit2/src/win32/path_w32.c +75 -0
  78. data/vendor/libgit2/src/win32/path_w32.h +3 -0
  79. data/vendor/libgit2/src/win32/posix.h +2 -2
  80. data/vendor/libgit2/src/win32/posix_w32.c +2 -118
  81. data/vendor/libgit2/src/win32/pthread.c +2 -0
  82. data/vendor/libgit2/src/win32/utf-conv.c +0 -4
  83. data/vendor/libgit2/src/win32/utf-conv.h +4 -0
  84. data/vendor/libgit2/src/win32/w32_util.h +72 -0
  85. metadata +14 -2
@@ -10,6 +10,7 @@
10
10
  #include "repository.h"
11
11
  #ifdef GIT_WIN32
12
12
  #include "win32/posix.h"
13
+ #include "win32/buffer.h"
13
14
  #include "win32/w32_util.h"
14
15
  #else
15
16
  #include <dirent.h>
@@ -260,6 +261,20 @@ int git_path_root(const char *path)
260
261
  return -1; /* Not a real error - signals that path is not rooted */
261
262
  }
262
263
 
264
+ void git_path_trim_slashes(git_buf *path)
265
+ {
266
+ int ceiling = git_path_root(path->ptr) + 1;
267
+ assert(ceiling >= 0);
268
+
269
+ while (path->size > (size_t)ceiling) {
270
+ if (path->ptr[path->size-1] != '/')
271
+ break;
272
+
273
+ path->ptr[path->size-1] = '\0';
274
+ path->size--;
275
+ }
276
+ }
277
+
263
278
  int git_path_join_unrooted(
264
279
  git_buf *path_out, const char *path, const char *base, ssize_t *root_at)
265
280
  {
@@ -1006,12 +1021,12 @@ int git_path_direach(
1006
1021
  path_dirent_data de_data;
1007
1022
  struct dirent *de, *de_buf = (struct dirent *)&de_data;
1008
1023
 
1009
- GIT_UNUSED(flags);
1010
-
1011
1024
  #ifdef GIT_USE_ICONV
1012
1025
  git_path_iconv_t ic = GIT_PATH_ICONV_INIT;
1013
1026
  #endif
1014
1027
 
1028
+ GIT_UNUSED(flags);
1029
+
1015
1030
  if (git_path_to_dir(path) < 0)
1016
1031
  return -1;
1017
1032
 
@@ -1064,205 +1079,327 @@ int git_path_direach(
1064
1079
  return error;
1065
1080
  }
1066
1081
 
1067
- static int entry_path_alloc(
1068
- char **out,
1082
+ #if defined(GIT_WIN32) && !defined(__MINGW32__)
1083
+
1084
+ /* Using _FIND_FIRST_EX_LARGE_FETCH may increase performance in Windows 7
1085
+ * and better. Prior versions will ignore this.
1086
+ */
1087
+ #ifndef FIND_FIRST_EX_LARGE_FETCH
1088
+ # define FIND_FIRST_EX_LARGE_FETCH 2
1089
+ #endif
1090
+
1091
+ int git_path_diriter_init(
1092
+ git_path_diriter *diriter,
1069
1093
  const char *path,
1070
- size_t path_len,
1071
- const char *de_path,
1072
- size_t de_len,
1073
- size_t alloc_extra)
1094
+ unsigned int flags)
1074
1095
  {
1075
- int need_slash = (path_len > 0 && path[path_len-1] != '/') ? 1 : 0;
1076
- size_t alloc_size;
1077
- char *entry_path;
1096
+ git_win32_path path_filter;
1097
+ git_buf hack = {0};
1098
+
1099
+ assert(diriter && path);
1100
+
1101
+ memset(diriter, 0, sizeof(git_path_diriter));
1102
+ diriter->handle = INVALID_HANDLE_VALUE;
1078
1103
 
1079
- GITERR_CHECK_ALLOC_ADD(&alloc_size, path_len, de_len);
1080
- GITERR_CHECK_ALLOC_ADD(&alloc_size, alloc_size, need_slash);
1081
- GITERR_CHECK_ALLOC_ADD(&alloc_size, alloc_size, 1);
1082
- GITERR_CHECK_ALLOC_ADD(&alloc_size, alloc_size, alloc_extra);
1083
- entry_path = git__calloc(1, alloc_size);
1084
- GITERR_CHECK_ALLOC(entry_path);
1104
+ if (git_buf_puts(&diriter->path_utf8, path) < 0)
1105
+ return -1;
1106
+
1107
+ git_path_trim_slashes(&diriter->path_utf8);
1108
+
1109
+ if (diriter->path_utf8.size == 0) {
1110
+ giterr_set(GITERR_FILESYSTEM, "Could not open directory '%s'", path);
1111
+ return -1;
1112
+ }
1085
1113
 
1086
- if (path_len)
1087
- memcpy(entry_path, path, path_len);
1114
+ if ((diriter->parent_len = git_win32_path_from_utf8(diriter->path, diriter->path_utf8.ptr)) < 0 ||
1115
+ !git_win32__findfirstfile_filter(path_filter, diriter->path_utf8.ptr)) {
1116
+ giterr_set(GITERR_OS, "Could not parse the directory path '%s'", path);
1117
+ return -1;
1118
+ }
1088
1119
 
1089
- if (need_slash)
1090
- entry_path[path_len] = '/';
1120
+ diriter->handle = FindFirstFileExW(
1121
+ path_filter,
1122
+ FindExInfoBasic,
1123
+ &diriter->current,
1124
+ FindExSearchNameMatch,
1125
+ NULL,
1126
+ FIND_FIRST_EX_LARGE_FETCH);
1091
1127
 
1092
- memcpy(&entry_path[path_len + need_slash], de_path, de_len);
1128
+ if (diriter->handle == INVALID_HANDLE_VALUE) {
1129
+ giterr_set(GITERR_OS, "Could not open directory '%s'", path);
1130
+ return -1;
1131
+ }
1093
1132
 
1094
- *out = entry_path;
1133
+ diriter->parent_utf8_len = diriter->path_utf8.size;
1134
+ diriter->flags = flags;
1095
1135
  return 0;
1096
1136
  }
1097
1137
 
1098
- int git_path_dirload(
1099
- const char *path,
1100
- size_t prefix_len,
1101
- size_t alloc_extra,
1102
- unsigned int flags,
1103
- git_vector *contents)
1138
+ static int diriter_update_paths(git_path_diriter *diriter)
1104
1139
  {
1105
- int error;
1106
- DIR *dir;
1107
- size_t path_len;
1108
- path_dirent_data de_data;
1109
- struct dirent *de, *de_buf = (struct dirent *)&de_data;
1140
+ size_t filename_len, path_len;
1110
1141
 
1111
- GIT_UNUSED(flags);
1142
+ filename_len = wcslen(diriter->current.cFileName);
1112
1143
 
1113
- #ifdef GIT_USE_ICONV
1114
- git_path_iconv_t ic = GIT_PATH_ICONV_INIT;
1115
- #endif
1144
+ if (GIT_ADD_SIZET_OVERFLOW(&path_len, diriter->parent_len, filename_len) ||
1145
+ GIT_ADD_SIZET_OVERFLOW(&path_len, path_len, 2))
1146
+ return -1;
1147
+
1148
+ if (path_len > GIT_WIN_PATH_UTF16) {
1149
+ giterr_set(GITERR_FILESYSTEM,
1150
+ "invalid path '%.*ls\\%ls' (path too long)",
1151
+ diriter->parent_len, diriter->path, diriter->current.cFileName);
1152
+ return -1;
1153
+ }
1154
+
1155
+ diriter->path[diriter->parent_len] = L'\\';
1156
+ memcpy(&diriter->path[diriter->parent_len+1],
1157
+ diriter->current.cFileName, filename_len * sizeof(wchar_t));
1158
+ diriter->path[path_len-1] = L'\0';
1159
+
1160
+ git_buf_truncate(&diriter->path_utf8, diriter->parent_utf8_len);
1161
+ git_buf_putc(&diriter->path_utf8, '/');
1162
+ git_buf_put_w(&diriter->path_utf8, diriter->current.cFileName, filename_len);
1163
+
1164
+ if (git_buf_oom(&diriter->path_utf8))
1165
+ return -1;
1166
+
1167
+ return 0;
1168
+ }
1169
+
1170
+ int git_path_diriter_next(git_path_diriter *diriter)
1171
+ {
1172
+ bool skip_dot = !(diriter->flags & GIT_PATH_DIR_INCLUDE_DOT_AND_DOTDOT);
1173
+
1174
+ do {
1175
+ /* Our first time through, we already have the data from
1176
+ * FindFirstFileW. Use it, otherwise get the next file.
1177
+ */
1178
+ if (!diriter->needs_next)
1179
+ diriter->needs_next = 1;
1180
+ else if (!FindNextFileW(diriter->handle, &diriter->current))
1181
+ return GIT_ITEROVER;
1182
+ } while (skip_dot && git_path_is_dot_or_dotdotW(diriter->current.cFileName));
1183
+
1184
+ if (diriter_update_paths(diriter) < 0)
1185
+ return -1;
1186
+
1187
+ return 0;
1188
+ }
1189
+
1190
+ int git_path_diriter_filename(
1191
+ const char **out,
1192
+ size_t *out_len,
1193
+ git_path_diriter *diriter)
1194
+ {
1195
+ assert(out && out_len && diriter);
1196
+
1197
+ assert(diriter->path_utf8.size > diriter->parent_utf8_len);
1198
+
1199
+ *out = &diriter->path_utf8.ptr[diriter->parent_utf8_len+1];
1200
+ *out_len = diriter->path_utf8.size - diriter->parent_utf8_len - 1;
1201
+ return 0;
1202
+ }
1203
+
1204
+ int git_path_diriter_fullpath(
1205
+ const char **out,
1206
+ size_t *out_len,
1207
+ git_path_diriter *diriter)
1208
+ {
1209
+ assert(out && out_len && diriter);
1210
+
1211
+ *out = diriter->path_utf8.ptr;
1212
+ *out_len = diriter->path_utf8.size;
1213
+ return 0;
1214
+ }
1215
+
1216
+ int git_path_diriter_stat(struct stat *out, git_path_diriter *diriter)
1217
+ {
1218
+ assert(out && diriter);
1219
+
1220
+ return git_win32__file_attribute_to_stat(out,
1221
+ (WIN32_FILE_ATTRIBUTE_DATA *)&diriter->current,
1222
+ diriter->path);
1223
+ }
1224
+
1225
+ void git_path_diriter_free(git_path_diriter *diriter)
1226
+ {
1227
+ if (diriter == NULL)
1228
+ return;
1229
+
1230
+ if (diriter->handle != INVALID_HANDLE_VALUE) {
1231
+ FindClose(diriter->handle);
1232
+ diriter->handle = INVALID_HANDLE_VALUE;
1233
+ }
1234
+ }
1235
+
1236
+ #else
1116
1237
 
1117
- assert(path && contents);
1238
+ int git_path_diriter_init(
1239
+ git_path_diriter *diriter,
1240
+ const char *path,
1241
+ unsigned int flags)
1242
+ {
1243
+ assert(diriter && path);
1118
1244
 
1119
- path_len = strlen(path);
1245
+ memset(diriter, 0, sizeof(git_path_diriter));
1120
1246
 
1121
- if (!path_len || path_len < prefix_len) {
1122
- giterr_set(GITERR_INVALID, "Invalid directory path '%s'", path);
1247
+ if (git_buf_puts(&diriter->path, path) < 0)
1248
+ return -1;
1249
+
1250
+ git_path_trim_slashes(&diriter->path);
1251
+
1252
+ if (diriter->path.size == 0) {
1253
+ giterr_set(GITERR_FILESYSTEM, "Could not open directory '%s'", path);
1123
1254
  return -1;
1124
1255
  }
1125
- if ((dir = opendir(path)) == NULL) {
1256
+
1257
+ if ((diriter->dir = opendir(diriter->path.ptr)) == NULL) {
1258
+ git_buf_free(&diriter->path);
1259
+
1126
1260
  giterr_set(GITERR_OS, "Failed to open directory '%s'", path);
1127
1261
  return -1;
1128
1262
  }
1129
1263
 
1130
1264
  #ifdef GIT_USE_ICONV
1131
1265
  if ((flags & GIT_PATH_DIR_PRECOMPOSE_UNICODE) != 0)
1132
- (void)git_path_iconv_init_precompose(&ic);
1266
+ (void)git_path_iconv_init_precompose(&diriter->ic);
1133
1267
  #endif
1134
1268
 
1135
- path += prefix_len;
1136
- path_len -= prefix_len;
1269
+ diriter->parent_len = diriter->path.size;
1270
+ diriter->flags = flags;
1137
1271
 
1138
- while ((error = p_readdir_r(dir, de_buf, &de)) == 0 && de != NULL) {
1139
- char *entry_path, *de_path = de->d_name;
1140
- size_t de_len = strlen(de_path);
1272
+ return 0;
1273
+ }
1141
1274
 
1142
- if (git_path_is_dot_or_dotdot(de_path))
1143
- continue;
1275
+ int git_path_diriter_next(git_path_diriter *diriter)
1276
+ {
1277
+ struct dirent *de;
1278
+ const char *filename;
1279
+ size_t filename_len;
1280
+ bool skip_dot = !(diriter->flags & GIT_PATH_DIR_INCLUDE_DOT_AND_DOTDOT);
1281
+ int error = 0;
1144
1282
 
1145
- #ifdef GIT_USE_ICONV
1146
- if ((error = git_path_iconv(&ic, &de_path, &de_len)) < 0)
1147
- break;
1148
- #endif
1283
+ assert(diriter);
1149
1284
 
1150
- if ((error = entry_path_alloc(&entry_path,
1151
- path, path_len, de_path, de_len, alloc_extra)) < 0)
1152
- break;
1285
+ errno = 0;
1153
1286
 
1154
- if ((error = git_vector_insert(contents, entry_path)) < 0) {
1155
- git__free(entry_path);
1156
- break;
1287
+ do {
1288
+ if ((de = readdir(diriter->dir)) == NULL) {
1289
+ if (!errno)
1290
+ return GIT_ITEROVER;
1291
+
1292
+ giterr_set(GITERR_OS,
1293
+ "Could not read directory '%s'", diriter->path);
1294
+ return -1;
1157
1295
  }
1158
- }
1296
+ } while (skip_dot && git_path_is_dot_or_dotdot(de->d_name));
1159
1297
 
1160
- closedir(dir);
1298
+ filename = de->d_name;
1299
+ filename_len = strlen(filename);
1161
1300
 
1162
1301
  #ifdef GIT_USE_ICONV
1163
- git_path_iconv_clear(&ic);
1302
+ if ((diriter->flags & GIT_PATH_DIR_PRECOMPOSE_UNICODE) != 0 &&
1303
+ (error = git_path_iconv(&diriter->ic, (char **)&filename, &filename_len)) < 0)
1304
+ return error;
1164
1305
  #endif
1165
1306
 
1166
- if (error != 0)
1167
- giterr_set(GITERR_OS, "Failed to process directory entry in '%s'", path);
1307
+ git_buf_truncate(&diriter->path, diriter->parent_len);
1308
+ git_buf_putc(&diriter->path, '/');
1309
+ git_buf_put(&diriter->path, filename, filename_len);
1310
+
1311
+ if (git_buf_oom(&diriter->path))
1312
+ return -1;
1168
1313
 
1169
1314
  return error;
1170
1315
  }
1171
1316
 
1172
- int git_path_with_stat_cmp(const void *a, const void *b)
1317
+ int git_path_diriter_filename(
1318
+ const char **out,
1319
+ size_t *out_len,
1320
+ git_path_diriter *diriter)
1321
+ {
1322
+ assert(out && out_len && diriter);
1323
+
1324
+ assert(diriter->path.size > diriter->parent_len);
1325
+
1326
+ *out = &diriter->path.ptr[diriter->parent_len+1];
1327
+ *out_len = diriter->path.size - diriter->parent_len - 1;
1328
+ return 0;
1329
+ }
1330
+
1331
+ int git_path_diriter_fullpath(
1332
+ const char **out,
1333
+ size_t *out_len,
1334
+ git_path_diriter *diriter)
1173
1335
  {
1174
- const git_path_with_stat *psa = a, *psb = b;
1175
- return strcmp(psa->path, psb->path);
1336
+ assert(out && out_len && diriter);
1337
+
1338
+ *out = diriter->path.ptr;
1339
+ *out_len = diriter->path.size;
1340
+ return 0;
1176
1341
  }
1177
1342
 
1178
- int git_path_with_stat_cmp_icase(const void *a, const void *b)
1343
+ int git_path_diriter_stat(struct stat *out, git_path_diriter *diriter)
1179
1344
  {
1180
- const git_path_with_stat *psa = a, *psb = b;
1181
- return strcasecmp(psa->path, psb->path);
1345
+ assert(out && diriter);
1346
+
1347
+ return git_path_lstat(diriter->path.ptr, out);
1182
1348
  }
1183
1349
 
1184
- int git_path_dirload_with_stat(
1185
- const char *path,
1186
- size_t prefix_len,
1187
- unsigned int flags,
1188
- const char *start_stat,
1189
- const char *end_stat,
1190
- git_vector *contents)
1350
+ void git_path_diriter_free(git_path_diriter *diriter)
1191
1351
  {
1192
- int error;
1193
- unsigned int i;
1194
- git_path_with_stat *ps;
1195
- git_buf full = GIT_BUF_INIT;
1196
- int (*strncomp)(const char *a, const char *b, size_t sz);
1197
- size_t start_len = start_stat ? strlen(start_stat) : 0;
1198
- size_t end_len = end_stat ? strlen(end_stat) : 0, cmp_len;
1199
-
1200
- if (git_buf_set(&full, path, prefix_len) < 0)
1201
- return -1;
1352
+ if (diriter == NULL)
1353
+ return;
1202
1354
 
1203
- error = git_path_dirload(
1204
- path, prefix_len, sizeof(git_path_with_stat) + 1, flags, contents);
1205
- if (error < 0) {
1206
- git_buf_free(&full);
1207
- return error;
1355
+ if (diriter->dir) {
1356
+ closedir(diriter->dir);
1357
+ diriter->dir = NULL;
1208
1358
  }
1209
1359
 
1210
- strncomp = (flags & GIT_PATH_DIR_IGNORE_CASE) != 0 ?
1211
- git__strncasecmp : git__strncmp;
1360
+ #ifdef GIT_USE_ICONV
1361
+ git_path_iconv_clear(&diriter->ic);
1362
+ #endif
1212
1363
 
1213
- /* stat struct at start of git_path_with_stat, so shift path text */
1214
- git_vector_foreach(contents, i, ps) {
1215
- size_t path_len = strlen((char *)ps);
1216
- memmove(ps->path, ps, path_len + 1);
1217
- ps->path_len = path_len;
1218
- }
1364
+ git_buf_free(&diriter->path);
1365
+ }
1219
1366
 
1220
- git_vector_foreach(contents, i, ps) {
1221
- /* skip if before start_stat or after end_stat */
1222
- cmp_len = min(start_len, ps->path_len);
1223
- if (cmp_len && strncomp(ps->path, start_stat, cmp_len) < 0)
1224
- continue;
1225
- cmp_len = min(end_len, ps->path_len);
1226
- if (cmp_len && strncomp(ps->path, end_stat, cmp_len) > 0)
1227
- continue;
1367
+ #endif
1228
1368
 
1229
- git_buf_truncate(&full, prefix_len);
1369
+ int git_path_dirload(
1370
+ git_vector *contents,
1371
+ const char *path,
1372
+ size_t prefix_len,
1373
+ unsigned int flags)
1374
+ {
1375
+ git_path_diriter iter = GIT_PATH_DIRITER_INIT;
1376
+ const char *name;
1377
+ size_t name_len;
1378
+ char *dup;
1379
+ int error;
1230
1380
 
1231
- if ((error = git_buf_joinpath(&full, full.ptr, ps->path)) < 0 ||
1232
- (error = git_path_lstat(full.ptr, &ps->st)) < 0) {
1381
+ assert(contents && path);
1233
1382
 
1234
- if (error == GIT_ENOTFOUND) {
1235
- /* file was removed between readdir and lstat */
1236
- char *entry_path = git_vector_get(contents, i);
1237
- git_vector_remove(contents, i--);
1238
- git__free(entry_path);
1239
- } else {
1240
- /* Treat the file as unreadable if we get any other error */
1241
- memset(&ps->st, 0, sizeof(ps->st));
1242
- ps->st.st_mode = GIT_FILEMODE_UNREADABLE;
1243
- }
1383
+ if ((error = git_path_diriter_init(&iter, path, flags)) < 0)
1384
+ return error;
1244
1385
 
1245
- giterr_clear();
1246
- error = 0;
1247
- continue;
1248
- }
1386
+ while ((error = git_path_diriter_next(&iter)) == 0) {
1387
+ if ((error = git_path_diriter_fullpath(&name, &name_len, &iter)) < 0)
1388
+ break;
1249
1389
 
1250
- if (S_ISDIR(ps->st.st_mode)) {
1251
- ps->path[ps->path_len++] = '/';
1252
- ps->path[ps->path_len] = '\0';
1253
- }
1254
- else if (!S_ISREG(ps->st.st_mode) && !S_ISLNK(ps->st.st_mode)) {
1255
- char *entry_path = git_vector_get(contents, i);
1256
- git_vector_remove(contents, i--);
1257
- git__free(entry_path);
1258
- }
1259
- }
1390
+ assert(name_len > prefix_len);
1391
+
1392
+ dup = git__strndup(name + prefix_len, name_len - prefix_len);
1393
+ GITERR_CHECK_ALLOC(dup);
1260
1394
 
1261
- /* sort now that directory suffix is added */
1262
- git_vector_sort(contents);
1395
+ if ((error = git_vector_insert(contents, dup)) < 0)
1396
+ break;
1397
+ }
1263
1398
 
1264
- git_buf_free(&full);
1399
+ if (error == GIT_ITEROVER)
1400
+ error = 0;
1265
1401
 
1402
+ git_path_diriter_free(&iter);
1266
1403
  return error;
1267
1404
  }
1268
1405