rugged 1.5.0.1 → 1.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (250) hide show
  1. checksums.yaml +4 -4
  2. data/ext/rugged/extconf.rb +2 -2
  3. data/ext/rugged/rugged_allocator.c +0 -54
  4. data/ext/rugged/rugged_blame.c +2 -0
  5. data/ext/rugged/rugged_blob.c +3 -0
  6. data/ext/rugged/rugged_commit.c +1 -0
  7. data/ext/rugged/rugged_config.c +2 -0
  8. data/ext/rugged/rugged_diff.c +1 -0
  9. data/ext/rugged/rugged_index.c +2 -0
  10. data/ext/rugged/rugged_patch.c +1 -0
  11. data/ext/rugged/rugged_rebase.c +1 -0
  12. data/ext/rugged/rugged_reference.c +1 -0
  13. data/ext/rugged/rugged_remote.c +1 -0
  14. data/ext/rugged/rugged_repo.c +5 -2
  15. data/ext/rugged/rugged_revwalk.c +5 -1
  16. data/ext/rugged/rugged_submodule.c +1 -0
  17. data/ext/rugged/rugged_tag.c +1 -0
  18. data/ext/rugged/rugged_tree.c +4 -0
  19. data/lib/rugged/index.rb +1 -1
  20. data/lib/rugged/tree.rb +1 -1
  21. data/lib/rugged/version.rb +1 -1
  22. data/vendor/libgit2/CMakeLists.txt +7 -8
  23. data/vendor/libgit2/COPYING +30 -0
  24. data/vendor/libgit2/cmake/CheckPrototypeDefinitionSafe.cmake +16 -0
  25. data/vendor/libgit2/cmake/ExperimentalFeatures.cmake +23 -0
  26. data/vendor/libgit2/cmake/SelectGSSAPI.cmake +3 -3
  27. data/vendor/libgit2/cmake/SelectHTTPSBackend.cmake +21 -2
  28. data/vendor/libgit2/cmake/SelectHashes.cmake +4 -0
  29. data/vendor/libgit2/cmake/SelectXdiff.cmake +9 -0
  30. data/vendor/libgit2/deps/ntlmclient/CMakeLists.txt +2 -0
  31. data/vendor/libgit2/deps/pcre/LICENCE +5 -5
  32. data/vendor/libgit2/deps/pcre/pcre.h +2 -2
  33. data/vendor/libgit2/deps/pcre/pcre_compile.c +6 -3
  34. data/vendor/libgit2/deps/pcre/pcre_exec.c +2 -2
  35. data/vendor/libgit2/deps/xdiff/CMakeLists.txt +28 -0
  36. data/vendor/libgit2/{src/libgit2 → deps}/xdiff/git-xdiff.h +4 -1
  37. data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xdiffi.c +19 -18
  38. data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xdiffi.h +2 -4
  39. data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xemit.c +3 -3
  40. data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xhistogram.c +7 -18
  41. data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xmacros.h +18 -1
  42. data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xmerge.c +24 -22
  43. data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xpatience.c +21 -30
  44. data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xprepare.c +13 -30
  45. data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xutils.c +18 -1
  46. data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xutils.h +2 -1
  47. data/vendor/libgit2/include/git2/common.h +38 -6
  48. data/vendor/libgit2/include/git2/deprecated.h +6 -0
  49. data/vendor/libgit2/include/git2/diff.h +42 -4
  50. data/vendor/libgit2/include/git2/errors.h +4 -2
  51. data/vendor/libgit2/include/git2/experimental.h +20 -0
  52. data/vendor/libgit2/include/git2/index.h +9 -0
  53. data/vendor/libgit2/include/git2/indexer.h +29 -0
  54. data/vendor/libgit2/include/git2/object.h +28 -2
  55. data/vendor/libgit2/include/git2/odb.h +58 -7
  56. data/vendor/libgit2/include/git2/odb_backend.h +106 -18
  57. data/vendor/libgit2/include/git2/oid.h +116 -16
  58. data/vendor/libgit2/include/git2/remote.h +18 -0
  59. data/vendor/libgit2/include/git2/repository.h +32 -3
  60. data/vendor/libgit2/include/git2/stash.h +60 -6
  61. data/vendor/libgit2/include/git2/strarray.h +0 -13
  62. data/vendor/libgit2/include/git2/sys/alloc.h +0 -34
  63. data/vendor/libgit2/include/git2/sys/commit_graph.h +12 -2
  64. data/vendor/libgit2/include/git2/sys/midx.h +5 -1
  65. data/vendor/libgit2/include/git2/sys/odb_backend.h +1 -1
  66. data/vendor/libgit2/include/git2/sys/stream.h +16 -2
  67. data/vendor/libgit2/include/git2/sys/transport.h +32 -2
  68. data/vendor/libgit2/include/git2/version.h +4 -4
  69. data/vendor/libgit2/include/git2/worktree.h +3 -1
  70. data/vendor/libgit2/include/git2.h +1 -0
  71. data/vendor/libgit2/src/CMakeLists.txt +34 -17
  72. data/vendor/libgit2/src/cli/CMakeLists.txt +5 -2
  73. data/vendor/libgit2/src/cli/cmd_clone.c +22 -6
  74. data/vendor/libgit2/src/cli/cmd_hash_object.c +27 -8
  75. data/vendor/libgit2/src/cli/opt.c +1 -1
  76. data/vendor/libgit2/src/cli/progress.c +9 -8
  77. data/vendor/libgit2/src/cli/progress.h +4 -4
  78. data/vendor/libgit2/src/libgit2/CMakeLists.txt +25 -34
  79. data/vendor/libgit2/src/libgit2/annotated_commit.c +2 -2
  80. data/vendor/libgit2/src/libgit2/annotated_commit.h +1 -1
  81. data/vendor/libgit2/src/libgit2/apply.c +4 -3
  82. data/vendor/libgit2/src/libgit2/attr_file.c +1 -1
  83. data/vendor/libgit2/src/libgit2/attrcache.c +1 -1
  84. data/vendor/libgit2/src/libgit2/blame.c +23 -14
  85. data/vendor/libgit2/src/libgit2/blame_git.c +0 -1
  86. data/vendor/libgit2/src/libgit2/blob.c +4 -2
  87. data/vendor/libgit2/src/libgit2/blob.h +2 -2
  88. data/vendor/libgit2/src/libgit2/branch.c +2 -2
  89. data/vendor/libgit2/src/libgit2/cherrypick.c +3 -3
  90. data/vendor/libgit2/src/libgit2/clone.c +34 -3
  91. data/vendor/libgit2/src/libgit2/commit.c +78 -21
  92. data/vendor/libgit2/src/libgit2/commit.h +25 -7
  93. data/vendor/libgit2/src/libgit2/commit_graph.c +129 -47
  94. data/vendor/libgit2/src/libgit2/commit_graph.h +23 -4
  95. data/vendor/libgit2/src/libgit2/commit_list.c +16 -5
  96. data/vendor/libgit2/src/libgit2/commit_list.h +1 -0
  97. data/vendor/libgit2/src/libgit2/config.c +6 -3
  98. data/vendor/libgit2/src/libgit2/config_file.c +16 -10
  99. data/vendor/libgit2/src/libgit2/describe.c +11 -8
  100. data/vendor/libgit2/src/libgit2/diff.c +19 -6
  101. data/vendor/libgit2/src/libgit2/diff.h +6 -6
  102. data/vendor/libgit2/src/libgit2/diff_file.c +16 -7
  103. data/vendor/libgit2/src/libgit2/diff_generate.c +37 -11
  104. data/vendor/libgit2/src/libgit2/diff_parse.c +20 -4
  105. data/vendor/libgit2/src/libgit2/diff_print.c +26 -7
  106. data/vendor/libgit2/src/libgit2/diff_tform.c +4 -0
  107. data/vendor/libgit2/src/libgit2/diff_xdiff.h +1 -1
  108. data/vendor/libgit2/src/libgit2/email.c +4 -3
  109. data/vendor/libgit2/src/libgit2/errors.c +73 -18
  110. data/vendor/libgit2/src/libgit2/experimental.h.in +13 -0
  111. data/vendor/libgit2/src/libgit2/fetch.c +38 -13
  112. data/vendor/libgit2/src/libgit2/fetch.h +0 -2
  113. data/vendor/libgit2/src/libgit2/fetchhead.c +11 -9
  114. data/vendor/libgit2/src/libgit2/grafts.c +272 -0
  115. data/vendor/libgit2/src/libgit2/grafts.h +36 -0
  116. data/vendor/libgit2/src/libgit2/ident.c +3 -3
  117. data/vendor/libgit2/src/libgit2/index.c +327 -123
  118. data/vendor/libgit2/src/libgit2/index.h +14 -1
  119. data/vendor/libgit2/src/libgit2/indexer.c +116 -46
  120. data/vendor/libgit2/src/libgit2/iterator.c +21 -4
  121. data/vendor/libgit2/src/libgit2/iterator.h +3 -0
  122. data/vendor/libgit2/src/libgit2/libgit2.c +58 -0
  123. data/vendor/libgit2/src/libgit2/merge.c +14 -9
  124. data/vendor/libgit2/src/libgit2/merge_file.c +0 -2
  125. data/vendor/libgit2/src/libgit2/midx.c +68 -38
  126. data/vendor/libgit2/src/libgit2/midx.h +13 -3
  127. data/vendor/libgit2/src/libgit2/mwindow.c +5 -2
  128. data/vendor/libgit2/src/libgit2/mwindow.h +4 -1
  129. data/vendor/libgit2/src/libgit2/notes.c +9 -8
  130. data/vendor/libgit2/src/libgit2/object.c +118 -29
  131. data/vendor/libgit2/src/libgit2/object.h +17 -2
  132. data/vendor/libgit2/src/libgit2/odb.c +224 -55
  133. data/vendor/libgit2/src/libgit2/odb.h +43 -4
  134. data/vendor/libgit2/src/libgit2/odb_loose.c +128 -70
  135. data/vendor/libgit2/src/libgit2/odb_pack.c +111 -46
  136. data/vendor/libgit2/src/libgit2/oid.c +141 -77
  137. data/vendor/libgit2/src/libgit2/oid.h +183 -9
  138. data/vendor/libgit2/src/libgit2/oidarray.c +49 -3
  139. data/vendor/libgit2/src/libgit2/oidarray.h +5 -1
  140. data/vendor/libgit2/src/libgit2/pack-objects.c +31 -13
  141. data/vendor/libgit2/src/libgit2/pack-objects.h +5 -2
  142. data/vendor/libgit2/src/libgit2/pack.c +93 -70
  143. data/vendor/libgit2/src/libgit2/pack.h +29 -15
  144. data/vendor/libgit2/src/libgit2/parse.c +8 -4
  145. data/vendor/libgit2/src/libgit2/parse.h +1 -1
  146. data/vendor/libgit2/src/libgit2/patch.h +7 -1
  147. data/vendor/libgit2/src/libgit2/patch_generate.c +24 -5
  148. data/vendor/libgit2/src/libgit2/patch_parse.c +16 -8
  149. data/vendor/libgit2/src/libgit2/push.c +13 -3
  150. data/vendor/libgit2/src/libgit2/reader.c +1 -1
  151. data/vendor/libgit2/src/libgit2/rebase.c +72 -83
  152. data/vendor/libgit2/src/libgit2/refdb_fs.c +92 -52
  153. data/vendor/libgit2/src/libgit2/reflog.c +7 -5
  154. data/vendor/libgit2/src/libgit2/reflog.h +1 -2
  155. data/vendor/libgit2/src/libgit2/refs.c +9 -0
  156. data/vendor/libgit2/src/libgit2/remote.c +47 -37
  157. data/vendor/libgit2/src/libgit2/remote.h +41 -0
  158. data/vendor/libgit2/src/libgit2/repository.c +784 -329
  159. data/vendor/libgit2/src/libgit2/repository.h +26 -2
  160. data/vendor/libgit2/src/libgit2/reset.c +2 -2
  161. data/vendor/libgit2/src/libgit2/revert.c +8 -11
  162. data/vendor/libgit2/src/libgit2/revparse.c +23 -7
  163. data/vendor/libgit2/src/libgit2/revwalk.c +31 -5
  164. data/vendor/libgit2/src/libgit2/stash.c +209 -33
  165. data/vendor/libgit2/src/libgit2/strarray.c +1 -0
  166. data/vendor/libgit2/src/libgit2/strarray.h +25 -0
  167. data/vendor/libgit2/src/libgit2/streams/mbedtls.c +0 -1
  168. data/vendor/libgit2/src/libgit2/streams/openssl.c +9 -17
  169. data/vendor/libgit2/src/libgit2/streams/openssl_dynamic.c +7 -3
  170. data/vendor/libgit2/src/libgit2/streams/schannel.c +715 -0
  171. data/vendor/libgit2/src/libgit2/streams/schannel.h +28 -0
  172. data/vendor/libgit2/src/libgit2/streams/socket.c +240 -51
  173. data/vendor/libgit2/src/libgit2/streams/socket.h +3 -1
  174. data/vendor/libgit2/src/libgit2/streams/stransport.c +40 -12
  175. data/vendor/libgit2/src/libgit2/streams/tls.c +5 -0
  176. data/vendor/libgit2/src/libgit2/submodule.c +6 -2
  177. data/vendor/libgit2/src/libgit2/submodule.h +3 -3
  178. data/vendor/libgit2/src/libgit2/sysdir.c +294 -7
  179. data/vendor/libgit2/src/libgit2/sysdir.h +41 -9
  180. data/vendor/libgit2/src/libgit2/tag.c +29 -10
  181. data/vendor/libgit2/src/libgit2/tag.h +2 -2
  182. data/vendor/libgit2/src/libgit2/threadstate.c +15 -2
  183. data/vendor/libgit2/src/libgit2/threadstate.h +1 -3
  184. data/vendor/libgit2/src/libgit2/transports/auth.h +1 -2
  185. data/vendor/libgit2/src/libgit2/transports/{auth_negotiate.c → auth_gssapi.c} +32 -32
  186. data/vendor/libgit2/src/libgit2/transports/auth_negotiate.h +1 -1
  187. data/vendor/libgit2/src/libgit2/transports/auth_ntlm.h +1 -1
  188. data/vendor/libgit2/src/libgit2/transports/{auth_ntlm.c → auth_ntlmclient.c} +12 -12
  189. data/vendor/libgit2/src/libgit2/transports/auth_sspi.c +341 -0
  190. data/vendor/libgit2/src/libgit2/transports/git.c +7 -8
  191. data/vendor/libgit2/src/libgit2/transports/http.c +15 -9
  192. data/vendor/libgit2/src/libgit2/transports/httpclient.c +14 -0
  193. data/vendor/libgit2/src/libgit2/transports/httpclient.h +10 -0
  194. data/vendor/libgit2/src/libgit2/transports/local.c +27 -4
  195. data/vendor/libgit2/src/libgit2/transports/smart.c +68 -27
  196. data/vendor/libgit2/src/libgit2/transports/smart.h +33 -9
  197. data/vendor/libgit2/src/libgit2/transports/smart_pkt.c +281 -49
  198. data/vendor/libgit2/src/libgit2/transports/smart_protocol.c +192 -55
  199. data/vendor/libgit2/src/libgit2/transports/ssh.c +334 -102
  200. data/vendor/libgit2/src/libgit2/transports/winhttp.c +22 -18
  201. data/vendor/libgit2/src/libgit2/tree-cache.c +26 -16
  202. data/vendor/libgit2/src/libgit2/tree-cache.h +5 -3
  203. data/vendor/libgit2/src/libgit2/tree.c +23 -17
  204. data/vendor/libgit2/src/libgit2/tree.h +2 -2
  205. data/vendor/libgit2/src/libgit2/worktree.c +30 -10
  206. data/vendor/libgit2/src/util/CMakeLists.txt +6 -1
  207. data/vendor/libgit2/src/util/alloc.c +65 -6
  208. data/vendor/libgit2/src/util/alloc.h +34 -9
  209. data/vendor/libgit2/src/util/allocators/failalloc.c +0 -60
  210. data/vendor/libgit2/src/util/allocators/failalloc.h +0 -6
  211. data/vendor/libgit2/src/util/allocators/stdalloc.c +2 -105
  212. data/vendor/libgit2/src/util/allocators/win32_leakcheck.c +0 -68
  213. data/vendor/libgit2/src/util/array.h +6 -1
  214. data/vendor/libgit2/src/util/cc-compat.h +2 -0
  215. data/vendor/libgit2/src/util/filebuf.c +6 -1
  216. data/vendor/libgit2/src/util/filebuf.h +19 -6
  217. data/vendor/libgit2/src/util/fs_path.c +2 -2
  218. data/vendor/libgit2/src/util/futils.c +8 -8
  219. data/vendor/libgit2/src/{features.h.in → util/git2_features.h.in} +9 -3
  220. data/vendor/libgit2/src/util/git2_util.h +2 -2
  221. data/vendor/libgit2/src/util/hash/openssl.c +4 -3
  222. data/vendor/libgit2/src/util/hash/rfc6234/sha.h +0 -112
  223. data/vendor/libgit2/src/util/hash.h +13 -0
  224. data/vendor/libgit2/src/util/net.c +492 -87
  225. data/vendor/libgit2/src/util/net.h +32 -0
  226. data/vendor/libgit2/src/util/posix.c +54 -0
  227. data/vendor/libgit2/src/util/posix.h +24 -0
  228. data/vendor/libgit2/src/util/rand.c +10 -4
  229. data/vendor/libgit2/src/util/regexp.c +3 -3
  230. data/vendor/libgit2/src/util/staticstr.h +66 -0
  231. data/vendor/libgit2/src/util/thread.h +20 -19
  232. data/vendor/libgit2/src/util/util.c +15 -10
  233. data/vendor/libgit2/src/util/util.h +25 -16
  234. data/vendor/libgit2/src/util/win32/error.c +1 -1
  235. data/vendor/libgit2/src/util/win32/path_w32.c +8 -8
  236. data/vendor/libgit2/src/util/win32/posix_w32.c +1 -1
  237. data/vendor/libgit2/src/util/win32/utf-conv.c +73 -75
  238. data/vendor/libgit2/src/util/win32/utf-conv.h +81 -14
  239. data/vendor/libgit2/src/util/win32/w32_util.c +1 -1
  240. metadata +34 -26
  241. data/vendor/libgit2/cmake/SelectWinHTTP.cmake +0 -17
  242. data/vendor/libgit2/src/libgit2/netops.c +0 -124
  243. data/vendor/libgit2/src/libgit2/netops.h +0 -68
  244. data/vendor/libgit2/src/util/win32/findfile.c +0 -286
  245. data/vendor/libgit2/src/util/win32/findfile.h +0 -22
  246. /data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xdiff.h +0 -0
  247. /data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xemit.h +0 -0
  248. /data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xinclude.h +0 -0
  249. /data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xprepare.h +0 -0
  250. /data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xtypes.h +0 -0
@@ -15,6 +15,7 @@
15
15
  #include "buf.h"
16
16
  #include "common.h"
17
17
  #include "commit.h"
18
+ #include "grafts.h"
18
19
  #include "tag.h"
19
20
  #include "blob.h"
20
21
  #include "futils.h"
@@ -66,7 +67,8 @@ static const struct {
66
67
 
67
68
  static int check_repositoryformatversion(int *version, git_config *config);
68
69
  static int check_extensions(git_config *config, int version);
69
- static int load_global_config(git_config **config);
70
+ static int load_global_config(git_config **config, bool use_env);
71
+ static int load_objectformat(git_repository *repo, git_config *config);
70
72
 
71
73
  #define GIT_COMMONDIR_FILE "commondir"
72
74
  #define GIT_GITDIR_FILE "gitdir"
@@ -75,8 +77,8 @@ static int load_global_config(git_config **config);
75
77
 
76
78
  #define GIT_BRANCH_DEFAULT "master"
77
79
 
78
- #define GIT_REPO_VERSION 0
79
- #define GIT_REPO_MAX_VERSION 1
80
+ #define GIT_REPO_VERSION_DEFAULT 0
81
+ #define GIT_REPO_VERSION_MAX 1
80
82
 
81
83
  git_str git_repository__reserved_names_win32[] = {
82
84
  { DOT_GIT, 0, CONST_STRLEN(DOT_GIT) },
@@ -150,6 +152,10 @@ int git_repository__cleanup(git_repository *repo)
150
152
  git_repository_submodule_cache_clear(repo);
151
153
  git_cache_clear(&repo->objects);
152
154
  git_attr_cache_flush(repo);
155
+ git_grafts_free(repo->grafts);
156
+ repo->grafts = NULL;
157
+ git_grafts_free(repo->shallow_grafts);
158
+ repo->shallow_grafts = NULL;
153
159
 
154
160
  set_config(repo, NULL);
155
161
  set_index(repo, NULL);
@@ -190,11 +196,23 @@ void git_repository_free(git_repository *repo)
190
196
  }
191
197
 
192
198
  /* Check if we have a separate commondir (e.g. we have a worktree) */
193
- static int lookup_commondir(bool *separate, git_str *commondir, git_str *repository_path)
199
+ static int lookup_commondir(
200
+ bool *separate,
201
+ git_str *commondir,
202
+ git_str *repository_path,
203
+ uint32_t flags)
194
204
  {
195
- git_str common_link = GIT_STR_INIT;
205
+ git_str common_link = GIT_STR_INIT;
196
206
  int error;
197
207
 
208
+ /* Environment variable overrides configuration */
209
+ if ((flags & GIT_REPOSITORY_OPEN_FROM_ENV)) {
210
+ error = git__getenv(commondir, "GIT_COMMON_DIR");
211
+
212
+ if (!error || error != GIT_ENOTFOUND)
213
+ goto done;
214
+ }
215
+
198
216
  /*
199
217
  * If there's no commondir file, the repository path is the
200
218
  * common path, but it needs a trailing slash.
@@ -221,12 +239,11 @@ static int lookup_commondir(bool *separate, git_str *commondir, git_str *reposit
221
239
  git_str_swap(commondir, &common_link);
222
240
  }
223
241
 
224
- git_str_dispose(&common_link);
225
-
226
242
  /* Make sure the commondir path always has a trailing slash */
227
243
  error = git_fs_path_prettify_dir(commondir, commondir->ptr, NULL);
228
244
 
229
245
  done:
246
+ git_str_dispose(&common_link);
230
247
  return error;
231
248
  }
232
249
 
@@ -240,7 +257,7 @@ GIT_INLINE(int) validate_repo_path(git_str *path)
240
257
  */
241
258
  static size_t suffix_len =
242
259
  CONST_STRLEN("objects/pack/pack-.pack.lock") +
243
- GIT_OID_HEXSZ;
260
+ GIT_OID_MAX_HEXSIZE;
244
261
 
245
262
  return git_fs_path_validate_str_length_with_suffix(
246
263
  path, suffix_len);
@@ -251,14 +268,19 @@ GIT_INLINE(int) validate_repo_path(git_str *path)
251
268
  *
252
269
  * Open a repository object from its path
253
270
  */
254
- static int is_valid_repository_path(bool *out, git_str *repository_path, git_str *common_path)
271
+ static int is_valid_repository_path(
272
+ bool *out,
273
+ git_str *repository_path,
274
+ git_str *common_path,
275
+ uint32_t flags)
255
276
  {
256
277
  bool separate_commondir = false;
257
278
  int error;
258
279
 
259
280
  *out = false;
260
281
 
261
- if ((error = lookup_commondir(&separate_commondir, common_path, repository_path)) < 0)
282
+ if ((error = lookup_commondir(&separate_commondir,
283
+ common_path, repository_path, flags)) < 0)
262
284
  return error;
263
285
 
264
286
  /* Ensure HEAD file exists */
@@ -336,19 +358,42 @@ static int load_config_data(git_repository *repo, const git_config *config)
336
358
  return 0;
337
359
  }
338
360
 
339
- static int load_workdir(git_repository *repo, git_config *config, git_str *parent_path)
361
+ static int load_workdir(
362
+ git_repository *repo,
363
+ git_config *config,
364
+ git_str *parent_path)
340
365
  {
341
- int error;
342
- git_config_entry *ce;
366
+ git_config_entry *ce = NULL;
343
367
  git_str worktree = GIT_STR_INIT;
344
368
  git_str path = GIT_STR_INIT;
369
+ git_str workdir_env = GIT_STR_INIT;
370
+ const char *value = NULL;
371
+ int error;
345
372
 
346
373
  if (repo->is_bare)
347
374
  return 0;
348
375
 
349
- if ((error = git_config__lookup_entry(
350
- &ce, config, "core.worktree", false)) < 0)
351
- return error;
376
+ /* Environment variables are preferred */
377
+ if (repo->use_env) {
378
+ error = git__getenv(&workdir_env, "GIT_WORK_TREE");
379
+
380
+ if (error == 0)
381
+ value = workdir_env.ptr;
382
+ else if (error == GIT_ENOTFOUND)
383
+ error = 0;
384
+ else
385
+ goto cleanup;
386
+ }
387
+
388
+ /* Examine configuration values if necessary */
389
+ if (!value) {
390
+ if ((error = git_config__lookup_entry(&ce, config,
391
+ "core.worktree", false)) < 0)
392
+ return error;
393
+
394
+ if (ce && ce->value)
395
+ value = ce->value;
396
+ }
352
397
 
353
398
  if (repo->is_worktree) {
354
399
  char *gitlink = git_worktree__read_link(repo->gitdir, GIT_GITDIR_FILE);
@@ -366,17 +411,21 @@ static int load_workdir(git_repository *repo, git_config *config, git_str *paren
366
411
  }
367
412
 
368
413
  repo->workdir = git_str_detach(&worktree);
369
- }
370
- else if (ce && ce->value) {
371
- if ((error = git_fs_path_prettify_dir(
372
- &worktree, ce->value, repo->gitdir)) < 0)
414
+ } else if (value) {
415
+ if (!*value) {
416
+ git_error_set(GIT_ERROR_NET, "working directory cannot be set to empty path");
417
+ error = -1;
418
+ goto cleanup;
419
+ }
420
+
421
+ if ((error = git_fs_path_prettify_dir(&worktree,
422
+ value, repo->gitdir)) < 0)
373
423
  goto cleanup;
374
424
 
375
425
  repo->workdir = git_str_detach(&worktree);
376
- }
377
- else if (parent_path && git_fs_path_isdir(parent_path->ptr))
426
+ } else if (parent_path && git_fs_path_isdir(parent_path->ptr)) {
378
427
  repo->workdir = git_str_detach(parent_path);
379
- else {
428
+ } else {
380
429
  if (git_fs_path_dirname_r(&worktree, repo->gitdir) < 0 ||
381
430
  git_fs_path_to_dir(&worktree) < 0) {
382
431
  error = -1;
@@ -387,8 +436,10 @@ static int load_workdir(git_repository *repo, git_config *config, git_str *paren
387
436
  }
388
437
 
389
438
  GIT_ERROR_CHECK_ALLOC(repo->workdir);
439
+
390
440
  cleanup:
391
441
  git_str_dispose(&path);
442
+ git_str_dispose(&workdir_env);
392
443
  git_config_entry_free(ce);
393
444
  return error;
394
445
  }
@@ -495,17 +546,55 @@ static int validate_ownership_cb(const git_config_entry *entry, void *payload)
495
546
  {
496
547
  validate_ownership_data *data = payload;
497
548
 
498
- if (strcmp(entry->value, "") == 0)
549
+ if (strcmp(entry->value, "") == 0) {
499
550
  *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)
551
+ } else if (strcmp(entry->value, "*") == 0) {
503
552
  *data->is_safe = true;
553
+ } else {
554
+ const char *test_path = entry->value;
555
+
556
+ #ifdef GIT_WIN32
557
+ /*
558
+ * Git for Windows does some truly bizarre things with
559
+ * paths that start with a forward slash; and expects you
560
+ * to escape that with `%(prefix)`. This syntax generally
561
+ * means to add the prefix that Git was installed to -- eg
562
+ * `/usr/local` -- unless it's an absolute path, in which
563
+ * case the leading `%(prefix)/` is just removed. And Git
564
+ * for Windows expects you to use this syntax for absolute
565
+ * Unix-style paths (in "Git Bash" or Windows Subsystem for
566
+ * Linux).
567
+ *
568
+ * Worse, the behavior used to be that a leading `/` was
569
+ * not absolute. It would indicate that Git for Windows
570
+ * should add the prefix. So `//` is required for absolute
571
+ * Unix-style paths. Yes, this is truly horrifying.
572
+ *
573
+ * Emulate that behavior, I guess, but only for absolute
574
+ * paths. We won't deal with the Git install prefix. Also,
575
+ * give WSL users an escape hatch where they don't have to
576
+ * think about this and can use the literal path that the
577
+ * filesystem APIs provide (`//wsl.localhost/...`).
578
+ */
579
+ if (strncmp(test_path, "%(prefix)//", strlen("%(prefix)//")) == 0)
580
+ test_path += strlen("%(prefix)/");
581
+ else if (strncmp(test_path, "//", 2) == 0 &&
582
+ strncmp(test_path, "//wsl.localhost/", strlen("//wsl.localhost/")) != 0)
583
+ test_path++;
584
+ #endif
585
+
586
+ if (git_fs_path_prettify_dir(&data->tmp, test_path, NULL) == 0 &&
587
+ strcmp(data->tmp.ptr, data->repo_path) == 0)
588
+ *data->is_safe = true;
589
+ }
504
590
 
505
591
  return 0;
506
592
  }
507
593
 
508
- static int validate_ownership_config(bool *is_safe, const char *path)
594
+ static int validate_ownership_config(
595
+ bool *is_safe,
596
+ const char *path,
597
+ bool use_env)
509
598
  {
510
599
  validate_ownership_data ownership_data = {
511
600
  path, GIT_STR_INIT, is_safe
@@ -513,7 +602,7 @@ static int validate_ownership_config(bool *is_safe, const char *path)
513
602
  git_config *config;
514
603
  int error;
515
604
 
516
- if (load_global_config(&config) != 0)
605
+ if (load_global_config(&config, use_env) != 0)
517
606
  return 0;
518
607
 
519
608
  error = git_config_get_multivar_foreach(config,
@@ -521,6 +610,9 @@ static int validate_ownership_config(bool *is_safe, const char *path)
521
610
  validate_ownership_cb,
522
611
  &ownership_data);
523
612
 
613
+ if (error == GIT_ENOTFOUND)
614
+ error = 0;
615
+
524
616
  git_config_free(config);
525
617
  git_str_dispose(&ownership_data.tmp);
526
618
 
@@ -541,6 +633,9 @@ static int validate_ownership_path(bool *is_safe, const char *path)
541
633
  if (error == GIT_ENOTFOUND) {
542
634
  *is_safe = true;
543
635
  error = 0;
636
+ } else if (error == GIT_EINVALID) {
637
+ *is_safe = false;
638
+ error = 0;
544
639
  }
545
640
 
546
641
  return error;
@@ -581,7 +676,8 @@ static int validate_ownership(git_repository *repo)
581
676
  }
582
677
 
583
678
  if (is_safe ||
584
- (error = validate_ownership_config(&is_safe, validation_paths[0])) < 0)
679
+ (error = validate_ownership_config(
680
+ &is_safe, validation_paths[0], repo->use_env)) < 0)
585
681
  goto done;
586
682
 
587
683
  if (!is_safe) {
@@ -595,14 +691,28 @@ done:
595
691
  return error;
596
692
  }
597
693
 
598
- static int find_repo(
599
- git_str *gitdir_path,
600
- git_str *workdir_path,
601
- git_str *gitlink_path,
602
- git_str *commondir_path,
694
+ struct repo_paths {
695
+ git_str gitdir;
696
+ git_str workdir;
697
+ git_str gitlink;
698
+ git_str commondir;
699
+ };
700
+
701
+ #define REPO_PATHS_INIT { GIT_STR_INIT }
702
+
703
+ GIT_INLINE(void) repo_paths_dispose(struct repo_paths *paths)
704
+ {
705
+ git_str_dispose(&paths->gitdir);
706
+ git_str_dispose(&paths->workdir);
707
+ git_str_dispose(&paths->gitlink);
708
+ git_str_dispose(&paths->commondir);
709
+ }
710
+
711
+ static int find_repo_traverse(
712
+ struct repo_paths *out,
603
713
  const char *start_path,
604
- uint32_t flags,
605
- const char *ceiling_dirs)
714
+ const char *ceiling_dirs,
715
+ uint32_t flags)
606
716
  {
607
717
  git_str path = GIT_STR_INIT;
608
718
  git_str repo_link = GIT_STR_INIT;
@@ -614,19 +724,23 @@ static int find_repo(
614
724
  size_t ceiling_offset = 0;
615
725
  int error;
616
726
 
617
- git_str_clear(gitdir_path);
727
+ git_str_clear(&out->gitdir);
618
728
 
619
- error = git_fs_path_prettify(&path, start_path, NULL);
620
- if (error < 0)
729
+ if ((error = git_fs_path_prettify(&path, start_path, NULL)) < 0)
621
730
  return error;
622
731
 
623
- /* in_dot_git toggles each loop:
732
+ /*
733
+ * In each loop we look first for a `.git` dir within the
734
+ * directory, then to see if the directory itself is a repo.
735
+ *
736
+ * In other words: if we start in /a/b/c, then we look at:
624
737
  * /a/b/c/.git, /a/b/c, /a/b/.git, /a/b, /a/.git, /a
625
- * With GIT_REPOSITORY_OPEN_BARE or GIT_REPOSITORY_OPEN_NO_DOTGIT, we
626
- * assume we started with /a/b/c.git and don't append .git the first
627
- * time through.
628
- * min_iterations indicates the number of iterations left before going
629
- * further counts as a search. */
738
+ *
739
+ * With GIT_REPOSITORY_OPEN_BARE or GIT_REPOSITORY_OPEN_NO_DOTGIT,
740
+ * we assume we started with /a/b/c.git and don't append .git the
741
+ * first time through. min_iterations indicates the number of
742
+ * iterations left before going further counts as a search.
743
+ */
630
744
  if (flags & (GIT_REPOSITORY_OPEN_BARE | GIT_REPOSITORY_OPEN_NO_DOTGIT)) {
631
745
  in_dot_git = true;
632
746
  min_iterations = 1;
@@ -653,48 +767,51 @@ static int find_repo(
653
767
  break;
654
768
 
655
769
  if (S_ISDIR(st.st_mode)) {
656
- if ((error = is_valid_repository_path(&is_valid, &path, &common_link)) < 0)
770
+ if ((error = is_valid_repository_path(&is_valid, &path, &common_link, flags)) < 0)
657
771
  goto out;
658
772
 
659
773
  if (is_valid) {
660
774
  if ((error = git_fs_path_to_dir(&path)) < 0 ||
661
- (error = git_str_set(gitdir_path, path.ptr, path.size)) < 0)
775
+ (error = git_str_set(&out->gitdir, path.ptr, path.size)) < 0)
776
+ goto out;
777
+
778
+ if ((error = git_str_attach(&out->gitlink, git_worktree__read_link(path.ptr, GIT_GITDIR_FILE), 0)) < 0)
662
779
  goto out;
663
780
 
664
- if (gitlink_path)
665
- if ((error = git_str_attach(gitlink_path, git_worktree__read_link(path.ptr, GIT_GITDIR_FILE), 0)) < 0)
666
- goto out;
667
- if (commondir_path)
668
- git_str_swap(&common_link, commondir_path);
781
+ git_str_swap(&common_link, &out->commondir);
669
782
 
670
783
  break;
671
784
  }
672
785
  } else if (S_ISREG(st.st_mode) && git__suffixcmp(path.ptr, "/" DOT_GIT) == 0) {
673
786
  if ((error = read_gitfile(&repo_link, path.ptr)) < 0 ||
674
- (error = is_valid_repository_path(&is_valid, &repo_link, &common_link)) < 0)
787
+ (error = is_valid_repository_path(&is_valid, &repo_link, &common_link, flags)) < 0)
675
788
  goto out;
676
789
 
677
790
  if (is_valid) {
678
- git_str_swap(gitdir_path, &repo_link);
791
+ git_str_swap(&out->gitdir, &repo_link);
792
+
793
+ if ((error = git_str_put(&out->gitlink, path.ptr, path.size)) < 0)
794
+ goto out;
679
795
 
680
- if (gitlink_path)
681
- if ((error = git_str_put(gitlink_path, path.ptr, path.size)) < 0)
682
- goto out;
683
- if (commondir_path)
684
- git_str_swap(&common_link, commondir_path);
796
+ git_str_swap(&common_link, &out->commondir);
685
797
  }
686
798
  break;
687
799
  }
688
800
  }
689
801
 
690
- /* Move up one directory. If we're in_dot_git, we'll search the
691
- * parent itself next. If we're !in_dot_git, we'll search .git
692
- * in the parent directory next (added at the top of the loop). */
802
+ /*
803
+ * Move up one directory. If we're in_dot_git, we'll
804
+ * search the parent itself next. If we're !in_dot_git,
805
+ * we'll search .git in the parent directory next (added
806
+ * at the top of the loop).
807
+ */
693
808
  if ((error = git_fs_path_dirname_r(&path, path.ptr)) < 0)
694
809
  goto out;
695
810
 
696
- /* Once we've checked the directory (and .git if applicable),
697
- * find the ceiling for a search. */
811
+ /*
812
+ * Once we've checked the directory (and .git if
813
+ * applicable), find the ceiling for a search.
814
+ */
698
815
  if (min_iterations && (--min_iterations == 0))
699
816
  ceiling_offset = find_ceiling_dir_offset(path.ptr, ceiling_dirs);
700
817
 
@@ -704,29 +821,154 @@ static int find_repo(
704
821
  break;
705
822
  }
706
823
 
707
- if (workdir_path && !(flags & GIT_REPOSITORY_OPEN_BARE)) {
708
- if (!git_str_len(gitdir_path))
709
- git_str_clear(workdir_path);
710
- else if ((error = git_fs_path_dirname_r(workdir_path, path.ptr)) < 0 ||
711
- (error = git_fs_path_to_dir(workdir_path)) < 0)
824
+ if (!(flags & GIT_REPOSITORY_OPEN_BARE)) {
825
+ if (!git_str_len(&out->gitdir))
826
+ git_str_clear(&out->workdir);
827
+ else if ((error = git_fs_path_dirname_r(&out->workdir, path.ptr)) < 0 ||
828
+ (error = git_fs_path_to_dir(&out->workdir)) < 0)
712
829
  goto out;
713
830
  }
714
831
 
715
- /* If we didn't find the repository, and we don't have any other error
716
- * to report, report that. */
717
- if (!git_str_len(gitdir_path)) {
718
- git_error_set(GIT_ERROR_REPOSITORY, "could not find repository from '%s'", start_path);
832
+ /* If we didn't find the repository, and we don't have any other
833
+ * error to report, report that. */
834
+ if (!git_str_len(&out->gitdir)) {
835
+ git_error_set(GIT_ERROR_REPOSITORY, "could not find repository at '%s'", start_path);
719
836
  error = GIT_ENOTFOUND;
720
837
  goto out;
721
838
  }
722
839
 
723
840
  out:
841
+ if (error)
842
+ repo_paths_dispose(out);
843
+
724
844
  git_str_dispose(&path);
725
845
  git_str_dispose(&repo_link);
726
846
  git_str_dispose(&common_link);
727
847
  return error;
728
848
  }
729
849
 
850
+ static int load_grafts(git_repository *repo)
851
+ {
852
+ git_str path = GIT_STR_INIT;
853
+ int error;
854
+
855
+ if ((error = git_repository__item_path(&path, repo, GIT_REPOSITORY_ITEM_INFO)) < 0 ||
856
+ (error = git_str_joinpath(&path, path.ptr, "grafts")) < 0 ||
857
+ (error = git_grafts_open_or_refresh(&repo->grafts, path.ptr, repo->oid_type)) < 0)
858
+ goto error;
859
+
860
+ git_str_clear(&path);
861
+
862
+ if ((error = git_str_joinpath(&path, repo->gitdir, "shallow")) < 0 ||
863
+ (error = git_grafts_open_or_refresh(&repo->shallow_grafts, path.ptr, repo->oid_type)) < 0)
864
+ goto error;
865
+
866
+ error:
867
+ git_str_dispose(&path);
868
+ return error;
869
+ }
870
+
871
+ static int find_repo(
872
+ struct repo_paths *out,
873
+ const char *start_path,
874
+ const char *ceiling_dirs,
875
+ uint32_t flags)
876
+ {
877
+ bool use_env = !!(flags & GIT_REPOSITORY_OPEN_FROM_ENV);
878
+ git_str gitdir_buf = GIT_STR_INIT,
879
+ ceiling_dirs_buf = GIT_STR_INIT,
880
+ across_fs_buf = GIT_STR_INIT;
881
+ int error;
882
+
883
+ if (use_env && !start_path) {
884
+ error = git__getenv(&gitdir_buf, "GIT_DIR");
885
+
886
+ if (!error) {
887
+ start_path = gitdir_buf.ptr;
888
+ flags |= GIT_REPOSITORY_OPEN_NO_SEARCH;
889
+ flags |= GIT_REPOSITORY_OPEN_NO_DOTGIT;
890
+ } else if (error == GIT_ENOTFOUND) {
891
+ start_path = ".";
892
+ } else {
893
+ goto done;
894
+ }
895
+ }
896
+
897
+ if (use_env && !ceiling_dirs) {
898
+ error = git__getenv(&ceiling_dirs_buf,
899
+ "GIT_CEILING_DIRECTORIES");
900
+
901
+ if (!error)
902
+ ceiling_dirs = ceiling_dirs_buf.ptr;
903
+ else if (error != GIT_ENOTFOUND)
904
+ goto done;
905
+ }
906
+
907
+ if (use_env) {
908
+ error = git__getenv(&across_fs_buf,
909
+ "GIT_DISCOVERY_ACROSS_FILESYSTEM");
910
+
911
+ if (!error) {
912
+ int across_fs = 0;
913
+
914
+ if ((error = git_config_parse_bool(&across_fs,
915
+ git_str_cstr(&across_fs_buf))) < 0)
916
+ goto done;
917
+
918
+ if (across_fs)
919
+ flags |= GIT_REPOSITORY_OPEN_CROSS_FS;
920
+ } else if (error != GIT_ENOTFOUND) {
921
+ goto done;
922
+ }
923
+ }
924
+
925
+ error = find_repo_traverse(out, start_path, ceiling_dirs, flags);
926
+
927
+ done:
928
+ git_str_dispose(&gitdir_buf);
929
+ git_str_dispose(&ceiling_dirs_buf);
930
+ git_str_dispose(&across_fs_buf);
931
+
932
+ return error;
933
+ }
934
+
935
+ static int obtain_config_and_set_oid_type(
936
+ git_config **config_ptr,
937
+ git_repository *repo)
938
+ {
939
+ int error;
940
+ git_config *config = NULL;
941
+ int version = 0;
942
+
943
+ /*
944
+ * We'd like to have the config, but git doesn't particularly
945
+ * care if it's not there, so we need to deal with that.
946
+ */
947
+
948
+ error = git_repository_config_snapshot(&config, repo);
949
+ if (error < 0 && error != GIT_ENOTFOUND)
950
+ goto out;
951
+
952
+ if (config &&
953
+ (error = check_repositoryformatversion(&version, config)) < 0)
954
+ goto out;
955
+
956
+ if ((error = check_extensions(config, version)) < 0)
957
+ goto out;
958
+
959
+ if (version > 0) {
960
+ if ((error = load_objectformat(repo, config)) < 0)
961
+ goto out;
962
+ } else {
963
+ repo->oid_type = GIT_OID_DEFAULT;
964
+ }
965
+
966
+ out:
967
+ *config_ptr = config;
968
+
969
+ return error;
970
+ }
971
+
730
972
  int git_repository_open_bare(
731
973
  git_repository **repo_ptr,
732
974
  const char *bare_path)
@@ -735,9 +977,10 @@ int git_repository_open_bare(
735
977
  git_repository *repo = NULL;
736
978
  bool is_valid;
737
979
  int error;
980
+ git_config *config;
738
981
 
739
982
  if ((error = git_fs_path_prettify_dir(&path, bare_path, NULL)) < 0 ||
740
- (error = is_valid_repository_path(&is_valid, &path, &common_path)) < 0)
983
+ (error = is_valid_repository_path(&is_valid, &path, &common_path, 0)) < 0)
741
984
  return error;
742
985
 
743
986
  if (!is_valid) {
@@ -760,177 +1003,33 @@ int git_repository_open_bare(
760
1003
  repo->is_worktree = 0;
761
1004
  repo->workdir = NULL;
762
1005
 
1006
+ if ((error = obtain_config_and_set_oid_type(&config, repo)) < 0)
1007
+ goto cleanup;
1008
+
763
1009
  *repo_ptr = repo;
764
- return 0;
1010
+
1011
+ cleanup:
1012
+ git_config_free(config);
1013
+
1014
+ return error;
765
1015
  }
766
1016
 
767
- static int _git_repository_open_ext_from_env(
768
- git_repository **out,
769
- const char *start_path)
1017
+ static int repo_load_namespace(git_repository *repo)
770
1018
  {
771
- git_repository *repo = NULL;
772
- git_index *index = NULL;
773
- git_odb *odb = NULL;
774
- git_str dir_buf = GIT_STR_INIT;
775
- git_str ceiling_dirs_buf = GIT_STR_INIT;
776
- git_str across_fs_buf = GIT_STR_INIT;
777
- git_str index_file_buf = GIT_STR_INIT;
778
1019
  git_str namespace_buf = GIT_STR_INIT;
779
- git_str object_dir_buf = GIT_STR_INIT;
780
- git_str alts_buf = GIT_STR_INIT;
781
- git_str work_tree_buf = GIT_STR_INIT;
782
- git_str common_dir_buf = GIT_STR_INIT;
783
- const char *ceiling_dirs = NULL;
784
- unsigned flags = 0;
785
1020
  int error;
786
1021
 
787
- if (!start_path) {
788
- error = git__getenv(&dir_buf, "GIT_DIR");
789
- if (error == GIT_ENOTFOUND) {
790
- git_error_clear();
791
- start_path = ".";
792
- } else if (error < 0)
793
- goto error;
794
- else {
795
- start_path = git_str_cstr(&dir_buf);
796
- flags |= GIT_REPOSITORY_OPEN_NO_SEARCH;
797
- flags |= GIT_REPOSITORY_OPEN_NO_DOTGIT;
798
- }
799
- }
800
-
801
- error = git__getenv(&ceiling_dirs_buf, "GIT_CEILING_DIRECTORIES");
802
- if (error == GIT_ENOTFOUND)
803
- git_error_clear();
804
- else if (error < 0)
805
- goto error;
806
- else
807
- ceiling_dirs = git_str_cstr(&ceiling_dirs_buf);
808
-
809
- error = git__getenv(&across_fs_buf, "GIT_DISCOVERY_ACROSS_FILESYSTEM");
810
- if (error == GIT_ENOTFOUND)
811
- git_error_clear();
812
- else if (error < 0)
813
- goto error;
814
- else {
815
- int across_fs = 0;
816
- error = git_config_parse_bool(&across_fs, git_str_cstr(&across_fs_buf));
817
- if (error < 0)
818
- goto error;
819
- if (across_fs)
820
- flags |= GIT_REPOSITORY_OPEN_CROSS_FS;
821
- }
822
-
823
- error = git__getenv(&index_file_buf, "GIT_INDEX_FILE");
824
- if (error == GIT_ENOTFOUND)
825
- git_error_clear();
826
- else if (error < 0)
827
- goto error;
828
- else {
829
- error = git_index_open(&index, git_str_cstr(&index_file_buf));
830
- if (error < 0)
831
- goto error;
832
- }
1022
+ if (!repo->use_env)
1023
+ return 0;
833
1024
 
834
1025
  error = git__getenv(&namespace_buf, "GIT_NAMESPACE");
835
- if (error == GIT_ENOTFOUND)
836
- git_error_clear();
837
- else if (error < 0)
838
- goto error;
839
-
840
- error = git__getenv(&object_dir_buf, "GIT_OBJECT_DIRECTORY");
841
- if (error == GIT_ENOTFOUND)
842
- git_error_clear();
843
- else if (error < 0)
844
- goto error;
845
- else {
846
- error = git_odb_open(&odb, git_str_cstr(&object_dir_buf));
847
- if (error < 0)
848
- goto error;
849
- }
850
-
851
- error = git__getenv(&work_tree_buf, "GIT_WORK_TREE");
852
- if (error == GIT_ENOTFOUND)
853
- git_error_clear();
854
- else if (error < 0)
855
- goto error;
856
- else {
857
- git_error_set(GIT_ERROR_INVALID, "GIT_WORK_TREE unimplemented");
858
- error = GIT_ERROR;
859
- goto error;
860
- }
861
-
862
- error = git__getenv(&work_tree_buf, "GIT_COMMON_DIR");
863
- if (error == GIT_ENOTFOUND)
864
- git_error_clear();
865
- else if (error < 0)
866
- goto error;
867
- else {
868
- git_error_set(GIT_ERROR_INVALID, "GIT_COMMON_DIR unimplemented");
869
- error = GIT_ERROR;
870
- goto error;
871
- }
872
-
873
- error = git_repository_open_ext(&repo, start_path, flags, ceiling_dirs);
874
- if (error < 0)
875
- goto error;
876
1026
 
877
- if (odb)
878
- git_repository_set_odb(repo, odb);
879
-
880
- error = git__getenv(&alts_buf, "GIT_ALTERNATE_OBJECT_DIRECTORIES");
881
- if (error == GIT_ENOTFOUND) {
882
- git_error_clear();
883
- error = 0;
884
- } else if (error < 0)
885
- goto error;
886
- else {
887
- const char *end;
888
- char *alt, *sep;
889
- if (!odb) {
890
- error = git_repository_odb(&odb, repo);
891
- if (error < 0)
892
- goto error;
893
- }
894
-
895
- end = git_str_cstr(&alts_buf) + git_str_len(&alts_buf);
896
- for (sep = alt = alts_buf.ptr; sep != end; alt = sep+1) {
897
- for (sep = alt; *sep && *sep != GIT_PATH_LIST_SEPARATOR; sep++)
898
- ;
899
- if (*sep)
900
- *sep = '\0';
901
- error = git_odb_add_disk_alternate(odb, alt);
902
- if (error < 0)
903
- goto error;
904
- }
905
- }
906
-
907
- if (git_str_len(&namespace_buf)) {
908
- error = git_repository_set_namespace(repo, git_str_cstr(&namespace_buf));
909
- if (error < 0)
910
- goto error;
911
- }
912
-
913
- git_repository_set_index(repo, index);
1027
+ if (error == 0)
1028
+ repo->namespace = git_str_detach(&namespace_buf);
1029
+ else if (error != GIT_ENOTFOUND)
1030
+ return error;
914
1031
 
915
- if (out) {
916
- *out = repo;
917
- goto success;
918
- }
919
- error:
920
- git_repository_free(repo);
921
- success:
922
- git_odb_free(odb);
923
- git_index_free(index);
924
- git_str_dispose(&common_dir_buf);
925
- git_str_dispose(&work_tree_buf);
926
- git_str_dispose(&alts_buf);
927
- git_str_dispose(&object_dir_buf);
928
- git_str_dispose(&namespace_buf);
929
- git_str_dispose(&index_file_buf);
930
- git_str_dispose(&across_fs_buf);
931
- git_str_dispose(&ceiling_dirs_buf);
932
- git_str_dispose(&dir_buf);
933
- return error;
1032
+ return 0;
934
1033
  }
935
1034
 
936
1035
  static int repo_is_worktree(unsigned *out, const git_repository *repo)
@@ -962,22 +1061,16 @@ int git_repository_open_ext(
962
1061
  unsigned int flags,
963
1062
  const char *ceiling_dirs)
964
1063
  {
965
- int error;
966
- unsigned is_worktree;
967
- git_str gitdir = GIT_STR_INIT, workdir = GIT_STR_INIT,
968
- gitlink = GIT_STR_INIT, commondir = GIT_STR_INIT;
1064
+ struct repo_paths paths = { GIT_STR_INIT };
969
1065
  git_repository *repo = NULL;
970
1066
  git_config *config = NULL;
971
- int version = 0;
972
-
973
- if (flags & GIT_REPOSITORY_OPEN_FROM_ENV)
974
- return _git_repository_open_ext_from_env(repo_ptr, start_path);
1067
+ unsigned is_worktree;
1068
+ int error;
975
1069
 
976
1070
  if (repo_ptr)
977
1071
  *repo_ptr = NULL;
978
1072
 
979
- error = find_repo(
980
- &gitdir, &workdir, &gitlink, &commondir, start_path, flags, ceiling_dirs);
1073
+ error = find_repo(&paths, start_path, ceiling_dirs, flags);
981
1074
 
982
1075
  if (error < 0 || !repo_ptr)
983
1076
  goto cleanup;
@@ -985,35 +1078,30 @@ int git_repository_open_ext(
985
1078
  repo = repository_alloc();
986
1079
  GIT_ERROR_CHECK_ALLOC(repo);
987
1080
 
988
- repo->gitdir = git_str_detach(&gitdir);
1081
+ repo->use_env = !!(flags & GIT_REPOSITORY_OPEN_FROM_ENV);
1082
+
1083
+ repo->gitdir = git_str_detach(&paths.gitdir);
989
1084
  GIT_ERROR_CHECK_ALLOC(repo->gitdir);
990
1085
 
991
- if (gitlink.size) {
992
- repo->gitlink = git_str_detach(&gitlink);
1086
+ if (paths.gitlink.size) {
1087
+ repo->gitlink = git_str_detach(&paths.gitlink);
993
1088
  GIT_ERROR_CHECK_ALLOC(repo->gitlink);
994
1089
  }
995
- if (commondir.size) {
996
- repo->commondir = git_str_detach(&commondir);
1090
+ if (paths.commondir.size) {
1091
+ repo->commondir = git_str_detach(&paths.commondir);
997
1092
  GIT_ERROR_CHECK_ALLOC(repo->commondir);
998
1093
  }
999
1094
 
1000
1095
  if ((error = repo_is_worktree(&is_worktree, repo)) < 0)
1001
1096
  goto cleanup;
1002
- repo->is_worktree = is_worktree;
1003
1097
 
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;
1098
+ repo->is_worktree = is_worktree;
1012
1099
 
1013
- if (config && (error = check_repositoryformatversion(&version, config)) < 0)
1100
+ error = obtain_config_and_set_oid_type(&config, repo);
1101
+ if (error < 0)
1014
1102
  goto cleanup;
1015
1103
 
1016
- if ((error = check_extensions(config, version)) < 0)
1104
+ if ((error = load_grafts(repo)) < 0)
1017
1105
  goto cleanup;
1018
1106
 
1019
1107
  if ((flags & GIT_REPOSITORY_OPEN_BARE) != 0) {
@@ -1021,10 +1109,13 @@ int git_repository_open_ext(
1021
1109
  } else {
1022
1110
  if (config &&
1023
1111
  ((error = load_config_data(repo, config)) < 0 ||
1024
- (error = load_workdir(repo, config, &workdir)) < 0))
1112
+ (error = load_workdir(repo, config, &paths.workdir)) < 0))
1025
1113
  goto cleanup;
1026
1114
  }
1027
1115
 
1116
+ if ((error = repo_load_namespace(repo)) < 0)
1117
+ goto cleanup;
1118
+
1028
1119
  /*
1029
1120
  * Ensure that the git directory and worktree are
1030
1121
  * owned by the current user.
@@ -1034,10 +1125,7 @@ int git_repository_open_ext(
1034
1125
  goto cleanup;
1035
1126
 
1036
1127
  cleanup:
1037
- git_str_dispose(&gitdir);
1038
- git_str_dispose(&workdir);
1039
- git_str_dispose(&gitlink);
1040
- git_str_dispose(&commondir);
1128
+ repo_paths_dispose(&paths);
1041
1129
  git_config_free(config);
1042
1130
 
1043
1131
  if (error < 0)
@@ -1086,30 +1174,56 @@ out:
1086
1174
  return err;
1087
1175
  }
1088
1176
 
1089
- int git_repository_wrap_odb(git_repository **repo_out, git_odb *odb)
1177
+ int git_repository__wrap_odb(
1178
+ git_repository **out,
1179
+ git_odb *odb,
1180
+ git_oid_t oid_type)
1090
1181
  {
1091
1182
  git_repository *repo;
1092
1183
 
1093
1184
  repo = repository_alloc();
1094
1185
  GIT_ERROR_CHECK_ALLOC(repo);
1095
1186
 
1187
+ repo->oid_type = oid_type;
1188
+
1096
1189
  git_repository_set_odb(repo, odb);
1097
- *repo_out = repo;
1190
+ *out = repo;
1098
1191
 
1099
1192
  return 0;
1100
1193
  }
1101
1194
 
1195
+ #ifdef GIT_EXPERIMENTAL_SHA256
1196
+ int git_repository_wrap_odb(
1197
+ git_repository **out,
1198
+ git_odb *odb,
1199
+ git_oid_t oid_type)
1200
+ {
1201
+ return git_repository__wrap_odb(out, odb, oid_type);
1202
+ }
1203
+ #else
1204
+ int git_repository_wrap_odb(git_repository **out, git_odb *odb)
1205
+ {
1206
+ return git_repository__wrap_odb(out, odb, GIT_OID_DEFAULT);
1207
+ }
1208
+ #endif
1209
+
1102
1210
  int git_repository_discover(
1103
1211
  git_buf *out,
1104
1212
  const char *start_path,
1105
1213
  int across_fs,
1106
1214
  const char *ceiling_dirs)
1107
1215
  {
1216
+ struct repo_paths paths = { GIT_STR_INIT };
1108
1217
  uint32_t flags = across_fs ? GIT_REPOSITORY_OPEN_CROSS_FS : 0;
1218
+ int error;
1109
1219
 
1110
1220
  GIT_ASSERT_ARG(start_path);
1111
1221
 
1112
- GIT_BUF_WRAP_PRIVATE(out, find_repo, NULL, NULL, NULL, start_path, flags, ceiling_dirs);
1222
+ if ((error = find_repo(&paths, start_path, ceiling_dirs, flags)) == 0)
1223
+ error = git_buf_fromstr(out, &paths.gitdir);
1224
+
1225
+ repo_paths_dispose(&paths);
1226
+ return error;
1113
1227
  }
1114
1228
 
1115
1229
  static int load_config(
@@ -1180,32 +1294,81 @@ static const char *path_unless_empty(git_str *buf)
1180
1294
  return git_str_len(buf) > 0 ? git_str_cstr(buf) : NULL;
1181
1295
  }
1182
1296
 
1297
+ GIT_INLINE(int) config_path_system(git_str *out, bool use_env)
1298
+ {
1299
+ if (use_env) {
1300
+ git_str no_system_buf = GIT_STR_INIT;
1301
+ int no_system = 0;
1302
+ int error;
1303
+
1304
+ error = git__getenv(&no_system_buf, "GIT_CONFIG_NOSYSTEM");
1305
+
1306
+ if (error && error != GIT_ENOTFOUND)
1307
+ return error;
1308
+
1309
+ error = git_config_parse_bool(&no_system, no_system_buf.ptr);
1310
+ git_str_dispose(&no_system_buf);
1311
+
1312
+ if (no_system)
1313
+ return 0;
1314
+
1315
+ error = git__getenv(out, "GIT_CONFIG_SYSTEM");
1316
+
1317
+ if (error == 0 || error != GIT_ENOTFOUND)
1318
+ return 0;
1319
+ }
1320
+
1321
+ git_config__find_system(out);
1322
+ return 0;
1323
+ }
1324
+
1325
+ GIT_INLINE(int) config_path_global(git_str *out, bool use_env)
1326
+ {
1327
+ if (use_env) {
1328
+ int error = git__getenv(out, "GIT_CONFIG_GLOBAL");
1329
+
1330
+ if (error == 0 || error != GIT_ENOTFOUND)
1331
+ return 0;
1332
+ }
1333
+
1334
+ git_config__find_global(out);
1335
+ return 0;
1336
+ }
1337
+
1183
1338
  int git_repository_config__weakptr(git_config **out, git_repository *repo)
1184
1339
  {
1185
1340
  int error = 0;
1186
1341
 
1187
1342
  if (repo->_config == NULL) {
1343
+ git_str system_buf = GIT_STR_INIT;
1188
1344
  git_str global_buf = GIT_STR_INIT;
1189
1345
  git_str xdg_buf = GIT_STR_INIT;
1190
- git_str system_buf = GIT_STR_INIT;
1191
1346
  git_str programdata_buf = GIT_STR_INIT;
1347
+ bool use_env = repo->use_env;
1192
1348
  git_config *config;
1193
1349
 
1194
- git_config__find_global(&global_buf);
1195
- git_config__find_xdg(&xdg_buf);
1196
- git_config__find_system(&system_buf);
1197
- git_config__find_programdata(&programdata_buf);
1350
+ if (!(error = config_path_system(&system_buf, use_env)) &&
1351
+ !(error = config_path_global(&global_buf, use_env))) {
1352
+ git_config__find_xdg(&xdg_buf);
1353
+ git_config__find_programdata(&programdata_buf);
1354
+ }
1198
1355
 
1199
- /* If there is no global file, open a backend for it anyway */
1200
- if (git_str_len(&global_buf) == 0)
1201
- git_config__global_location(&global_buf);
1356
+ if (!error) {
1357
+ /*
1358
+ * If there is no global file, open a backend
1359
+ * for it anyway.
1360
+ */
1361
+ if (git_str_len(&global_buf) == 0)
1362
+ git_config__global_location(&global_buf);
1363
+
1364
+ error = load_config(
1365
+ &config, repo,
1366
+ path_unless_empty(&global_buf),
1367
+ path_unless_empty(&xdg_buf),
1368
+ path_unless_empty(&system_buf),
1369
+ path_unless_empty(&programdata_buf));
1370
+ }
1202
1371
 
1203
- error = load_config(
1204
- &config, repo,
1205
- path_unless_empty(&global_buf),
1206
- path_unless_empty(&xdg_buf),
1207
- path_unless_empty(&system_buf),
1208
- path_unless_empty(&programdata_buf));
1209
1372
  if (!error) {
1210
1373
  GIT_REFCOUNT_OWN(config, repo);
1211
1374
 
@@ -1254,6 +1417,56 @@ int git_repository_set_config(git_repository *repo, git_config *config)
1254
1417
  return 0;
1255
1418
  }
1256
1419
 
1420
+ static int repository_odb_path(git_str *out, git_repository *repo)
1421
+ {
1422
+ int error = GIT_ENOTFOUND;
1423
+
1424
+ if (repo->use_env)
1425
+ error = git__getenv(out, "GIT_OBJECT_DIRECTORY");
1426
+
1427
+ if (error == GIT_ENOTFOUND)
1428
+ error = git_repository__item_path(out, repo,
1429
+ GIT_REPOSITORY_ITEM_OBJECTS);
1430
+
1431
+ return error;
1432
+ }
1433
+
1434
+ static int repository_odb_alternates(
1435
+ git_odb *odb,
1436
+ git_repository *repo)
1437
+ {
1438
+ git_str alternates = GIT_STR_INIT;
1439
+ char *sep, *alt;
1440
+ int error;
1441
+
1442
+ if (!repo->use_env)
1443
+ return 0;
1444
+
1445
+ error = git__getenv(&alternates, "GIT_ALTERNATE_OBJECT_DIRECTORIES");
1446
+
1447
+ if (error != 0)
1448
+ return (error == GIT_ENOTFOUND) ? 0 : error;
1449
+
1450
+ alt = alternates.ptr;
1451
+
1452
+ while (*alt) {
1453
+ sep = strchr(alt, GIT_PATH_LIST_SEPARATOR);
1454
+
1455
+ if (sep)
1456
+ *sep = '\0';
1457
+
1458
+ error = git_odb_add_disk_alternate(odb, alt);
1459
+
1460
+ if (sep)
1461
+ alt = sep + 1;
1462
+ else
1463
+ break;
1464
+ }
1465
+
1466
+ git_str_dispose(&alternates);
1467
+ return 0;
1468
+ }
1469
+
1257
1470
  int git_repository_odb__weakptr(git_odb **out, git_repository *repo)
1258
1471
  {
1259
1472
  int error = 0;
@@ -1264,11 +1477,14 @@ int git_repository_odb__weakptr(git_odb **out, git_repository *repo)
1264
1477
  *out = git_atomic_load(repo->_odb);
1265
1478
  if (*out == NULL) {
1266
1479
  git_str odb_path = GIT_STR_INIT;
1480
+ git_odb_options odb_opts = GIT_ODB_OPTIONS_INIT;
1267
1481
  git_odb *odb;
1268
1482
 
1269
- if ((error = git_repository__item_path(&odb_path, repo,
1270
- GIT_REPOSITORY_ITEM_OBJECTS)) < 0 ||
1271
- (error = git_odb_new(&odb)) < 0)
1483
+ odb_opts.oid_type = repo->oid_type;
1484
+
1485
+ if ((error = repository_odb_path(&odb_path, repo)) < 0 ||
1486
+ (error = git_odb__new(&odb, &odb_opts)) < 0 ||
1487
+ (error = repository_odb_alternates(odb, repo)) < 0)
1272
1488
  return error;
1273
1489
 
1274
1490
  GIT_REFCOUNT_OWN(odb, repo);
@@ -1352,6 +1568,20 @@ int git_repository_set_refdb(git_repository *repo, git_refdb *refdb)
1352
1568
  return 0;
1353
1569
  }
1354
1570
 
1571
+ static int repository_index_path(git_str *out, git_repository *repo)
1572
+ {
1573
+ int error = GIT_ENOTFOUND;
1574
+
1575
+ if (repo->use_env)
1576
+ error = git__getenv(out, "GIT_INDEX_FILE");
1577
+
1578
+ if (error == GIT_ENOTFOUND)
1579
+ error = git_repository__item_path(out, repo,
1580
+ GIT_REPOSITORY_ITEM_INDEX);
1581
+
1582
+ return error;
1583
+ }
1584
+
1355
1585
  int git_repository_index__weakptr(git_index **out, git_repository *repo)
1356
1586
  {
1357
1587
  int error = 0;
@@ -1363,10 +1593,11 @@ int git_repository_index__weakptr(git_index **out, git_repository *repo)
1363
1593
  git_str index_path = GIT_STR_INIT;
1364
1594
  git_index *index;
1365
1595
 
1366
- if ((error = git_str_joinpath(&index_path, repo->gitdir, GIT_INDEX_FILE)) < 0)
1596
+ if ((error = repository_index_path(&index_path, repo)) < 0)
1367
1597
  return error;
1368
1598
 
1369
- error = git_index_open(&index, index_path.ptr);
1599
+ error = git_index__open(&index, index_path.ptr, repo->oid_type);
1600
+
1370
1601
  if (!error) {
1371
1602
  GIT_REFCOUNT_OWN(index, repo);
1372
1603
 
@@ -1402,6 +1633,22 @@ int git_repository_set_index(git_repository *repo, git_index *index)
1402
1633
  return 0;
1403
1634
  }
1404
1635
 
1636
+ int git_repository_grafts__weakptr(git_grafts **out, git_repository *repo)
1637
+ {
1638
+ GIT_ASSERT_ARG(out && repo);
1639
+ GIT_ASSERT(repo->grafts);
1640
+ *out = repo->grafts;
1641
+ return 0;
1642
+ }
1643
+
1644
+ int git_repository_shallow_grafts__weakptr(git_grafts **out, git_repository *repo)
1645
+ {
1646
+ GIT_ASSERT_ARG(out && repo);
1647
+ GIT_ASSERT(repo->shallow_grafts);
1648
+ *out = repo->shallow_grafts;
1649
+ return 0;
1650
+ }
1651
+
1405
1652
  int git_repository_set_namespace(git_repository *repo, const char *namespace)
1406
1653
  {
1407
1654
  git__free(repo->namespace);
@@ -1526,6 +1773,7 @@ static int check_repositoryformatversion(int *version, git_config *config)
1526
1773
  int error;
1527
1774
 
1528
1775
  error = git_config_get_int32(version, config, "core.repositoryformatversion");
1776
+
1529
1777
  /* git ignores this if the config variable isn't there */
1530
1778
  if (error == GIT_ENOTFOUND)
1531
1779
  return 0;
@@ -1533,10 +1781,15 @@ static int check_repositoryformatversion(int *version, git_config *config)
1533
1781
  if (error < 0)
1534
1782
  return -1;
1535
1783
 
1536
- if (GIT_REPO_MAX_VERSION < *version) {
1784
+ if (*version < 0) {
1785
+ git_error_set(GIT_ERROR_REPOSITORY,
1786
+ "invalid repository version %d", *version);
1787
+ }
1788
+
1789
+ if (GIT_REPO_VERSION_MAX < *version) {
1537
1790
  git_error_set(GIT_ERROR_REPOSITORY,
1538
1791
  "unsupported repository version %d; only versions up to %d are supported",
1539
- *version, GIT_REPO_MAX_VERSION);
1792
+ *version, GIT_REPO_VERSION_MAX);
1540
1793
  return -1;
1541
1794
  }
1542
1795
 
@@ -1544,10 +1797,11 @@ static int check_repositoryformatversion(int *version, git_config *config)
1544
1797
  }
1545
1798
 
1546
1799
  static const char *builtin_extensions[] = {
1547
- "noop"
1800
+ "noop",
1801
+ "objectformat"
1548
1802
  };
1549
1803
 
1550
- static git_vector user_extensions = GIT_VECTOR_INIT;
1804
+ static git_vector user_extensions = { 0, git__strcmp_cb };
1551
1805
 
1552
1806
  static int check_valid_extension(const git_config_entry *entry, void *payload)
1553
1807
  {
@@ -1608,6 +1862,79 @@ static int check_extensions(git_config *config, int version)
1608
1862
  return git_config_foreach_match(config, "^extensions\\.", check_valid_extension, NULL);
1609
1863
  }
1610
1864
 
1865
+ static int load_objectformat(git_repository *repo, git_config *config)
1866
+ {
1867
+ git_config_entry *entry = NULL;
1868
+ int error;
1869
+
1870
+ if ((error = git_config_get_entry(&entry, config, "extensions.objectformat")) < 0) {
1871
+ if (error == GIT_ENOTFOUND) {
1872
+ repo->oid_type = GIT_OID_DEFAULT;
1873
+ git_error_clear();
1874
+ error = 0;
1875
+ }
1876
+
1877
+ goto done;
1878
+ }
1879
+
1880
+ if ((repo->oid_type = git_oid_type_fromstr(entry->value)) == 0) {
1881
+ git_error_set(GIT_ERROR_REPOSITORY,
1882
+ "unknown object format '%s'", entry->value);
1883
+ error = GIT_EINVALID;
1884
+ }
1885
+
1886
+ done:
1887
+ git_config_entry_free(entry);
1888
+ return error;
1889
+ }
1890
+
1891
+ int git_repository__set_objectformat(
1892
+ git_repository *repo,
1893
+ git_oid_t oid_type)
1894
+ {
1895
+ git_config *cfg;
1896
+
1897
+ /*
1898
+ * Older clients do not necessarily understand the
1899
+ * `objectformat` extension, even when it's set to an
1900
+ * object format that they understand (SHA1). Do not set
1901
+ * the objectformat extension unless we're not using the
1902
+ * default object format.
1903
+ */
1904
+ if (oid_type == GIT_OID_DEFAULT)
1905
+ return 0;
1906
+
1907
+ if (!git_repository_is_empty(repo) && repo->oid_type != oid_type) {
1908
+ git_error_set(GIT_ERROR_REPOSITORY,
1909
+ "cannot change object id type of existing repository");
1910
+ return -1;
1911
+ }
1912
+
1913
+ if (git_repository_config__weakptr(&cfg, repo) < 0)
1914
+ return -1;
1915
+
1916
+ if (git_config_set_int32(cfg,
1917
+ "core.repositoryformatversion", 1) < 0 ||
1918
+ git_config_set_string(cfg, "extensions.objectformat",
1919
+ git_oid_type_name(oid_type)) < 0)
1920
+ return -1;
1921
+
1922
+ /*
1923
+ * During repo init, we may create some backends with the
1924
+ * default oid type. Clear them so that we create them with
1925
+ * the proper oid type.
1926
+ */
1927
+ if (repo->oid_type != oid_type) {
1928
+ set_index(repo, NULL);
1929
+ set_odb(repo, NULL);
1930
+ set_refdb(repo, NULL);
1931
+
1932
+ repo->oid_type = oid_type;
1933
+ }
1934
+
1935
+ return 0;
1936
+ }
1937
+
1611
1938
  int git_repository__extensions(char ***out, size_t *out_len)
1612
1939
  {
1613
1940
  git_vector extensions;
@@ -1615,7 +1942,7 @@ int git_repository__extensions(char ***out, size_t *out_len)
1615
1942
  char *extension;
1616
1943
  size_t i, j;
1617
1944
 
1618
- if (git_vector_init(&extensions, 8, NULL) < 0)
1945
+ if (git_vector_init(&extensions, 8, git__strcmp_cb) < 0)
1619
1946
  return -1;
1620
1947
 
1621
1948
  for (i = 0; i < ARRAY_SIZE(builtin_extensions); i++) {
@@ -1647,21 +1974,49 @@ int git_repository__extensions(char ***out, size_t *out_len)
1647
1974
  return -1;
1648
1975
  }
1649
1976
 
1977
+ git_vector_sort(&extensions);
1978
+
1650
1979
  *out = (char **)git_vector_detach(out_len, NULL, &extensions);
1651
1980
  return 0;
1652
1981
  }
1653
1982
 
1983
+ static int dup_ext_err(void **old, void *extension)
1984
+ {
1985
+ GIT_UNUSED(old);
1986
+ GIT_UNUSED(extension);
1987
+ return GIT_EEXISTS;
1988
+ }
1989
+
1654
1990
  int git_repository__set_extensions(const char **extensions, size_t len)
1655
1991
  {
1656
1992
  char *extension;
1657
- size_t i;
1993
+ size_t i, j;
1994
+ int error;
1658
1995
 
1659
1996
  git_repository__free_extensions();
1660
1997
 
1661
1998
  for (i = 0; i < len; i++) {
1662
- if ((extension = git__strdup(extensions[i])) == NULL ||
1663
- git_vector_insert(&user_extensions, extension) < 0)
1999
+ bool is_builtin = false;
2000
+
2001
+ for (j = 0; j < ARRAY_SIZE(builtin_extensions); j++) {
2002
+ if (strcmp(builtin_extensions[j], extensions[i]) == 0) {
2003
+ is_builtin = true;
2004
+ break;
2005
+ }
2006
+ }
2007
+
2008
+ if (is_builtin)
2009
+ continue;
2010
+
2011
+ if ((extension = git__strdup(extensions[i])) == NULL)
1664
2012
  return -1;
2013
+
2014
+ if ((error = git_vector_insert_sorted(&user_extensions, extension, dup_ext_err)) < 0) {
2015
+ git__free(extension);
2016
+
2017
+ if (error != GIT_EEXISTS)
2018
+ return -1;
2019
+ }
1665
2020
  }
1666
2021
 
1667
2022
  return 0;
@@ -1730,7 +2085,7 @@ static bool is_filesystem_case_insensitive(const char *gitdir_path)
1730
2085
  * Return a configuration object with only the global and system
1731
2086
  * configurations; no repository-level configuration.
1732
2087
  */
1733
- static int load_global_config(git_config **config)
2088
+ static int load_global_config(git_config **config, bool use_env)
1734
2089
  {
1735
2090
  git_str global_buf = GIT_STR_INIT;
1736
2091
  git_str xdg_buf = GIT_STR_INIT;
@@ -1738,16 +2093,17 @@ static int load_global_config(git_config **config)
1738
2093
  git_str programdata_buf = GIT_STR_INIT;
1739
2094
  int error;
1740
2095
 
1741
- git_config__find_global(&global_buf);
1742
- git_config__find_xdg(&xdg_buf);
1743
- git_config__find_system(&system_buf);
1744
- git_config__find_programdata(&programdata_buf);
2096
+ if (!(error = config_path_system(&system_buf, use_env)) &&
2097
+ !(error = config_path_global(&global_buf, use_env))) {
2098
+ git_config__find_xdg(&xdg_buf);
2099
+ git_config__find_programdata(&programdata_buf);
1745
2100
 
1746
- error = load_config(config, NULL,
1747
- path_unless_empty(&global_buf),
1748
- path_unless_empty(&xdg_buf),
1749
- path_unless_empty(&system_buf),
1750
- path_unless_empty(&programdata_buf));
2101
+ error = load_config(config, NULL,
2102
+ path_unless_empty(&global_buf),
2103
+ path_unless_empty(&xdg_buf),
2104
+ path_unless_empty(&system_buf),
2105
+ path_unless_empty(&programdata_buf));
2106
+ }
1751
2107
 
1752
2108
  git_str_dispose(&global_buf);
1753
2109
  git_str_dispose(&xdg_buf);
@@ -1757,7 +2113,7 @@ static int load_global_config(git_config **config)
1757
2113
  return error;
1758
2114
  }
1759
2115
 
1760
- static bool are_symlinks_supported(const char *wd_path)
2116
+ static bool are_symlinks_supported(const char *wd_path, bool use_env)
1761
2117
  {
1762
2118
  git_config *config = NULL;
1763
2119
  int symlinks = 0;
@@ -1770,10 +2126,12 @@ static bool are_symlinks_supported(const char *wd_path)
1770
2126
  * _not_ set, then we do not test or enable symlink support.
1771
2127
  */
1772
2128
  #ifdef GIT_WIN32
1773
- if (load_global_config(&config) < 0 ||
2129
+ if (load_global_config(&config, use_env) < 0 ||
1774
2130
  git_config_get_bool(&symlinks, config, "core.symlinks") < 0 ||
1775
2131
  !symlinks)
1776
2132
  goto done;
2133
+ #else
2134
+ GIT_UNUSED(use_env);
1777
2135
  #endif
1778
2136
 
1779
2137
  if (!(symlinks = git_fs_path_supports_symlinks(wd_path)))
@@ -1846,7 +2204,8 @@ static int repo_init_fs_configs(
1846
2204
  const char *cfg_path,
1847
2205
  const char *repo_dir,
1848
2206
  const char *work_dir,
1849
- bool update_ignorecase)
2207
+ bool update_ignorecase,
2208
+ bool use_env)
1850
2209
  {
1851
2210
  int error = 0;
1852
2211
 
@@ -1857,7 +2216,7 @@ static int repo_init_fs_configs(
1857
2216
  cfg, "core.filemode", is_chmod_supported(cfg_path))) < 0)
1858
2217
  return error;
1859
2218
 
1860
- if (!are_symlinks_supported(work_dir)) {
2219
+ if (!are_symlinks_supported(work_dir, use_env)) {
1861
2220
  if ((error = git_config_set_bool(cfg, "core.symlinks", false)) < 0)
1862
2221
  return error;
1863
2222
  } else if (git_config_delete_entry(cfg, "core.symlinks") < 0)
@@ -1886,19 +2245,22 @@ static int repo_init_config(
1886
2245
  const char *repo_dir,
1887
2246
  const char *work_dir,
1888
2247
  uint32_t flags,
1889
- uint32_t mode)
2248
+ uint32_t mode,
2249
+ git_oid_t oid_type)
1890
2250
  {
1891
2251
  int error = 0;
1892
2252
  git_str cfg_path = GIT_STR_INIT, worktree_path = GIT_STR_INIT;
1893
2253
  git_config *config = NULL;
1894
2254
  bool is_bare = ((flags & GIT_REPOSITORY_INIT_BARE) != 0);
1895
2255
  bool is_reinit = ((flags & GIT_REPOSITORY_INIT__IS_REINIT) != 0);
1896
- int version = 0;
2256
+ bool use_env = ((flags & GIT_REPOSITORY_OPEN_FROM_ENV) != 0);
2257
+ int version = GIT_REPO_VERSION_DEFAULT;
1897
2258
 
1898
2259
  if ((error = repo_local_config(&config, &cfg_path, NULL, repo_dir)) < 0)
1899
2260
  goto cleanup;
1900
2261
 
1901
- if (is_reinit && (error = check_repositoryformatversion(&version, config)) < 0)
2262
+ if (is_reinit &&
2263
+ (error = check_repositoryformatversion(&version, config)) < 0)
1902
2264
  goto cleanup;
1903
2265
 
1904
2266
  if ((error = check_extensions(config, version)) < 0)
@@ -1909,10 +2271,11 @@ static int repo_init_config(
1909
2271
  goto cleanup; } while (0)
1910
2272
 
1911
2273
  SET_REPO_CONFIG(bool, "core.bare", is_bare);
1912
- SET_REPO_CONFIG(int32, "core.repositoryformatversion", GIT_REPO_VERSION);
2274
+ SET_REPO_CONFIG(int32, "core.repositoryformatversion", version);
1913
2275
 
1914
2276
  if ((error = repo_init_fs_configs(
1915
- config, cfg_path.ptr, repo_dir, work_dir, !is_reinit)) < 0)
2277
+ config, cfg_path.ptr, repo_dir, work_dir,
2278
+ !is_reinit, use_env)) < 0)
1916
2279
  goto cleanup;
1917
2280
 
1918
2281
  if (!is_bare) {
@@ -1942,6 +2305,11 @@ static int repo_init_config(
1942
2305
  SET_REPO_CONFIG(bool, "receive.denyNonFastforwards", true);
1943
2306
  }
1944
2307
 
2308
+ if (oid_type != GIT_OID_DEFAULT) {
2309
+ SET_REPO_CONFIG(int32, "core.repositoryformatversion", 1);
2310
+ SET_REPO_CONFIG(string, "extensions.objectformat", git_oid_type_name(oid_type));
2311
+ }
2312
+
1945
2313
  cleanup:
1946
2314
  git_str_dispose(&cfg_path);
1947
2315
  git_str_dispose(&worktree_path);
@@ -1971,8 +2339,8 @@ int git_repository_reinit_filesystem(git_repository *repo, int recurse)
1971
2339
  const char *repo_dir = git_repository_path(repo);
1972
2340
 
1973
2341
  if (!(error = repo_local_config(&config, &path, repo, repo_dir)))
1974
- error = repo_init_fs_configs(
1975
- config, path.ptr, repo_dir, git_repository_workdir(repo), true);
2342
+ error = repo_init_fs_configs(config, path.ptr, repo_dir,
2343
+ git_repository_workdir(repo), true, repo->use_env);
1976
2344
 
1977
2345
  git_config_free(config);
1978
2346
  git_str_dispose(&path);
@@ -2422,6 +2790,7 @@ int git_repository_init_ext(
2422
2790
  common_path = GIT_STR_INIT;
2423
2791
  const char *wd;
2424
2792
  bool is_valid;
2793
+ git_oid_t oid_type = GIT_OID_DEFAULT;
2425
2794
  int error;
2426
2795
 
2427
2796
  GIT_ASSERT_ARG(out);
@@ -2430,12 +2799,17 @@ int git_repository_init_ext(
2430
2799
 
2431
2800
  GIT_ERROR_CHECK_VERSION(opts, GIT_REPOSITORY_INIT_OPTIONS_VERSION, "git_repository_init_options");
2432
2801
 
2802
+ #ifdef GIT_EXPERIMENTAL_SHA256
2803
+ if (opts->oid_type)
2804
+ oid_type = opts->oid_type;
2805
+ #endif
2806
+
2433
2807
  if ((error = repo_init_directories(&repo_path, &wd_path, given_repo, opts)) < 0)
2434
2808
  goto out;
2435
2809
 
2436
2810
  wd = (opts->flags & GIT_REPOSITORY_INIT_BARE) ? NULL : git_str_cstr(&wd_path);
2437
2811
 
2438
- if ((error = is_valid_repository_path(&is_valid, &repo_path, &common_path)) < 0)
2812
+ if ((error = is_valid_repository_path(&is_valid, &repo_path, &common_path, opts->flags)) < 0)
2439
2813
  goto out;
2440
2814
 
2441
2815
  if (is_valid) {
@@ -2448,13 +2822,13 @@ int git_repository_init_ext(
2448
2822
 
2449
2823
  opts->flags |= GIT_REPOSITORY_INIT__IS_REINIT;
2450
2824
 
2451
- if ((error = repo_init_config(repo_path.ptr, wd, opts->flags, opts->mode)) < 0)
2825
+ if ((error = repo_init_config(repo_path.ptr, wd, opts->flags, opts->mode, oid_type)) < 0)
2452
2826
  goto out;
2453
2827
 
2454
2828
  /* TODO: reinitialize the templates */
2455
2829
  } else {
2456
2830
  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 ||
2831
+ (error = repo_init_config(repo_path.ptr, wd, opts->flags, opts->mode, oid_type)) < 0 ||
2458
2832
  (error = repo_init_head(repo_path.ptr, opts->initial_head)) < 0)
2459
2833
  goto out;
2460
2834
  }
@@ -2917,14 +3291,14 @@ int git_repository__set_orig_head(git_repository *repo, const git_oid *orig_head
2917
3291
  {
2918
3292
  git_filebuf file = GIT_FILEBUF_INIT;
2919
3293
  git_str file_path = GIT_STR_INIT;
2920
- char orig_head_str[GIT_OID_HEXSZ];
3294
+ char orig_head_str[GIT_OID_MAX_HEXSIZE];
2921
3295
  int error = 0;
2922
3296
 
2923
3297
  git_oid_fmt(orig_head_str, orig_head);
2924
3298
 
2925
3299
  if ((error = git_str_joinpath(&file_path, repo->gitdir, GIT_ORIG_HEAD_FILE)) == 0 &&
2926
3300
  (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)
3301
+ (error = git_filebuf_printf(&file, "%.*s\n", (int)git_oid_hexsize(repo->oid_type), orig_head_str)) == 0)
2928
3302
  error = git_filebuf_commit(&file);
2929
3303
 
2930
3304
  if (error < 0)
@@ -3037,7 +3411,7 @@ int git_repository_hashfile(
3037
3411
  goto cleanup;
3038
3412
  }
3039
3413
 
3040
- error = git_odb__hashfd_filtered(out, fd, (size_t)len, type, fl);
3414
+ error = git_odb__hashfd_filtered(out, fd, (size_t)len, type, repo->oid_type, fl);
3041
3415
 
3042
3416
  cleanup:
3043
3417
  if (fd >= 0)
@@ -3050,12 +3424,18 @@ cleanup:
3050
3424
 
3051
3425
  static int checkout_message(git_str *out, git_reference *old, const char *new)
3052
3426
  {
3427
+ const char *idstr;
3428
+
3053
3429
  git_str_puts(out, "checkout: moving from ");
3054
3430
 
3055
- if (git_reference_type(old) == GIT_REFERENCE_SYMBOLIC)
3431
+ if (git_reference_type(old) == GIT_REFERENCE_SYMBOLIC) {
3056
3432
  git_str_puts(out, git_reference__shorthand(git_reference_symbolic_target(old)));
3057
- else
3058
- git_str_puts(out, git_oid_tostr_s(git_reference_target(old)));
3433
+ } else {
3434
+ if ((idstr = git_oid_tostr_s(git_reference_target(old))) == NULL)
3435
+ return -1;
3436
+
3437
+ git_str_puts(out, idstr);
3438
+ }
3059
3439
 
3060
3440
  git_str_puts(out, " to ");
3061
3441
 
@@ -3091,8 +3471,11 @@ static int detach(git_repository *repo, const git_oid *id, const char *new)
3091
3471
  if ((error = git_object_peel(&peeled, object, GIT_OBJECT_COMMIT)) < 0)
3092
3472
  goto cleanup;
3093
3473
 
3094
- if (new == NULL)
3095
- new = git_oid_tostr_s(git_object_id(peeled));
3474
+ if (new == NULL &&
3475
+ (new = git_oid_tostr_s(git_object_id(peeled))) == NULL) {
3476
+ error = -1;
3477
+ goto cleanup;
3478
+ }
3096
3479
 
3097
3480
  if ((error = checkout_message(&log_message, current, new)) < 0)
3098
3481
  goto cleanup;
@@ -3180,6 +3563,7 @@ int git_repository_detach_head(git_repository *repo)
3180
3563
  git_reference *old_head = NULL, *new_head = NULL, *current = NULL;
3181
3564
  git_object *object = NULL;
3182
3565
  git_str log_message = GIT_STR_INIT;
3566
+ const char *idstr;
3183
3567
  int error;
3184
3568
 
3185
3569
  GIT_ASSERT_ARG(repo);
@@ -3193,7 +3577,12 @@ int git_repository_detach_head(git_repository *repo)
3193
3577
  if ((error = git_object_lookup(&object, repo, git_reference_target(old_head), GIT_OBJECT_COMMIT)) < 0)
3194
3578
  goto cleanup;
3195
3579
 
3196
- if ((error = checkout_message(&log_message, current, git_oid_tostr_s(git_object_id(object)))) < 0)
3580
+ if ((idstr = git_oid_tostr_s(git_object_id(object))) == NULL) {
3581
+ error = -1;
3582
+ goto cleanup;
3583
+ }
3584
+
3585
+ if ((error = checkout_message(&log_message, current, idstr)) < 0)
3197
3586
  goto cleanup;
3198
3587
 
3199
3588
  error = git_reference_create(&new_head, repo, GIT_HEAD_FILE, git_reference_target(old_head),
@@ -3299,6 +3688,66 @@ int git_repository_state_cleanup(git_repository *repo)
3299
3688
  return git_repository__cleanup_files(repo, state_files, ARRAY_SIZE(state_files));
3300
3689
  }
3301
3690
 
3691
+ int git_repository__shallow_roots(
3692
+ git_oid **out,
3693
+ size_t *out_len,
3694
+ git_repository *repo)
3695
+ {
3696
+ int error = 0;
3697
+
3698
+ if (!repo->shallow_grafts && (error = load_grafts(repo)) < 0)
3699
+ return error;
3700
+
3701
+ if ((error = git_grafts_refresh(repo->shallow_grafts)) < 0)
3702
+ return error;
3703
+
3704
+ if ((error = git_grafts_oids(out, out_len, repo->shallow_grafts)) < 0)
3705
+ return error;
3706
+
3707
+ return 0;
3708
+ }
3709
+
3710
+ int git_repository__shallow_roots_write(git_repository *repo, git_oidarray *roots)
3711
+ {
3712
+ git_filebuf file = GIT_FILEBUF_INIT;
3713
+ git_str path = GIT_STR_INIT;
3714
+ char oid_str[GIT_OID_MAX_HEXSIZE + 1];
3715
+ size_t i;
3716
+ int filebuf_hash, error = 0;
3717
+
3718
+ GIT_ASSERT_ARG(repo);
3719
+
3720
+ filebuf_hash = git_filebuf_hash_flags(git_oid_algorithm(repo->oid_type));
3721
+ GIT_ASSERT(filebuf_hash);
3722
+
3723
+ if ((error = git_str_joinpath(&path, repo->gitdir, "shallow")) < 0)
3724
+ goto on_error;
3725
+
3726
+ if ((error = git_filebuf_open(&file, git_str_cstr(&path), filebuf_hash, 0666)) < 0)
3727
+ goto on_error;
3728
+
3729
+ for (i = 0; i < roots->count; i++) {
3730
+ git_oid_tostr(oid_str, sizeof(oid_str), &roots->ids[i]);
3731
+ git_filebuf_write(&file, oid_str, git_oid_hexsize(repo->oid_type));
3732
+ git_filebuf_write(&file, "\n", 1);
3733
+ }
3734
+
3735
+ git_filebuf_commit(&file);
3736
+
3737
+ if ((error = load_grafts(repo)) < 0) {
3738
+ error = -1;
3739
+ goto on_error;
3740
+ }
3741
+
3742
+ if (!roots->count)
3743
+ remove(path.ptr);
3744
+
3745
+ on_error:
3746
+ git_str_dispose(&path);
3747
+
3748
+ return error;
3749
+ }
3750
+
3302
3751
  int git_repository_is_shallow(git_repository *repo)
3303
3752
  {
3304
3753
  git_str path = GIT_STR_INIT;
@@ -3318,6 +3767,7 @@ int git_repository_is_shallow(git_repository *repo)
3318
3767
 
3319
3768
  if (error < 0)
3320
3769
  return error;
3770
+
3321
3771
  return st.st_size == 0 ? 0 : 1;
3322
3772
  }
3323
3773
 
@@ -3384,3 +3834,8 @@ int git_repository_submodule_cache_clear(git_repository *repo)
3384
3834
  repo->submodule_cache = NULL;
3385
3835
  return error;
3386
3836
  }
3837
+
3838
+ git_oid_t git_repository_oid_type(git_repository *repo)
3839
+ {
3840
+ return repo ? repo->oid_type : 0;
3841
+ }