rugged 0.23.0b2 → 0.23.0b4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (124) hide show
  1. checksums.yaml +4 -4
  2. data/ext/rugged/rugged_blob.c +39 -0
  3. data/ext/rugged/rugged_diff.c +7 -3
  4. data/ext/rugged/rugged_index.c +2 -2
  5. data/ext/rugged/rugged_remote.c +27 -148
  6. data/ext/rugged/rugged_remote_collection.c +134 -12
  7. data/ext/rugged/rugged_repo.c +74 -5
  8. data/ext/rugged/rugged_submodule.c +18 -208
  9. data/ext/rugged/rugged_submodule_collection.c +148 -0
  10. data/lib/rugged/version.rb +1 -1
  11. data/vendor/libgit2/AUTHORS +1 -0
  12. data/vendor/libgit2/CMakeLists.txt +33 -25
  13. data/vendor/libgit2/deps/winhttp/winhttp.def +29 -29
  14. data/vendor/libgit2/include/git2.h +1 -1
  15. data/vendor/libgit2/include/git2/blob.h +4 -6
  16. data/vendor/libgit2/include/git2/checkout.h +10 -1
  17. data/vendor/libgit2/include/git2/clone.h +6 -7
  18. data/vendor/libgit2/include/git2/commit.h +11 -0
  19. data/vendor/libgit2/include/git2/cred_helpers.h +2 -2
  20. data/vendor/libgit2/include/git2/describe.h +1 -1
  21. data/vendor/libgit2/include/git2/diff.h +68 -11
  22. data/vendor/libgit2/include/git2/errors.h +4 -1
  23. data/vendor/libgit2/include/git2/filter.h +16 -0
  24. data/vendor/libgit2/include/git2/index.h +38 -11
  25. data/vendor/libgit2/include/git2/odb.h +1 -1
  26. data/vendor/libgit2/include/git2/odb_backend.h +2 -2
  27. data/vendor/libgit2/include/git2/remote.h +300 -207
  28. data/vendor/libgit2/include/git2/reset.h +1 -0
  29. data/vendor/libgit2/include/git2/stash.h +135 -4
  30. data/vendor/libgit2/include/git2/status.h +1 -0
  31. data/vendor/libgit2/include/git2/submodule.h +46 -75
  32. data/vendor/libgit2/include/git2/sys/odb_backend.h +1 -1
  33. data/vendor/libgit2/include/git2/sys/stream.h +2 -0
  34. data/vendor/libgit2/include/git2/sys/transport.h +1 -21
  35. data/vendor/libgit2/include/git2/transport.h +27 -0
  36. data/vendor/libgit2/include/git2/types.h +20 -10
  37. data/vendor/libgit2/include/git2/version.h +3 -3
  38. data/vendor/libgit2/libgit2.pc.in +4 -2
  39. data/vendor/libgit2/src/attr.c +2 -1
  40. data/vendor/libgit2/src/attr_file.c +18 -37
  41. data/vendor/libgit2/src/blame.c +2 -2
  42. data/vendor/libgit2/src/blob.c +4 -3
  43. data/vendor/libgit2/src/branch.c +6 -3
  44. data/vendor/libgit2/src/buf_text.c +4 -6
  45. data/vendor/libgit2/src/buf_text.h +1 -2
  46. data/vendor/libgit2/src/buffer.c +8 -6
  47. data/vendor/libgit2/src/buffer.h +1 -1
  48. data/vendor/libgit2/src/cache.c +1 -0
  49. data/vendor/libgit2/src/checkout.c +34 -20
  50. data/vendor/libgit2/src/clone.c +29 -29
  51. data/vendor/libgit2/src/commit.c +65 -0
  52. data/vendor/libgit2/src/common.h +5 -0
  53. data/vendor/libgit2/src/config.c +20 -0
  54. data/vendor/libgit2/src/config.h +6 -0
  55. data/vendor/libgit2/src/config_file.c +2 -2
  56. data/vendor/libgit2/src/crlf.c +39 -17
  57. data/vendor/libgit2/src/curl_stream.c +257 -0
  58. data/vendor/libgit2/src/curl_stream.h +14 -0
  59. data/vendor/libgit2/src/diff.c +223 -88
  60. data/vendor/libgit2/src/diff.h +21 -1
  61. data/vendor/libgit2/src/diff_file.c +23 -13
  62. data/vendor/libgit2/src/diff_file.h +4 -2
  63. data/vendor/libgit2/src/diff_patch.c +266 -71
  64. data/vendor/libgit2/src/diff_patch.h +36 -0
  65. data/vendor/libgit2/src/diff_print.c +156 -126
  66. data/vendor/libgit2/src/diff_tform.c +32 -54
  67. data/vendor/libgit2/src/fetch.c +27 -10
  68. data/vendor/libgit2/src/fetch.h +2 -2
  69. data/vendor/libgit2/src/filebuf.c +1 -1
  70. data/vendor/libgit2/src/fileops.c +6 -2
  71. data/vendor/libgit2/src/filter.c +28 -7
  72. data/vendor/libgit2/src/fnmatch.c +5 -5
  73. data/vendor/libgit2/src/global.c +16 -0
  74. data/vendor/libgit2/src/ident.c +2 -2
  75. data/vendor/libgit2/src/ignore.c +1 -0
  76. data/vendor/libgit2/src/index.c +338 -80
  77. data/vendor/libgit2/src/index.h +4 -1
  78. data/vendor/libgit2/src/indexer.c +19 -5
  79. data/vendor/libgit2/src/iterator.c +118 -11
  80. data/vendor/libgit2/src/iterator.h +25 -0
  81. data/vendor/libgit2/src/merge.c +96 -106
  82. data/vendor/libgit2/src/merge.h +14 -4
  83. data/vendor/libgit2/src/netops.c +3 -3
  84. data/vendor/libgit2/src/odb.c +17 -9
  85. data/vendor/libgit2/src/odb.h +1 -1
  86. data/vendor/libgit2/src/odb_loose.c +2 -2
  87. data/vendor/libgit2/src/odb_pack.c +1 -1
  88. data/vendor/libgit2/src/openssl_stream.c +118 -27
  89. data/vendor/libgit2/src/pack-objects.c +28 -0
  90. data/vendor/libgit2/src/pack-objects.h +1 -0
  91. data/vendor/libgit2/src/pack.c +18 -10
  92. data/vendor/libgit2/src/path.c +16 -11
  93. data/vendor/libgit2/src/path.h +1 -1
  94. data/vendor/libgit2/src/push.c +26 -42
  95. data/vendor/libgit2/src/push.h +2 -34
  96. data/vendor/libgit2/src/rebase.c +1 -1
  97. data/vendor/libgit2/src/refs.c +1 -1
  98. data/vendor/libgit2/src/refspec.c +6 -0
  99. data/vendor/libgit2/src/remote.c +381 -274
  100. data/vendor/libgit2/src/remote.h +0 -4
  101. data/vendor/libgit2/src/repository.c +33 -12
  102. data/vendor/libgit2/src/repository.h +0 -1
  103. data/vendor/libgit2/src/reset.c +1 -0
  104. data/vendor/libgit2/src/stash.c +439 -17
  105. data/vendor/libgit2/src/status.c +6 -0
  106. data/vendor/libgit2/src/stransport_stream.c +58 -21
  107. data/vendor/libgit2/src/stream.h +15 -0
  108. data/vendor/libgit2/src/submodule.c +410 -664
  109. data/vendor/libgit2/src/submodule.h +0 -24
  110. data/vendor/libgit2/src/transaction.c +1 -0
  111. data/vendor/libgit2/src/transports/cred.c +55 -1
  112. data/vendor/libgit2/src/transports/http.c +18 -2
  113. data/vendor/libgit2/src/transports/local.c +60 -59
  114. data/vendor/libgit2/src/transports/smart.h +1 -1
  115. data/vendor/libgit2/src/transports/smart_protocol.c +11 -11
  116. data/vendor/libgit2/src/transports/ssh.c +46 -7
  117. data/vendor/libgit2/src/unix/posix.h +4 -0
  118. data/vendor/libgit2/src/util.c +9 -9
  119. data/vendor/libgit2/src/util.h +9 -0
  120. data/vendor/libgit2/src/win32/posix.h +3 -0
  121. data/vendor/libgit2/src/win32/posix_w32.c +38 -0
  122. data/vendor/libgit2/src/win32/w32_util.h +10 -0
  123. metadata +4 -3
  124. data/vendor/libgit2/include/git2/push.h +0 -94
@@ -150,6 +150,15 @@ static int checkout_notify(
150
150
  }
151
151
  }
152
152
 
153
+ GIT_INLINE(bool) is_workdir_base_or_new(
154
+ const git_oid *workdir_id,
155
+ const git_diff_file *baseitem,
156
+ const git_diff_file *newitem)
157
+ {
158
+ return (git_oid__cmp(&baseitem->id, workdir_id) == 0 ||
159
+ git_oid__cmp(&newitem->id, workdir_id) == 0);
160
+ }
161
+
153
162
  static bool checkout_is_workdir_modified(
154
163
  checkout_data *data,
155
164
  const git_diff_file *baseitem,
@@ -171,7 +180,7 @@ static bool checkout_is_workdir_modified(
171
180
  return true;
172
181
  }
173
182
 
174
- if (git_submodule_status(&sm_status, sm) < 0 ||
183
+ if (git_submodule_status(&sm_status, data->repo, wditem->path, GIT_SUBMODULE_IGNORE_UNSPECIFIED) < 0 ||
175
184
  GIT_SUBMODULE_STATUS_IS_WD_DIRTY(sm_status))
176
185
  rval = true;
177
186
  else if ((sm_oid = git_submodule_wd_id(sm)) == NULL)
@@ -193,8 +202,7 @@ static bool checkout_is_workdir_modified(
193
202
  if (wditem->mtime.seconds == ie->mtime.seconds &&
194
203
  wditem->mtime.nanoseconds == ie->mtime.nanoseconds &&
195
204
  wditem->file_size == ie->file_size)
196
- return (git_oid__cmp(&baseitem->id, &ie->id) != 0 &&
197
- git_oid_cmp(&newitem->id, &ie->id) != 0);
205
+ return !is_workdir_base_or_new(&ie->id, baseitem, newitem);
198
206
  }
199
207
 
200
208
  /* depending on where base is coming from, we may or may not know
@@ -203,10 +211,13 @@ static bool checkout_is_workdir_modified(
203
211
  if (baseitem->size && wditem->file_size != baseitem->size)
204
212
  return true;
205
213
 
206
- if (git_diff__oid_for_entry(&oid, data->diff, wditem, NULL) < 0)
214
+ if (git_diff__oid_for_entry(&oid, data->diff, wditem, wditem->mode, NULL) < 0)
207
215
  return false;
208
216
 
209
- return (git_oid__cmp(&baseitem->id, &oid) != 0);
217
+ /* Allow the checkout if the workdir is not modified *or* if the checkout
218
+ * target's contents are already in the working directory.
219
+ */
220
+ return !is_workdir_base_or_new(&oid, baseitem, newitem);
210
221
  }
211
222
 
212
223
  #define CHECKOUT_ACTION_IF(FLAG,YES,NO) \
@@ -1292,7 +1303,7 @@ static int checkout_get_actions(
1292
1303
  (int)counts[CHECKOUT_ACTION__CONFLICT],
1293
1304
  counts[CHECKOUT_ACTION__CONFLICT] == 1 ?
1294
1305
  "conflict prevents" : "conflicts prevent");
1295
- error = GIT_EMERGECONFLICT;
1306
+ error = GIT_ECONFLICT;
1296
1307
  goto fail;
1297
1308
  }
1298
1309
 
@@ -1849,11 +1860,6 @@ static int checkout_create_submodules(
1849
1860
  git_diff_delta *delta;
1850
1861
  size_t i;
1851
1862
 
1852
- /* initial reload of submodules if .gitmodules was changed */
1853
- if (data->reload_submodules &&
1854
- (error = git_submodule_reload_all(data->repo, 1)) < 0)
1855
- return error;
1856
-
1857
1863
  git_vector_foreach(&data->diff->deltas, i, delta) {
1858
1864
  if (actions[i] & CHECKOUT_ACTION__DEFER_REMOVE) {
1859
1865
  /* this has a blocker directory that should only be removed iff
@@ -1874,8 +1880,7 @@ static int checkout_create_submodules(
1874
1880
  }
1875
1881
  }
1876
1882
 
1877
- /* final reload once submodules have been updated */
1878
- return git_submodule_reload_all(data->repo, 1);
1883
+ return 0;
1879
1884
  }
1880
1885
 
1881
1886
  static int checkout_lookup_head_tree(git_tree **out, git_repository *repo)
@@ -2062,7 +2067,7 @@ static int checkout_write_merge(
2062
2067
 
2063
2068
  if (result.path == NULL || result.mode == 0) {
2064
2069
  giterr_set(GITERR_CHECKOUT, "Could not merge contents of file");
2065
- error = GIT_EMERGECONFLICT;
2070
+ error = GIT_ECONFLICT;
2066
2071
  goto done;
2067
2072
  }
2068
2073
 
@@ -2357,7 +2362,7 @@ static int checkout_data_init(
2357
2362
  /* cannot checkout if unresolved conflicts exist */
2358
2363
  if ((data->opts.checkout_strategy & GIT_CHECKOUT_FORCE) == 0 &&
2359
2364
  git_index_has_conflicts(data->index)) {
2360
- error = GIT_EMERGECONFLICT;
2365
+ error = GIT_ECONFLICT;
2361
2366
  giterr_set(GITERR_CHECKOUT,
2362
2367
  "unresolved conflicts exist in the index");
2363
2368
  goto cleanup;
@@ -2397,7 +2402,7 @@ static int checkout_data_init(
2397
2402
  &data->can_symlink, repo, GIT_CVAR_SYMLINKS)) < 0)
2398
2403
  goto cleanup;
2399
2404
 
2400
- if (!data->opts.baseline) {
2405
+ if (!data->opts.baseline && !data->opts.baseline_index) {
2401
2406
  data->opts_free_baseline = true;
2402
2407
 
2403
2408
  error = checkout_lookup_head_tree(&data->opts.baseline, repo);
@@ -2501,12 +2506,21 @@ int git_checkout_iterator(
2501
2506
  (error = git_iterator_for_workdir_ext(
2502
2507
  &workdir, data.repo, data.opts.target_directory, index, NULL,
2503
2508
  iterflags | GIT_ITERATOR_DONT_AUTOEXPAND,
2504
- data.pfx, data.pfx)) < 0 ||
2505
- (error = git_iterator_for_tree(
2506
- &baseline, data.opts.baseline,
2507
- iterflags, data.pfx, data.pfx)) < 0)
2509
+ data.pfx, data.pfx)) < 0)
2508
2510
  goto cleanup;
2509
2511
 
2512
+ if (data.opts.baseline_index) {
2513
+ if ((error = git_iterator_for_index(
2514
+ &baseline, data.opts.baseline_index,
2515
+ iterflags, data.pfx, data.pfx)) < 0)
2516
+ goto cleanup;
2517
+ } else {
2518
+ if ((error = git_iterator_for_tree(
2519
+ &baseline, data.opts.baseline,
2520
+ iterflags, data.pfx, data.pfx)) < 0)
2521
+ goto cleanup;
2522
+ }
2523
+
2510
2524
  /* Should not have case insensitivity mismatch */
2511
2525
  assert(git_iterator_ignore_case(workdir) == git_iterator_ignore_case(baseline));
2512
2526
 
@@ -24,7 +24,7 @@
24
24
  #include "repository.h"
25
25
  #include "odb.h"
26
26
 
27
- static int clone_local_into(git_repository *repo, git_remote *remote, const git_checkout_options *co_opts, const char *branch, int link);
27
+ static int clone_local_into(git_repository *repo, git_remote *remote, const git_fetch_options *fetch_opts, const git_checkout_options *co_opts, const char *branch, int link);
28
28
 
29
29
  static int create_branch(
30
30
  git_reference **branch,
@@ -242,13 +242,9 @@ static int default_remote_create(
242
242
  const char *url,
243
243
  void *payload)
244
244
  {
245
- int error;
246
- git_remote_callbacks *callbacks = payload;
247
-
248
- if ((error = git_remote_create(out, repo, name, url)) < 0)
249
- return error;
245
+ GIT_UNUSED(payload);
250
246
 
251
- return git_remote_set_callbacks(*out, callbacks);
247
+ return git_remote_create(out, repo, name, url);
252
248
  }
253
249
 
254
250
  /*
@@ -277,15 +273,12 @@ static int create_and_configure_origin(
277
273
 
278
274
  if (!remote_create) {
279
275
  remote_create = default_remote_create;
280
- payload = (void *)&options->remote_callbacks;
276
+ payload = NULL;
281
277
  }
282
278
 
283
279
  if ((error = remote_create(&origin, repo, "origin", url, payload)) < 0)
284
280
  goto on_error;
285
281
 
286
- if ((error = git_remote_save(origin)) < 0)
287
- goto on_error;
288
-
289
282
  *out = origin;
290
283
  return 0;
291
284
 
@@ -328,12 +321,12 @@ static int checkout_branch(git_repository *repo, git_remote *remote, const git_c
328
321
  return error;
329
322
  }
330
323
 
331
- static int clone_into(git_repository *repo, git_remote *_remote, const git_checkout_options *co_opts, const char *branch)
324
+ static int clone_into(git_repository *repo, git_remote *_remote, const git_fetch_options *opts, const git_checkout_options *co_opts, const char *branch)
332
325
  {
333
326
  int error;
334
327
  git_buf reflog_message = GIT_BUF_INIT;
328
+ git_fetch_options fetch_opts;
335
329
  git_remote *remote;
336
- const git_remote_callbacks *callbacks;
337
330
 
338
331
  assert(repo && _remote);
339
332
 
@@ -345,18 +338,12 @@ static int clone_into(git_repository *repo, git_remote *_remote, const git_check
345
338
  if ((error = git_remote_dup(&remote, _remote)) < 0)
346
339
  return error;
347
340
 
348
- callbacks = git_remote_get_callbacks(_remote);
349
- if (!giterr__check_version(callbacks, 1, "git_remote_callbacks") &&
350
- (error = git_remote_set_callbacks(remote, callbacks)) < 0)
351
- goto cleanup;
352
-
353
- if ((error = git_remote_add_fetch(remote, "refs/tags/*:refs/tags/*")) < 0)
354
- goto cleanup;
355
-
356
- git_remote_set_update_fetchhead(remote, 0);
341
+ memcpy(&fetch_opts, opts, sizeof(git_fetch_options));
342
+ fetch_opts.update_fetchhead = 0;
343
+ fetch_opts.download_tags = GIT_REMOTE_DOWNLOAD_TAGS_ALL;
357
344
  git_buf_printf(&reflog_message, "clone: from %s", git_remote_url(remote));
358
345
 
359
- if ((error = git_remote_fetch(remote, NULL, git_buf_cstr(&reflog_message))) != 0)
346
+ if ((error = git_remote_fetch(remote, NULL, &fetch_opts, git_buf_cstr(&reflog_message))) != 0)
360
347
  goto cleanup;
361
348
 
362
349
  error = checkout_branch(repo, remote, co_opts, branch, git_buf_cstr(&reflog_message));
@@ -439,11 +426,11 @@ int git_clone(
439
426
 
440
427
  if (clone_local == 1)
441
428
  error = clone_local_into(
442
- repo, origin, &options.checkout_opts,
429
+ repo, origin, &options.fetch_opts, &options.checkout_opts,
443
430
  options.checkout_branch, link);
444
431
  else if (clone_local == 0)
445
432
  error = clone_into(
446
- repo, origin, &options.checkout_opts,
433
+ repo, origin, &options.fetch_opts, &options.checkout_opts,
447
434
  options.checkout_branch);
448
435
  else
449
436
  error = -1;
@@ -506,7 +493,7 @@ static bool can_link(const char *src, const char *dst, int link)
506
493
  #endif
507
494
  }
508
495
 
509
- static int clone_local_into(git_repository *repo, git_remote *remote, const git_checkout_options *co_opts, const char *branch, int link)
496
+ static int clone_local_into(git_repository *repo, git_remote *remote, const git_fetch_options *fetch_opts, const git_checkout_options *co_opts, const char *branch, int link)
510
497
  {
511
498
  int error, flags;
512
499
  git_repository *src;
@@ -545,13 +532,26 @@ static int clone_local_into(git_repository *repo, git_remote *remote, const git_
545
532
  if (can_link(git_repository_path(src), git_repository_path(repo), link))
546
533
  flags |= GIT_CPDIR_LINK_FILES;
547
534
 
548
- if ((error = git_futils_cp_r(git_buf_cstr(&src_odb), git_buf_cstr(&dst_odb),
549
- flags, GIT_OBJECT_DIR_MODE)) < 0)
535
+ error = git_futils_cp_r(git_buf_cstr(&src_odb), git_buf_cstr(&dst_odb),
536
+ flags, GIT_OBJECT_DIR_MODE);
537
+
538
+ /*
539
+ * can_link() doesn't catch all variations, so if we hit an
540
+ * error and did want to link, let's try again without trying
541
+ * to link.
542
+ */
543
+ if (error < 0 && link) {
544
+ flags &= ~GIT_CPDIR_LINK_FILES;
545
+ error = git_futils_cp_r(git_buf_cstr(&src_odb), git_buf_cstr(&dst_odb),
546
+ flags, GIT_OBJECT_DIR_MODE);
547
+ }
548
+
549
+ if (error < 0)
550
550
  goto cleanup;
551
551
 
552
552
  git_buf_printf(&reflog_message, "clone: from %s", git_remote_url(remote));
553
553
 
554
- if ((error = git_remote_fetch(remote, NULL, git_buf_cstr(&reflog_message))) != 0)
554
+ if ((error = git_remote_fetch(remote, NULL, fetch_opts, git_buf_cstr(&reflog_message))) != 0)
555
555
  goto cleanup;
556
556
 
557
557
  error = checkout_branch(repo, remote, co_opts, branch, git_buf_cstr(&reflog_message));
@@ -309,6 +309,7 @@ int git_commit__parse(void *_commit, git_odb_object *odb_obj)
309
309
  const char *buffer_end = buffer_start + git_odb_object_size(odb_obj);
310
310
  git_oid parent_id;
311
311
  size_t header_len;
312
+ git_signature dummy_sig;
312
313
 
313
314
  buffer = buffer_start;
314
315
 
@@ -337,6 +338,15 @@ int git_commit__parse(void *_commit, git_odb_object *odb_obj)
337
338
  if (git_signature__parse(commit->author, &buffer, buffer_end, "author ", '\n') < 0)
338
339
  return -1;
339
340
 
341
+ /* Some tools create multiple author fields, ignore the extra ones */
342
+ while ((size_t)(buffer_end - buffer) >= strlen("author ") && !git__prefixcmp(buffer, "author ")) {
343
+ if (git_signature__parse(&dummy_sig, &buffer, buffer_end, "author ", '\n') < 0)
344
+ return -1;
345
+
346
+ git__free(dummy_sig.name);
347
+ git__free(dummy_sig.email);
348
+ }
349
+
340
350
  /* Always parse the committer; we need the commit time */
341
351
  commit->committer = git__malloc(sizeof(git_signature));
342
352
  GITERR_CHECK_ALLOC(commit->committer);
@@ -508,3 +518,58 @@ int git_commit_nth_gen_ancestor(
508
518
  *ancestor = parent;
509
519
  return 0;
510
520
  }
521
+
522
+ int git_commit_header_field(git_buf *out, const git_commit *commit, const char *field)
523
+ {
524
+ const char *buf = commit->raw_header;
525
+ const char *h, *eol;
526
+
527
+ git_buf_sanitize(out);
528
+ while ((h = strchr(buf, '\n')) && h[1] != '\0' && h[1] != '\n') {
529
+ h++;
530
+ if (git__prefixcmp(h, field)) {
531
+ buf = h;
532
+ continue;
533
+ }
534
+
535
+ h += strlen(field);
536
+ eol = strchr(h, '\n');
537
+ if (h[0] != ' ') {
538
+ buf = h;
539
+ continue;
540
+ }
541
+ if (!eol)
542
+ goto malformed;
543
+
544
+ h++; /* skip the SP */
545
+
546
+ git_buf_put(out, h, eol - h);
547
+ if (git_buf_oom(out))
548
+ goto oom;
549
+
550
+ /* If the next line starts with SP, it's multi-line, we must continue */
551
+ while (eol[1] == ' ') {
552
+ git_buf_putc(out, '\n');
553
+ h = eol + 2;
554
+ eol = strchr(h, '\n');
555
+ if (!eol)
556
+ goto malformed;
557
+
558
+ git_buf_put(out, h, eol - h);
559
+ }
560
+
561
+ if (git_buf_oom(out))
562
+ goto oom;
563
+
564
+ return 0;
565
+ }
566
+
567
+ return GIT_ENOTFOUND;
568
+
569
+ malformed:
570
+ giterr_set(GITERR_OBJECT, "malformed header");
571
+ return -1;
572
+ oom:
573
+ giterr_set_oom();
574
+ return -1;
575
+ }
@@ -68,6 +68,11 @@
68
68
 
69
69
  #include <regex.h>
70
70
 
71
+ #define DEFAULT_BUFSIZE 65536
72
+ #define FILEIO_BUFSIZE DEFAULT_BUFSIZE
73
+ #define FILTERIO_BUFSIZE DEFAULT_BUFSIZE
74
+ #define NETIO_BUFSIZE DEFAULT_BUFSIZE
75
+
71
76
  /**
72
77
  * Check a pointer allocation result, returning -1 if it failed.
73
78
  */
@@ -1194,6 +1194,26 @@ fail_parse:
1194
1194
  return -1;
1195
1195
  }
1196
1196
 
1197
+ int git_config_lookup_map_enum(git_cvar_t *type_out, const char **str_out,
1198
+ const git_cvar_map *maps, size_t map_n, int enum_val)
1199
+ {
1200
+ size_t i;
1201
+
1202
+ for (i = 0; i < map_n; i++) {
1203
+ const git_cvar_map *m = &maps[i];
1204
+
1205
+ if (m->map_value != enum_val)
1206
+ continue;
1207
+
1208
+ *type_out = m->cvar_type;
1209
+ *str_out = m->str_match;
1210
+ return 0;
1211
+ }
1212
+
1213
+ giterr_set(GITERR_CONFIG, "invalid enum value");
1214
+ return GIT_ENOTFOUND;
1215
+ }
1216
+
1197
1217
  int git_config_parse_bool(int *out, const char *value)
1198
1218
  {
1199
1219
  if (git__parse_bool(out, value) == 0)
@@ -82,4 +82,10 @@ extern int git_config__get_int_force(
82
82
  extern int git_config__cvar(
83
83
  int *out, git_config *config, git_cvar_cached cvar);
84
84
 
85
+ /**
86
+ * The opposite of git_config_lookup_map_value, we take an enum value
87
+ * and map it to the string or bool value on the config.
88
+ */
89
+ int git_config_lookup_map_enum(git_cvar_t *type_out, const char **str_out,
90
+ const git_cvar_map *maps, size_t map_n, int enum_val);
85
91
  #endif
@@ -156,7 +156,7 @@ int git_config_file_normalize_section(char *start, char *end)
156
156
  if (end && scan >= end)
157
157
  break;
158
158
  if (isalnum(*scan))
159
- *scan = (char)tolower(*scan);
159
+ *scan = (char)git__tolower(*scan);
160
160
  else if (*scan != '-' || scan == start)
161
161
  return GIT_EINVALIDSPEC;
162
162
  }
@@ -1083,7 +1083,7 @@ static int parse_section_header(struct reader *reader, char **section_out)
1083
1083
  goto fail_parse;
1084
1084
  }
1085
1085
 
1086
- name[name_length++] = (char) tolower(c);
1086
+ name[name_length++] = (char)git__tolower(c);
1087
1087
 
1088
1088
  } while ((c = line[pos++]) != ']');
1089
1089
 
@@ -193,28 +193,29 @@ static const char *line_ending(struct crlf_attrs *ca)
193
193
  case GIT_CRLF_CRLF:
194
194
  return "\r\n";
195
195
 
196
+ case GIT_CRLF_GUESS:
197
+ if (ca->auto_crlf == GIT_AUTO_CRLF_FALSE)
198
+ return "\n";
199
+ break;
200
+
196
201
  case GIT_CRLF_AUTO:
197
202
  case GIT_CRLF_TEXT:
198
- case GIT_CRLF_GUESS:
199
203
  break;
200
204
 
201
205
  default:
202
206
  goto line_ending_error;
203
207
  }
204
208
 
205
- switch (ca->eol) {
206
- case GIT_EOL_UNSET:
207
- return GIT_EOL_NATIVE == GIT_EOL_CRLF ? "\r\n" : "\n";
208
-
209
- case GIT_EOL_CRLF:
209
+ if (ca->auto_crlf == GIT_AUTO_CRLF_TRUE)
210
210
  return "\r\n";
211
-
212
- case GIT_EOL_LF:
211
+ else if (ca->auto_crlf == GIT_AUTO_CRLF_INPUT)
213
212
  return "\n";
214
-
215
- default:
216
- goto line_ending_error;
217
- }
213
+ else if (ca->eol == GIT_EOL_UNSET)
214
+ return GIT_EOL_NATIVE == GIT_EOL_CRLF ? "\r\n" : "\n";
215
+ else if (ca->eol == GIT_EOL_LF)
216
+ return "\n";
217
+ else if (ca->eol == GIT_EOL_CRLF)
218
+ return "\r\n";
218
219
 
219
220
  line_ending_error:
220
221
  giterr_set(GITERR_INVALID, "Invalid input to line ending filter");
@@ -224,16 +225,14 @@ line_ending_error:
224
225
  static int crlf_apply_to_workdir(
225
226
  struct crlf_attrs *ca, git_buf *to, const git_buf *from)
226
227
  {
228
+ git_buf_text_stats stats;
227
229
  const char *workdir_ending = NULL;
230
+ bool is_binary;
228
231
 
229
232
  /* Empty file? Nothing to do. */
230
233
  if (git_buf_len(from) == 0)
231
234
  return 0;
232
235
 
233
- /* Don't filter binary files */
234
- if (git_buf_text_is_binary(from))
235
- return GIT_PASSTHROUGH;
236
-
237
236
  /* Determine proper line ending */
238
237
  workdir_ending = line_ending(ca);
239
238
  if (!workdir_ending)
@@ -243,6 +242,29 @@ static int crlf_apply_to_workdir(
243
242
  if (strcmp(workdir_ending, "\r\n") != 0)
244
243
  return GIT_PASSTHROUGH;
245
244
 
245
+ /* If there are no LFs, or all LFs are part of a CRLF, nothing to do */
246
+ is_binary = git_buf_text_gather_stats(&stats, from, false);
247
+
248
+ if (stats.lf == 0 || stats.lf == stats.crlf)
249
+ return GIT_PASSTHROUGH;
250
+
251
+ if (ca->crlf_action == GIT_CRLF_AUTO ||
252
+ ca->crlf_action == GIT_CRLF_GUESS) {
253
+
254
+ /* If we have any existing CR or CRLF line endings, do nothing */
255
+ if (ca->crlf_action == GIT_CRLF_GUESS &&
256
+ stats.cr > 0 && stats.crlf > 0)
257
+ return GIT_PASSTHROUGH;
258
+
259
+ /* If we have bare CR characters, do nothing */
260
+ if (stats.cr != stats.crlf)
261
+ return GIT_PASSTHROUGH;
262
+
263
+ /* Don't filter binary files */
264
+ if (is_binary)
265
+ return GIT_PASSTHROUGH;
266
+ }
267
+
246
268
  return git_buf_text_lf_to_crlf(to, from);
247
269
  }
248
270
 
@@ -278,7 +300,7 @@ static int crlf_check(
278
300
  return GIT_PASSTHROUGH;
279
301
 
280
302
  if (ca.crlf_action == GIT_CRLF_GUESS ||
281
- (ca.crlf_action == GIT_CRLF_AUTO &&
303
+ ((ca.crlf_action == GIT_CRLF_AUTO || ca.crlf_action == GIT_CRLF_TEXT) &&
282
304
  git_filter_source_mode(src) == GIT_FILTER_SMUDGE)) {
283
305
 
284
306
  error = git_repository__cvar(