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.
- checksums.yaml +4 -4
- data/ext/rugged/extconf.rb +2 -2
- data/ext/rugged/rugged_allocator.c +0 -54
- data/ext/rugged/rugged_blame.c +2 -0
- data/ext/rugged/rugged_blob.c +3 -0
- data/ext/rugged/rugged_commit.c +1 -0
- data/ext/rugged/rugged_config.c +2 -0
- data/ext/rugged/rugged_diff.c +1 -0
- data/ext/rugged/rugged_index.c +2 -0
- data/ext/rugged/rugged_patch.c +1 -0
- data/ext/rugged/rugged_rebase.c +1 -0
- data/ext/rugged/rugged_reference.c +1 -0
- data/ext/rugged/rugged_remote.c +1 -0
- data/ext/rugged/rugged_repo.c +5 -2
- data/ext/rugged/rugged_revwalk.c +5 -1
- data/ext/rugged/rugged_submodule.c +1 -0
- data/ext/rugged/rugged_tag.c +1 -0
- data/ext/rugged/rugged_tree.c +4 -0
- data/lib/rugged/index.rb +1 -1
- data/lib/rugged/tree.rb +1 -1
- data/lib/rugged/version.rb +1 -1
- data/vendor/libgit2/CMakeLists.txt +7 -8
- data/vendor/libgit2/COPYING +30 -0
- data/vendor/libgit2/cmake/CheckPrototypeDefinitionSafe.cmake +16 -0
- data/vendor/libgit2/cmake/ExperimentalFeatures.cmake +23 -0
- data/vendor/libgit2/cmake/SelectGSSAPI.cmake +3 -3
- data/vendor/libgit2/cmake/SelectHTTPSBackend.cmake +21 -2
- data/vendor/libgit2/cmake/SelectHashes.cmake +4 -0
- data/vendor/libgit2/cmake/SelectXdiff.cmake +9 -0
- data/vendor/libgit2/deps/ntlmclient/CMakeLists.txt +2 -0
- data/vendor/libgit2/deps/pcre/LICENCE +5 -5
- data/vendor/libgit2/deps/pcre/pcre.h +2 -2
- data/vendor/libgit2/deps/pcre/pcre_compile.c +6 -3
- data/vendor/libgit2/deps/pcre/pcre_exec.c +2 -2
- data/vendor/libgit2/deps/xdiff/CMakeLists.txt +28 -0
- data/vendor/libgit2/{src/libgit2 → deps}/xdiff/git-xdiff.h +4 -1
- data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xdiffi.c +19 -18
- data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xdiffi.h +2 -4
- data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xemit.c +3 -3
- data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xhistogram.c +7 -18
- data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xmacros.h +18 -1
- data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xmerge.c +24 -22
- data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xpatience.c +21 -30
- data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xprepare.c +13 -30
- data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xutils.c +18 -1
- data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xutils.h +2 -1
- data/vendor/libgit2/include/git2/common.h +38 -6
- data/vendor/libgit2/include/git2/deprecated.h +6 -0
- data/vendor/libgit2/include/git2/diff.h +42 -4
- data/vendor/libgit2/include/git2/errors.h +4 -2
- data/vendor/libgit2/include/git2/experimental.h +20 -0
- data/vendor/libgit2/include/git2/index.h +9 -0
- data/vendor/libgit2/include/git2/indexer.h +29 -0
- data/vendor/libgit2/include/git2/object.h +28 -2
- data/vendor/libgit2/include/git2/odb.h +58 -7
- data/vendor/libgit2/include/git2/odb_backend.h +106 -18
- data/vendor/libgit2/include/git2/oid.h +116 -16
- data/vendor/libgit2/include/git2/remote.h +18 -0
- data/vendor/libgit2/include/git2/repository.h +32 -3
- data/vendor/libgit2/include/git2/stash.h +60 -6
- data/vendor/libgit2/include/git2/strarray.h +0 -13
- data/vendor/libgit2/include/git2/sys/alloc.h +0 -34
- data/vendor/libgit2/include/git2/sys/commit_graph.h +12 -2
- data/vendor/libgit2/include/git2/sys/midx.h +5 -1
- data/vendor/libgit2/include/git2/sys/odb_backend.h +1 -1
- data/vendor/libgit2/include/git2/sys/stream.h +16 -2
- data/vendor/libgit2/include/git2/sys/transport.h +32 -2
- data/vendor/libgit2/include/git2/version.h +4 -4
- data/vendor/libgit2/include/git2/worktree.h +3 -1
- data/vendor/libgit2/include/git2.h +1 -0
- data/vendor/libgit2/src/CMakeLists.txt +34 -17
- data/vendor/libgit2/src/cli/CMakeLists.txt +5 -2
- data/vendor/libgit2/src/cli/cmd_clone.c +22 -6
- data/vendor/libgit2/src/cli/cmd_hash_object.c +27 -8
- data/vendor/libgit2/src/cli/opt.c +1 -1
- data/vendor/libgit2/src/cli/progress.c +9 -8
- data/vendor/libgit2/src/cli/progress.h +4 -4
- data/vendor/libgit2/src/libgit2/CMakeLists.txt +25 -34
- data/vendor/libgit2/src/libgit2/annotated_commit.c +2 -2
- data/vendor/libgit2/src/libgit2/annotated_commit.h +1 -1
- data/vendor/libgit2/src/libgit2/apply.c +4 -3
- data/vendor/libgit2/src/libgit2/attr_file.c +1 -1
- data/vendor/libgit2/src/libgit2/attrcache.c +1 -1
- data/vendor/libgit2/src/libgit2/blame.c +23 -14
- data/vendor/libgit2/src/libgit2/blame_git.c +0 -1
- data/vendor/libgit2/src/libgit2/blob.c +4 -2
- data/vendor/libgit2/src/libgit2/blob.h +2 -2
- data/vendor/libgit2/src/libgit2/branch.c +2 -2
- data/vendor/libgit2/src/libgit2/cherrypick.c +3 -3
- data/vendor/libgit2/src/libgit2/clone.c +34 -3
- data/vendor/libgit2/src/libgit2/commit.c +78 -21
- data/vendor/libgit2/src/libgit2/commit.h +25 -7
- data/vendor/libgit2/src/libgit2/commit_graph.c +129 -47
- data/vendor/libgit2/src/libgit2/commit_graph.h +23 -4
- data/vendor/libgit2/src/libgit2/commit_list.c +16 -5
- data/vendor/libgit2/src/libgit2/commit_list.h +1 -0
- data/vendor/libgit2/src/libgit2/config.c +6 -3
- data/vendor/libgit2/src/libgit2/config_file.c +16 -10
- data/vendor/libgit2/src/libgit2/describe.c +11 -8
- data/vendor/libgit2/src/libgit2/diff.c +19 -6
- data/vendor/libgit2/src/libgit2/diff.h +6 -6
- data/vendor/libgit2/src/libgit2/diff_file.c +16 -7
- data/vendor/libgit2/src/libgit2/diff_generate.c +37 -11
- data/vendor/libgit2/src/libgit2/diff_parse.c +20 -4
- data/vendor/libgit2/src/libgit2/diff_print.c +26 -7
- data/vendor/libgit2/src/libgit2/diff_tform.c +4 -0
- data/vendor/libgit2/src/libgit2/diff_xdiff.h +1 -1
- data/vendor/libgit2/src/libgit2/email.c +4 -3
- data/vendor/libgit2/src/libgit2/errors.c +73 -18
- data/vendor/libgit2/src/libgit2/experimental.h.in +13 -0
- data/vendor/libgit2/src/libgit2/fetch.c +38 -13
- data/vendor/libgit2/src/libgit2/fetch.h +0 -2
- data/vendor/libgit2/src/libgit2/fetchhead.c +11 -9
- data/vendor/libgit2/src/libgit2/grafts.c +272 -0
- data/vendor/libgit2/src/libgit2/grafts.h +36 -0
- data/vendor/libgit2/src/libgit2/ident.c +3 -3
- data/vendor/libgit2/src/libgit2/index.c +327 -123
- data/vendor/libgit2/src/libgit2/index.h +14 -1
- data/vendor/libgit2/src/libgit2/indexer.c +116 -46
- data/vendor/libgit2/src/libgit2/iterator.c +21 -4
- data/vendor/libgit2/src/libgit2/iterator.h +3 -0
- data/vendor/libgit2/src/libgit2/libgit2.c +58 -0
- data/vendor/libgit2/src/libgit2/merge.c +14 -9
- data/vendor/libgit2/src/libgit2/merge_file.c +0 -2
- data/vendor/libgit2/src/libgit2/midx.c +68 -38
- data/vendor/libgit2/src/libgit2/midx.h +13 -3
- data/vendor/libgit2/src/libgit2/mwindow.c +5 -2
- data/vendor/libgit2/src/libgit2/mwindow.h +4 -1
- data/vendor/libgit2/src/libgit2/notes.c +9 -8
- data/vendor/libgit2/src/libgit2/object.c +118 -29
- data/vendor/libgit2/src/libgit2/object.h +17 -2
- data/vendor/libgit2/src/libgit2/odb.c +224 -55
- data/vendor/libgit2/src/libgit2/odb.h +43 -4
- data/vendor/libgit2/src/libgit2/odb_loose.c +128 -70
- data/vendor/libgit2/src/libgit2/odb_pack.c +111 -46
- data/vendor/libgit2/src/libgit2/oid.c +141 -77
- data/vendor/libgit2/src/libgit2/oid.h +183 -9
- data/vendor/libgit2/src/libgit2/oidarray.c +49 -3
- data/vendor/libgit2/src/libgit2/oidarray.h +5 -1
- data/vendor/libgit2/src/libgit2/pack-objects.c +31 -13
- data/vendor/libgit2/src/libgit2/pack-objects.h +5 -2
- data/vendor/libgit2/src/libgit2/pack.c +93 -70
- data/vendor/libgit2/src/libgit2/pack.h +29 -15
- data/vendor/libgit2/src/libgit2/parse.c +8 -4
- data/vendor/libgit2/src/libgit2/parse.h +1 -1
- data/vendor/libgit2/src/libgit2/patch.h +7 -1
- data/vendor/libgit2/src/libgit2/patch_generate.c +24 -5
- data/vendor/libgit2/src/libgit2/patch_parse.c +16 -8
- data/vendor/libgit2/src/libgit2/push.c +13 -3
- data/vendor/libgit2/src/libgit2/reader.c +1 -1
- data/vendor/libgit2/src/libgit2/rebase.c +72 -83
- data/vendor/libgit2/src/libgit2/refdb_fs.c +92 -52
- data/vendor/libgit2/src/libgit2/reflog.c +7 -5
- data/vendor/libgit2/src/libgit2/reflog.h +1 -2
- data/vendor/libgit2/src/libgit2/refs.c +9 -0
- data/vendor/libgit2/src/libgit2/remote.c +47 -37
- data/vendor/libgit2/src/libgit2/remote.h +41 -0
- data/vendor/libgit2/src/libgit2/repository.c +784 -329
- data/vendor/libgit2/src/libgit2/repository.h +26 -2
- data/vendor/libgit2/src/libgit2/reset.c +2 -2
- data/vendor/libgit2/src/libgit2/revert.c +8 -11
- data/vendor/libgit2/src/libgit2/revparse.c +23 -7
- data/vendor/libgit2/src/libgit2/revwalk.c +31 -5
- data/vendor/libgit2/src/libgit2/stash.c +209 -33
- data/vendor/libgit2/src/libgit2/strarray.c +1 -0
- data/vendor/libgit2/src/libgit2/strarray.h +25 -0
- data/vendor/libgit2/src/libgit2/streams/mbedtls.c +0 -1
- data/vendor/libgit2/src/libgit2/streams/openssl.c +9 -17
- data/vendor/libgit2/src/libgit2/streams/openssl_dynamic.c +7 -3
- data/vendor/libgit2/src/libgit2/streams/schannel.c +715 -0
- data/vendor/libgit2/src/libgit2/streams/schannel.h +28 -0
- data/vendor/libgit2/src/libgit2/streams/socket.c +240 -51
- data/vendor/libgit2/src/libgit2/streams/socket.h +3 -1
- data/vendor/libgit2/src/libgit2/streams/stransport.c +40 -12
- data/vendor/libgit2/src/libgit2/streams/tls.c +5 -0
- data/vendor/libgit2/src/libgit2/submodule.c +6 -2
- data/vendor/libgit2/src/libgit2/submodule.h +3 -3
- data/vendor/libgit2/src/libgit2/sysdir.c +294 -7
- data/vendor/libgit2/src/libgit2/sysdir.h +41 -9
- data/vendor/libgit2/src/libgit2/tag.c +29 -10
- data/vendor/libgit2/src/libgit2/tag.h +2 -2
- data/vendor/libgit2/src/libgit2/threadstate.c +15 -2
- data/vendor/libgit2/src/libgit2/threadstate.h +1 -3
- data/vendor/libgit2/src/libgit2/transports/auth.h +1 -2
- data/vendor/libgit2/src/libgit2/transports/{auth_negotiate.c → auth_gssapi.c} +32 -32
- data/vendor/libgit2/src/libgit2/transports/auth_negotiate.h +1 -1
- data/vendor/libgit2/src/libgit2/transports/auth_ntlm.h +1 -1
- data/vendor/libgit2/src/libgit2/transports/{auth_ntlm.c → auth_ntlmclient.c} +12 -12
- data/vendor/libgit2/src/libgit2/transports/auth_sspi.c +341 -0
- data/vendor/libgit2/src/libgit2/transports/git.c +7 -8
- data/vendor/libgit2/src/libgit2/transports/http.c +15 -9
- data/vendor/libgit2/src/libgit2/transports/httpclient.c +14 -0
- data/vendor/libgit2/src/libgit2/transports/httpclient.h +10 -0
- data/vendor/libgit2/src/libgit2/transports/local.c +27 -4
- data/vendor/libgit2/src/libgit2/transports/smart.c +68 -27
- data/vendor/libgit2/src/libgit2/transports/smart.h +33 -9
- data/vendor/libgit2/src/libgit2/transports/smart_pkt.c +281 -49
- data/vendor/libgit2/src/libgit2/transports/smart_protocol.c +192 -55
- data/vendor/libgit2/src/libgit2/transports/ssh.c +334 -102
- data/vendor/libgit2/src/libgit2/transports/winhttp.c +22 -18
- data/vendor/libgit2/src/libgit2/tree-cache.c +26 -16
- data/vendor/libgit2/src/libgit2/tree-cache.h +5 -3
- data/vendor/libgit2/src/libgit2/tree.c +23 -17
- data/vendor/libgit2/src/libgit2/tree.h +2 -2
- data/vendor/libgit2/src/libgit2/worktree.c +30 -10
- data/vendor/libgit2/src/util/CMakeLists.txt +6 -1
- data/vendor/libgit2/src/util/alloc.c +65 -6
- data/vendor/libgit2/src/util/alloc.h +34 -9
- data/vendor/libgit2/src/util/allocators/failalloc.c +0 -60
- data/vendor/libgit2/src/util/allocators/failalloc.h +0 -6
- data/vendor/libgit2/src/util/allocators/stdalloc.c +2 -105
- data/vendor/libgit2/src/util/allocators/win32_leakcheck.c +0 -68
- data/vendor/libgit2/src/util/array.h +6 -1
- data/vendor/libgit2/src/util/cc-compat.h +2 -0
- data/vendor/libgit2/src/util/filebuf.c +6 -1
- data/vendor/libgit2/src/util/filebuf.h +19 -6
- data/vendor/libgit2/src/util/fs_path.c +2 -2
- data/vendor/libgit2/src/util/futils.c +8 -8
- data/vendor/libgit2/src/{features.h.in → util/git2_features.h.in} +9 -3
- data/vendor/libgit2/src/util/git2_util.h +2 -2
- data/vendor/libgit2/src/util/hash/openssl.c +4 -3
- data/vendor/libgit2/src/util/hash/rfc6234/sha.h +0 -112
- data/vendor/libgit2/src/util/hash.h +13 -0
- data/vendor/libgit2/src/util/net.c +492 -87
- data/vendor/libgit2/src/util/net.h +32 -0
- data/vendor/libgit2/src/util/posix.c +54 -0
- data/vendor/libgit2/src/util/posix.h +24 -0
- data/vendor/libgit2/src/util/rand.c +10 -4
- data/vendor/libgit2/src/util/regexp.c +3 -3
- data/vendor/libgit2/src/util/staticstr.h +66 -0
- data/vendor/libgit2/src/util/thread.h +20 -19
- data/vendor/libgit2/src/util/util.c +15 -10
- data/vendor/libgit2/src/util/util.h +25 -16
- data/vendor/libgit2/src/util/win32/error.c +1 -1
- data/vendor/libgit2/src/util/win32/path_w32.c +8 -8
- data/vendor/libgit2/src/util/win32/posix_w32.c +1 -1
- data/vendor/libgit2/src/util/win32/utf-conv.c +73 -75
- data/vendor/libgit2/src/util/win32/utf-conv.h +81 -14
- data/vendor/libgit2/src/util/win32/w32_util.c +1 -1
- metadata +34 -26
- data/vendor/libgit2/cmake/SelectWinHTTP.cmake +0 -17
- data/vendor/libgit2/src/libgit2/netops.c +0 -124
- data/vendor/libgit2/src/libgit2/netops.h +0 -68
- data/vendor/libgit2/src/util/win32/findfile.c +0 -286
- data/vendor/libgit2/src/util/win32/findfile.h +0 -22
- /data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xdiff.h +0 -0
- /data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xemit.h +0 -0
- /data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xinclude.h +0 -0
- /data/vendor/libgit2/{src/libgit2 → deps}/xdiff/xprepare.h +0 -0
- /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
|
79
|
-
#define
|
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(
|
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
|
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
|
-
|
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(
|
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,
|
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(
|
361
|
+
static int load_workdir(
|
362
|
+
git_repository *repo,
|
363
|
+
git_config *config,
|
364
|
+
git_str *parent_path)
|
340
365
|
{
|
341
|
-
|
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
|
-
|
350
|
-
|
351
|
-
|
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
|
-
|
371
|
-
|
372
|
-
|
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(
|
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(
|
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
|
-
|
599
|
-
git_str
|
600
|
-
git_str
|
601
|
-
git_str
|
602
|
-
git_str
|
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
|
-
|
605
|
-
|
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(
|
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
|
-
/*
|
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
|
-
*
|
626
|
-
*
|
627
|
-
*
|
628
|
-
* min_iterations indicates the number of
|
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(
|
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
|
-
|
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(
|
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
|
-
|
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
|
-
/*
|
691
|
-
*
|
692
|
-
*
|
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
|
-
/*
|
697
|
-
*
|
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 (
|
708
|
-
if (!git_str_len(
|
709
|
-
git_str_clear(
|
710
|
-
else if ((error = git_fs_path_dirname_r(
|
711
|
-
(error = git_fs_path_to_dir(
|
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
|
716
|
-
* to report, report that. */
|
717
|
-
if (!git_str_len(
|
718
|
-
git_error_set(GIT_ERROR_REPOSITORY, "could not find repository
|
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
|
-
|
1010
|
+
|
1011
|
+
cleanup:
|
1012
|
+
git_config_free(config);
|
1013
|
+
|
1014
|
+
return error;
|
765
1015
|
}
|
766
1016
|
|
767
|
-
static int
|
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 (!
|
788
|
-
|
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 (
|
878
|
-
|
879
|
-
|
880
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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->
|
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
|
-
|
1100
|
+
error = obtain_config_and_set_oid_type(&config, repo);
|
1101
|
+
if (error < 0)
|
1014
1102
|
goto cleanup;
|
1015
1103
|
|
1016
|
-
if ((error =
|
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
|
-
|
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
|
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
|
-
*
|
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
|
-
|
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
|
-
|
1195
|
-
|
1196
|
-
|
1197
|
-
|
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
|
-
|
1200
|
-
|
1201
|
-
|
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
|
-
|
1270
|
-
|
1271
|
-
|
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 =
|
1596
|
+
if ((error = repository_index_path(&index_path, repo)) < 0)
|
1367
1597
|
return error;
|
1368
1598
|
|
1369
|
-
error =
|
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 (
|
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,
|
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 =
|
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,
|
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
|
-
|
1663
|
-
|
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
|
-
|
1742
|
-
|
1743
|
-
|
1744
|
-
|
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
|
-
|
1747
|
-
|
1748
|
-
|
1749
|
-
|
1750
|
-
|
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
|
-
|
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 &&
|
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",
|
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,
|
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
|
-
|
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[
|
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",
|
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
|
-
|
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
|
-
|
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 ((
|
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
|
+
}
|