rugged 1.5.1 → 1.6.2

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 (154) hide show
  1. checksums.yaml +4 -4
  2. data/ext/rugged/extconf.rb +2 -2
  3. data/ext/rugged/rugged_blame.c +2 -0
  4. data/ext/rugged/rugged_blob.c +3 -0
  5. data/ext/rugged/rugged_commit.c +1 -0
  6. data/ext/rugged/rugged_config.c +2 -0
  7. data/ext/rugged/rugged_diff.c +1 -0
  8. data/ext/rugged/rugged_index.c +2 -0
  9. data/ext/rugged/rugged_patch.c +1 -0
  10. data/ext/rugged/rugged_rebase.c +1 -0
  11. data/ext/rugged/rugged_reference.c +1 -0
  12. data/ext/rugged/rugged_remote.c +1 -0
  13. data/ext/rugged/rugged_repo.c +5 -2
  14. data/ext/rugged/rugged_revwalk.c +5 -1
  15. data/ext/rugged/rugged_submodule.c +1 -0
  16. data/ext/rugged/rugged_tag.c +1 -0
  17. data/ext/rugged/rugged_tree.c +4 -0
  18. data/lib/rugged/index.rb +1 -1
  19. data/lib/rugged/tree.rb +1 -1
  20. data/lib/rugged/version.rb +1 -1
  21. data/vendor/libgit2/CMakeLists.txt +5 -1
  22. data/vendor/libgit2/COPYING +30 -0
  23. data/vendor/libgit2/cmake/ExperimentalFeatures.cmake +23 -0
  24. data/vendor/libgit2/deps/ntlmclient/CMakeLists.txt +2 -0
  25. data/vendor/libgit2/include/git2/common.h +13 -6
  26. data/vendor/libgit2/include/git2/deprecated.h +6 -0
  27. data/vendor/libgit2/include/git2/diff.h +1 -1
  28. data/vendor/libgit2/include/git2/experimental.h +20 -0
  29. data/vendor/libgit2/include/git2/indexer.h +29 -0
  30. data/vendor/libgit2/include/git2/object.h +28 -2
  31. data/vendor/libgit2/include/git2/odb.h +58 -7
  32. data/vendor/libgit2/include/git2/odb_backend.h +106 -18
  33. data/vendor/libgit2/include/git2/oid.h +115 -15
  34. data/vendor/libgit2/include/git2/repository.h +20 -1
  35. data/vendor/libgit2/include/git2/stash.h +60 -6
  36. data/vendor/libgit2/include/git2/strarray.h +0 -13
  37. data/vendor/libgit2/include/git2/sys/odb_backend.h +1 -1
  38. data/vendor/libgit2/include/git2/sys/transport.h +12 -0
  39. data/vendor/libgit2/include/git2/version.h +4 -4
  40. data/vendor/libgit2/include/git2.h +1 -0
  41. data/vendor/libgit2/src/CMakeLists.txt +0 -6
  42. data/vendor/libgit2/src/cli/CMakeLists.txt +6 -2
  43. data/vendor/libgit2/src/cli/cmd_hash_object.c +27 -8
  44. data/vendor/libgit2/src/cli/opt.c +1 -1
  45. data/vendor/libgit2/src/libgit2/CMakeLists.txt +25 -15
  46. data/vendor/libgit2/src/libgit2/annotated_commit.c +1 -1
  47. data/vendor/libgit2/src/libgit2/annotated_commit.h +1 -1
  48. data/vendor/libgit2/src/libgit2/attr_file.c +1 -1
  49. data/vendor/libgit2/src/libgit2/attrcache.c +1 -1
  50. data/vendor/libgit2/src/libgit2/blame.c +2 -0
  51. data/vendor/libgit2/src/libgit2/blob.c +4 -2
  52. data/vendor/libgit2/src/libgit2/blob.h +2 -2
  53. data/vendor/libgit2/src/libgit2/branch.c +2 -2
  54. data/vendor/libgit2/src/libgit2/cherrypick.c +3 -3
  55. data/vendor/libgit2/src/libgit2/clone.c +31 -2
  56. data/vendor/libgit2/src/libgit2/commit.c +52 -17
  57. data/vendor/libgit2/src/libgit2/commit.h +25 -7
  58. data/vendor/libgit2/src/libgit2/commit_graph.c +47 -32
  59. data/vendor/libgit2/src/libgit2/commit_graph.h +3 -0
  60. data/vendor/libgit2/src/libgit2/commit_list.c +6 -2
  61. data/vendor/libgit2/src/libgit2/config.c +1 -1
  62. data/vendor/libgit2/src/libgit2/config_file.c +2 -2
  63. data/vendor/libgit2/src/libgit2/describe.c +8 -8
  64. data/vendor/libgit2/src/libgit2/diff.c +5 -1
  65. data/vendor/libgit2/src/libgit2/diff_file.c +15 -6
  66. data/vendor/libgit2/src/libgit2/diff_generate.c +17 -12
  67. data/vendor/libgit2/src/libgit2/diff_print.c +5 -5
  68. data/vendor/libgit2/src/libgit2/diff_tform.c +4 -0
  69. data/vendor/libgit2/src/libgit2/email.c +2 -2
  70. data/vendor/libgit2/src/libgit2/experimental.h.in +13 -0
  71. data/vendor/libgit2/src/libgit2/fetch.c +3 -6
  72. data/vendor/libgit2/src/libgit2/fetchhead.c +4 -4
  73. data/vendor/libgit2/src/libgit2/ident.c +3 -3
  74. data/vendor/libgit2/src/libgit2/index.c +11 -9
  75. data/vendor/libgit2/src/libgit2/indexer.c +107 -44
  76. data/vendor/libgit2/src/libgit2/iterator.c +4 -2
  77. data/vendor/libgit2/src/libgit2/libgit2.c +19 -0
  78. data/vendor/libgit2/src/libgit2/merge.c +3 -3
  79. data/vendor/libgit2/src/libgit2/midx.c +16 -15
  80. data/vendor/libgit2/src/libgit2/mwindow.c +5 -2
  81. data/vendor/libgit2/src/libgit2/mwindow.h +4 -1
  82. data/vendor/libgit2/src/libgit2/notes.c +5 -5
  83. data/vendor/libgit2/src/libgit2/object.c +89 -25
  84. data/vendor/libgit2/src/libgit2/object.h +12 -3
  85. data/vendor/libgit2/src/libgit2/odb.c +194 -50
  86. data/vendor/libgit2/src/libgit2/odb.h +43 -4
  87. data/vendor/libgit2/src/libgit2/odb_loose.c +128 -70
  88. data/vendor/libgit2/src/libgit2/odb_pack.c +96 -44
  89. data/vendor/libgit2/src/libgit2/oid.c +134 -76
  90. data/vendor/libgit2/src/libgit2/oid.h +183 -9
  91. data/vendor/libgit2/src/libgit2/pack-objects.c +15 -4
  92. data/vendor/libgit2/src/libgit2/pack.c +90 -66
  93. data/vendor/libgit2/src/libgit2/pack.h +29 -15
  94. data/vendor/libgit2/src/libgit2/parse.c +4 -3
  95. data/vendor/libgit2/src/libgit2/patch_parse.c +5 -5
  96. data/vendor/libgit2/src/libgit2/push.c +13 -3
  97. data/vendor/libgit2/src/libgit2/reader.c +1 -1
  98. data/vendor/libgit2/src/libgit2/rebase.c +19 -18
  99. data/vendor/libgit2/src/libgit2/refdb_fs.c +70 -39
  100. data/vendor/libgit2/src/libgit2/reflog.c +7 -5
  101. data/vendor/libgit2/src/libgit2/reflog.h +1 -2
  102. data/vendor/libgit2/src/libgit2/refs.c +2 -0
  103. data/vendor/libgit2/src/libgit2/remote.c +38 -37
  104. data/vendor/libgit2/src/libgit2/remote.h +40 -0
  105. data/vendor/libgit2/src/libgit2/repository.c +212 -36
  106. data/vendor/libgit2/src/libgit2/repository.h +9 -0
  107. data/vendor/libgit2/src/libgit2/reset.c +2 -2
  108. data/vendor/libgit2/src/libgit2/revert.c +4 -4
  109. data/vendor/libgit2/src/libgit2/revparse.c +23 -7
  110. data/vendor/libgit2/src/libgit2/revwalk.c +5 -1
  111. data/vendor/libgit2/src/libgit2/stash.c +201 -26
  112. data/vendor/libgit2/src/libgit2/strarray.c +1 -0
  113. data/vendor/libgit2/src/libgit2/strarray.h +25 -0
  114. data/vendor/libgit2/src/libgit2/streams/openssl.c +1 -1
  115. data/vendor/libgit2/src/libgit2/streams/openssl_dynamic.c +7 -3
  116. data/vendor/libgit2/src/libgit2/streams/socket.c +4 -1
  117. data/vendor/libgit2/src/libgit2/submodule.c +6 -2
  118. data/vendor/libgit2/src/libgit2/sysdir.c +294 -7
  119. data/vendor/libgit2/src/libgit2/sysdir.h +39 -9
  120. data/vendor/libgit2/src/libgit2/tag.c +29 -10
  121. data/vendor/libgit2/src/libgit2/tag.h +2 -2
  122. data/vendor/libgit2/src/libgit2/threadstate.h +1 -1
  123. data/vendor/libgit2/src/libgit2/transports/http.c +8 -7
  124. data/vendor/libgit2/src/libgit2/transports/httpclient.c +9 -0
  125. data/vendor/libgit2/src/libgit2/transports/httpclient.h +10 -0
  126. data/vendor/libgit2/src/libgit2/transports/local.c +14 -0
  127. data/vendor/libgit2/src/libgit2/transports/smart.c +35 -0
  128. data/vendor/libgit2/src/libgit2/transports/smart.h +10 -1
  129. data/vendor/libgit2/src/libgit2/transports/smart_pkt.c +153 -41
  130. data/vendor/libgit2/src/libgit2/transports/smart_protocol.c +42 -12
  131. data/vendor/libgit2/src/libgit2/transports/ssh.c +62 -65
  132. data/vendor/libgit2/src/libgit2/transports/winhttp.c +9 -4
  133. data/vendor/libgit2/src/libgit2/tree-cache.c +4 -4
  134. data/vendor/libgit2/src/libgit2/tree.c +22 -16
  135. data/vendor/libgit2/src/libgit2/tree.h +2 -2
  136. data/vendor/libgit2/src/libgit2/worktree.c +5 -0
  137. data/vendor/libgit2/src/util/CMakeLists.txt +7 -1
  138. data/vendor/libgit2/src/util/fs_path.c +1 -1
  139. data/vendor/libgit2/src/util/futils.c +0 -3
  140. data/vendor/libgit2/src/util/git2_util.h +2 -2
  141. data/vendor/libgit2/src/util/hash/openssl.c +4 -3
  142. data/vendor/libgit2/src/util/hash/rfc6234/sha.h +0 -112
  143. data/vendor/libgit2/src/util/hash.h +13 -0
  144. data/vendor/libgit2/src/util/net.c +338 -84
  145. data/vendor/libgit2/src/util/net.h +7 -0
  146. data/vendor/libgit2/src/util/posix.h +2 -0
  147. data/vendor/libgit2/src/util/rand.c +4 -0
  148. data/vendor/libgit2/src/util/regexp.c +3 -3
  149. data/vendor/libgit2/src/util/thread.h +20 -19
  150. data/vendor/libgit2/src/util/util.h +1 -0
  151. metadata +7 -5
  152. data/vendor/libgit2/src/util/win32/findfile.c +0 -286
  153. data/vendor/libgit2/src/util/win32/findfile.h +0 -22
  154. /data/vendor/libgit2/src/{features.h.in → util/git2_features.h.in} +0 -0
@@ -17,6 +17,7 @@
17
17
  #include "refspec.h"
18
18
  #include "vector.h"
19
19
  #include "net.h"
20
+ #include "proxy.h"
20
21
 
21
22
  #define GIT_REMOTE_ORIGIN "origin"
22
23
 
@@ -56,5 +57,44 @@ int git_remote_connect_options_normalize(
56
57
  const git_remote_connect_options *src);
57
58
 
58
59
  int git_remote_capabilities(unsigned int *out, git_remote *remote);
60
+ int git_remote_oid_type(git_oid_t *out, git_remote *remote);
61
+
62
+
63
+ #define git_remote_connect_options__copy_opts(out, in) \
64
+ if (in) { \
65
+ (out)->callbacks = (in)->callbacks; \
66
+ (out)->proxy_opts = (in)->proxy_opts; \
67
+ (out)->custom_headers = (in)->custom_headers; \
68
+ (out)->follow_redirects = (in)->follow_redirects; \
69
+ }
70
+
71
+ GIT_INLINE(int) git_remote_connect_options__from_fetch_opts(
72
+ git_remote_connect_options *out,
73
+ git_remote *remote,
74
+ const git_fetch_options *fetch_opts)
75
+ {
76
+ git_remote_connect_options tmp = GIT_REMOTE_CONNECT_OPTIONS_INIT;
77
+ git_remote_connect_options__copy_opts(&tmp, fetch_opts);
78
+ return git_remote_connect_options_normalize(out, remote->repo, &tmp);
79
+ }
80
+
81
+ GIT_INLINE(int) git_remote_connect_options__from_push_opts(
82
+ git_remote_connect_options *out,
83
+ git_remote *remote,
84
+ const git_push_options *push_opts)
85
+ {
86
+ git_remote_connect_options tmp = GIT_REMOTE_CONNECT_OPTIONS_INIT;
87
+ git_remote_connect_options__copy_opts(&tmp, push_opts);
88
+ return git_remote_connect_options_normalize(out, remote->repo, &tmp);
89
+ }
90
+
91
+ #undef git_remote_connect_options__copy_opts
92
+
93
+ GIT_INLINE(void) git_remote_connect_options__dispose(
94
+ git_remote_connect_options *opts)
95
+ {
96
+ git_proxy_options_dispose(&opts->proxy_opts);
97
+ git_strarray_dispose(&opts->custom_headers);
98
+ }
59
99
 
60
100
  #endif
@@ -67,6 +67,7 @@ static const struct {
67
67
  static int check_repositoryformatversion(int *version, git_config *config);
68
68
  static int check_extensions(git_config *config, int version);
69
69
  static int load_global_config(git_config **config);
70
+ static int load_objectformat(git_repository *repo, git_config *config);
70
71
 
71
72
  #define GIT_COMMONDIR_FILE "commondir"
72
73
  #define GIT_GITDIR_FILE "gitdir"
@@ -75,8 +76,8 @@ static int load_global_config(git_config **config);
75
76
 
76
77
  #define GIT_BRANCH_DEFAULT "master"
77
78
 
78
- #define GIT_REPO_VERSION 0
79
- #define GIT_REPO_MAX_VERSION 1
79
+ #define GIT_REPO_VERSION_DEFAULT 0
80
+ #define GIT_REPO_VERSION_MAX 1
80
81
 
81
82
  git_str git_repository__reserved_names_win32[] = {
82
83
  { DOT_GIT, 0, CONST_STRLEN(DOT_GIT) },
@@ -240,7 +241,7 @@ GIT_INLINE(int) validate_repo_path(git_str *path)
240
241
  */
241
242
  static size_t suffix_len =
242
243
  CONST_STRLEN("objects/pack/pack-.pack.lock") +
243
- GIT_OID_HEXSZ;
244
+ GIT_OID_MAX_HEXSIZE;
244
245
 
245
246
  return git_fs_path_validate_str_length_with_suffix(
246
247
  path, suffix_len);
@@ -495,12 +496,47 @@ static int validate_ownership_cb(const git_config_entry *entry, void *payload)
495
496
  {
496
497
  validate_ownership_data *data = payload;
497
498
 
498
- if (strcmp(entry->value, "") == 0)
499
+ if (strcmp(entry->value, "") == 0) {
499
500
  *data->is_safe = false;
500
-
501
- if (git_fs_path_prettify_dir(&data->tmp, entry->value, NULL) == 0 &&
502
- strcmp(data->tmp.ptr, data->repo_path) == 0)
501
+ } else if (strcmp(entry->value, "*") == 0) {
503
502
  *data->is_safe = true;
503
+ } else {
504
+ const char *test_path = entry->value;
505
+
506
+ #ifdef GIT_WIN32
507
+ /*
508
+ * Git for Windows does some truly bizarre things with
509
+ * paths that start with a forward slash; and expects you
510
+ * to escape that with `%(prefix)`. This syntax generally
511
+ * means to add the prefix that Git was installed to -- eg
512
+ * `/usr/local` -- unless it's an absolute path, in which
513
+ * case the leading `%(prefix)/` is just removed. And Git
514
+ * for Windows expects you to use this syntax for absolute
515
+ * Unix-style paths (in "Git Bash" or Windows Subsystem for
516
+ * Linux).
517
+ *
518
+ * Worse, the behavior used to be that a leading `/` was
519
+ * not absolute. It would indicate that Git for Windows
520
+ * should add the prefix. So `//` is required for absolute
521
+ * Unix-style paths. Yes, this is truly horrifying.
522
+ *
523
+ * Emulate that behavior, I guess, but only for absolute
524
+ * paths. We won't deal with the Git install prefix. Also,
525
+ * give WSL users an escape hatch where they don't have to
526
+ * think about this and can use the literal path that the
527
+ * filesystem APIs provide (`//wsl.localhost/...`).
528
+ */
529
+ if (strncmp(test_path, "%(prefix)//", strlen("%(prefix)//")) == 0)
530
+ test_path += strlen("%(prefix)/");
531
+ else if (strncmp(test_path, "//", 2) == 0 &&
532
+ strncmp(test_path, "//wsl.localhost/", strlen("//wsl.localhost/")) != 0)
533
+ test_path++;
534
+ #endif
535
+
536
+ if (git_fs_path_prettify_dir(&data->tmp, test_path, NULL) == 0 &&
537
+ strcmp(data->tmp.ptr, data->repo_path) == 0)
538
+ *data->is_safe = true;
539
+ }
504
540
 
505
541
  return 0;
506
542
  }
@@ -521,6 +557,9 @@ static int validate_ownership_config(bool *is_safe, const char *path)
521
557
  validate_ownership_cb,
522
558
  &ownership_data);
523
559
 
560
+ if (error == GIT_ENOTFOUND)
561
+ error = 0;
562
+
524
563
  git_config_free(config);
525
564
  git_str_dispose(&ownership_data.tmp);
526
565
 
@@ -541,6 +580,9 @@ static int validate_ownership_path(bool *is_safe, const char *path)
541
580
  if (error == GIT_ENOTFOUND) {
542
581
  *is_safe = true;
543
582
  error = 0;
583
+ } else if (error == GIT_EINVALID) {
584
+ *is_safe = false;
585
+ error = 0;
544
586
  }
545
587
 
546
588
  return error;
@@ -727,6 +769,43 @@ out:
727
769
  return error;
728
770
  }
729
771
 
772
+ static int obtain_config_and_set_oid_type(
773
+ git_config **config_ptr,
774
+ git_repository *repo)
775
+ {
776
+ int error;
777
+ git_config *config = NULL;
778
+ int version = 0;
779
+
780
+ /*
781
+ * We'd like to have the config, but git doesn't particularly
782
+ * care if it's not there, so we need to deal with that.
783
+ */
784
+
785
+ error = git_repository_config_snapshot(&config, repo);
786
+ if (error < 0 && error != GIT_ENOTFOUND)
787
+ goto out;
788
+
789
+ if (config &&
790
+ (error = check_repositoryformatversion(&version, config)) < 0)
791
+ goto out;
792
+
793
+ if ((error = check_extensions(config, version)) < 0)
794
+ goto out;
795
+
796
+ if (version > 0) {
797
+ if ((error = load_objectformat(repo, config)) < 0)
798
+ goto out;
799
+ } else {
800
+ repo->oid_type = GIT_OID_SHA1;
801
+ }
802
+
803
+ out:
804
+ *config_ptr = config;
805
+
806
+ return error;
807
+ }
808
+
730
809
  int git_repository_open_bare(
731
810
  git_repository **repo_ptr,
732
811
  const char *bare_path)
@@ -735,6 +814,7 @@ int git_repository_open_bare(
735
814
  git_repository *repo = NULL;
736
815
  bool is_valid;
737
816
  int error;
817
+ git_config *config;
738
818
 
739
819
  if ((error = git_fs_path_prettify_dir(&path, bare_path, NULL)) < 0 ||
740
820
  (error = is_valid_repository_path(&is_valid, &path, &common_path)) < 0)
@@ -760,8 +840,15 @@ int git_repository_open_bare(
760
840
  repo->is_worktree = 0;
761
841
  repo->workdir = NULL;
762
842
 
843
+ if ((error = obtain_config_and_set_oid_type(&config, repo)) < 0)
844
+ goto cleanup;
845
+
763
846
  *repo_ptr = repo;
764
- return 0;
847
+
848
+ cleanup:
849
+ git_config_free(config);
850
+
851
+ return error;
765
852
  }
766
853
 
767
854
  static int _git_repository_open_ext_from_env(
@@ -843,7 +930,7 @@ static int _git_repository_open_ext_from_env(
843
930
  else if (error < 0)
844
931
  goto error;
845
932
  else {
846
- error = git_odb_open(&odb, git_str_cstr(&object_dir_buf));
933
+ error = git_odb__open(&odb, git_str_cstr(&object_dir_buf), NULL);
847
934
  if (error < 0)
848
935
  goto error;
849
936
  }
@@ -968,7 +1055,6 @@ int git_repository_open_ext(
968
1055
  gitlink = GIT_STR_INIT, commondir = GIT_STR_INIT;
969
1056
  git_repository *repo = NULL;
970
1057
  git_config *config = NULL;
971
- int version = 0;
972
1058
 
973
1059
  if (flags & GIT_REPOSITORY_OPEN_FROM_ENV)
974
1060
  return _git_repository_open_ext_from_env(repo_ptr, start_path);
@@ -1001,19 +1087,8 @@ int git_repository_open_ext(
1001
1087
  goto cleanup;
1002
1088
  repo->is_worktree = is_worktree;
1003
1089
 
1004
- /*
1005
- * We'd like to have the config, but git doesn't particularly
1006
- * care if it's not there, so we need to deal with that.
1007
- */
1008
-
1009
- error = git_repository_config_snapshot(&config, repo);
1010
- if (error < 0 && error != GIT_ENOTFOUND)
1011
- goto cleanup;
1012
-
1013
- if (config && (error = check_repositoryformatversion(&version, config)) < 0)
1014
- goto cleanup;
1015
-
1016
- if ((error = check_extensions(config, version)) < 0)
1090
+ error = obtain_config_and_set_oid_type(&config, repo);
1091
+ if (error < 0)
1017
1092
  goto cleanup;
1018
1093
 
1019
1094
  if ((flags & GIT_REPOSITORY_OPEN_BARE) != 0) {
@@ -1264,11 +1339,14 @@ int git_repository_odb__weakptr(git_odb **out, git_repository *repo)
1264
1339
  *out = git_atomic_load(repo->_odb);
1265
1340
  if (*out == NULL) {
1266
1341
  git_str odb_path = GIT_STR_INIT;
1342
+ git_odb_options odb_opts = GIT_ODB_OPTIONS_INIT;
1267
1343
  git_odb *odb;
1268
1344
 
1345
+ odb_opts.oid_type = repo->oid_type;
1346
+
1269
1347
  if ((error = git_repository__item_path(&odb_path, repo,
1270
1348
  GIT_REPOSITORY_ITEM_OBJECTS)) < 0 ||
1271
- (error = git_odb_new(&odb)) < 0)
1349
+ (error = git_odb__new(&odb, &odb_opts)) < 0)
1272
1350
  return error;
1273
1351
 
1274
1352
  GIT_REFCOUNT_OWN(odb, repo);
@@ -1526,6 +1604,7 @@ static int check_repositoryformatversion(int *version, git_config *config)
1526
1604
  int error;
1527
1605
 
1528
1606
  error = git_config_get_int32(version, config, "core.repositoryformatversion");
1607
+
1529
1608
  /* git ignores this if the config variable isn't there */
1530
1609
  if (error == GIT_ENOTFOUND)
1531
1610
  return 0;
@@ -1533,10 +1612,15 @@ static int check_repositoryformatversion(int *version, git_config *config)
1533
1612
  if (error < 0)
1534
1613
  return -1;
1535
1614
 
1536
- if (GIT_REPO_MAX_VERSION < *version) {
1615
+ if (*version < 0) {
1616
+ git_error_set(GIT_ERROR_REPOSITORY,
1617
+ "invalid repository version %d", *version);
1618
+ }
1619
+
1620
+ if (GIT_REPO_VERSION_MAX < *version) {
1537
1621
  git_error_set(GIT_ERROR_REPOSITORY,
1538
1622
  "unsupported repository version %d; only versions up to %d are supported",
1539
- *version, GIT_REPO_MAX_VERSION);
1623
+ *version, GIT_REPO_VERSION_MAX);
1540
1624
  return -1;
1541
1625
  }
1542
1626
 
@@ -1544,7 +1628,8 @@ static int check_repositoryformatversion(int *version, git_config *config)
1544
1628
  }
1545
1629
 
1546
1630
  static const char *builtin_extensions[] = {
1547
- "noop"
1631
+ "noop",
1632
+ "objectformat"
1548
1633
  };
1549
1634
 
1550
1635
  static git_vector user_extensions = GIT_VECTOR_INIT;
@@ -1608,6 +1693,79 @@ static int check_extensions(git_config *config, int version)
1608
1693
  return git_config_foreach_match(config, "^extensions\\.", check_valid_extension, NULL);
1609
1694
  }
1610
1695
 
1696
+ static int load_objectformat(git_repository *repo, git_config *config)
1697
+ {
1698
+ git_config_entry *entry = NULL;
1699
+ int error;
1700
+
1701
+ if ((error = git_config_get_entry(&entry, config, "extensions.objectformat")) < 0) {
1702
+ if (error == GIT_ENOTFOUND) {
1703
+ repo->oid_type = GIT_OID_SHA1;
1704
+ git_error_clear();
1705
+ error = 0;
1706
+ }
1707
+
1708
+ goto done;
1709
+ }
1710
+
1711
+ if ((repo->oid_type = git_oid_type_fromstr(entry->value)) == 0) {
1712
+ git_error_set(GIT_ERROR_REPOSITORY,
1713
+ "unknown object format '%s'", entry->value);
1714
+ error = GIT_EINVALID;
1715
+ }
1716
+
1717
+ done:
1718
+ git_config_entry_free(entry);
1719
+ return error;
1720
+ }
1721
+
1722
+ int git_repository__set_objectformat(
1723
+ git_repository *repo,
1724
+ git_oid_t oid_type)
1725
+ {
1726
+ git_config *cfg;
1727
+
1728
+ /*
1729
+ * Older clients do not necessarily understand the
1730
+ * `objectformat` extension, even when it's set to an
1731
+ * object format that they understand (SHA1). Do not set
1732
+ * the objectformat extension unless we're not using the
1733
+ * default object format.
1734
+ */
1735
+ if (oid_type == GIT_OID_DEFAULT)
1736
+ return 0;
1737
+
1738
+ if (!git_repository_is_empty(repo) && repo->oid_type != oid_type) {
1739
+ git_error_set(GIT_ERROR_REPOSITORY,
1740
+ "cannot change object id type of existing repository");
1741
+ return -1;
1742
+ }
1743
+
1744
+ if (git_repository_config__weakptr(&cfg, repo) < 0)
1745
+ return -1;
1746
+
1747
+ if (git_config_set_int32(cfg,
1748
+ "core.repositoryformatversion", 1) < 0 ||
1749
+ git_config_set_string(cfg, "extensions.objectformat",
1750
+ git_oid_type_name(oid_type)) < 0)
1751
+ return -1;
1752
+
1753
+ /*
1754
+ * During repo init, we may create some backends with the
1755
+ * default oid type. Clear them so that we create them with
1756
+ * the proper oid type.
1757
+ */
1758
+ if (repo->oid_type != oid_type) {
1759
+ set_index(repo, NULL);
1760
+ set_odb(repo, NULL);
1761
+ set_refdb(repo, NULL);
1762
+
1763
+ repo->oid_type = oid_type;
1764
+ }
1765
+
1766
+ return 0;
1767
+ }
1768
+
1611
1769
  int git_repository__extensions(char ***out, size_t *out_len)
1612
1770
  {
1613
1771
  git_vector extensions;
@@ -1886,19 +2044,21 @@ static int repo_init_config(
1886
2044
  const char *repo_dir,
1887
2045
  const char *work_dir,
1888
2046
  uint32_t flags,
1889
- uint32_t mode)
2047
+ uint32_t mode,
2048
+ git_oid_t oid_type)
1890
2049
  {
1891
2050
  int error = 0;
1892
2051
  git_str cfg_path = GIT_STR_INIT, worktree_path = GIT_STR_INIT;
1893
2052
  git_config *config = NULL;
1894
2053
  bool is_bare = ((flags & GIT_REPOSITORY_INIT_BARE) != 0);
1895
2054
  bool is_reinit = ((flags & GIT_REPOSITORY_INIT__IS_REINIT) != 0);
1896
- int version = 0;
2055
+ int version = GIT_REPO_VERSION_DEFAULT;
1897
2056
 
1898
2057
  if ((error = repo_local_config(&config, &cfg_path, NULL, repo_dir)) < 0)
1899
2058
  goto cleanup;
1900
2059
 
1901
- if (is_reinit && (error = check_repositoryformatversion(&version, config)) < 0)
2060
+ if (is_reinit &&
2061
+ (error = check_repositoryformatversion(&version, config)) < 0)
1902
2062
  goto cleanup;
1903
2063
 
1904
2064
  if ((error = check_extensions(config, version)) < 0)
@@ -1909,7 +2069,7 @@ static int repo_init_config(
1909
2069
  goto cleanup; } while (0)
1910
2070
 
1911
2071
  SET_REPO_CONFIG(bool, "core.bare", is_bare);
1912
- SET_REPO_CONFIG(int32, "core.repositoryformatversion", GIT_REPO_VERSION);
2072
+ SET_REPO_CONFIG(int32, "core.repositoryformatversion", version);
1913
2073
 
1914
2074
  if ((error = repo_init_fs_configs(
1915
2075
  config, cfg_path.ptr, repo_dir, work_dir, !is_reinit)) < 0)
@@ -1942,6 +2102,11 @@ static int repo_init_config(
1942
2102
  SET_REPO_CONFIG(bool, "receive.denyNonFastforwards", true);
1943
2103
  }
1944
2104
 
2105
+ if (oid_type != GIT_OID_SHA1) {
2106
+ SET_REPO_CONFIG(int32, "core.repositoryformatversion", 1);
2107
+ SET_REPO_CONFIG(string, "extensions.objectformat", git_oid_type_name(oid_type));
2108
+ }
2109
+
1945
2110
  cleanup:
1946
2111
  git_str_dispose(&cfg_path);
1947
2112
  git_str_dispose(&worktree_path);
@@ -2422,6 +2587,7 @@ int git_repository_init_ext(
2422
2587
  common_path = GIT_STR_INIT;
2423
2588
  const char *wd;
2424
2589
  bool is_valid;
2590
+ git_oid_t oid_type = GIT_OID_DEFAULT;
2425
2591
  int error;
2426
2592
 
2427
2593
  GIT_ASSERT_ARG(out);
@@ -2430,6 +2596,11 @@ int git_repository_init_ext(
2430
2596
 
2431
2597
  GIT_ERROR_CHECK_VERSION(opts, GIT_REPOSITORY_INIT_OPTIONS_VERSION, "git_repository_init_options");
2432
2598
 
2599
+ #ifdef GIT_EXPERIMENTAL_SHA256
2600
+ if (opts->oid_type)
2601
+ oid_type = opts->oid_type;
2602
+ #endif
2603
+
2433
2604
  if ((error = repo_init_directories(&repo_path, &wd_path, given_repo, opts)) < 0)
2434
2605
  goto out;
2435
2606
 
@@ -2448,13 +2619,13 @@ int git_repository_init_ext(
2448
2619
 
2449
2620
  opts->flags |= GIT_REPOSITORY_INIT__IS_REINIT;
2450
2621
 
2451
- if ((error = repo_init_config(repo_path.ptr, wd, opts->flags, opts->mode)) < 0)
2622
+ if ((error = repo_init_config(repo_path.ptr, wd, opts->flags, opts->mode, oid_type)) < 0)
2452
2623
  goto out;
2453
2624
 
2454
2625
  /* TODO: reinitialize the templates */
2455
2626
  } else {
2456
2627
  if ((error = repo_init_structure(repo_path.ptr, wd, opts)) < 0 ||
2457
- (error = repo_init_config(repo_path.ptr, wd, opts->flags, opts->mode)) < 0 ||
2628
+ (error = repo_init_config(repo_path.ptr, wd, opts->flags, opts->mode, oid_type)) < 0 ||
2458
2629
  (error = repo_init_head(repo_path.ptr, opts->initial_head)) < 0)
2459
2630
  goto out;
2460
2631
  }
@@ -2917,14 +3088,14 @@ int git_repository__set_orig_head(git_repository *repo, const git_oid *orig_head
2917
3088
  {
2918
3089
  git_filebuf file = GIT_FILEBUF_INIT;
2919
3090
  git_str file_path = GIT_STR_INIT;
2920
- char orig_head_str[GIT_OID_HEXSZ];
3091
+ char orig_head_str[GIT_OID_MAX_HEXSIZE];
2921
3092
  int error = 0;
2922
3093
 
2923
3094
  git_oid_fmt(orig_head_str, orig_head);
2924
3095
 
2925
3096
  if ((error = git_str_joinpath(&file_path, repo->gitdir, GIT_ORIG_HEAD_FILE)) == 0 &&
2926
3097
  (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_CREATE_LEADING_DIRS, GIT_MERGE_FILE_MODE)) == 0 &&
2927
- (error = git_filebuf_printf(&file, "%.*s\n", GIT_OID_HEXSZ, orig_head_str)) == 0)
3098
+ (error = git_filebuf_printf(&file, "%.*s\n", (int)git_oid_hexsize(repo->oid_type), orig_head_str)) == 0)
2928
3099
  error = git_filebuf_commit(&file);
2929
3100
 
2930
3101
  if (error < 0)
@@ -3037,7 +3208,7 @@ int git_repository_hashfile(
3037
3208
  goto cleanup;
3038
3209
  }
3039
3210
 
3040
- error = git_odb__hashfd_filtered(out, fd, (size_t)len, type, fl);
3211
+ error = git_odb__hashfd_filtered(out, fd, (size_t)len, type, repo->oid_type, fl);
3041
3212
 
3042
3213
  cleanup:
3043
3214
  if (fd >= 0)
@@ -3384,3 +3555,8 @@ int git_repository_submodule_cache_clear(git_repository *repo)
3384
3555
  repo->submodule_cache = NULL;
3385
3556
  return error;
3386
3557
  }
3558
+
3559
+ git_oid_t git_repository_oid_type(git_repository *repo)
3560
+ {
3561
+ return repo ? repo->oid_type : 0;
3562
+ }
@@ -153,6 +153,7 @@ struct git_repository {
153
153
 
154
154
  unsigned is_bare:1;
155
155
  unsigned is_worktree:1;
156
+ git_oid_t oid_type;
156
157
 
157
158
  unsigned int lru_counter;
158
159
 
@@ -256,4 +257,12 @@ int git_repository__extensions(char ***out, size_t *out_len);
256
257
  int git_repository__set_extensions(const char **extensions, size_t len);
257
258
  void git_repository__free_extensions(void);
258
259
 
260
+ /*
261
+ * Set the object format (OID type) for a repository; this will set
262
+ * both the configuration and the internal value for the oid type.
263
+ */
264
+ int git_repository__set_objectformat(
265
+ git_repository *repo,
266
+ git_oid_t oid_type);
267
+
259
268
  #endif
@@ -188,9 +188,9 @@ int git_reset(
188
188
  git_reset_t reset_type,
189
189
  const git_checkout_options *checkout_opts)
190
190
  {
191
- char to[GIT_OID_HEXSZ + 1];
191
+ char to[GIT_OID_SHA1_HEXSIZE + 1];
192
192
 
193
- git_oid_tostr(to, GIT_OID_HEXSZ + 1, git_object_id(target));
193
+ git_oid_tostr(to, GIT_OID_SHA1_HEXSIZE + 1, git_object_id(target));
194
194
  return reset(repo, target, to, reset_type, checkout_opts);
195
195
  }
196
196
 
@@ -107,10 +107,10 @@ static int revert_state_cleanup(git_repository *repo)
107
107
 
108
108
  static int revert_seterr(git_commit *commit, const char *fmt)
109
109
  {
110
- char commit_oidstr[GIT_OID_HEXSZ + 1];
110
+ char commit_oidstr[GIT_OID_SHA1_HEXSIZE + 1];
111
111
 
112
112
  git_oid_fmt(commit_oidstr, git_commit_id(commit));
113
- commit_oidstr[GIT_OID_HEXSZ] = '\0';
113
+ commit_oidstr[GIT_OID_SHA1_HEXSIZE] = '\0';
114
114
 
115
115
  git_error_set(GIT_ERROR_REVERT, fmt, commit_oidstr);
116
116
 
@@ -176,7 +176,7 @@ int git_revert(
176
176
  git_revert_options opts;
177
177
  git_reference *our_ref = NULL;
178
178
  git_commit *our_commit = NULL;
179
- char commit_oidstr[GIT_OID_HEXSZ + 1];
179
+ char commit_oidstr[GIT_OID_SHA1_HEXSIZE + 1];
180
180
  const char *commit_msg;
181
181
  git_str their_label = GIT_STR_INIT;
182
182
  git_index *index = NULL;
@@ -192,7 +192,7 @@ int git_revert(
192
192
  return error;
193
193
 
194
194
  git_oid_fmt(commit_oidstr, git_commit_id(commit));
195
- commit_oidstr[GIT_OID_HEXSZ] = '\0';
195
+ commit_oidstr[GIT_OID_SHA1_HEXSIZE] = '\0';
196
196
 
197
197
  if ((commit_msg = git_commit_summary(commit)) == NULL) {
198
198
  error = -1;
@@ -15,21 +15,28 @@
15
15
 
16
16
  #include "git2.h"
17
17
 
18
- static int maybe_sha_or_abbrev(git_object **out, git_repository *repo, const char *spec, size_t speclen)
18
+ static int maybe_sha_or_abbrev(
19
+ git_object **out,
20
+ git_repository *repo,
21
+ const char *spec,
22
+ size_t speclen)
19
23
  {
20
24
  git_oid oid;
21
25
 
22
- if (git_oid_fromstrn(&oid, spec, speclen) < 0)
26
+ if (git_oid__fromstrn(&oid, spec, speclen, repo->oid_type) < 0)
23
27
  return GIT_ENOTFOUND;
24
28
 
25
29
  return git_object_lookup_prefix(out, repo, &oid, speclen, GIT_OBJECT_ANY);
26
30
  }
27
31
 
28
- static int maybe_sha(git_object **out, git_repository *repo, const char *spec)
32
+ static int maybe_sha(
33
+ git_object **out,
34
+ git_repository *repo,
35
+ const char *spec)
29
36
  {
30
37
  size_t speclen = strlen(spec);
31
38
 
32
- if (speclen != GIT_OID_HEXSZ)
39
+ if (speclen != git_oid_hexsize(repo->oid_type))
33
40
  return GIT_ENOTFOUND;
34
41
 
35
42
  return maybe_sha_or_abbrev(out, repo, spec, speclen);
@@ -110,8 +117,8 @@ static int revparse_lookup_object(
110
117
  if (error != GIT_ENOTFOUND)
111
118
  return error;
112
119
 
113
- if ((strlen(spec) < GIT_OID_HEXSZ) &&
114
- ((error = maybe_abbrev(object_out, repo, spec)) != GIT_ENOTFOUND))
120
+ if ((strlen(spec) < git_oid_hexsize(repo->oid_type)) &&
121
+ ((error = maybe_abbrev(object_out, repo, spec)) != GIT_ENOTFOUND))
115
122
  return error;
116
123
 
117
124
  if ((error = maybe_describe(object_out, repo, spec)) != GIT_ENOTFOUND)
@@ -268,7 +275,16 @@ static int retrieve_revobject_from_reflog(git_object **out, git_reference **base
268
275
  int error = -1;
269
276
 
270
277
  if (*base_ref == NULL) {
271
- if ((error = git_reference_dwim(&ref, repo, identifier)) < 0)
278
+ /*
279
+ * When HEAD@{n} is specified, do not use dwim, which would resolve the
280
+ * reference (to the current branch that HEAD is pointing to).
281
+ */
282
+ if (position > 0 && strcmp(identifier, GIT_HEAD_FILE) == 0)
283
+ error = git_reference_lookup(&ref, repo, GIT_HEAD_FILE);
284
+ else
285
+ error = git_reference_dwim(&ref, repo, identifier);
286
+
287
+ if (error < 0)
272
288
  return error;
273
289
  } else {
274
290
  ref = *base_ref;
@@ -121,8 +121,12 @@ int git_revwalk__push_ref(git_revwalk *walk, const char *refname, const git_revw
121
121
  {
122
122
  git_oid oid;
123
123
 
124
- if (git_reference_name_to_id(&oid, walk->repo, refname) < 0)
124
+ int error = git_reference_name_to_id(&oid, walk->repo, refname);
125
+ if (opts->from_glob && (error == GIT_ENOTFOUND || error == GIT_EINVALIDSPEC || error == GIT_EPEEL)) {
126
+ return 0;
127
+ } else if (error < 0) {
125
128
  return -1;
129
+ }
126
130
 
127
131
  return git_revwalk__push_commit(walk, &oid, opts);
128
132
  }