rugged 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rugged/version.rb +1 -1
  3. data/vendor/libgit2/CMakeLists.txt +1 -1
  4. data/vendor/libgit2/cmake/FindLibSSH2.cmake +13 -0
  5. data/vendor/libgit2/include/git2/attr.h +7 -1
  6. data/vendor/libgit2/include/git2/blob.h +7 -1
  7. data/vendor/libgit2/include/git2/clone.h +1 -1
  8. data/vendor/libgit2/include/git2/common.h +19 -1
  9. data/vendor/libgit2/include/git2/deprecated.h +120 -0
  10. data/vendor/libgit2/include/git2/diff.h +3 -97
  11. data/vendor/libgit2/include/git2/email.h +127 -0
  12. data/vendor/libgit2/include/git2/filter.h +7 -1
  13. data/vendor/libgit2/include/git2/notes.h +2 -2
  14. data/vendor/libgit2/include/git2/oidarray.h +5 -8
  15. data/vendor/libgit2/include/git2/remote.h +4 -4
  16. data/vendor/libgit2/include/git2/repository.h +12 -10
  17. data/vendor/libgit2/include/git2/stash.h +1 -1
  18. data/vendor/libgit2/include/git2/stdint.h +3 -3
  19. data/vendor/libgit2/include/git2/sys/email.h +45 -0
  20. data/vendor/libgit2/include/git2/version.h +3 -3
  21. data/vendor/libgit2/include/git2.h +1 -0
  22. data/vendor/libgit2/src/CMakeLists.txt +7 -0
  23. data/vendor/libgit2/src/attr.c +24 -9
  24. data/vendor/libgit2/src/attr_file.c +23 -15
  25. data/vendor/libgit2/src/attr_file.h +3 -3
  26. data/vendor/libgit2/src/blame.c +4 -4
  27. data/vendor/libgit2/src/blame_git.c +1 -1
  28. data/vendor/libgit2/src/blob.c +15 -9
  29. data/vendor/libgit2/src/buffer.c +16 -8
  30. data/vendor/libgit2/src/buffer.h +2 -1
  31. data/vendor/libgit2/src/cc-compat.h +1 -7
  32. data/vendor/libgit2/src/checkout.c +6 -7
  33. data/vendor/libgit2/src/clone.c +1 -1
  34. data/vendor/libgit2/src/commit_graph.c +1 -1
  35. data/vendor/libgit2/src/config.c +1 -1
  36. data/vendor/libgit2/src/config_file.c +2 -2
  37. data/vendor/libgit2/src/config_parse.c +1 -1
  38. data/vendor/libgit2/src/describe.c +1 -1
  39. data/vendor/libgit2/src/diff.c +41 -173
  40. data/vendor/libgit2/src/email.c +299 -0
  41. data/vendor/libgit2/src/email.h +25 -0
  42. data/vendor/libgit2/src/filter.c +7 -1
  43. data/vendor/libgit2/src/hash/sha1/sha1dc/sha1.c +8 -8
  44. data/vendor/libgit2/src/ignore.c +2 -2
  45. data/vendor/libgit2/src/indexer.c +37 -3
  46. data/vendor/libgit2/src/libgit2.c +23 -0
  47. data/vendor/libgit2/src/merge.c +7 -4
  48. data/vendor/libgit2/src/notes.c +31 -31
  49. data/vendor/libgit2/src/oidarray.c +10 -1
  50. data/vendor/libgit2/src/path.c +1 -1
  51. data/vendor/libgit2/src/path.h +1 -1
  52. data/vendor/libgit2/src/pathspec.c +1 -1
  53. data/vendor/libgit2/src/refdb_fs.c +1 -1
  54. data/vendor/libgit2/src/refs.c +2 -2
  55. data/vendor/libgit2/src/refspec.c +1 -1
  56. data/vendor/libgit2/src/remote.c +12 -5
  57. data/vendor/libgit2/src/repository.c +130 -19
  58. data/vendor/libgit2/src/repository.h +4 -0
  59. data/vendor/libgit2/src/reset.c +1 -1
  60. data/vendor/libgit2/src/revparse.c +4 -4
  61. data/vendor/libgit2/src/stash.c +1 -1
  62. data/vendor/libgit2/src/streams/openssl_legacy.c +1 -1
  63. data/vendor/libgit2/src/streams/openssl_legacy.h +1 -1
  64. data/vendor/libgit2/src/threadstate.c +2 -1
  65. data/vendor/libgit2/src/trailer.c +1 -1
  66. data/vendor/libgit2/src/transports/ssh.c +4 -4
  67. data/vendor/libgit2/src/transports/winhttp.c +1 -1
  68. data/vendor/libgit2/src/util.c +1 -1
  69. data/vendor/libgit2/src/util.h +1 -1
  70. data/vendor/libgit2/src/win32/findfile.c +1 -1
  71. data/vendor/libgit2/src/win32/posix.h +6 -6
  72. data/vendor/libgit2/src/win32/posix_w32.c +9 -6
  73. metadata +11 -6
@@ -601,9 +601,10 @@ static void hash_partially(git_indexer *idx, const uint8_t *data, size_t size)
601
601
  idx->inbuf_len += size - to_expell;
602
602
  }
603
603
 
604
+ #if defined(NO_MMAP) || !defined(GIT_WIN32)
605
+
604
606
  static int write_at(git_indexer *idx, const void *data, off64_t offset, size_t size)
605
607
  {
606
- #ifdef NO_MMAP
607
608
  size_t remaining_size = size;
608
609
  const char *ptr = (const char *)data;
609
610
 
@@ -619,7 +620,31 @@ static int write_at(git_indexer *idx, const void *data, off64_t offset, size_t s
619
620
  offset += nb;
620
621
  remaining_size -= nb;
621
622
  }
623
+
624
+ return 0;
625
+ }
626
+
627
+ static int append_to_pack(git_indexer *idx, const void *data, size_t size)
628
+ {
629
+ if (write_at(idx, data, idx->pack->mwf.size, size) < 0) {
630
+ git_error_set(GIT_ERROR_OS, "cannot extend packfile '%s'", idx->pack->pack_name);
631
+ return -1;
632
+ }
633
+
634
+ return 0;
635
+ }
636
+
622
637
  #else
638
+
639
+ /*
640
+ * Windows may keep different views to a networked file for the mmap- and
641
+ * open-accessed versions of a file, so any writes done through
642
+ * `write(2)`/`pwrite(2)` may not be reflected on the data that `mmap(2)` is
643
+ * able to read.
644
+ */
645
+
646
+ static int write_at(git_indexer *idx, const void *data, off64_t offset, size_t size)
647
+ {
623
648
  git_file fd = idx->pack->mwf.fd;
624
649
  size_t mmap_alignment;
625
650
  size_t page_offset;
@@ -644,7 +669,6 @@ static int write_at(git_indexer *idx, const void *data, off64_t offset, size_t s
644
669
  map_data = (unsigned char *)map.data;
645
670
  memcpy(map_data + page_offset, data, size);
646
671
  p_munmap(&map);
647
- #endif
648
672
 
649
673
  return 0;
650
674
  }
@@ -680,6 +704,8 @@ static int append_to_pack(git_indexer *idx, const void *data, size_t size)
680
704
  return write_at(idx, data, idx->pack->mwf.size, size);
681
705
  }
682
706
 
707
+ #endif
708
+
683
709
  static int read_stream_object(git_indexer *idx, git_indexer_progress *stats)
684
710
  {
685
711
  git_packfile_stream *stream = &idx->stream;
@@ -1279,11 +1305,19 @@ int git_indexer_commit(git_indexer *idx, git_indexer_progress *stats)
1279
1305
  if (git_mwindow_free_all(&idx->pack->mwf) < 0)
1280
1306
  goto on_error;
1281
1307
 
1282
- /* Truncate file to undo rounding up to next page_size in append_to_pack */
1308
+ #if !defined(NO_MMAP) && defined(GIT_WIN32)
1309
+ /*
1310
+ * Some non-Windows remote filesystems fail when truncating files if the
1311
+ * file permissions change after opening the file (done by p_mkstemp).
1312
+ *
1313
+ * Truncation is only needed when mmap is used to undo rounding up to next
1314
+ * page_size in append_to_pack.
1315
+ */
1283
1316
  if (p_ftruncate(idx->pack->mwf.fd, idx->pack->mwf.size) < 0) {
1284
1317
  git_error_set(GIT_ERROR_OS, "failed to truncate pack file '%s'", idx->pack->pack_name);
1285
1318
  return -1;
1286
1319
  }
1320
+ #endif
1287
1321
 
1288
1322
  if (idx->do_fsync && p_fsync(idx->pack->mwf.fd) < 0) {
1289
1323
  git_error_set(GIT_ERROR_OS, "failed to fsync packfile");
@@ -52,6 +52,7 @@ static void libgit2_settings_global_shutdown(void)
52
52
  {
53
53
  git__free(git__user_agent);
54
54
  git__free(git__ssl_ciphers);
55
+ git_repository__free_extensions();
55
56
  }
56
57
 
57
58
  static int git_libgit2_settings_global_init(void)
@@ -367,6 +368,28 @@ int git_libgit2_opts(int key, ...)
367
368
  git_odb__loose_priority = va_arg(ap, int);
368
369
  break;
369
370
 
371
+ case GIT_OPT_SET_EXTENSIONS:
372
+ {
373
+ const char **extensions = va_arg(ap, const char **);
374
+ size_t len = va_arg(ap, size_t);
375
+ error = git_repository__set_extensions(extensions, len);
376
+ }
377
+ break;
378
+
379
+ case GIT_OPT_GET_EXTENSIONS:
380
+ {
381
+ git_strarray *out = va_arg(ap, git_strarray *);
382
+ char **extensions;
383
+ size_t len;
384
+
385
+ if ((error = git_repository__extensions(&extensions, &len)) < 0)
386
+ break;
387
+
388
+ out->strings = extensions;
389
+ out->count = len;
390
+ }
391
+ break;
392
+
370
393
  default:
371
394
  git_error_set(GIT_ERROR_INVALID, "invalid option key");
372
395
  error = -1;
@@ -816,8 +816,11 @@ static int merge_conflict_resolve_one_renamed(
816
816
  conflict->type == GIT_MERGE_DIFF_RENAMED_ADDED)
817
817
  return 0;
818
818
 
819
- ours_changed = (git_oid__cmp(&conflict->ancestor_entry.id, &conflict->our_entry.id) != 0);
820
- theirs_changed = (git_oid__cmp(&conflict->ancestor_entry.id, &conflict->their_entry.id) != 0);
819
+ ours_changed = (git_oid__cmp(&conflict->ancestor_entry.id, &conflict->our_entry.id) != 0) ||
820
+ (conflict->ancestor_entry.mode != conflict->our_entry.mode);
821
+
822
+ theirs_changed = (git_oid__cmp(&conflict->ancestor_entry.id, &conflict->their_entry.id) != 0) ||
823
+ (conflict->ancestor_entry.mode != conflict->their_entry.mode);
821
824
 
822
825
  /* if both are modified (and not to a common target) require a merge */
823
826
  if (ours_changed && theirs_changed &&
@@ -1151,7 +1154,7 @@ static void deletes_by_oid_free(git_oidmap *map) {
1151
1154
  git_oidmap_free(map);
1152
1155
  }
1153
1156
 
1154
- static int deletes_by_oid_enqueue(git_oidmap *map, git_pool* pool, const git_oid *id, size_t idx)
1157
+ static int deletes_by_oid_enqueue(git_oidmap *map, git_pool *pool, const git_oid *id, size_t idx)
1155
1158
  {
1156
1159
  deletes_by_oid_queue *queue;
1157
1160
  size_t *array_entry;
@@ -2366,7 +2369,7 @@ done:
2366
2369
 
2367
2370
  git_annotated_commit_free(other);
2368
2371
  git_annotated_commit_free(new_base);
2369
- git_oidarray_free(&bases);
2372
+ git_oidarray_dispose(&bases);
2370
2373
  git_array_clear(head_ids);
2371
2374
  return error;
2372
2375
  }
@@ -407,31 +407,33 @@ cleanup:
407
407
  return error;
408
408
  }
409
409
 
410
- static int note_get_default_ref(char **out, git_repository *repo)
410
+ static int note_get_default_ref(git_buf *out, git_repository *repo)
411
411
  {
412
412
  git_config *cfg;
413
- int ret = git_repository_config__weakptr(&cfg, repo);
413
+ int error;
414
+
415
+ if ((error = git_repository_config__weakptr(&cfg, repo)) < 0)
416
+ return error;
414
417
 
415
- *out = (ret != 0) ? NULL : git_config__get_string_force(
416
- cfg, "core.notesref", GIT_NOTES_DEFAULT_REF);
418
+ error = git_config_get_string_buf(out, cfg, "core.notesref");
417
419
 
418
- return ret;
420
+ if (error == GIT_ENOTFOUND)
421
+ error = git_buf_puts(out, GIT_NOTES_DEFAULT_REF);
422
+
423
+ return error;
419
424
  }
420
425
 
421
- static int normalize_namespace(char **out, git_repository *repo, const char *notes_ref)
426
+ static int normalize_namespace(git_buf *out, git_repository *repo, const char *notes_ref)
422
427
  {
423
- if (notes_ref) {
424
- *out = git__strdup(notes_ref);
425
- GIT_ERROR_CHECK_ALLOC(*out);
426
- return 0;
427
- }
428
+ if (notes_ref)
429
+ return git_buf_puts(out, notes_ref);
428
430
 
429
431
  return note_get_default_ref(out, repo);
430
432
  }
431
433
 
432
434
  static int retrieve_note_commit(
433
435
  git_commit **commit_out,
434
- char **notes_ref_out,
436
+ git_buf *notes_ref_out,
435
437
  git_repository *repo,
436
438
  const char *notes_ref)
437
439
  {
@@ -441,7 +443,7 @@ static int retrieve_note_commit(
441
443
  if ((error = normalize_namespace(notes_ref_out, repo, notes_ref)) < 0)
442
444
  return error;
443
445
 
444
- if ((error = git_reference_name_to_id(&oid, repo, *notes_ref_out)) < 0)
446
+ if ((error = git_reference_name_to_id(&oid, repo, notes_ref_out->ptr)) < 0)
445
447
  return error;
446
448
 
447
449
  if (git_commit_lookup(commit_out, repo, &oid) < 0)
@@ -476,7 +478,7 @@ int git_note_read(git_note **out, git_repository *repo,
476
478
  const char *notes_ref_in, const git_oid *oid)
477
479
  {
478
480
  int error;
479
- char *notes_ref = NULL;
481
+ git_buf notes_ref = GIT_BUF_INIT;
480
482
  git_commit *commit = NULL;
481
483
 
482
484
  error = retrieve_note_commit(&commit, &notes_ref, repo, notes_ref_in);
@@ -487,7 +489,7 @@ int git_note_read(git_note **out, git_repository *repo,
487
489
  error = git_note_commit_read(out, repo, commit, oid);
488
490
 
489
491
  cleanup:
490
- git__free(notes_ref);
492
+ git_buf_dispose(&notes_ref);
491
493
  git_commit_free(commit);
492
494
  return error;
493
495
  }
@@ -534,7 +536,7 @@ int git_note_create(
534
536
  int allow_note_overwrite)
535
537
  {
536
538
  int error;
537
- char *notes_ref = NULL;
539
+ git_buf notes_ref = GIT_BUF_INIT;
538
540
  git_commit *existing_notes_commit = NULL;
539
541
  git_reference *ref = NULL;
540
542
  git_oid notes_blob_oid, notes_commit_oid;
@@ -553,14 +555,14 @@ int git_note_create(
553
555
  if (error < 0)
554
556
  goto cleanup;
555
557
 
556
- error = git_reference_create(&ref, repo, notes_ref,
558
+ error = git_reference_create(&ref, repo, notes_ref.ptr,
557
559
  &notes_commit_oid, 1, NULL);
558
560
 
559
561
  if (out != NULL)
560
562
  git_oid_cpy(out, &notes_blob_oid);
561
563
 
562
564
  cleanup:
563
- git__free(notes_ref);
565
+ git_buf_dispose(&notes_ref);
564
566
  git_commit_free(existing_notes_commit);
565
567
  git_reference_free(ref);
566
568
  return error;
@@ -596,7 +598,7 @@ int git_note_remove(git_repository *repo, const char *notes_ref_in,
596
598
  const git_oid *oid)
597
599
  {
598
600
  int error;
599
- char *notes_ref_target = NULL;
601
+ git_buf notes_ref_target = GIT_BUF_INIT;
600
602
  git_commit *existing_notes_commit = NULL;
601
603
  git_oid new_notes_commit;
602
604
  git_reference *notes_ref = NULL;
@@ -612,11 +614,11 @@ int git_note_remove(git_repository *repo, const char *notes_ref_in,
612
614
  if (error < 0)
613
615
  goto cleanup;
614
616
 
615
- error = git_reference_create(&notes_ref, repo, notes_ref_target,
617
+ error = git_reference_create(&notes_ref, repo, notes_ref_target.ptr,
616
618
  &new_notes_commit, 1, NULL);
617
619
 
618
620
  cleanup:
619
- git__free(notes_ref_target);
621
+ git_buf_dispose(&notes_ref_target);
620
622
  git_reference_free(notes_ref);
621
623
  git_commit_free(existing_notes_commit);
622
624
  return error;
@@ -624,18 +626,16 @@ cleanup:
624
626
 
625
627
  int git_note_default_ref(git_buf *out, git_repository *repo)
626
628
  {
627
- char *default_ref;
628
629
  int error;
629
630
 
630
631
  GIT_ASSERT_ARG(out);
631
632
  GIT_ASSERT_ARG(repo);
632
633
 
633
634
  if ((error = git_buf_sanitize(out)) < 0 ||
634
- (error = note_get_default_ref(&default_ref, repo)) < 0)
635
- return error;
635
+ (error = note_get_default_ref(out, repo)) < 0)
636
+ git_buf_dispose(out);
636
637
 
637
- git_buf_attach(out, default_ref, strlen(default_ref));
638
- return 0;
638
+ return error;
639
639
  }
640
640
 
641
641
  const git_signature *git_note_committer(const git_note *note)
@@ -674,7 +674,7 @@ void git_note_free(git_note *note)
674
674
  }
675
675
 
676
676
  static int process_entry_path(
677
- const char* entry_path,
677
+ const char *entry_path,
678
678
  git_oid *annotated_object_id)
679
679
  {
680
680
  int error = 0;
@@ -780,7 +780,7 @@ int git_note_iterator_new(
780
780
  {
781
781
  int error;
782
782
  git_commit *commit = NULL;
783
- char *notes_ref;
783
+ git_buf notes_ref = GIT_BUF_INIT;
784
784
 
785
785
  error = retrieve_note_commit(&commit, &notes_ref, repo, notes_ref_in);
786
786
  if (error < 0)
@@ -789,15 +789,15 @@ int git_note_iterator_new(
789
789
  error = git_note_commit_iterator_new(it, commit);
790
790
 
791
791
  cleanup:
792
- git__free(notes_ref);
792
+ git_buf_dispose(&notes_ref);
793
793
  git_commit_free(commit);
794
794
 
795
795
  return error;
796
796
  }
797
797
 
798
798
  int git_note_next(
799
- git_oid* note_id,
800
- git_oid* annotated_id,
799
+ git_oid *note_id,
800
+ git_oid *annotated_id,
801
801
  git_note_iterator *it)
802
802
  {
803
803
  int error;
@@ -10,7 +10,7 @@
10
10
  #include "git2/oidarray.h"
11
11
  #include "array.h"
12
12
 
13
- void git_oidarray_free(git_oidarray *arr)
13
+ void git_oidarray_dispose(git_oidarray *arr)
14
14
  {
15
15
  git__free(arr->ids);
16
16
  }
@@ -32,3 +32,12 @@ void git_oidarray__reverse(git_oidarray *arr)
32
32
  git_oid_cpy(&arr->ids[(arr->count-1)-i], &tmp);
33
33
  }
34
34
  }
35
+
36
+ #ifndef GIT_DEPRECATE_HARD
37
+
38
+ void git_oidarray_free(git_oidarray *arr)
39
+ {
40
+ git_oidarray_dispose(arr);
41
+ }
42
+
43
+ #endif
@@ -413,7 +413,7 @@ int git_path_to_dir(git_buf *path)
413
413
  return git_buf_oom(path) ? -1 : 0;
414
414
  }
415
415
 
416
- void git_path_string_to_dir(char* path, size_t size)
416
+ void git_path_string_to_dir(char *path, size_t size)
417
417
  {
418
418
  size_t end = strlen(path);
419
419
 
@@ -85,7 +85,7 @@ extern int git_path_to_dir(git_buf *path);
85
85
  /**
86
86
  * Ensure string has a trailing '/' if there is space for it.
87
87
  */
88
- extern void git_path_string_to_dir(char* path, size_t size);
88
+ extern void git_path_string_to_dir(char *path, size_t size);
89
89
 
90
90
  /**
91
91
  * Taken from git.git; returns nonzero if the given path is "." or "..".
@@ -24,7 +24,7 @@ char *git_pathspec_prefix(const git_strarray *pathspec)
24
24
  const char *scan;
25
25
 
26
26
  if (!pathspec || !pathspec->count ||
27
- git_buf_common_prefix(&prefix, pathspec) < 0)
27
+ git_buf_common_prefix(&prefix, pathspec->strings, pathspec->count) < 0)
28
28
  return NULL;
29
29
 
30
30
  /* diff prefix will only be leading non-wildcards */
@@ -764,7 +764,7 @@ static bool ref_is_available(
764
764
  static int reference_path_available(
765
765
  refdb_fs_backend *backend,
766
766
  const char *new_ref,
767
- const char* old_ref,
767
+ const char *old_ref,
768
768
  int force)
769
769
  {
770
770
  size_t i;
@@ -249,7 +249,7 @@ int git_reference_dwim(git_reference **out, git_repository *repo, const char *re
249
249
  git_reference *ref;
250
250
  git_buf refnamebuf = GIT_BUF_INIT, name = GIT_BUF_INIT;
251
251
 
252
- static const char* formatters[] = {
252
+ static const char *formatters[] = {
253
253
  "%s",
254
254
  GIT_REFS_DIR "%s",
255
255
  GIT_REFS_TAGS_DIR "%s",
@@ -1246,7 +1246,7 @@ int git_reference_is_note(const git_reference *ref)
1246
1246
  return git_reference__is_note(ref->name);
1247
1247
  }
1248
1248
 
1249
- static int peel_error(int error, const git_reference *ref, const char* msg)
1249
+ static int peel_error(int error, const git_reference *ref, const char *msg)
1250
1250
  {
1251
1251
  git_error_set(
1252
1252
  GIT_ERROR_INVALID,
@@ -359,7 +359,7 @@ int git_refspec__dwim_one(git_vector *out, git_refspec *spec, git_vector *refs)
359
359
  git_remote_head key;
360
360
  git_refspec *cur;
361
361
 
362
- const char* formatters[] = {
362
+ const char *formatters[] = {
363
363
  GIT_REFS_DIR "%s",
364
364
  GIT_REFS_TAGS_DIR "%s",
365
365
  GIT_REFS_HEADS_DIR "%s",
@@ -677,7 +677,7 @@ int git_remote_set_instance_pushurl(git_remote *remote, const char *url)
677
677
  return 0;
678
678
  }
679
679
 
680
- int git_remote_set_pushurl(git_repository *repo, const char *remote, const char* url)
680
+ int git_remote_set_pushurl(git_repository *repo, const char *remote, const char *url)
681
681
  {
682
682
  return set_url(repo, remote, CONFIG_PUSHURL_FMT, url);
683
683
  }
@@ -884,15 +884,22 @@ static void url_config_trim(git_net_url *url)
884
884
 
885
885
  static int http_proxy_config(char **out, git_remote *remote, git_net_url *url)
886
886
  {
887
- git_config *cfg;
887
+ git_config *cfg = NULL;
888
888
  git_buf buf = GIT_BUF_INIT;
889
889
  git_net_url lookup_url = GIT_NET_URL_INIT;
890
890
  int error;
891
891
 
892
- if ((error = git_net_url_dup(&lookup_url, url)) < 0 ||
893
- (error = git_repository_config__weakptr(&cfg, remote->repo)) < 0)
892
+ if ((error = git_net_url_dup(&lookup_url, url)) < 0)
894
893
  goto done;
895
894
 
895
+ if (remote->repo) {
896
+ if ((error = git_repository_config(&cfg, remote->repo)) < 0)
897
+ goto done;
898
+ } else {
899
+ if ((error = git_config_open_default(&cfg)) < 0)
900
+ goto done;
901
+ }
902
+
896
903
  /* remote.<name>.proxy config setting */
897
904
  if (remote->name && remote->name[0]) {
898
905
  git_buf_clear(&buf);
@@ -922,6 +929,7 @@ static int http_proxy_config(char **out, git_remote *remote, git_net_url *url)
922
929
  error = lookup_config(out, cfg, "http.proxy");
923
930
 
924
931
  done:
932
+ git_config_free(cfg);
925
933
  git_buf_dispose(&buf);
926
934
  git_net_url_dispose(&lookup_url);
927
935
  return error;
@@ -971,7 +979,6 @@ int git_remote__http_proxy(char **out, git_remote *remote, git_net_url *url)
971
979
 
972
980
  GIT_ASSERT_ARG(out);
973
981
  GIT_ASSERT_ARG(remote);
974
- GIT_ASSERT_ARG(remote->repo);
975
982
 
976
983
  *out = NULL;
977
984
 
@@ -1427,15 +1427,60 @@ static int check_repositoryformatversion(int *version, git_config *config)
1427
1427
  return 0;
1428
1428
  }
1429
1429
 
1430
+ static const char *builtin_extensions[] = {
1431
+ "noop"
1432
+ };
1433
+
1434
+ static git_vector user_extensions = GIT_VECTOR_INIT;
1435
+
1430
1436
  static int check_valid_extension(const git_config_entry *entry, void *payload)
1431
1437
  {
1438
+ git_buf cfg = GIT_BUF_INIT;
1439
+ bool reject;
1440
+ const char *extension;
1441
+ size_t i;
1442
+ int error = 0;
1443
+
1432
1444
  GIT_UNUSED(payload);
1433
1445
 
1434
- if (!strcmp(entry->name, "extensions.noop"))
1435
- return 0;
1446
+ git_vector_foreach (&user_extensions, i, extension) {
1447
+ git_buf_clear(&cfg);
1448
+
1449
+ /*
1450
+ * Users can specify that they don't want to support an
1451
+ * extension with a '!' prefix.
1452
+ */
1453
+ if ((reject = (extension[0] == '!')) == true)
1454
+ extension = &extension[1];
1455
+
1456
+ if ((error = git_buf_printf(&cfg, "extensions.%s", extension)) < 0)
1457
+ goto done;
1458
+
1459
+ if (strcmp(entry->name, cfg.ptr) == 0) {
1460
+ if (reject)
1461
+ goto fail;
1462
+
1463
+ goto done;
1464
+ }
1465
+ }
1466
+
1467
+ for (i = 0; i < ARRAY_SIZE(builtin_extensions); i++) {
1468
+ extension = builtin_extensions[i];
1436
1469
 
1470
+ if ((error = git_buf_printf(&cfg, "extensions.%s", extension)) < 0)
1471
+ goto done;
1472
+
1473
+ if (strcmp(entry->name, cfg.ptr) == 0)
1474
+ goto done;
1475
+ }
1476
+
1477
+ fail:
1437
1478
  git_error_set(GIT_ERROR_REPOSITORY, "unsupported extension name %s", entry->name);
1438
- return -1;
1479
+ error = -1;
1480
+
1481
+ done:
1482
+ git_buf_dispose(&cfg);
1483
+ return error;
1439
1484
  }
1440
1485
 
1441
1486
  static int check_extensions(git_config *config, int version)
@@ -1446,6 +1491,70 @@ static int check_extensions(git_config *config, int version)
1446
1491
  return git_config_foreach_match(config, "^extensions\\.", check_valid_extension, NULL);
1447
1492
  }
1448
1493
 
1494
+ int git_repository__extensions(char ***out, size_t *out_len)
1495
+ {
1496
+ git_vector extensions;
1497
+ const char *builtin, *user;
1498
+ char *extension;
1499
+ size_t i, j;
1500
+
1501
+ if (git_vector_init(&extensions, 8, NULL) < 0)
1502
+ return -1;
1503
+
1504
+ for (i = 0; i < ARRAY_SIZE(builtin_extensions); i++) {
1505
+ bool match = false;
1506
+
1507
+ builtin = builtin_extensions[i];
1508
+
1509
+ git_vector_foreach (&user_extensions, j, user) {
1510
+ if (user[0] == '!' && strcmp(builtin, &user[1]) == 0) {
1511
+ match = true;
1512
+ break;
1513
+ }
1514
+ }
1515
+
1516
+ if (match)
1517
+ continue;
1518
+
1519
+ if ((extension = git__strdup(builtin)) == NULL ||
1520
+ git_vector_insert(&extensions, extension) < 0)
1521
+ return -1;
1522
+ }
1523
+
1524
+ git_vector_foreach (&user_extensions, i, user) {
1525
+ if (user[0] == '!')
1526
+ continue;
1527
+
1528
+ if ((extension = git__strdup(user)) == NULL ||
1529
+ git_vector_insert(&extensions, extension) < 0)
1530
+ return -1;
1531
+ }
1532
+
1533
+ *out = (char **)git_vector_detach(out_len, NULL, &extensions);
1534
+ return 0;
1535
+ }
1536
+
1537
+ int git_repository__set_extensions(const char **extensions, size_t len)
1538
+ {
1539
+ char *extension;
1540
+ size_t i;
1541
+
1542
+ git_repository__free_extensions();
1543
+
1544
+ for (i = 0; i < len; i++) {
1545
+ if ((extension = git__strdup(extensions[i])) == NULL ||
1546
+ git_vector_insert(&user_extensions, extension) < 0)
1547
+ return -1;
1548
+ }
1549
+
1550
+ return 0;
1551
+ }
1552
+
1553
+ void git_repository__free_extensions(void)
1554
+ {
1555
+ git_vector_free_deep(&user_extensions);
1556
+ }
1557
+
1449
1558
  int git_repository_create_head(const char *git_dir, const char *ref_name)
1450
1559
  {
1451
1560
  git_buf ref_path = GIT_BUF_INIT;
@@ -2731,34 +2840,36 @@ int git_repository_hashfile(
2731
2840
  git_file fd = -1;
2732
2841
  uint64_t len;
2733
2842
  git_buf full_path = GIT_BUF_INIT;
2843
+ const char *workdir = git_repository_workdir(repo);
2734
2844
 
2735
2845
  /* as_path can be NULL */
2736
2846
  GIT_ASSERT_ARG(out);
2737
2847
  GIT_ASSERT_ARG(path);
2738
2848
  GIT_ASSERT_ARG(repo);
2739
2849
 
2740
- /* At some point, it would be nice if repo could be NULL to just
2741
- * apply filter rules defined in system and global files, but for
2742
- * now that is not possible because git_filters_load() needs it.
2743
- */
2744
-
2745
- if ((error = git_path_join_unrooted(
2746
- &full_path, path, git_repository_workdir(repo), NULL)) < 0 ||
2850
+ if ((error = git_path_join_unrooted(&full_path, path, workdir, NULL)) < 0 ||
2747
2851
  (error = git_path_validate_workdir_buf(repo, &full_path)) < 0)
2748
2852
  return error;
2749
2853
 
2750
- if (!as_path)
2751
- as_path = path;
2854
+ /*
2855
+ * NULL as_path means that we should derive it from the
2856
+ * given path.
2857
+ */
2858
+ if (!as_path) {
2859
+ if (workdir && !git__prefixcmp(full_path.ptr, workdir))
2860
+ as_path = full_path.ptr + strlen(workdir);
2861
+ else
2862
+ as_path = "";
2863
+ }
2752
2864
 
2753
2865
  /* passing empty string for "as_path" indicated --no-filters */
2754
2866
  if (strlen(as_path) > 0) {
2755
2867
  error = git_filter_list_load(
2756
2868
  &fl, repo, NULL, as_path,
2757
2869
  GIT_FILTER_TO_ODB, GIT_FILTER_DEFAULT);
2870
+
2758
2871
  if (error < 0)
2759
2872
  return error;
2760
- } else {
2761
- error = 0;
2762
2873
  }
2763
2874
 
2764
2875
  /* at this point, error is a count of the number of loaded filters */
@@ -2850,8 +2961,8 @@ cleanup:
2850
2961
  }
2851
2962
 
2852
2963
  int git_repository_set_head(
2853
- git_repository* repo,
2854
- const char* refname)
2964
+ git_repository *repo,
2965
+ const char *refname)
2855
2966
  {
2856
2967
  git_reference *ref = NULL, *current = NULL, *new_head = NULL;
2857
2968
  git_buf log_message = GIT_BUF_INIT;
@@ -2900,8 +3011,8 @@ cleanup:
2900
3011
  }
2901
3012
 
2902
3013
  int git_repository_set_head_detached(
2903
- git_repository* repo,
2904
- const git_oid* commitish)
3014
+ git_repository *repo,
3015
+ const git_oid *commitish)
2905
3016
  {
2906
3017
  return detach(repo, commitish, NULL);
2907
3018
  }
@@ -2916,7 +3027,7 @@ int git_repository_set_head_detached_from_annotated(
2916
3027
  return detach(repo, git_annotated_commit_id(commitish), commitish->description);
2917
3028
  }
2918
3029
 
2919
- int git_repository_detach_head(git_repository* repo)
3030
+ int git_repository_detach_head(git_repository *repo)
2920
3031
  {
2921
3032
  git_reference *old_head = NULL, *new_head = NULL, *current = NULL;
2922
3033
  git_object *object = NULL;
@@ -249,4 +249,8 @@ int git_repository_initialbranch(git_buf *out, git_repository *repo);
249
249
  */
250
250
  int git_repository_workdir_path(git_buf *out, git_repository *repo, const char *path);
251
251
 
252
+ int git_repository__extensions(char ***out, size_t *out_len);
253
+ int git_repository__set_extensions(const char **extensions, size_t len);
254
+ void git_repository__free_extensions(void);
255
+
252
256
  #endif