rugged 1.5.1 → 1.6.2

Sign up to get free protection for your applications and to get access to all the features.
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
  }