rugged 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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