rugged 0.17.0.b7 → 0.18.0.b1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +1 -1
- data/README.md +88 -32
- data/ext/rugged/extconf.rb +4 -2
- data/ext/rugged/rugged.c +72 -10
- data/ext/rugged/rugged.h +14 -10
- data/ext/rugged/rugged_blob.c +8 -10
- data/ext/rugged/rugged_branch.c +11 -14
- data/ext/rugged/rugged_commit.c +31 -24
- data/ext/rugged/rugged_config.c +2 -2
- data/ext/rugged/rugged_index.c +133 -198
- data/ext/rugged/rugged_note.c +372 -0
- data/ext/rugged/rugged_object.c +50 -22
- data/ext/rugged/rugged_reference.c +122 -130
- data/ext/rugged/rugged_remote.c +72 -29
- data/ext/rugged/rugged_repo.c +402 -20
- data/ext/rugged/rugged_revwalk.c +7 -3
- data/ext/rugged/rugged_settings.c +110 -0
- data/ext/rugged/rugged_signature.c +23 -7
- data/ext/rugged/rugged_tag.c +32 -16
- data/ext/rugged/rugged_tree.c +44 -15
- data/lib/rugged.rb +1 -0
- data/lib/rugged/index.rb +8 -0
- data/lib/rugged/remote.rb +13 -0
- data/lib/rugged/repository.rb +3 -3
- data/lib/rugged/version.rb +1 -1
- data/test/blob_test.rb +13 -15
- data/test/branch_test.rb +32 -67
- data/test/commit_test.rb +50 -12
- data/test/config_test.rb +12 -11
- data/test/coverage/HEAD.json +1 -1
- data/test/coverage/cover.rb +40 -21
- data/test/errors_test.rb +34 -0
- data/test/fixtures/alternate/objects/14/6ae76773c91e3b1d00cf7a338ec55ae58297e2 +0 -0
- data/test/fixtures/alternate/objects/14/9c32d47e99d0a3572ff1e70a2e0051bbf347a9 +0 -0
- data/test/fixtures/alternate/objects/14/fb3108588f9421bf764041e5e3ac305eb6277f +0 -0
- data/test/fixtures/testrepo.git/logs/refs/notes/commits +1 -0
- data/test/fixtures/testrepo.git/objects/44/1034f860c1d5d90e4188d11ae0d325176869a8 +1 -0
- data/test/fixtures/testrepo.git/objects/60/d415052a33de2150bf68757f6461df4f563ae4 +0 -0
- data/test/fixtures/testrepo.git/objects/68/8a8f4ef7496901d15322972f96e212a9e466cc +1 -0
- data/test/fixtures/testrepo.git/objects/94/eca2de348d5f672faf56b0decafa5937e3235e +0 -0
- data/test/fixtures/testrepo.git/objects/9b/7384fe1676186192842f5d3e129457b62db9e3 +0 -0
- data/test/fixtures/testrepo.git/objects/b7/4713326bc972cc15751ed504dca6f6f3b91f7a +3 -0
- data/test/fixtures/testrepo.git/refs/notes/commits +1 -0
- data/test/index_test.rb +65 -69
- data/test/lib_test.rb +76 -11
- data/test/note_test.rb +158 -0
- data/test/object_test.rb +8 -11
- data/test/reference_test.rb +77 -85
- data/test/remote_test.rb +86 -8
- data/test/repo_pack_test.rb +9 -7
- data/test/repo_reset_test.rb +80 -0
- data/test/repo_test.rb +176 -53
- data/test/tag_test.rb +44 -7
- data/test/test_helper.rb +63 -35
- data/test/tree_test.rb +34 -13
- data/test/walker_test.rb +14 -14
- data/vendor/libgit2/Makefile.embed +1 -1
- data/vendor/libgit2/deps/http-parser/http_parser.c +974 -578
- data/vendor/libgit2/deps/http-parser/http_parser.h +106 -70
- data/vendor/libgit2/deps/regex/regcomp.c +7 -6
- data/vendor/libgit2/deps/regex/regex_internal.c +1 -1
- data/vendor/libgit2/deps/regex/regex_internal.h +12 -3
- data/vendor/libgit2/deps/regex/regexec.c +5 -5
- data/vendor/libgit2/include/git2.h +5 -1
- data/vendor/libgit2/include/git2/attr.h +4 -2
- data/vendor/libgit2/include/git2/blob.h +39 -12
- data/vendor/libgit2/include/git2/branch.h +123 -35
- data/vendor/libgit2/include/git2/checkout.h +206 -48
- data/vendor/libgit2/include/git2/clone.h +72 -27
- data/vendor/libgit2/include/git2/commit.h +20 -17
- data/vendor/libgit2/include/git2/common.h +67 -1
- data/vendor/libgit2/include/git2/config.h +81 -60
- data/vendor/libgit2/include/git2/cred_helpers.h +53 -0
- data/vendor/libgit2/include/git2/diff.h +459 -150
- data/vendor/libgit2/include/git2/errors.h +9 -1
- data/vendor/libgit2/include/git2/graph.h +41 -0
- data/vendor/libgit2/include/git2/ignore.h +7 -6
- data/vendor/libgit2/include/git2/index.h +323 -97
- data/vendor/libgit2/include/git2/indexer.h +27 -59
- data/vendor/libgit2/include/git2/inttypes.h +4 -0
- data/vendor/libgit2/include/git2/merge.h +13 -3
- data/vendor/libgit2/include/git2/message.h +14 -8
- data/vendor/libgit2/include/git2/net.h +9 -7
- data/vendor/libgit2/include/git2/notes.h +88 -29
- data/vendor/libgit2/include/git2/object.h +16 -6
- data/vendor/libgit2/include/git2/odb.h +80 -17
- data/vendor/libgit2/include/git2/odb_backend.h +47 -11
- data/vendor/libgit2/include/git2/oid.h +26 -17
- data/vendor/libgit2/include/git2/pack.h +62 -8
- data/vendor/libgit2/include/git2/push.h +131 -0
- data/vendor/libgit2/include/git2/refdb.h +103 -0
- data/vendor/libgit2/include/git2/refdb_backend.h +109 -0
- data/vendor/libgit2/include/git2/reflog.h +30 -21
- data/vendor/libgit2/include/git2/refs.h +215 -193
- data/vendor/libgit2/include/git2/refspec.h +22 -2
- data/vendor/libgit2/include/git2/remote.h +158 -37
- data/vendor/libgit2/include/git2/repository.h +150 -31
- data/vendor/libgit2/include/git2/reset.h +43 -9
- data/vendor/libgit2/include/git2/revparse.h +48 -4
- data/vendor/libgit2/include/git2/revwalk.h +25 -10
- data/vendor/libgit2/include/git2/signature.h +20 -12
- data/vendor/libgit2/include/git2/stash.h +121 -0
- data/vendor/libgit2/include/git2/status.h +122 -53
- data/vendor/libgit2/include/git2/strarray.h +17 -11
- data/vendor/libgit2/include/git2/submodule.h +42 -7
- data/vendor/libgit2/include/git2/tag.h +72 -59
- data/vendor/libgit2/include/git2/threads.h +4 -2
- data/vendor/libgit2/include/git2/trace.h +68 -0
- data/vendor/libgit2/include/git2/transport.h +328 -0
- data/vendor/libgit2/include/git2/tree.h +149 -120
- data/vendor/libgit2/include/git2/types.h +13 -12
- data/vendor/libgit2/include/git2/version.h +3 -3
- data/vendor/libgit2/src/amiga/map.c +2 -2
- data/vendor/libgit2/src/attr.c +58 -48
- data/vendor/libgit2/src/attr.h +4 -18
- data/vendor/libgit2/src/attr_file.c +30 -6
- data/vendor/libgit2/src/attr_file.h +6 -8
- data/vendor/libgit2/src/attrcache.h +24 -0
- data/vendor/libgit2/src/blob.c +30 -7
- data/vendor/libgit2/src/blob.h +1 -1
- data/vendor/libgit2/src/branch.c +361 -68
- data/vendor/libgit2/src/branch.h +17 -0
- data/vendor/libgit2/src/bswap.h +1 -1
- data/vendor/libgit2/src/buf_text.c +291 -0
- data/vendor/libgit2/src/buf_text.h +122 -0
- data/vendor/libgit2/src/buffer.c +27 -101
- data/vendor/libgit2/src/buffer.h +54 -39
- data/vendor/libgit2/src/cache.c +15 -6
- data/vendor/libgit2/src/cache.h +1 -1
- data/vendor/libgit2/src/cc-compat.h +3 -1
- data/vendor/libgit2/src/checkout.c +1165 -222
- data/vendor/libgit2/src/checkout.h +24 -0
- data/vendor/libgit2/src/clone.c +171 -86
- data/vendor/libgit2/src/commit.c +44 -45
- data/vendor/libgit2/src/commit.h +3 -3
- data/vendor/libgit2/src/commit_list.c +194 -0
- data/vendor/libgit2/src/commit_list.h +49 -0
- data/vendor/libgit2/src/common.h +44 -10
- data/vendor/libgit2/src/compress.c +1 -1
- data/vendor/libgit2/src/compress.h +1 -1
- data/vendor/libgit2/src/config.c +211 -124
- data/vendor/libgit2/src/config.h +23 -4
- data/vendor/libgit2/src/config_cache.c +2 -2
- data/vendor/libgit2/src/config_file.c +129 -53
- data/vendor/libgit2/src/config_file.h +10 -8
- data/vendor/libgit2/src/crlf.c +66 -67
- data/vendor/libgit2/src/date.c +12 -12
- data/vendor/libgit2/src/delta-apply.c +14 -1
- data/vendor/libgit2/src/delta-apply.h +18 -1
- data/vendor/libgit2/src/delta.c +40 -107
- data/vendor/libgit2/src/delta.h +19 -17
- data/vendor/libgit2/src/diff.c +347 -496
- data/vendor/libgit2/src/diff.h +27 -1
- data/vendor/libgit2/src/diff_output.c +564 -249
- data/vendor/libgit2/src/diff_output.h +15 -8
- data/vendor/libgit2/src/diff_tform.c +687 -0
- data/vendor/libgit2/src/errors.c +27 -36
- data/vendor/libgit2/src/fetch.c +13 -351
- data/vendor/libgit2/src/fetch.h +13 -3
- data/vendor/libgit2/src/fetchhead.c +295 -0
- data/vendor/libgit2/src/fetchhead.h +34 -0
- data/vendor/libgit2/src/filebuf.c +42 -15
- data/vendor/libgit2/src/filebuf.h +4 -2
- data/vendor/libgit2/src/fileops.c +466 -113
- data/vendor/libgit2/src/fileops.h +154 -28
- data/vendor/libgit2/src/filter.c +3 -75
- data/vendor/libgit2/src/filter.h +1 -29
- data/vendor/libgit2/src/fnmatch.c +1 -1
- data/vendor/libgit2/src/fnmatch.h +1 -1
- data/vendor/libgit2/src/global.c +54 -10
- data/vendor/libgit2/src/global.h +10 -1
- data/vendor/libgit2/src/graph.c +178 -0
- data/vendor/libgit2/src/hash.c +25 -52
- data/vendor/libgit2/src/hash.h +21 -9
- data/vendor/libgit2/src/{sha1/sha1.c → hash/hash_generic.c} +20 -12
- data/vendor/libgit2/src/hash/hash_generic.h +24 -0
- data/vendor/libgit2/src/hash/hash_openssl.h +45 -0
- data/vendor/libgit2/src/hash/hash_win32.c +291 -0
- data/vendor/libgit2/src/hash/hash_win32.h +140 -0
- data/vendor/libgit2/src/hashsig.c +368 -0
- data/vendor/libgit2/src/hashsig.h +72 -0
- data/vendor/libgit2/src/ignore.c +22 -15
- data/vendor/libgit2/src/ignore.h +6 -1
- data/vendor/libgit2/src/index.c +770 -171
- data/vendor/libgit2/src/index.h +13 -5
- data/vendor/libgit2/src/indexer.c +286 -431
- data/vendor/libgit2/src/iterator.c +854 -466
- data/vendor/libgit2/src/iterator.h +134 -109
- data/vendor/libgit2/src/map.h +1 -1
- data/vendor/libgit2/src/merge.c +296 -0
- data/vendor/libgit2/src/merge.h +22 -0
- data/vendor/libgit2/src/message.c +1 -1
- data/vendor/libgit2/src/message.h +1 -1
- data/vendor/libgit2/src/mwindow.c +35 -30
- data/vendor/libgit2/src/mwindow.h +2 -2
- data/vendor/libgit2/src/netops.c +162 -98
- data/vendor/libgit2/src/netops.h +50 -15
- data/vendor/libgit2/src/notes.c +109 -58
- data/vendor/libgit2/src/notes.h +2 -1
- data/vendor/libgit2/src/object.c +46 -57
- data/vendor/libgit2/src/object.h +1 -8
- data/vendor/libgit2/src/odb.c +151 -40
- data/vendor/libgit2/src/odb.h +5 -1
- data/vendor/libgit2/src/odb_loose.c +4 -5
- data/vendor/libgit2/src/odb_pack.c +122 -80
- data/vendor/libgit2/src/offmap.h +65 -0
- data/vendor/libgit2/src/oid.c +12 -4
- data/vendor/libgit2/src/oidmap.h +1 -1
- data/vendor/libgit2/src/pack-objects.c +88 -61
- data/vendor/libgit2/src/pack-objects.h +8 -8
- data/vendor/libgit2/src/pack.c +293 -28
- data/vendor/libgit2/src/pack.h +49 -4
- data/vendor/libgit2/src/path.c +103 -14
- data/vendor/libgit2/src/path.h +23 -7
- data/vendor/libgit2/src/pathspec.c +168 -0
- data/vendor/libgit2/src/pathspec.h +40 -0
- data/vendor/libgit2/src/pool.c +29 -4
- data/vendor/libgit2/src/pool.h +8 -1
- data/vendor/libgit2/src/posix.c +26 -27
- data/vendor/libgit2/src/posix.h +2 -3
- data/vendor/libgit2/src/pqueue.c +23 -1
- data/vendor/libgit2/src/pqueue.h +23 -1
- data/vendor/libgit2/src/push.c +653 -0
- data/vendor/libgit2/src/push.h +51 -0
- data/vendor/libgit2/src/refdb.c +185 -0
- data/vendor/libgit2/src/refdb.h +46 -0
- data/vendor/libgit2/src/refdb_fs.c +1024 -0
- data/vendor/libgit2/src/refdb_fs.h +15 -0
- data/vendor/libgit2/src/reflog.c +77 -45
- data/vendor/libgit2/src/reflog.h +1 -3
- data/vendor/libgit2/src/refs.c +366 -1326
- data/vendor/libgit2/src/refs.h +22 -13
- data/vendor/libgit2/src/refspec.c +46 -7
- data/vendor/libgit2/src/refspec.h +11 -1
- data/vendor/libgit2/src/remote.c +758 -120
- data/vendor/libgit2/src/remote.h +10 -5
- data/vendor/libgit2/src/repo_template.h +6 -6
- data/vendor/libgit2/src/repository.c +315 -96
- data/vendor/libgit2/src/repository.h +5 -3
- data/vendor/libgit2/src/reset.c +99 -81
- data/vendor/libgit2/src/revparse.c +157 -84
- data/vendor/libgit2/src/revwalk.c +68 -470
- data/vendor/libgit2/src/revwalk.h +44 -0
- data/vendor/libgit2/src/sha1_lookup.c +1 -1
- data/vendor/libgit2/src/sha1_lookup.h +1 -1
- data/vendor/libgit2/src/signature.c +68 -200
- data/vendor/libgit2/src/signature.h +1 -1
- data/vendor/libgit2/src/stash.c +663 -0
- data/vendor/libgit2/src/status.c +101 -79
- data/vendor/libgit2/src/strmap.h +1 -1
- data/vendor/libgit2/src/submodule.c +67 -51
- data/vendor/libgit2/src/submodule.h +1 -1
- data/vendor/libgit2/src/tag.c +35 -29
- data/vendor/libgit2/src/tag.h +1 -1
- data/vendor/libgit2/src/thread-utils.c +1 -1
- data/vendor/libgit2/src/thread-utils.h +2 -2
- data/vendor/libgit2/src/trace.c +39 -0
- data/vendor/libgit2/src/trace.h +56 -0
- data/vendor/libgit2/src/transport.c +81 -34
- data/vendor/libgit2/src/transports/cred.c +60 -0
- data/vendor/libgit2/src/transports/cred_helpers.c +49 -0
- data/vendor/libgit2/src/transports/git.c +234 -127
- data/vendor/libgit2/src/transports/http.c +761 -433
- data/vendor/libgit2/src/transports/local.c +460 -64
- data/vendor/libgit2/src/transports/smart.c +345 -0
- data/vendor/libgit2/src/transports/smart.h +179 -0
- data/vendor/libgit2/src/{pkt.c → transports/smart_pkt.c} +131 -12
- data/vendor/libgit2/src/transports/smart_protocol.c +856 -0
- data/vendor/libgit2/src/transports/winhttp.c +1136 -0
- data/vendor/libgit2/src/tree-cache.c +2 -2
- data/vendor/libgit2/src/tree-cache.h +1 -1
- data/vendor/libgit2/src/tree.c +239 -166
- data/vendor/libgit2/src/tree.h +11 -2
- data/vendor/libgit2/src/tsort.c +39 -23
- data/vendor/libgit2/src/unix/map.c +1 -1
- data/vendor/libgit2/src/unix/posix.h +12 -2
- data/vendor/libgit2/src/unix/realpath.c +30 -0
- data/vendor/libgit2/src/util.c +250 -13
- data/vendor/libgit2/src/util.h +71 -14
- data/vendor/libgit2/src/vector.c +123 -60
- data/vendor/libgit2/src/vector.h +24 -22
- data/vendor/libgit2/src/win32/dir.c +1 -1
- data/vendor/libgit2/src/win32/dir.h +1 -1
- data/vendor/libgit2/src/win32/error.c +77 -0
- data/vendor/libgit2/src/win32/error.h +13 -0
- data/vendor/libgit2/src/win32/findfile.c +143 -54
- data/vendor/libgit2/src/win32/findfile.h +10 -6
- data/vendor/libgit2/src/win32/map.c +1 -1
- data/vendor/libgit2/src/win32/mingw-compat.h +1 -1
- data/vendor/libgit2/src/win32/msvc-compat.h +10 -1
- data/vendor/libgit2/src/win32/posix.h +10 -1
- data/vendor/libgit2/src/win32/posix_w32.c +132 -63
- data/vendor/libgit2/src/win32/precompiled.c +1 -1
- data/vendor/libgit2/src/win32/pthread.c +1 -1
- data/vendor/libgit2/src/win32/pthread.h +1 -1
- data/vendor/libgit2/src/win32/utf-conv.c +5 -5
- data/vendor/libgit2/src/win32/utf-conv.h +3 -3
- data/vendor/libgit2/src/win32/version.h +20 -0
- metadata +308 -252
- data/test/fixtures/testrepo.git/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 +0 -0
- data/test/fixtures/testrepo.git/objects/7f/043268ea43ce18e3540acaabf9e090c91965b0 +0 -0
- data/test/fixtures/testrepo.git/objects/a3/e05719b428a2d0ed7a55c4ce53dcc5768c6d5e +0 -0
- data/test/index_test.rb~ +0 -218
- data/vendor/libgit2/src/pkt.h +0 -91
- data/vendor/libgit2/src/ppc/sha1.c +0 -70
- data/vendor/libgit2/src/ppc/sha1.h +0 -26
- data/vendor/libgit2/src/protocol.c +0 -110
- data/vendor/libgit2/src/protocol.h +0 -21
- data/vendor/libgit2/src/sha1.h +0 -33
- data/vendor/libgit2/src/transport.h +0 -148
@@ -0,0 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (C) the libgit2 contributors. All rights reserved.
|
3
|
+
*
|
4
|
+
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
5
|
+
* a Linking Exception. For full terms see the included COPYING file.
|
6
|
+
*/
|
7
|
+
#ifndef INCLUDE_refdb_fs_h__
|
8
|
+
#define INCLUDE_refdb_fs_h__
|
9
|
+
|
10
|
+
typedef struct {
|
11
|
+
git_strmap *packfile;
|
12
|
+
time_t packfile_time;
|
13
|
+
} git_refcache;
|
14
|
+
|
15
|
+
#endif
|
data/vendor/libgit2/src/reflog.c
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
/*
|
2
|
-
* Copyright (C)
|
2
|
+
* Copyright (C) the libgit2 contributors. All rights reserved.
|
3
3
|
*
|
4
4
|
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
5
5
|
* a Linking Exception. For full terms see the included COPYING file.
|
@@ -10,7 +10,7 @@
|
|
10
10
|
#include "filebuf.h"
|
11
11
|
#include "signature.h"
|
12
12
|
|
13
|
-
static int reflog_init(git_reflog **reflog, git_reference *ref)
|
13
|
+
static int reflog_init(git_reflog **reflog, const git_reference *ref)
|
14
14
|
{
|
15
15
|
git_reflog *log;
|
16
16
|
|
@@ -163,9 +163,12 @@ fail:
|
|
163
163
|
|
164
164
|
void git_reflog_free(git_reflog *reflog)
|
165
165
|
{
|
166
|
-
|
166
|
+
size_t i;
|
167
167
|
git_reflog_entry *entry;
|
168
168
|
|
169
|
+
if (reflog == NULL)
|
170
|
+
return;
|
171
|
+
|
169
172
|
for (i=0; i < reflog->entries.length; i++) {
|
170
173
|
entry = git_vector_get(&reflog->entries, i);
|
171
174
|
|
@@ -177,7 +180,7 @@ void git_reflog_free(git_reflog *reflog)
|
|
177
180
|
git__free(reflog);
|
178
181
|
}
|
179
182
|
|
180
|
-
static int retrieve_reflog_path(git_buf *path, git_reference *ref)
|
183
|
+
static int retrieve_reflog_path(git_buf *path, const git_reference *ref)
|
181
184
|
{
|
182
185
|
return git_buf_join_n(path, '/', 3,
|
183
186
|
git_reference_owner(ref)->path_repository, GIT_REFLOG_DIR, ref->name);
|
@@ -185,7 +188,10 @@ static int retrieve_reflog_path(git_buf *path, git_reference *ref)
|
|
185
188
|
|
186
189
|
static int create_new_reflog_file(const char *filepath)
|
187
190
|
{
|
188
|
-
int fd;
|
191
|
+
int fd, error;
|
192
|
+
|
193
|
+
if ((error = git_futils_mkpath2file(filepath, GIT_REFLOG_DIR_MODE)) < 0)
|
194
|
+
return error;
|
189
195
|
|
190
196
|
if ((fd = p_open(filepath,
|
191
197
|
O_WRONLY | O_CREAT | O_TRUNC,
|
@@ -195,17 +201,17 @@ static int create_new_reflog_file(const char *filepath)
|
|
195
201
|
return p_close(fd);
|
196
202
|
}
|
197
203
|
|
198
|
-
int git_reflog_read(git_reflog **reflog, git_reference *ref)
|
204
|
+
int git_reflog_read(git_reflog **reflog, const git_reference *ref)
|
199
205
|
{
|
200
206
|
int error = -1;
|
201
207
|
git_buf log_path = GIT_BUF_INIT;
|
202
208
|
git_buf log_file = GIT_BUF_INIT;
|
203
209
|
git_reflog *log = NULL;
|
204
210
|
|
205
|
-
*reflog = NULL;
|
206
|
-
|
207
211
|
assert(reflog && ref);
|
208
212
|
|
213
|
+
*reflog = NULL;
|
214
|
+
|
209
215
|
if (reflog_init(&log, ref) < 0)
|
210
216
|
return -1;
|
211
217
|
|
@@ -248,7 +254,6 @@ int git_reflog_write(git_reflog *reflog)
|
|
248
254
|
|
249
255
|
assert(reflog);
|
250
256
|
|
251
|
-
|
252
257
|
if (git_buf_join_n(&log_path, '/', 3,
|
253
258
|
git_repository_path(reflog->owner), GIT_REFLOG_DIR, reflog->ref_name) < 0)
|
254
259
|
return -1;
|
@@ -269,7 +274,7 @@ int git_reflog_write(git_reflog *reflog)
|
|
269
274
|
if ((error = git_filebuf_write(&fbuf, log.ptr, log.size)) < 0)
|
270
275
|
goto cleanup;
|
271
276
|
}
|
272
|
-
|
277
|
+
|
273
278
|
error = git_filebuf_commit(&fbuf, GIT_REFLOG_FILE_MODE);
|
274
279
|
goto success;
|
275
280
|
|
@@ -285,8 +290,8 @@ success:
|
|
285
290
|
int git_reflog_append(git_reflog *reflog, const git_oid *new_oid,
|
286
291
|
const git_signature *committer, const char *msg)
|
287
292
|
{
|
288
|
-
int count;
|
289
293
|
git_reflog_entry *entry;
|
294
|
+
const git_reflog_entry *previous;
|
290
295
|
const char *newline;
|
291
296
|
|
292
297
|
assert(reflog && new_oid && committer);
|
@@ -313,16 +318,12 @@ int git_reflog_append(git_reflog *reflog, const git_oid *new_oid,
|
|
313
318
|
}
|
314
319
|
}
|
315
320
|
|
316
|
-
|
321
|
+
previous = git_reflog_entry_byindex(reflog, 0);
|
317
322
|
|
318
|
-
if (
|
323
|
+
if (previous == NULL)
|
319
324
|
git_oid_fromstr(&entry->oid_old, GIT_OID_HEX_ZERO);
|
320
|
-
else
|
321
|
-
const git_reflog_entry *previous;
|
322
|
-
|
323
|
-
previous = git_reflog_entry_byindex(reflog, count -1);
|
325
|
+
else
|
324
326
|
git_oid_cpy(&entry->oid_old, &previous->oid_cur);
|
325
|
-
}
|
326
327
|
|
327
328
|
git_oid_cpy(&entry->oid_cur, new_oid);
|
328
329
|
|
@@ -338,21 +339,26 @@ cleanup:
|
|
338
339
|
|
339
340
|
int git_reflog_rename(git_reference *ref, const char *new_name)
|
340
341
|
{
|
341
|
-
int error =
|
342
|
+
int error = 0, fd;
|
342
343
|
git_buf old_path = GIT_BUF_INIT;
|
343
344
|
git_buf new_path = GIT_BUF_INIT;
|
344
345
|
git_buf temp_path = GIT_BUF_INIT;
|
346
|
+
git_buf normalized = GIT_BUF_INIT;
|
345
347
|
|
346
348
|
assert(ref && new_name);
|
347
349
|
|
350
|
+
if ((error = git_reference__normalize_name(
|
351
|
+
&normalized, new_name, GIT_REF_FORMAT_ALLOW_ONELEVEL)) < 0)
|
352
|
+
return error;
|
353
|
+
|
348
354
|
if (git_buf_joinpath(&temp_path, git_reference_owner(ref)->path_repository, GIT_REFLOG_DIR) < 0)
|
349
355
|
return -1;
|
350
356
|
|
351
357
|
if (git_buf_joinpath(&old_path, git_buf_cstr(&temp_path), ref->name) < 0)
|
352
|
-
|
358
|
+
return -1;
|
353
359
|
|
354
|
-
if (git_buf_joinpath(&new_path, git_buf_cstr(&temp_path),
|
355
|
-
|
360
|
+
if (git_buf_joinpath(&new_path, git_buf_cstr(&temp_path), git_buf_cstr(&normalized)) < 0)
|
361
|
+
return -1;
|
356
362
|
|
357
363
|
/*
|
358
364
|
* Move the reflog to a temporary place. This two-phase renaming is required
|
@@ -362,28 +368,42 @@ int git_reflog_rename(git_reference *ref, const char *new_name)
|
|
362
368
|
* - a/b/c/d -> a/b/c
|
363
369
|
*/
|
364
370
|
if (git_buf_joinpath(&temp_path, git_buf_cstr(&temp_path), "temp_reflog") < 0)
|
365
|
-
|
371
|
+
return -1;
|
366
372
|
|
367
|
-
if ((fd = git_futils_mktmp(&temp_path, git_buf_cstr(&temp_path))) < 0)
|
373
|
+
if ((fd = git_futils_mktmp(&temp_path, git_buf_cstr(&temp_path))) < 0) {
|
374
|
+
error = -1;
|
368
375
|
goto cleanup;
|
376
|
+
}
|
377
|
+
|
369
378
|
p_close(fd);
|
370
379
|
|
371
|
-
if (p_rename(git_buf_cstr(&old_path), git_buf_cstr(&temp_path)) < 0)
|
380
|
+
if (p_rename(git_buf_cstr(&old_path), git_buf_cstr(&temp_path)) < 0) {
|
381
|
+
giterr_set(GITERR_OS, "Failed to rename reflog for %s", new_name);
|
382
|
+
error = -1;
|
372
383
|
goto cleanup;
|
384
|
+
}
|
373
385
|
|
374
386
|
if (git_path_isdir(git_buf_cstr(&new_path)) &&
|
375
|
-
(git_futils_rmdir_r(git_buf_cstr(&new_path), NULL,
|
387
|
+
(git_futils_rmdir_r(git_buf_cstr(&new_path), NULL, GIT_RMDIR_SKIP_NONEMPTY) < 0)) {
|
388
|
+
error = -1;
|
376
389
|
goto cleanup;
|
390
|
+
}
|
377
391
|
|
378
|
-
if (git_futils_mkpath2file(git_buf_cstr(&new_path), GIT_REFLOG_DIR_MODE) < 0)
|
392
|
+
if (git_futils_mkpath2file(git_buf_cstr(&new_path), GIT_REFLOG_DIR_MODE) < 0) {
|
393
|
+
error = -1;
|
379
394
|
goto cleanup;
|
395
|
+
}
|
380
396
|
|
381
|
-
|
397
|
+
if (p_rename(git_buf_cstr(&temp_path), git_buf_cstr(&new_path)) < 0) {
|
398
|
+
giterr_set(GITERR_OS, "Failed to rename reflog for %s", new_name);
|
399
|
+
error = -1;
|
400
|
+
}
|
382
401
|
|
383
402
|
cleanup:
|
384
403
|
git_buf_free(&temp_path);
|
385
404
|
git_buf_free(&old_path);
|
386
405
|
git_buf_free(&new_path);
|
406
|
+
git_buf_free(&normalized);
|
387
407
|
|
388
408
|
return error;
|
389
409
|
}
|
@@ -403,37 +423,47 @@ int git_reflog_delete(git_reference *ref)
|
|
403
423
|
return error;
|
404
424
|
}
|
405
425
|
|
406
|
-
|
426
|
+
size_t git_reflog_entrycount(git_reflog *reflog)
|
407
427
|
{
|
408
428
|
assert(reflog);
|
409
|
-
return
|
429
|
+
return reflog->entries.length;
|
430
|
+
}
|
431
|
+
|
432
|
+
GIT_INLINE(size_t) reflog_inverse_index(size_t idx, size_t total)
|
433
|
+
{
|
434
|
+
return (total - 1) - idx;
|
410
435
|
}
|
411
436
|
|
412
437
|
const git_reflog_entry * git_reflog_entry_byindex(git_reflog *reflog, size_t idx)
|
413
438
|
{
|
414
439
|
assert(reflog);
|
415
|
-
|
440
|
+
|
441
|
+
if (idx >= reflog->entries.length)
|
442
|
+
return NULL;
|
443
|
+
|
444
|
+
return git_vector_get(
|
445
|
+
&reflog->entries, reflog_inverse_index(idx, reflog->entries.length));
|
416
446
|
}
|
417
447
|
|
418
|
-
const git_oid *
|
448
|
+
const git_oid * git_reflog_entry_id_old(const git_reflog_entry *entry)
|
419
449
|
{
|
420
450
|
assert(entry);
|
421
451
|
return &entry->oid_old;
|
422
452
|
}
|
423
453
|
|
424
|
-
const git_oid *
|
454
|
+
const git_oid * git_reflog_entry_id_new(const git_reflog_entry *entry)
|
425
455
|
{
|
426
456
|
assert(entry);
|
427
457
|
return &entry->oid_cur;
|
428
458
|
}
|
429
459
|
|
430
|
-
git_signature * git_reflog_entry_committer(const git_reflog_entry *entry)
|
460
|
+
const git_signature * git_reflog_entry_committer(const git_reflog_entry *entry)
|
431
461
|
{
|
432
462
|
assert(entry);
|
433
463
|
return entry->committer;
|
434
464
|
}
|
435
465
|
|
436
|
-
char *
|
466
|
+
const char * git_reflog_entry_message(const git_reflog_entry *entry)
|
437
467
|
{
|
438
468
|
assert(entry);
|
439
469
|
return entry->msg;
|
@@ -441,44 +471,46 @@ char * git_reflog_entry_msg(const git_reflog_entry *entry)
|
|
441
471
|
|
442
472
|
int git_reflog_drop(
|
443
473
|
git_reflog *reflog,
|
444
|
-
|
474
|
+
size_t idx,
|
445
475
|
int rewrite_previous_entry)
|
446
476
|
{
|
447
|
-
|
477
|
+
size_t entrycount;
|
448
478
|
git_reflog_entry *entry, *previous;
|
449
479
|
|
450
480
|
assert(reflog);
|
451
481
|
|
452
482
|
entrycount = git_reflog_entrycount(reflog);
|
453
483
|
|
454
|
-
|
484
|
+
entry = (git_reflog_entry *)git_reflog_entry_byindex(reflog, idx);
|
485
|
+
|
486
|
+
if (entry == NULL)
|
455
487
|
return GIT_ENOTFOUND;
|
456
488
|
|
457
|
-
entry = git_vector_get(&reflog->entries, idx);
|
458
489
|
reflog_entry_free(entry);
|
459
490
|
|
460
|
-
if (git_vector_remove(
|
491
|
+
if (git_vector_remove(
|
492
|
+
&reflog->entries, reflog_inverse_index(idx, entrycount)) < 0)
|
461
493
|
return -1;
|
462
494
|
|
463
495
|
if (!rewrite_previous_entry)
|
464
496
|
return 0;
|
465
497
|
|
466
|
-
/* No need to rewrite anything when removing the
|
498
|
+
/* No need to rewrite anything when removing the most recent entry */
|
467
499
|
if (idx == 0)
|
468
500
|
return 0;
|
469
501
|
|
470
|
-
/*
|
502
|
+
/* Have the latest entry just been dropped? */
|
471
503
|
if (entrycount == 1)
|
472
504
|
return 0;
|
473
505
|
|
474
506
|
entry = (git_reflog_entry *)git_reflog_entry_byindex(reflog, idx - 1);
|
475
507
|
|
476
|
-
/* If the
|
508
|
+
/* If the oldest entry has just been removed... */
|
477
509
|
if (idx == entrycount - 1) {
|
478
|
-
/* ...clear the oid_old member of the "new"
|
510
|
+
/* ...clear the oid_old member of the "new" oldest entry */
|
479
511
|
if (git_oid_fromstr(&entry->oid_old, GIT_OID_HEX_ZERO) < 0)
|
480
512
|
return -1;
|
481
|
-
|
513
|
+
|
482
514
|
return 0;
|
483
515
|
}
|
484
516
|
|
data/vendor/libgit2/src/reflog.h
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
/*
|
2
|
-
* Copyright (C)
|
2
|
+
* Copyright (C) the libgit2 contributors. All rights reserved.
|
3
3
|
*
|
4
4
|
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
5
5
|
* a Linking Exception. For full terms see the included COPYING file.
|
@@ -17,8 +17,6 @@
|
|
17
17
|
|
18
18
|
#define GIT_REFLOG_SIZE_MIN (2*GIT_OID_HEXSZ+2+17)
|
19
19
|
|
20
|
-
#define GIT_OID_HEX_ZERO "0000000000000000000000000000000000000000"
|
21
|
-
|
22
20
|
struct git_reflog_entry {
|
23
21
|
git_oid oid_old;
|
24
22
|
git_oid oid_cur;
|
data/vendor/libgit2/src/refs.c
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
/*
|
2
|
-
* Copyright (C)
|
2
|
+
* Copyright (C) the libgit2 contributors. All rights reserved.
|
3
3
|
*
|
4
4
|
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
5
5
|
* a Linking Exception. For full terms see the included COPYING file.
|
@@ -11,11 +11,15 @@
|
|
11
11
|
#include "fileops.h"
|
12
12
|
#include "pack.h"
|
13
13
|
#include "reflog.h"
|
14
|
+
#include "refdb.h"
|
14
15
|
|
15
16
|
#include <git2/tag.h>
|
16
17
|
#include <git2/object.h>
|
17
18
|
#include <git2/oid.h>
|
18
19
|
#include <git2/branch.h>
|
20
|
+
#include <git2/refs.h>
|
21
|
+
#include <git2/refdb.h>
|
22
|
+
#include <git2/refdb_backend.h>
|
19
23
|
|
20
24
|
GIT__USE_STRMAP;
|
21
25
|
|
@@ -27,784 +31,75 @@ enum {
|
|
27
31
|
GIT_PACKREF_WAS_LOOSE = 2
|
28
32
|
};
|
29
33
|
|
30
|
-
|
31
|
-
git_oid oid;
|
32
|
-
git_oid peel;
|
33
|
-
char flags;
|
34
|
-
char name[GIT_FLEX_ARRAY];
|
35
|
-
};
|
36
|
-
|
37
|
-
static int reference_read(
|
38
|
-
git_buf *file_content,
|
39
|
-
time_t *mtime,
|
40
|
-
const char *repo_path,
|
41
|
-
const char *ref_name,
|
42
|
-
int *updated);
|
43
|
-
|
44
|
-
/* loose refs */
|
45
|
-
static int loose_parse_symbolic(git_reference *ref, git_buf *file_content);
|
46
|
-
static int loose_parse_oid(git_oid *ref, git_buf *file_content);
|
47
|
-
static int loose_lookup(git_reference *ref);
|
48
|
-
static int loose_lookup_to_packfile(struct packref **ref_out,
|
49
|
-
git_repository *repo, const char *name);
|
50
|
-
static int loose_write(git_reference *ref);
|
51
|
-
|
52
|
-
/* packed refs */
|
53
|
-
static int packed_parse_peel(struct packref *tag_ref,
|
54
|
-
const char **buffer_out, const char *buffer_end);
|
55
|
-
static int packed_parse_oid(struct packref **ref_out,
|
56
|
-
const char **buffer_out, const char *buffer_end);
|
57
|
-
static int packed_load(git_repository *repo);
|
58
|
-
static int packed_loadloose(git_repository *repository);
|
59
|
-
static int packed_write_ref(struct packref *ref, git_filebuf *file);
|
60
|
-
static int packed_find_peel(git_repository *repo, struct packref *ref);
|
61
|
-
static int packed_remove_loose(git_repository *repo, git_vector *packing_list);
|
62
|
-
static int packed_sort(const void *a, const void *b);
|
63
|
-
static int packed_lookup(git_reference *ref);
|
64
|
-
static int packed_write(git_repository *repo);
|
65
|
-
|
66
|
-
/* internal helpers */
|
67
|
-
static int reference_path_available(git_repository *repo,
|
68
|
-
const char *ref, const char *old_ref);
|
69
|
-
static int reference_delete(git_reference *ref);
|
70
|
-
static int reference_lookup(git_reference *ref);
|
71
|
-
|
72
|
-
void git_reference_free(git_reference *reference)
|
73
|
-
{
|
74
|
-
if (reference == NULL)
|
75
|
-
return;
|
76
|
-
|
77
|
-
git__free(reference->name);
|
78
|
-
reference->name = NULL;
|
79
|
-
|
80
|
-
if (reference->flags & GIT_REF_SYMBOLIC) {
|
81
|
-
git__free(reference->target.symbolic);
|
82
|
-
reference->target.symbolic = NULL;
|
83
|
-
}
|
84
|
-
|
85
|
-
git__free(reference);
|
86
|
-
}
|
87
|
-
|
88
|
-
static int reference_alloc(
|
89
|
-
git_reference **ref_out,
|
90
|
-
git_repository *repo,
|
91
|
-
const char *name)
|
92
|
-
{
|
93
|
-
git_reference *reference = NULL;
|
94
|
-
|
95
|
-
assert(ref_out && repo && name);
|
96
|
-
|
97
|
-
reference = git__malloc(sizeof(git_reference));
|
98
|
-
GITERR_CHECK_ALLOC(reference);
|
99
|
-
|
100
|
-
memset(reference, 0x0, sizeof(git_reference));
|
101
|
-
reference->owner = repo;
|
102
|
-
|
103
|
-
reference->name = git__strdup(name);
|
104
|
-
GITERR_CHECK_ALLOC(reference->name);
|
105
|
-
|
106
|
-
*ref_out = reference;
|
107
|
-
return 0;
|
108
|
-
}
|
109
|
-
|
110
|
-
static int reference_read(
|
111
|
-
git_buf *file_content,
|
112
|
-
time_t *mtime,
|
113
|
-
const char *repo_path,
|
114
|
-
const char *ref_name,
|
115
|
-
int *updated)
|
116
|
-
{
|
117
|
-
git_buf path = GIT_BUF_INIT;
|
118
|
-
int result;
|
119
|
-
|
120
|
-
assert(file_content && repo_path && ref_name);
|
121
|
-
|
122
|
-
/* Determine the full path of the file */
|
123
|
-
if (git_buf_joinpath(&path, repo_path, ref_name) < 0)
|
124
|
-
return -1;
|
125
|
-
|
126
|
-
result = git_futils_readbuffer_updated(file_content, path.ptr, mtime, updated);
|
127
|
-
git_buf_free(&path);
|
128
|
-
|
129
|
-
return result;
|
130
|
-
}
|
131
|
-
|
132
|
-
static int loose_parse_symbolic(git_reference *ref, git_buf *file_content)
|
133
|
-
{
|
134
|
-
const unsigned int header_len = (unsigned int)strlen(GIT_SYMREF);
|
135
|
-
const char *refname_start;
|
136
|
-
|
137
|
-
refname_start = (const char *)file_content->ptr;
|
138
|
-
|
139
|
-
if (git_buf_len(file_content) < header_len + 1) {
|
140
|
-
giterr_set(GITERR_REFERENCE, "Corrupted loose reference file");
|
141
|
-
return -1;
|
142
|
-
}
|
143
|
-
|
144
|
-
/*
|
145
|
-
* Assume we have already checked for the header
|
146
|
-
* before calling this function
|
147
|
-
*/
|
148
|
-
refname_start += header_len;
|
149
|
-
|
150
|
-
ref->target.symbolic = git__strdup(refname_start);
|
151
|
-
GITERR_CHECK_ALLOC(ref->target.symbolic);
|
152
|
-
|
153
|
-
return 0;
|
154
|
-
}
|
155
|
-
|
156
|
-
static int loose_parse_oid(git_oid *oid, git_buf *file_content)
|
157
|
-
{
|
158
|
-
size_t len;
|
159
|
-
const char *str;
|
160
|
-
|
161
|
-
len = git_buf_len(file_content);
|
162
|
-
if (len < GIT_OID_HEXSZ)
|
163
|
-
goto corrupted;
|
164
|
-
|
165
|
-
/* str is guranteed to be zero-terminated */
|
166
|
-
str = git_buf_cstr(file_content);
|
167
|
-
|
168
|
-
/* If the file is longer than 40 chars, the 41st must be a space */
|
169
|
-
if (git_oid_fromstr(oid, git_buf_cstr(file_content)) < 0)
|
170
|
-
goto corrupted;
|
171
|
-
|
172
|
-
/* If the file is longer than 40 chars, the 41st must be a space */
|
173
|
-
str += GIT_OID_HEXSZ;
|
174
|
-
if (*str == '\0' || git__isspace(*str))
|
175
|
-
return 0;
|
176
|
-
|
177
|
-
corrupted:
|
178
|
-
giterr_set(GITERR_REFERENCE, "Corrupted loose reference file");
|
179
|
-
return -1;
|
180
|
-
}
|
181
|
-
|
182
|
-
static git_ref_t loose_guess_rtype(const git_buf *full_path)
|
183
|
-
{
|
184
|
-
git_buf ref_file = GIT_BUF_INIT;
|
185
|
-
git_ref_t type;
|
186
|
-
|
187
|
-
type = GIT_REF_INVALID;
|
188
|
-
|
189
|
-
if (git_futils_readbuffer(&ref_file, full_path->ptr) == 0) {
|
190
|
-
if (git__prefixcmp((const char *)(ref_file.ptr), GIT_SYMREF) == 0)
|
191
|
-
type = GIT_REF_SYMBOLIC;
|
192
|
-
else
|
193
|
-
type = GIT_REF_OID;
|
194
|
-
}
|
195
|
-
|
196
|
-
git_buf_free(&ref_file);
|
197
|
-
return type;
|
198
|
-
}
|
199
|
-
|
200
|
-
static int loose_lookup(git_reference *ref)
|
201
|
-
{
|
202
|
-
int result, updated;
|
203
|
-
git_buf ref_file = GIT_BUF_INIT;
|
204
|
-
|
205
|
-
result = reference_read(&ref_file, &ref->mtime,
|
206
|
-
ref->owner->path_repository, ref->name, &updated);
|
207
|
-
|
208
|
-
if (result < 0)
|
209
|
-
return result;
|
210
|
-
|
211
|
-
if (!updated)
|
212
|
-
return 0;
|
213
|
-
|
214
|
-
if (ref->flags & GIT_REF_SYMBOLIC) {
|
215
|
-
git__free(ref->target.symbolic);
|
216
|
-
ref->target.symbolic = NULL;
|
217
|
-
}
|
218
|
-
|
219
|
-
ref->flags = 0;
|
220
|
-
|
221
|
-
if (git__prefixcmp((const char *)(ref_file.ptr), GIT_SYMREF) == 0) {
|
222
|
-
ref->flags |= GIT_REF_SYMBOLIC;
|
223
|
-
git_buf_rtrim(&ref_file);
|
224
|
-
result = loose_parse_symbolic(ref, &ref_file);
|
225
|
-
} else {
|
226
|
-
ref->flags |= GIT_REF_OID;
|
227
|
-
result = loose_parse_oid(&ref->target.oid, &ref_file);
|
228
|
-
}
|
229
|
-
|
230
|
-
git_buf_free(&ref_file);
|
231
|
-
return result;
|
232
|
-
}
|
233
|
-
|
234
|
-
static int loose_lookup_to_packfile(
|
235
|
-
struct packref **ref_out,
|
236
|
-
git_repository *repo,
|
237
|
-
const char *name)
|
238
|
-
{
|
239
|
-
git_buf ref_file = GIT_BUF_INIT;
|
240
|
-
struct packref *ref = NULL;
|
241
|
-
size_t name_len;
|
242
|
-
|
243
|
-
*ref_out = NULL;
|
244
|
-
|
245
|
-
if (reference_read(&ref_file, NULL, repo->path_repository, name, NULL) < 0)
|
246
|
-
return -1;
|
247
|
-
|
248
|
-
git_buf_rtrim(&ref_file);
|
249
|
-
|
250
|
-
name_len = strlen(name);
|
251
|
-
ref = git__malloc(sizeof(struct packref) + name_len + 1);
|
252
|
-
GITERR_CHECK_ALLOC(ref);
|
253
|
-
|
254
|
-
memcpy(ref->name, name, name_len);
|
255
|
-
ref->name[name_len] = 0;
|
256
|
-
|
257
|
-
if (loose_parse_oid(&ref->oid, &ref_file) < 0) {
|
258
|
-
git_buf_free(&ref_file);
|
259
|
-
git__free(ref);
|
260
|
-
return -1;
|
261
|
-
}
|
262
|
-
|
263
|
-
ref->flags = GIT_PACKREF_WAS_LOOSE;
|
264
|
-
|
265
|
-
*ref_out = ref;
|
266
|
-
git_buf_free(&ref_file);
|
267
|
-
return 0;
|
268
|
-
}
|
269
|
-
|
270
|
-
static int loose_write(git_reference *ref)
|
271
|
-
{
|
272
|
-
git_filebuf file = GIT_FILEBUF_INIT;
|
273
|
-
git_buf ref_path = GIT_BUF_INIT;
|
274
|
-
struct stat st;
|
275
|
-
|
276
|
-
if (git_buf_joinpath(&ref_path, ref->owner->path_repository, ref->name) < 0)
|
277
|
-
return -1;
|
278
|
-
|
279
|
-
/* Remove a possibly existing empty directory hierarchy
|
280
|
-
* which name would collide with the reference name
|
281
|
-
*/
|
282
|
-
if (git_path_isdir(git_buf_cstr(&ref_path)) &&
|
283
|
-
git_futils_rmdir_r(git_buf_cstr(&ref_path), NULL,
|
284
|
-
GIT_DIRREMOVAL_ONLY_EMPTY_DIRS) < 0) {
|
285
|
-
git_buf_free(&ref_path);
|
286
|
-
return -1;
|
287
|
-
}
|
288
|
-
|
289
|
-
if (git_filebuf_open(&file, ref_path.ptr, GIT_FILEBUF_FORCE) < 0) {
|
290
|
-
git_buf_free(&ref_path);
|
291
|
-
return -1;
|
292
|
-
}
|
293
|
-
|
294
|
-
git_buf_free(&ref_path);
|
295
|
-
|
296
|
-
if (ref->flags & GIT_REF_OID) {
|
297
|
-
char oid[GIT_OID_HEXSZ + 1];
|
298
|
-
|
299
|
-
git_oid_fmt(oid, &ref->target.oid);
|
300
|
-
oid[GIT_OID_HEXSZ] = '\0';
|
301
|
-
|
302
|
-
git_filebuf_printf(&file, "%s\n", oid);
|
303
|
-
|
304
|
-
} else if (ref->flags & GIT_REF_SYMBOLIC) {
|
305
|
-
git_filebuf_printf(&file, GIT_SYMREF "%s\n", ref->target.symbolic);
|
306
|
-
} else {
|
307
|
-
assert(0); /* don't let this happen */
|
308
|
-
}
|
309
|
-
|
310
|
-
if (p_stat(ref_path.ptr, &st) == 0)
|
311
|
-
ref->mtime = st.st_mtime;
|
312
|
-
|
313
|
-
return git_filebuf_commit(&file, GIT_REFS_FILE_MODE);
|
314
|
-
}
|
315
|
-
|
316
|
-
static int packed_parse_peel(
|
317
|
-
struct packref *tag_ref,
|
318
|
-
const char **buffer_out,
|
319
|
-
const char *buffer_end)
|
320
|
-
{
|
321
|
-
const char *buffer = *buffer_out + 1;
|
322
|
-
|
323
|
-
assert(buffer[-1] == '^');
|
324
|
-
|
325
|
-
/* Ensure it's not the first entry of the file */
|
326
|
-
if (tag_ref == NULL)
|
327
|
-
goto corrupt;
|
328
|
-
|
329
|
-
/* Ensure reference is a tag */
|
330
|
-
if (git__prefixcmp(tag_ref->name, GIT_REFS_TAGS_DIR) != 0)
|
331
|
-
goto corrupt;
|
332
|
-
|
333
|
-
if (buffer + GIT_OID_HEXSZ >= buffer_end)
|
334
|
-
goto corrupt;
|
335
|
-
|
336
|
-
/* Is this a valid object id? */
|
337
|
-
if (git_oid_fromstr(&tag_ref->peel, buffer) < 0)
|
338
|
-
goto corrupt;
|
339
|
-
|
340
|
-
buffer = buffer + GIT_OID_HEXSZ;
|
341
|
-
if (*buffer == '\r')
|
342
|
-
buffer++;
|
343
|
-
|
344
|
-
if (*buffer != '\n')
|
345
|
-
goto corrupt;
|
346
|
-
|
347
|
-
*buffer_out = buffer + 1;
|
348
|
-
return 0;
|
349
|
-
|
350
|
-
corrupt:
|
351
|
-
giterr_set(GITERR_REFERENCE, "The packed references file is corrupted");
|
352
|
-
return -1;
|
353
|
-
}
|
354
|
-
|
355
|
-
static int packed_parse_oid(
|
356
|
-
struct packref **ref_out,
|
357
|
-
const char **buffer_out,
|
358
|
-
const char *buffer_end)
|
359
|
-
{
|
360
|
-
struct packref *ref = NULL;
|
361
|
-
|
362
|
-
const char *buffer = *buffer_out;
|
363
|
-
const char *refname_begin, *refname_end;
|
364
|
-
|
365
|
-
size_t refname_len;
|
366
|
-
git_oid id;
|
367
|
-
|
368
|
-
refname_begin = (buffer + GIT_OID_HEXSZ + 1);
|
369
|
-
if (refname_begin >= buffer_end || refname_begin[-1] != ' ')
|
370
|
-
goto corrupt;
|
371
|
-
|
372
|
-
/* Is this a valid object id? */
|
373
|
-
if (git_oid_fromstr(&id, buffer) < 0)
|
374
|
-
goto corrupt;
|
375
|
-
|
376
|
-
refname_end = memchr(refname_begin, '\n', buffer_end - refname_begin);
|
377
|
-
if (refname_end == NULL)
|
378
|
-
goto corrupt;
|
379
|
-
|
380
|
-
if (refname_end[-1] == '\r')
|
381
|
-
refname_end--;
|
382
|
-
|
383
|
-
refname_len = refname_end - refname_begin;
|
384
|
-
|
385
|
-
ref = git__malloc(sizeof(struct packref) + refname_len + 1);
|
386
|
-
GITERR_CHECK_ALLOC(ref);
|
387
|
-
|
388
|
-
memcpy(ref->name, refname_begin, refname_len);
|
389
|
-
ref->name[refname_len] = 0;
|
390
|
-
|
391
|
-
git_oid_cpy(&ref->oid, &id);
|
392
|
-
|
393
|
-
ref->flags = 0;
|
394
|
-
|
395
|
-
*ref_out = ref;
|
396
|
-
*buffer_out = refname_end + 1;
|
397
|
-
|
398
|
-
return 0;
|
399
|
-
|
400
|
-
corrupt:
|
401
|
-
git__free(ref);
|
402
|
-
giterr_set(GITERR_REFERENCE, "The packed references file is corrupted");
|
403
|
-
return -1;
|
404
|
-
}
|
405
|
-
|
406
|
-
static int packed_load(git_repository *repo)
|
407
|
-
{
|
408
|
-
int result, updated;
|
409
|
-
git_buf packfile = GIT_BUF_INIT;
|
410
|
-
const char *buffer_start, *buffer_end;
|
411
|
-
git_refcache *ref_cache = &repo->references;
|
412
|
-
|
413
|
-
/* First we make sure we have allocated the hash table */
|
414
|
-
if (ref_cache->packfile == NULL) {
|
415
|
-
ref_cache->packfile = git_strmap_alloc();
|
416
|
-
GITERR_CHECK_ALLOC(ref_cache->packfile);
|
417
|
-
}
|
418
|
-
|
419
|
-
result = reference_read(&packfile, &ref_cache->packfile_time,
|
420
|
-
repo->path_repository, GIT_PACKEDREFS_FILE, &updated);
|
421
|
-
|
422
|
-
/*
|
423
|
-
* If we couldn't find the file, we need to clear the table and
|
424
|
-
* return. On any other error, we return that error. If everything
|
425
|
-
* went fine and the file wasn't updated, then there's nothing new
|
426
|
-
* for us here, so just return. Anything else means we need to
|
427
|
-
* refresh the packed refs.
|
428
|
-
*/
|
429
|
-
if (result == GIT_ENOTFOUND) {
|
430
|
-
git_strmap_clear(ref_cache->packfile);
|
431
|
-
return 0;
|
432
|
-
}
|
433
|
-
|
434
|
-
if (result < 0)
|
435
|
-
return -1;
|
436
|
-
|
437
|
-
if (!updated)
|
438
|
-
return 0;
|
439
|
-
|
440
|
-
/*
|
441
|
-
* At this point, we want to refresh the packed refs. We already
|
442
|
-
* have the contents in our buffer.
|
443
|
-
*/
|
444
|
-
git_strmap_clear(ref_cache->packfile);
|
445
|
-
|
446
|
-
buffer_start = (const char *)packfile.ptr;
|
447
|
-
buffer_end = (const char *)(buffer_start) + packfile.size;
|
448
|
-
|
449
|
-
while (buffer_start < buffer_end && buffer_start[0] == '#') {
|
450
|
-
buffer_start = strchr(buffer_start, '\n');
|
451
|
-
if (buffer_start == NULL)
|
452
|
-
goto parse_failed;
|
453
|
-
|
454
|
-
buffer_start++;
|
455
|
-
}
|
456
|
-
|
457
|
-
while (buffer_start < buffer_end) {
|
458
|
-
int err;
|
459
|
-
struct packref *ref = NULL;
|
460
|
-
|
461
|
-
if (packed_parse_oid(&ref, &buffer_start, buffer_end) < 0)
|
462
|
-
goto parse_failed;
|
463
|
-
|
464
|
-
if (buffer_start[0] == '^') {
|
465
|
-
if (packed_parse_peel(ref, &buffer_start, buffer_end) < 0)
|
466
|
-
goto parse_failed;
|
467
|
-
}
|
468
|
-
|
469
|
-
git_strmap_insert(ref_cache->packfile, ref->name, ref, err);
|
470
|
-
if (err < 0)
|
471
|
-
goto parse_failed;
|
472
|
-
}
|
473
|
-
|
474
|
-
git_buf_free(&packfile);
|
475
|
-
return 0;
|
476
|
-
|
477
|
-
parse_failed:
|
478
|
-
git_strmap_free(ref_cache->packfile);
|
479
|
-
ref_cache->packfile = NULL;
|
480
|
-
git_buf_free(&packfile);
|
481
|
-
return -1;
|
482
|
-
}
|
483
|
-
|
484
|
-
|
485
|
-
struct dirent_list_data {
|
486
|
-
git_repository *repo;
|
487
|
-
size_t repo_path_len;
|
488
|
-
unsigned int list_flags;
|
489
|
-
|
490
|
-
int (*callback)(const char *, void *);
|
491
|
-
void *callback_payload;
|
492
|
-
int callback_error;
|
493
|
-
};
|
494
|
-
|
495
|
-
static int _dirent_loose_listall(void *_data, git_buf *full_path)
|
34
|
+
static git_reference *alloc_ref(git_refdb *refdb, const char *name)
|
496
35
|
{
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
if (git_path_isdir(full_path->ptr) == true)
|
501
|
-
return git_path_direach(full_path, _dirent_loose_listall, _data);
|
502
|
-
|
503
|
-
/* do not add twice a reference that exists already in the packfile */
|
504
|
-
if ((data->list_flags & GIT_REF_PACKED) != 0 &&
|
505
|
-
git_strmap_exists(data->repo->references.packfile, file_path))
|
506
|
-
return 0;
|
507
|
-
|
508
|
-
if (data->list_flags != GIT_REF_LISTALL) {
|
509
|
-
if ((data->list_flags & loose_guess_rtype(full_path)) == 0)
|
510
|
-
return 0; /* we are filtering out this reference */
|
511
|
-
}
|
36
|
+
git_reference *ref;
|
37
|
+
size_t namelen = strlen(name);
|
512
38
|
|
513
|
-
|
514
|
-
|
515
|
-
return 0;
|
39
|
+
if ((ref = git__calloc(1, sizeof(git_reference) + namelen + 1)) == NULL)
|
40
|
+
return NULL;
|
516
41
|
|
517
|
-
|
518
|
-
|
42
|
+
ref->db = refdb;
|
43
|
+
memcpy(ref->name, name, namelen + 1);
|
519
44
|
|
520
|
-
return
|
45
|
+
return ref;
|
521
46
|
}
|
522
47
|
|
523
|
-
|
48
|
+
git_reference *git_reference__alloc_symbolic(
|
49
|
+
git_refdb *refdb,
|
50
|
+
const char *name,
|
51
|
+
const char *target)
|
524
52
|
{
|
525
|
-
|
526
|
-
void *old_ref = NULL;
|
527
|
-
struct packref *ref;
|
528
|
-
const char *file_path;
|
529
|
-
int err;
|
53
|
+
git_reference *ref;
|
530
54
|
|
531
|
-
|
532
|
-
return git_path_direach(full_path, _dirent_loose_load, repository);
|
55
|
+
assert(refdb && name && target);
|
533
56
|
|
534
|
-
|
57
|
+
ref = alloc_ref(refdb, name);
|
58
|
+
if (!ref)
|
59
|
+
return NULL;
|
535
60
|
|
536
|
-
|
537
|
-
return -1;
|
61
|
+
ref->type = GIT_REF_SYMBOLIC;
|
538
62
|
|
539
|
-
|
540
|
-
repository->references.packfile, ref->name, ref, old_ref, err);
|
541
|
-
if (err < 0) {
|
63
|
+
if ((ref->target.symbolic = git__strdup(target)) == NULL) {
|
542
64
|
git__free(ref);
|
543
|
-
return
|
544
|
-
}
|
545
|
-
|
546
|
-
git__free(old_ref);
|
547
|
-
return 0;
|
548
|
-
}
|
549
|
-
|
550
|
-
/*
|
551
|
-
* Load all the loose references from the repository
|
552
|
-
* into the in-memory Packfile, and build a vector with
|
553
|
-
* all the references so it can be written back to
|
554
|
-
* disk.
|
555
|
-
*/
|
556
|
-
static int packed_loadloose(git_repository *repository)
|
557
|
-
{
|
558
|
-
git_buf refs_path = GIT_BUF_INIT;
|
559
|
-
int result;
|
560
|
-
|
561
|
-
/* the packfile must have been previously loaded! */
|
562
|
-
assert(repository->references.packfile);
|
563
|
-
|
564
|
-
if (git_buf_joinpath(&refs_path, repository->path_repository, GIT_REFS_DIR) < 0)
|
565
|
-
return -1;
|
566
|
-
|
567
|
-
/*
|
568
|
-
* Load all the loose files from disk into the Packfile table.
|
569
|
-
* This will overwrite any old packed entries with their
|
570
|
-
* updated loose versions
|
571
|
-
*/
|
572
|
-
result = git_path_direach(&refs_path, _dirent_loose_load, repository);
|
573
|
-
git_buf_free(&refs_path);
|
574
|
-
|
575
|
-
return result;
|
576
|
-
}
|
577
|
-
|
578
|
-
/*
|
579
|
-
* Write a single reference into a packfile
|
580
|
-
*/
|
581
|
-
static int packed_write_ref(struct packref *ref, git_filebuf *file)
|
582
|
-
{
|
583
|
-
char oid[GIT_OID_HEXSZ + 1];
|
584
|
-
|
585
|
-
git_oid_fmt(oid, &ref->oid);
|
586
|
-
oid[GIT_OID_HEXSZ] = 0;
|
587
|
-
|
588
|
-
/*
|
589
|
-
* For references that peel to an object in the repo, we must
|
590
|
-
* write the resulting peel on a separate line, e.g.
|
591
|
-
*
|
592
|
-
* 6fa8a902cc1d18527e1355773c86721945475d37 refs/tags/libgit2-0.4
|
593
|
-
* ^2ec0cb7959b0bf965d54f95453f5b4b34e8d3100
|
594
|
-
*
|
595
|
-
* This obviously only applies to tags.
|
596
|
-
* The required peels have already been loaded into `ref->peel_target`.
|
597
|
-
*/
|
598
|
-
if (ref->flags & GIT_PACKREF_HAS_PEEL) {
|
599
|
-
char peel[GIT_OID_HEXSZ + 1];
|
600
|
-
git_oid_fmt(peel, &ref->peel);
|
601
|
-
peel[GIT_OID_HEXSZ] = 0;
|
602
|
-
|
603
|
-
if (git_filebuf_printf(file, "%s %s\n^%s\n", oid, ref->name, peel) < 0)
|
604
|
-
return -1;
|
605
|
-
} else {
|
606
|
-
if (git_filebuf_printf(file, "%s %s\n", oid, ref->name) < 0)
|
607
|
-
return -1;
|
608
|
-
}
|
609
|
-
|
610
|
-
return 0;
|
611
|
-
}
|
612
|
-
|
613
|
-
/*
|
614
|
-
* Find out what object this reference resolves to.
|
615
|
-
*
|
616
|
-
* For references that point to a 'big' tag (e.g. an
|
617
|
-
* actual tag object on the repository), we need to
|
618
|
-
* cache on the packfile the OID of the object to
|
619
|
-
* which that 'big tag' is pointing to.
|
620
|
-
*/
|
621
|
-
static int packed_find_peel(git_repository *repo, struct packref *ref)
|
622
|
-
{
|
623
|
-
git_object *object;
|
624
|
-
|
625
|
-
if (ref->flags & GIT_PACKREF_HAS_PEEL)
|
626
|
-
return 0;
|
627
|
-
|
628
|
-
/*
|
629
|
-
* Only applies to tags, i.e. references
|
630
|
-
* in the /refs/tags folder
|
631
|
-
*/
|
632
|
-
if (git__prefixcmp(ref->name, GIT_REFS_TAGS_DIR) != 0)
|
633
|
-
return 0;
|
634
|
-
|
635
|
-
/*
|
636
|
-
* Find the tagged object in the repository
|
637
|
-
*/
|
638
|
-
if (git_object_lookup(&object, repo, &ref->oid, GIT_OBJ_ANY) < 0)
|
639
|
-
return -1;
|
640
|
-
|
641
|
-
/*
|
642
|
-
* If the tagged object is a Tag object, we need to resolve it;
|
643
|
-
* if the ref is actually a 'weak' ref, we don't need to resolve
|
644
|
-
* anything.
|
645
|
-
*/
|
646
|
-
if (git_object_type(object) == GIT_OBJ_TAG) {
|
647
|
-
git_tag *tag = (git_tag *)object;
|
648
|
-
|
649
|
-
/*
|
650
|
-
* Find the object pointed at by this tag
|
651
|
-
*/
|
652
|
-
git_oid_cpy(&ref->peel, git_tag_target_oid(tag));
|
653
|
-
ref->flags |= GIT_PACKREF_HAS_PEEL;
|
654
|
-
|
655
|
-
/*
|
656
|
-
* The reference has now cached the resolved OID, and is
|
657
|
-
* marked at such. When written to the packfile, it'll be
|
658
|
-
* accompanied by this resolved oid
|
659
|
-
*/
|
65
|
+
return NULL;
|
660
66
|
}
|
661
67
|
|
662
|
-
|
663
|
-
return 0;
|
68
|
+
return ref;
|
664
69
|
}
|
665
70
|
|
666
|
-
|
667
|
-
*
|
668
|
-
*
|
669
|
-
*
|
670
|
-
*
|
671
|
-
* removed from disk.
|
672
|
-
*
|
673
|
-
* This is a dangerous method; make sure the packfile
|
674
|
-
* is well-written, because we are destructing references
|
675
|
-
* here otherwise.
|
676
|
-
*/
|
677
|
-
static int packed_remove_loose(git_repository *repo, git_vector *packing_list)
|
71
|
+
git_reference *git_reference__alloc(
|
72
|
+
git_refdb *refdb,
|
73
|
+
const char *name,
|
74
|
+
const git_oid *oid,
|
75
|
+
const git_oid *peel)
|
678
76
|
{
|
679
|
-
|
680
|
-
git_buf full_path = GIT_BUF_INIT;
|
681
|
-
int failed = 0;
|
682
|
-
|
683
|
-
for (i = 0; i < packing_list->length; ++i) {
|
684
|
-
struct packref *ref = git_vector_get(packing_list, i);
|
685
|
-
|
686
|
-
if ((ref->flags & GIT_PACKREF_WAS_LOOSE) == 0)
|
687
|
-
continue;
|
688
|
-
|
689
|
-
if (git_buf_joinpath(&full_path, repo->path_repository, ref->name) < 0)
|
690
|
-
return -1; /* critical; do not try to recover on oom */
|
691
|
-
|
692
|
-
if (git_path_exists(full_path.ptr) == true && p_unlink(full_path.ptr) < 0) {
|
693
|
-
if (failed)
|
694
|
-
continue;
|
695
|
-
|
696
|
-
giterr_set(GITERR_REFERENCE,
|
697
|
-
"Failed to remove loose reference '%s' after packing: %s",
|
698
|
-
full_path.ptr, strerror(errno));
|
77
|
+
git_reference *ref;
|
699
78
|
|
700
|
-
|
701
|
-
}
|
79
|
+
assert(refdb && name && oid);
|
702
80
|
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
* After we've removed as many files as possible, we return
|
707
|
-
* the error code anyway.
|
708
|
-
*/
|
709
|
-
}
|
81
|
+
ref = alloc_ref(refdb, name);
|
82
|
+
if (!ref)
|
83
|
+
return NULL;
|
710
84
|
|
711
|
-
|
712
|
-
|
713
|
-
}
|
85
|
+
ref->type = GIT_REF_OID;
|
86
|
+
git_oid_cpy(&ref->target.oid, oid);
|
714
87
|
|
715
|
-
|
716
|
-
|
717
|
-
const struct packref *ref_a = (const struct packref *)a;
|
718
|
-
const struct packref *ref_b = (const struct packref *)b;
|
88
|
+
if (peel != NULL)
|
89
|
+
git_oid_cpy(&ref->peel, peel);
|
719
90
|
|
720
|
-
return
|
91
|
+
return ref;
|
721
92
|
}
|
722
93
|
|
723
|
-
|
724
|
-
* Write all the contents in the in-memory packfile to disk.
|
725
|
-
*/
|
726
|
-
static int packed_write(git_repository *repo)
|
94
|
+
void git_reference_free(git_reference *reference)
|
727
95
|
{
|
728
|
-
|
729
|
-
|
730
|
-
git_buf pack_file_path = GIT_BUF_INIT;
|
731
|
-
git_vector packing_list;
|
732
|
-
unsigned int total_refs;
|
733
|
-
|
734
|
-
assert(repo && repo->references.packfile);
|
735
|
-
|
736
|
-
total_refs =
|
737
|
-
(unsigned int)git_strmap_num_entries(repo->references.packfile);
|
738
|
-
|
739
|
-
if (git_vector_init(&packing_list, total_refs, packed_sort) < 0)
|
740
|
-
return -1;
|
741
|
-
|
742
|
-
/* Load all the packfile into a vector */
|
743
|
-
{
|
744
|
-
struct packref *reference;
|
745
|
-
|
746
|
-
/* cannot fail: vector already has the right size */
|
747
|
-
git_strmap_foreach_value(repo->references.packfile, reference, {
|
748
|
-
git_vector_insert(&packing_list, reference);
|
749
|
-
});
|
750
|
-
}
|
751
|
-
|
752
|
-
/* sort the vector so the entries appear sorted on the packfile */
|
753
|
-
git_vector_sort(&packing_list);
|
754
|
-
|
755
|
-
/* Now we can open the file! */
|
756
|
-
if (git_buf_joinpath(&pack_file_path, repo->path_repository, GIT_PACKEDREFS_FILE) < 0)
|
757
|
-
goto cleanup_memory;
|
758
|
-
|
759
|
-
if (git_filebuf_open(&pack_file, pack_file_path.ptr, 0) < 0)
|
760
|
-
goto cleanup_packfile;
|
761
|
-
|
762
|
-
/* Packfiles have a header... apparently
|
763
|
-
* This is in fact not required, but we might as well print it
|
764
|
-
* just for kicks */
|
765
|
-
if (git_filebuf_printf(&pack_file, "%s\n", GIT_PACKEDREFS_HEADER) < 0)
|
766
|
-
goto cleanup_packfile;
|
767
|
-
|
768
|
-
for (i = 0; i < packing_list.length; ++i) {
|
769
|
-
struct packref *ref = (struct packref *)git_vector_get(&packing_list, i);
|
770
|
-
|
771
|
-
if (packed_find_peel(repo, ref) < 0)
|
772
|
-
goto cleanup_packfile;
|
773
|
-
|
774
|
-
if (packed_write_ref(ref, &pack_file) < 0)
|
775
|
-
goto cleanup_packfile;
|
776
|
-
}
|
777
|
-
|
778
|
-
/* if we've written all the references properly, we can commit
|
779
|
-
* the packfile to make the changes effective */
|
780
|
-
if (git_filebuf_commit(&pack_file, GIT_PACKEDREFS_FILE_MODE) < 0)
|
781
|
-
goto cleanup_memory;
|
782
|
-
|
783
|
-
/* when and only when the packfile has been properly written,
|
784
|
-
* we can go ahead and remove the loose refs */
|
785
|
-
if (packed_remove_loose(repo, &packing_list) < 0)
|
786
|
-
goto cleanup_memory;
|
787
|
-
|
788
|
-
{
|
789
|
-
struct stat st;
|
790
|
-
if (p_stat(pack_file_path.ptr, &st) == 0)
|
791
|
-
repo->references.packfile_time = st.st_mtime;
|
792
|
-
}
|
793
|
-
|
794
|
-
git_vector_free(&packing_list);
|
795
|
-
git_buf_free(&pack_file_path);
|
796
|
-
|
797
|
-
/* we're good now */
|
798
|
-
return 0;
|
799
|
-
|
800
|
-
cleanup_packfile:
|
801
|
-
git_filebuf_cleanup(&pack_file);
|
96
|
+
if (reference == NULL)
|
97
|
+
return;
|
802
98
|
|
803
|
-
|
804
|
-
|
805
|
-
git_buf_free(&pack_file_path);
|
99
|
+
if (reference->type == GIT_REF_SYMBOLIC)
|
100
|
+
git__free(reference->target.symbolic);
|
806
101
|
|
807
|
-
|
102
|
+
git__free(reference);
|
808
103
|
}
|
809
104
|
|
810
105
|
struct reference_available_t {
|
@@ -861,28 +156,6 @@ static int reference_path_available(
|
|
861
156
|
return 0;
|
862
157
|
}
|
863
158
|
|
864
|
-
static int reference_exists(int *exists, git_repository *repo, const char *ref_name)
|
865
|
-
{
|
866
|
-
git_buf ref_path = GIT_BUF_INIT;
|
867
|
-
|
868
|
-
if (packed_load(repo) < 0)
|
869
|
-
return -1;
|
870
|
-
|
871
|
-
if (git_buf_joinpath(&ref_path, repo->path_repository, ref_name) < 0)
|
872
|
-
return -1;
|
873
|
-
|
874
|
-
if (git_path_isfile(ref_path.ptr) == true ||
|
875
|
-
git_strmap_exists(repo->references.packfile, ref_path.ptr))
|
876
|
-
{
|
877
|
-
*exists = 1;
|
878
|
-
} else {
|
879
|
-
*exists = 0;
|
880
|
-
}
|
881
|
-
|
882
|
-
git_buf_free(&ref_path);
|
883
|
-
return 0;
|
884
|
-
}
|
885
|
-
|
886
159
|
/*
|
887
160
|
* Check if a reference could be written to disk, based on:
|
888
161
|
*
|
@@ -898,6 +171,11 @@ static int reference_can_write(
|
|
898
171
|
const char *previous_name,
|
899
172
|
int force)
|
900
173
|
{
|
174
|
+
git_refdb *refdb;
|
175
|
+
|
176
|
+
if (git_repository_refdb__weakptr(&refdb, repo) < 0)
|
177
|
+
return -1;
|
178
|
+
|
901
179
|
/* see if the reference shares a path with an existing reference;
|
902
180
|
* if a path is shared, we cannot create the reference, even when forcing */
|
903
181
|
if (reference_path_available(repo, refname, previous_name) < 0)
|
@@ -908,166 +186,36 @@ static int reference_can_write(
|
|
908
186
|
if (!force) {
|
909
187
|
int exists;
|
910
188
|
|
911
|
-
if (
|
189
|
+
if (git_refdb_exists(&exists, refdb, refname) < 0)
|
912
190
|
return -1;
|
913
191
|
|
914
192
|
/* We cannot proceed if the reference already exists and we're not forcing
|
915
193
|
* the rename; the existing one would be overwritten */
|
916
194
|
if (exists) {
|
917
195
|
giterr_set(GITERR_REFERENCE,
|
918
|
-
"A reference with that name (%s) already exists", refname);
|
919
|
-
return GIT_EEXISTS;
|
920
|
-
}
|
921
|
-
}
|
922
|
-
|
923
|
-
/* FIXME: if the reference exists and we are forcing, do we really need to
|
924
|
-
* remove the reference first?
|
925
|
-
*
|
926
|
-
* Two cases:
|
927
|
-
*
|
928
|
-
* - the reference already exists and is loose: not a problem, the file
|
929
|
-
* gets overwritten on disk
|
930
|
-
*
|
931
|
-
* - the reference already exists and is packed: we write a new one as
|
932
|
-
* loose, which by all means renders the packed one useless
|
933
|
-
*/
|
934
|
-
|
935
|
-
return 0;
|
936
|
-
}
|
937
|
-
|
938
|
-
|
939
|
-
static int packed_lookup(git_reference *ref)
|
940
|
-
{
|
941
|
-
struct packref *pack_ref = NULL;
|
942
|
-
git_strmap *packfile_refs;
|
943
|
-
khiter_t pos;
|
944
|
-
|
945
|
-
if (packed_load(ref->owner) < 0)
|
946
|
-
return -1;
|
947
|
-
|
948
|
-
/* maybe the packfile hasn't changed at all, so we don't
|
949
|
-
* have to re-lookup the reference */
|
950
|
-
if ((ref->flags & GIT_REF_PACKED) &&
|
951
|
-
ref->mtime == ref->owner->references.packfile_time)
|
952
|
-
return 0;
|
953
|
-
|
954
|
-
if (ref->flags & GIT_REF_SYMBOLIC) {
|
955
|
-
git__free(ref->target.symbolic);
|
956
|
-
ref->target.symbolic = NULL;
|
957
|
-
}
|
958
|
-
|
959
|
-
/* Look up on the packfile */
|
960
|
-
packfile_refs = ref->owner->references.packfile;
|
961
|
-
pos = git_strmap_lookup_index(packfile_refs, ref->name);
|
962
|
-
if (!git_strmap_valid_index(packfile_refs, pos)) {
|
963
|
-
giterr_set(GITERR_REFERENCE, "Reference '%s' not found", ref->name);
|
964
|
-
return GIT_ENOTFOUND;
|
965
|
-
}
|
966
|
-
|
967
|
-
pack_ref = git_strmap_value_at(packfile_refs, pos);
|
968
|
-
|
969
|
-
ref->flags = GIT_REF_OID | GIT_REF_PACKED;
|
970
|
-
ref->mtime = ref->owner->references.packfile_time;
|
971
|
-
git_oid_cpy(&ref->target.oid, &pack_ref->oid);
|
972
|
-
|
973
|
-
return 0;
|
974
|
-
}
|
975
|
-
|
976
|
-
static int reference_lookup(git_reference *ref)
|
977
|
-
{
|
978
|
-
int result;
|
979
|
-
|
980
|
-
result = loose_lookup(ref);
|
981
|
-
if (result == 0)
|
982
|
-
return 0;
|
983
|
-
|
984
|
-
/* only try to lookup this reference on the packfile if it
|
985
|
-
* wasn't found on the loose refs; not if there was a critical error */
|
986
|
-
if (result == GIT_ENOTFOUND) {
|
987
|
-
giterr_clear();
|
988
|
-
result = packed_lookup(ref);
|
989
|
-
if (result == 0)
|
990
|
-
return 0;
|
991
|
-
}
|
992
|
-
|
993
|
-
/* unexpected error; free the reference */
|
994
|
-
git_reference_free(ref);
|
995
|
-
return result;
|
996
|
-
}
|
997
|
-
|
998
|
-
/*
|
999
|
-
* Delete a reference.
|
1000
|
-
* This is an internal method; the reference is removed
|
1001
|
-
* from disk or the packfile, but the pointer is not freed
|
1002
|
-
*/
|
1003
|
-
static int reference_delete(git_reference *ref)
|
1004
|
-
{
|
1005
|
-
int result;
|
1006
|
-
|
1007
|
-
assert(ref);
|
1008
|
-
|
1009
|
-
/* If the reference is packed, this is an expensive operation.
|
1010
|
-
* We need to reload the packfile, remove the reference from the
|
1011
|
-
* packing list, and repack */
|
1012
|
-
if (ref->flags & GIT_REF_PACKED) {
|
1013
|
-
git_strmap *packfile_refs;
|
1014
|
-
struct packref *packref;
|
1015
|
-
khiter_t pos;
|
1016
|
-
|
1017
|
-
/* load the existing packfile */
|
1018
|
-
if (packed_load(ref->owner) < 0)
|
1019
|
-
return -1;
|
1020
|
-
|
1021
|
-
packfile_refs = ref->owner->references.packfile;
|
1022
|
-
pos = git_strmap_lookup_index(packfile_refs, ref->name);
|
1023
|
-
if (!git_strmap_valid_index(packfile_refs, pos)) {
|
1024
|
-
giterr_set(GITERR_REFERENCE,
|
1025
|
-
"Reference %s stopped existing in the packfile", ref->name);
|
1026
|
-
return -1;
|
1027
|
-
}
|
1028
|
-
|
1029
|
-
packref = git_strmap_value_at(packfile_refs, pos);
|
1030
|
-
git_strmap_delete_at(packfile_refs, pos);
|
1031
|
-
|
1032
|
-
git__free(packref);
|
1033
|
-
if (packed_write(ref->owner) < 0)
|
1034
|
-
return -1;
|
1035
|
-
|
1036
|
-
/* If the reference is loose, we can just remove the reference
|
1037
|
-
* from the filesystem */
|
1038
|
-
} else {
|
1039
|
-
git_reference *ref_in_pack;
|
1040
|
-
git_buf full_path = GIT_BUF_INIT;
|
1041
|
-
|
1042
|
-
if (git_buf_joinpath(&full_path, ref->owner->path_repository, ref->name) < 0)
|
1043
|
-
return -1;
|
1044
|
-
|
1045
|
-
result = p_unlink(full_path.ptr);
|
1046
|
-
git_buf_free(&full_path); /* done with path at this point */
|
1047
|
-
|
1048
|
-
if (result < 0) {
|
1049
|
-
giterr_set(GITERR_OS, "Failed to unlink '%s'", full_path.ptr);
|
1050
|
-
return -1;
|
1051
|
-
}
|
1052
|
-
|
1053
|
-
/* When deleting a loose reference, we have to ensure that an older
|
1054
|
-
* packed version of it doesn't exist */
|
1055
|
-
if (git_reference_lookup(&ref_in_pack, ref->owner, ref->name) == 0) {
|
1056
|
-
assert((ref_in_pack->flags & GIT_REF_PACKED) != 0);
|
1057
|
-
return git_reference_delete(ref_in_pack);
|
196
|
+
"A reference with that name (%s) already exists", refname);
|
197
|
+
return GIT_EEXISTS;
|
1058
198
|
}
|
1059
|
-
|
1060
|
-
giterr_clear();
|
1061
199
|
}
|
1062
200
|
|
201
|
+
/* FIXME: if the reference exists and we are forcing, do we really need to
|
202
|
+
* remove the reference first?
|
203
|
+
*
|
204
|
+
* Two cases:
|
205
|
+
*
|
206
|
+
* - the reference already exists and is loose: not a problem, the file
|
207
|
+
* gets overwritten on disk
|
208
|
+
*
|
209
|
+
* - the reference already exists and is packed: we write a new one as
|
210
|
+
* loose, which by all means renders the packed one useless
|
211
|
+
*/
|
212
|
+
|
1063
213
|
return 0;
|
1064
214
|
}
|
1065
215
|
|
1066
216
|
int git_reference_delete(git_reference *ref)
|
1067
217
|
{
|
1068
|
-
|
1069
|
-
git_reference_free(ref);
|
1070
|
-
return result;
|
218
|
+
return git_refdb_delete(ref->db, ref);
|
1071
219
|
}
|
1072
220
|
|
1073
221
|
int git_reference_lookup(git_reference **ref_out,
|
@@ -1076,7 +224,7 @@ int git_reference_lookup(git_reference **ref_out,
|
|
1076
224
|
return git_reference_lookup_resolved(ref_out, repo, name, 0);
|
1077
225
|
}
|
1078
226
|
|
1079
|
-
int
|
227
|
+
int git_reference_name_to_id(
|
1080
228
|
git_oid *out, git_repository *repo, const char *name)
|
1081
229
|
{
|
1082
230
|
int error;
|
@@ -1085,7 +233,7 @@ int git_reference_name_to_oid(
|
|
1085
233
|
if ((error = git_reference_lookup_resolved(&ref, repo, name, -1)) < 0)
|
1086
234
|
return error;
|
1087
235
|
|
1088
|
-
git_oid_cpy(out,
|
236
|
+
git_oid_cpy(out, git_reference_target(ref));
|
1089
237
|
git_reference_free(ref);
|
1090
238
|
return 0;
|
1091
239
|
}
|
@@ -1096,8 +244,11 @@ int git_reference_lookup_resolved(
|
|
1096
244
|
const char *name,
|
1097
245
|
int max_nesting)
|
1098
246
|
{
|
1099
|
-
|
1100
|
-
|
247
|
+
char scan_name[GIT_REFNAME_MAX];
|
248
|
+
git_ref_t scan_type;
|
249
|
+
int error = 0, nesting;
|
250
|
+
git_reference *ref = NULL;
|
251
|
+
git_refdb *refdb;
|
1101
252
|
|
1102
253
|
assert(ref_out && repo && name);
|
1103
254
|
|
@@ -1107,419 +258,316 @@ int git_reference_lookup_resolved(
|
|
1107
258
|
max_nesting = MAX_NESTING_LEVEL;
|
1108
259
|
else if (max_nesting < 0)
|
1109
260
|
max_nesting = DEFAULT_NESTING_LEVEL;
|
261
|
+
|
262
|
+
strncpy(scan_name, name, GIT_REFNAME_MAX);
|
263
|
+
scan_type = GIT_REF_SYMBOLIC;
|
264
|
+
|
265
|
+
if ((error = git_repository_refdb__weakptr(&refdb, repo)) < 0)
|
266
|
+
return -1;
|
1110
267
|
|
1111
|
-
|
1112
|
-
|
1113
|
-
|
1114
|
-
scan->name = git__calloc(GIT_REFNAME_MAX + 1, sizeof(char));
|
1115
|
-
GITERR_CHECK_ALLOC(scan->name);
|
1116
|
-
|
1117
|
-
if ((result = git_reference__normalize_name_lax(
|
1118
|
-
scan->name,
|
1119
|
-
GIT_REFNAME_MAX,
|
1120
|
-
name)) < 0) {
|
1121
|
-
git_reference_free(scan);
|
1122
|
-
return result;
|
1123
|
-
}
|
1124
|
-
|
1125
|
-
scan->target.symbolic = git__strdup(scan->name);
|
1126
|
-
GITERR_CHECK_ALLOC(scan->target.symbolic);
|
1127
|
-
|
1128
|
-
scan->owner = repo;
|
1129
|
-
scan->flags = GIT_REF_SYMBOLIC;
|
268
|
+
if ((error = git_reference__normalize_name_lax(scan_name, GIT_REFNAME_MAX, name)) < 0)
|
269
|
+
return error;
|
1130
270
|
|
1131
271
|
for (nesting = max_nesting;
|
1132
|
-
nesting >= 0 &&
|
272
|
+
nesting >= 0 && scan_type == GIT_REF_SYMBOLIC;
|
1133
273
|
nesting--)
|
1134
274
|
{
|
1135
|
-
if (nesting != max_nesting)
|
1136
|
-
strncpy(
|
1137
|
-
|
1138
|
-
|
275
|
+
if (nesting != max_nesting) {
|
276
|
+
strncpy(scan_name, ref->target.symbolic, GIT_REFNAME_MAX);
|
277
|
+
git_reference_free(ref);
|
278
|
+
}
|
1139
279
|
|
1140
|
-
if ((
|
1141
|
-
return
|
280
|
+
if ((error = git_refdb_lookup(&ref, refdb, scan_name)) < 0)
|
281
|
+
return error;
|
282
|
+
|
283
|
+
scan_type = ref->type;
|
1142
284
|
}
|
1143
285
|
|
1144
|
-
if (
|
286
|
+
if (scan_type != GIT_REF_OID && max_nesting != 0) {
|
1145
287
|
giterr_set(GITERR_REFERENCE,
|
1146
288
|
"Cannot resolve reference (>%u levels deep)", max_nesting);
|
1147
|
-
git_reference_free(
|
289
|
+
git_reference_free(ref);
|
1148
290
|
return -1;
|
1149
291
|
}
|
1150
292
|
|
1151
|
-
*ref_out =
|
293
|
+
*ref_out = ref;
|
1152
294
|
return 0;
|
1153
295
|
}
|
1154
296
|
|
1155
297
|
/**
|
1156
298
|
* Getters
|
1157
299
|
*/
|
1158
|
-
git_ref_t git_reference_type(git_reference *ref)
|
300
|
+
git_ref_t git_reference_type(const git_reference *ref)
|
1159
301
|
{
|
1160
302
|
assert(ref);
|
1161
|
-
|
1162
|
-
if (ref->flags & GIT_REF_OID)
|
1163
|
-
return GIT_REF_OID;
|
1164
|
-
|
1165
|
-
if (ref->flags & GIT_REF_SYMBOLIC)
|
1166
|
-
return GIT_REF_SYMBOLIC;
|
1167
|
-
|
1168
|
-
return GIT_REF_INVALID;
|
303
|
+
return ref->type;
|
1169
304
|
}
|
1170
305
|
|
1171
|
-
|
306
|
+
const char *git_reference_name(const git_reference *ref)
|
1172
307
|
{
|
1173
308
|
assert(ref);
|
1174
|
-
return
|
309
|
+
return ref->name;
|
1175
310
|
}
|
1176
311
|
|
1177
|
-
|
312
|
+
git_repository *git_reference_owner(const git_reference *ref)
|
1178
313
|
{
|
1179
314
|
assert(ref);
|
1180
|
-
return ref->
|
315
|
+
return ref->db->repo;
|
1181
316
|
}
|
1182
317
|
|
1183
|
-
|
318
|
+
const git_oid *git_reference_target(const git_reference *ref)
|
1184
319
|
{
|
1185
320
|
assert(ref);
|
1186
|
-
|
321
|
+
|
322
|
+
if (ref->type != GIT_REF_OID)
|
323
|
+
return NULL;
|
324
|
+
|
325
|
+
return &ref->target.oid;
|
1187
326
|
}
|
1188
327
|
|
1189
|
-
const git_oid *
|
328
|
+
const git_oid *git_reference_target_peel(const git_reference *ref)
|
1190
329
|
{
|
1191
330
|
assert(ref);
|
1192
331
|
|
1193
|
-
if (
|
332
|
+
if (ref->type != GIT_REF_OID || git_oid_iszero(&ref->peel))
|
1194
333
|
return NULL;
|
1195
334
|
|
1196
|
-
return &ref->
|
335
|
+
return &ref->peel;
|
1197
336
|
}
|
1198
337
|
|
1199
|
-
const char *
|
338
|
+
const char *git_reference_symbolic_target(const git_reference *ref)
|
1200
339
|
{
|
1201
340
|
assert(ref);
|
1202
341
|
|
1203
|
-
if (
|
342
|
+
if (ref->type != GIT_REF_SYMBOLIC)
|
1204
343
|
return NULL;
|
1205
344
|
|
1206
345
|
return ref->target.symbolic;
|
1207
346
|
}
|
1208
347
|
|
1209
|
-
int
|
348
|
+
static int reference__create(
|
1210
349
|
git_reference **ref_out,
|
1211
350
|
git_repository *repo,
|
1212
351
|
const char *name,
|
1213
|
-
const
|
352
|
+
const git_oid *oid,
|
353
|
+
const char *symbolic,
|
1214
354
|
int force)
|
1215
355
|
{
|
1216
356
|
char normalized[GIT_REFNAME_MAX];
|
357
|
+
git_refdb *refdb;
|
1217
358
|
git_reference *ref = NULL;
|
1218
|
-
int error;
|
1219
|
-
|
1220
|
-
if (
|
1221
|
-
|
1222
|
-
sizeof(normalized),
|
1223
|
-
name) < 0)
|
1224
|
-
return -1;
|
359
|
+
int error = 0;
|
360
|
+
|
361
|
+
if (ref_out)
|
362
|
+
*ref_out = NULL;
|
1225
363
|
|
1226
|
-
if ((error =
|
364
|
+
if ((error = git_reference__normalize_name_lax(normalized, sizeof(normalized), name)) < 0 ||
|
365
|
+
(error = reference_can_write(repo, normalized, NULL, force)) < 0 ||
|
366
|
+
(error = git_repository_refdb__weakptr(&refdb, repo)) < 0)
|
1227
367
|
return error;
|
1228
368
|
|
1229
|
-
if (
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
369
|
+
if (oid != NULL) {
|
370
|
+
assert(symbolic == NULL);
|
371
|
+
ref = git_reference__alloc(refdb, name, oid, NULL);
|
372
|
+
} else {
|
373
|
+
ref = git_reference__alloc_symbolic(refdb, name, symbolic);
|
374
|
+
}
|
375
|
+
|
376
|
+
GITERR_CHECK_ALLOC(ref);
|
1233
377
|
|
1234
|
-
|
1235
|
-
* and write the reference on disk */
|
1236
|
-
if (git_reference_set_target(ref, target) < 0) {
|
378
|
+
if ((error = git_refdb_write(refdb, ref)) < 0) {
|
1237
379
|
git_reference_free(ref);
|
1238
|
-
return
|
380
|
+
return error;
|
1239
381
|
}
|
1240
|
-
|
382
|
+
|
383
|
+
if (ref_out == NULL)
|
1241
384
|
git_reference_free(ref);
|
1242
|
-
|
385
|
+
else
|
1243
386
|
*ref_out = ref;
|
1244
|
-
}
|
1245
387
|
|
1246
388
|
return 0;
|
1247
389
|
}
|
1248
390
|
|
1249
|
-
int
|
391
|
+
int git_reference_create(
|
1250
392
|
git_reference **ref_out,
|
1251
393
|
git_repository *repo,
|
1252
394
|
const char *name,
|
1253
|
-
const git_oid *
|
395
|
+
const git_oid *oid,
|
1254
396
|
int force)
|
1255
397
|
{
|
1256
|
-
|
1257
|
-
|
1258
|
-
char normalized[GIT_REFNAME_MAX];
|
1259
|
-
|
1260
|
-
if (git_reference__normalize_name_lax(
|
1261
|
-
normalized,
|
1262
|
-
sizeof(normalized),
|
1263
|
-
name) < 0)
|
1264
|
-
return -1;
|
398
|
+
git_odb *odb;
|
399
|
+
int error = 0;
|
1265
400
|
|
1266
|
-
|
401
|
+
assert(repo && name && oid);
|
402
|
+
|
403
|
+
/* Sanity check the reference being created - target must exist. */
|
404
|
+
if ((error = git_repository_odb__weakptr(&odb, repo)) < 0)
|
1267
405
|
return error;
|
1268
|
-
|
1269
|
-
if (
|
1270
|
-
|
1271
|
-
|
1272
|
-
ref->flags |= GIT_REF_OID;
|
1273
|
-
|
1274
|
-
/* set the oid; this will write the reference on disk */
|
1275
|
-
if (git_reference_set_oid(ref, id) < 0) {
|
1276
|
-
git_reference_free(ref);
|
406
|
+
|
407
|
+
if (!git_odb_exists(odb, oid)) {
|
408
|
+
giterr_set(GITERR_REFERENCE,
|
409
|
+
"Target OID for the reference doesn't exist on the repository");
|
1277
410
|
return -1;
|
1278
411
|
}
|
1279
|
-
|
1280
|
-
|
1281
|
-
git_reference_free(ref);
|
1282
|
-
} else {
|
1283
|
-
*ref_out = ref;
|
1284
|
-
}
|
1285
|
-
|
1286
|
-
return 0;
|
412
|
+
|
413
|
+
return reference__create(ref_out, repo, name, oid, NULL, force);
|
1287
414
|
}
|
1288
|
-
/*
|
1289
|
-
* Change the OID target of a reference.
|
1290
|
-
*
|
1291
|
-
* For both loose and packed references, just change
|
1292
|
-
* the oid in memory and (over)write the file in disk.
|
1293
|
-
*
|
1294
|
-
* We do not repack packed references because of performance
|
1295
|
-
* reasons.
|
1296
|
-
*/
|
1297
|
-
int git_reference_set_oid(git_reference *ref, const git_oid *id)
|
1298
|
-
{
|
1299
|
-
git_odb *odb = NULL;
|
1300
415
|
|
1301
|
-
|
1302
|
-
|
1303
|
-
|
1304
|
-
|
416
|
+
int git_reference_symbolic_create(
|
417
|
+
git_reference **ref_out,
|
418
|
+
git_repository *repo,
|
419
|
+
const char *name,
|
420
|
+
const char *target,
|
421
|
+
int force)
|
422
|
+
{
|
423
|
+
char normalized[GIT_REFNAME_MAX];
|
424
|
+
int error = 0;
|
1305
425
|
|
1306
|
-
assert(
|
426
|
+
assert(repo && name && target);
|
427
|
+
|
428
|
+
if ((error = git_reference__normalize_name_lax(
|
429
|
+
normalized, sizeof(normalized), target)) < 0)
|
430
|
+
return error;
|
1307
431
|
|
1308
|
-
|
1309
|
-
|
432
|
+
return reference__create(ref_out, repo, name, NULL, normalized, force);
|
433
|
+
}
|
1310
434
|
|
1311
|
-
|
1312
|
-
|
1313
|
-
|
1314
|
-
|
1315
|
-
|
435
|
+
int git_reference_set_target(
|
436
|
+
git_reference **out,
|
437
|
+
git_reference *ref,
|
438
|
+
const git_oid *id)
|
439
|
+
{
|
440
|
+
assert(out && ref && id);
|
441
|
+
|
442
|
+
if (ref->type != GIT_REF_OID) {
|
443
|
+
giterr_set(GITERR_REFERENCE, "Cannot set OID on symbolic reference");
|
1316
444
|
return -1;
|
1317
445
|
}
|
1318
446
|
|
1319
|
-
|
1320
|
-
git_oid_cpy(&ref->target.oid, id);
|
1321
|
-
|
1322
|
-
/* Write back to disk */
|
1323
|
-
return loose_write(ref);
|
447
|
+
return git_reference_create(out, ref->db->repo, ref->name, id, 1);
|
1324
448
|
}
|
1325
449
|
|
1326
|
-
|
1327
|
-
|
1328
|
-
*
|
1329
|
-
*
|
1330
|
-
* a pack. We just change the target in memory
|
1331
|
-
* and overwrite the file on disk.
|
1332
|
-
*/
|
1333
|
-
int git_reference_set_target(git_reference *ref, const char *target)
|
450
|
+
int git_reference_symbolic_set_target(
|
451
|
+
git_reference **out,
|
452
|
+
git_reference *ref,
|
453
|
+
const char *target)
|
1334
454
|
{
|
1335
|
-
|
1336
|
-
|
1337
|
-
if (
|
455
|
+
assert(out && ref && target);
|
456
|
+
|
457
|
+
if (ref->type != GIT_REF_SYMBOLIC) {
|
1338
458
|
giterr_set(GITERR_REFERENCE,
|
1339
459
|
"Cannot set symbolic target on a direct reference");
|
1340
460
|
return -1;
|
1341
461
|
}
|
1342
|
-
|
1343
|
-
|
1344
|
-
normalized,
|
1345
|
-
sizeof(normalized),
|
1346
|
-
target))
|
1347
|
-
return -1;
|
1348
|
-
|
1349
|
-
git__free(ref->target.symbolic);
|
1350
|
-
ref->target.symbolic = git__strdup(normalized);
|
1351
|
-
GITERR_CHECK_ALLOC(ref->target.symbolic);
|
1352
|
-
|
1353
|
-
return loose_write(ref);
|
462
|
+
|
463
|
+
return git_reference_symbolic_create(out, ref->db->repo, ref->name, target, 1);
|
1354
464
|
}
|
1355
465
|
|
1356
|
-
int git_reference_rename(
|
466
|
+
int git_reference_rename(
|
467
|
+
git_reference **out,
|
468
|
+
git_reference *ref,
|
469
|
+
const char *new_name,
|
470
|
+
int force)
|
1357
471
|
{
|
1358
|
-
int result;
|
1359
472
|
unsigned int normalization_flags;
|
1360
|
-
git_buf aux_path = GIT_BUF_INIT;
|
1361
473
|
char normalized[GIT_REFNAME_MAX];
|
1362
474
|
bool should_head_be_updated = false;
|
475
|
+
git_reference *result = NULL;
|
476
|
+
int error = 0;
|
477
|
+
int reference_has_log;
|
478
|
+
|
479
|
+
*out = NULL;
|
1363
480
|
|
1364
|
-
normalization_flags = ref->
|
1365
|
-
GIT_REF_FORMAT_ALLOW_ONELEVEL
|
1366
|
-
: GIT_REF_FORMAT_NORMAL;
|
1367
|
-
|
1368
|
-
if (git_reference_normalize_name(
|
1369
|
-
normalized,
|
1370
|
-
sizeof(normalized),
|
1371
|
-
new_name,
|
1372
|
-
normalization_flags) < 0)
|
1373
|
-
return -1;
|
1374
|
-
|
1375
|
-
if ((result = reference_can_write(ref->owner, normalized, ref->name, force)) < 0)
|
1376
|
-
return result;
|
1377
|
-
|
1378
|
-
/* Initialize path now so we won't get an allocation failure once
|
1379
|
-
* we actually start removing things. */
|
1380
|
-
if (git_buf_joinpath(&aux_path, ref->owner->path_repository, new_name) < 0)
|
1381
|
-
return -1;
|
1382
|
-
|
1383
|
-
/*
|
1384
|
-
* Check if we have to update HEAD.
|
1385
|
-
*/
|
1386
|
-
if ((should_head_be_updated = git_branch_is_head(ref)) < 0)
|
1387
|
-
goto cleanup;
|
481
|
+
normalization_flags = ref->type == GIT_REF_SYMBOLIC ?
|
482
|
+
GIT_REF_FORMAT_ALLOW_ONELEVEL : GIT_REF_FORMAT_NORMAL;
|
1388
483
|
|
1389
|
-
|
1390
|
-
|
1391
|
-
|
1392
|
-
|
1393
|
-
* we can still access the ref's attributes for creating the new one
|
1394
|
-
*/
|
1395
|
-
if (reference_delete(ref) < 0)
|
1396
|
-
goto cleanup;
|
484
|
+
if ((error = git_reference_normalize_name(
|
485
|
+
normalized, sizeof(normalized), new_name, normalization_flags)) < 0 ||
|
486
|
+
(error = reference_can_write(ref->db->repo, normalized, ref->name, force)) < 0)
|
487
|
+
return error;
|
1397
488
|
|
1398
489
|
/*
|
1399
|
-
*
|
490
|
+
* Create the new reference.
|
1400
491
|
*/
|
1401
|
-
if (ref->
|
1402
|
-
result =
|
1403
|
-
|
492
|
+
if (ref->type == GIT_REF_OID) {
|
493
|
+
result = git_reference__alloc(ref->db, new_name,
|
494
|
+
&ref->target.oid, &ref->peel);
|
495
|
+
} else if (ref->type == GIT_REF_SYMBOLIC) {
|
496
|
+
result = git_reference__alloc_symbolic(ref->db, new_name, ref->target.symbolic);
|
1404
497
|
} else {
|
1405
|
-
|
1406
|
-
NULL, ref->owner, new_name, &ref->target.oid, force);
|
498
|
+
assert(0);
|
1407
499
|
}
|
1408
500
|
|
1409
|
-
if (result
|
1410
|
-
|
501
|
+
if (result == NULL)
|
502
|
+
return -1;
|
1411
503
|
|
1412
|
-
/*
|
1413
|
-
|
1414
|
-
|
1415
|
-
if (should_head_be_updated &&
|
1416
|
-
git_repository_set_head(ref->owner, new_name) < 0) {
|
1417
|
-
giterr_set(GITERR_REFERENCE,
|
1418
|
-
"Failed to update HEAD after renaming reference");
|
1419
|
-
goto cleanup;
|
1420
|
-
}
|
504
|
+
/* Check if we have to update HEAD. */
|
505
|
+
if ((error = git_branch_is_head(ref)) < 0)
|
506
|
+
goto on_error;
|
1421
507
|
|
1422
|
-
|
1423
|
-
* Rename the reflog file, if it exists.
|
1424
|
-
*/
|
1425
|
-
if ((git_reference_has_log(ref)) && (git_reflog_rename(ref, new_name) < 0))
|
1426
|
-
goto cleanup;
|
508
|
+
should_head_be_updated = (error > 0);
|
1427
509
|
|
1428
|
-
/*
|
1429
|
-
|
1430
|
-
|
1431
|
-
|
1432
|
-
|
510
|
+
/* Now delete the old ref and save the new one. */
|
511
|
+
if ((error = git_refdb_delete(ref->db, ref)) < 0)
|
512
|
+
goto on_error;
|
513
|
+
|
514
|
+
/* Save the new reference. */
|
515
|
+
if ((error = git_refdb_write(ref->db, result)) < 0)
|
516
|
+
goto rollback;
|
517
|
+
|
518
|
+
/* Update HEAD it was poiting to the reference being renamed. */
|
519
|
+
if (should_head_be_updated && (error = git_repository_set_head(ref->db->repo, new_name)) < 0) {
|
520
|
+
giterr_set(GITERR_REFERENCE, "Failed to update HEAD after renaming reference");
|
521
|
+
goto on_error;
|
522
|
+
}
|
1433
523
|
|
1434
|
-
/*
|
1435
|
-
|
524
|
+
/* Rename the reflog file, if it exists. */
|
525
|
+
reference_has_log = git_reference_has_log(ref);
|
526
|
+
if (reference_has_log < 0) {
|
527
|
+
error = reference_has_log;
|
528
|
+
goto on_error;
|
529
|
+
}
|
530
|
+
if (reference_has_log && (error = git_reflog_rename(ref, new_name)) < 0)
|
531
|
+
goto on_error;
|
1436
532
|
|
1437
|
-
|
1438
|
-
return 0;
|
533
|
+
*out = result;
|
1439
534
|
|
1440
|
-
|
1441
|
-
git_buf_free(&aux_path);
|
1442
|
-
return -1;
|
535
|
+
return error;
|
1443
536
|
|
1444
537
|
rollback:
|
1445
|
-
|
1446
|
-
* Try to create the old reference again, ignore failures
|
1447
|
-
*/
|
1448
|
-
if (ref->flags & GIT_REF_SYMBOLIC)
|
1449
|
-
git_reference_create_symbolic(
|
1450
|
-
NULL, ref->owner, ref->name, ref->target.symbolic, 0);
|
1451
|
-
else
|
1452
|
-
git_reference_create_oid(
|
1453
|
-
NULL, ref->owner, ref->name, &ref->target.oid, 0);
|
538
|
+
git_refdb_write(ref->db, ref);
|
1454
539
|
|
1455
|
-
|
1456
|
-
|
540
|
+
on_error:
|
541
|
+
git_reference_free(result);
|
1457
542
|
|
1458
|
-
|
1459
|
-
return -1;
|
543
|
+
return error;
|
1460
544
|
}
|
1461
545
|
|
1462
|
-
int git_reference_resolve(git_reference **ref_out, git_reference *ref)
|
546
|
+
int git_reference_resolve(git_reference **ref_out, const git_reference *ref)
|
1463
547
|
{
|
1464
|
-
|
1465
|
-
|
1466
|
-
|
1467
|
-
|
1468
|
-
|
548
|
+
switch (git_reference_type(ref)) {
|
549
|
+
case GIT_REF_OID:
|
550
|
+
return git_reference_lookup(ref_out, ref->db->repo, ref->name);
|
551
|
+
|
552
|
+
case GIT_REF_SYMBOLIC:
|
553
|
+
return git_reference_lookup_resolved(ref_out, ref->db->repo, ref->target.symbolic, -1);
|
1469
554
|
|
1470
|
-
|
1471
|
-
|
1472
|
-
if (packed_load(repo) < 0 || /* load the existing packfile */
|
1473
|
-
packed_loadloose(repo) < 0 || /* add all the loose refs */
|
1474
|
-
packed_write(repo) < 0) /* write back to disk */
|
555
|
+
default:
|
556
|
+
giterr_set(GITERR_REFERENCE, "Invalid reference");
|
1475
557
|
return -1;
|
1476
|
-
|
1477
|
-
return 0;
|
558
|
+
}
|
1478
559
|
}
|
1479
560
|
|
1480
561
|
int git_reference_foreach(
|
1481
562
|
git_repository *repo,
|
1482
563
|
unsigned int list_flags,
|
1483
|
-
|
564
|
+
git_reference_foreach_cb callback,
|
1484
565
|
void *payload)
|
1485
566
|
{
|
1486
|
-
|
1487
|
-
|
1488
|
-
git_buf refs_path = GIT_BUF_INIT;
|
1489
|
-
|
1490
|
-
/* list all the packed references first */
|
1491
|
-
if (list_flags & GIT_REF_PACKED) {
|
1492
|
-
const char *ref_name;
|
1493
|
-
void *ref;
|
1494
|
-
GIT_UNUSED(ref);
|
1495
|
-
|
1496
|
-
if (packed_load(repo) < 0)
|
1497
|
-
return -1;
|
1498
|
-
|
1499
|
-
git_strmap_foreach(repo->references.packfile, ref_name, ref, {
|
1500
|
-
if (callback(ref_name, payload))
|
1501
|
-
return GIT_EUSER;
|
1502
|
-
});
|
1503
|
-
}
|
1504
|
-
|
1505
|
-
/* now list the loose references, trying not to
|
1506
|
-
* duplicate the ref names already in the packed-refs file */
|
1507
|
-
|
1508
|
-
data.repo_path_len = strlen(repo->path_repository);
|
1509
|
-
data.list_flags = list_flags;
|
1510
|
-
data.repo = repo;
|
1511
|
-
data.callback = callback;
|
1512
|
-
data.callback_payload = payload;
|
1513
|
-
data.callback_error = 0;
|
1514
|
-
|
1515
|
-
if (git_buf_joinpath(&refs_path, repo->path_repository, GIT_REFS_DIR) < 0)
|
1516
|
-
return -1;
|
567
|
+
git_refdb *refdb;
|
568
|
+
git_repository_refdb__weakptr(&refdb, repo);
|
1517
569
|
|
1518
|
-
|
1519
|
-
|
1520
|
-
git_buf_free(&refs_path);
|
1521
|
-
|
1522
|
-
return data.callback_error ? GIT_EUSER : result;
|
570
|
+
return git_refdb_foreach(refdb, list_flags, callback, payload);
|
1523
571
|
}
|
1524
572
|
|
1525
573
|
static int cb__reflist_add(const char *ref, void *data)
|
@@ -1553,26 +601,6 @@ int git_reference_list(
|
|
1553
601
|
return 0;
|
1554
602
|
}
|
1555
603
|
|
1556
|
-
int git_reference_reload(git_reference *ref)
|
1557
|
-
{
|
1558
|
-
return reference_lookup(ref);
|
1559
|
-
}
|
1560
|
-
|
1561
|
-
void git_repository__refcache_free(git_refcache *refs)
|
1562
|
-
{
|
1563
|
-
assert(refs);
|
1564
|
-
|
1565
|
-
if (refs->packfile) {
|
1566
|
-
struct packref *reference;
|
1567
|
-
|
1568
|
-
git_strmap_foreach_value(refs->packfile, reference, {
|
1569
|
-
git__free(reference);
|
1570
|
-
});
|
1571
|
-
|
1572
|
-
git_strmap_free(refs->packfile);
|
1573
|
-
}
|
1574
|
-
}
|
1575
|
-
|
1576
604
|
static int is_valid_ref_char(char ch)
|
1577
605
|
{
|
1578
606
|
if ((unsigned) ch <= ' ')
|
@@ -1596,6 +624,8 @@ static int ensure_segment_validity(const char *name)
|
|
1596
624
|
{
|
1597
625
|
const char *current = name;
|
1598
626
|
char prev = '\0';
|
627
|
+
const int lock_len = (int)strlen(GIT_FILELOCK_EXTENSION);
|
628
|
+
int segment_len;
|
1599
629
|
|
1600
630
|
if (*current == '.')
|
1601
631
|
return -1; /* Refname starts with "." */
|
@@ -1616,7 +646,14 @@ static int ensure_segment_validity(const char *name)
|
|
1616
646
|
prev = *current;
|
1617
647
|
}
|
1618
648
|
|
1619
|
-
|
649
|
+
segment_len = (int)(current - name);
|
650
|
+
|
651
|
+
/* A refname component can not end with ".lock" */
|
652
|
+
if (segment_len >= lock_len &&
|
653
|
+
!memcmp(current - lock_len, GIT_FILELOCK_EXTENSION, lock_len))
|
654
|
+
return -1;
|
655
|
+
|
656
|
+
return segment_len;
|
1620
657
|
}
|
1621
658
|
|
1622
659
|
static bool is_all_caps_and_underscore(const char *name, size_t len)
|
@@ -1647,7 +684,7 @@ int git_reference__normalize_name(
|
|
1647
684
|
// Inspired from https://github.com/git/git/blob/f06d47e7e0d9db709ee204ed13a8a7486149f494/refs.c#L36-100
|
1648
685
|
|
1649
686
|
char *current;
|
1650
|
-
int segment_len, segments_count = 0, error =
|
687
|
+
int segment_len, segments_count = 0, error = GIT_EINVALIDSPEC;
|
1651
688
|
unsigned int process_flags;
|
1652
689
|
bool normalize = (buf != NULL);
|
1653
690
|
assert(name);
|
@@ -1655,6 +692,9 @@ int git_reference__normalize_name(
|
|
1655
692
|
process_flags = flags;
|
1656
693
|
current = (char *)name;
|
1657
694
|
|
695
|
+
if (*current == '/')
|
696
|
+
goto cleanup;
|
697
|
+
|
1658
698
|
if (normalize)
|
1659
699
|
git_buf_clear(buf);
|
1660
700
|
|
@@ -1679,13 +719,19 @@ int git_reference__normalize_name(
|
|
1679
719
|
git_buf_truncate(buf,
|
1680
720
|
cur_len + segment_len + (segments_count ? 1 : 0));
|
1681
721
|
|
1682
|
-
if (git_buf_oom(buf))
|
722
|
+
if (git_buf_oom(buf)) {
|
723
|
+
error = -1;
|
1683
724
|
goto cleanup;
|
725
|
+
}
|
1684
726
|
}
|
1685
727
|
|
1686
728
|
segments_count++;
|
1687
729
|
}
|
1688
730
|
|
731
|
+
/* No empty segment is allowed when not normalizing */
|
732
|
+
if (segment_len == 0 && !normalize)
|
733
|
+
goto cleanup;
|
734
|
+
|
1689
735
|
if (current[segment_len] == '\0')
|
1690
736
|
break;
|
1691
737
|
|
@@ -1704,10 +750,6 @@ int git_reference__normalize_name(
|
|
1704
750
|
if (current[segment_len - 1] == '/')
|
1705
751
|
goto cleanup;
|
1706
752
|
|
1707
|
-
/* A refname can not end with ".lock" */
|
1708
|
-
if (!git__suffixcmp(name, GIT_FILELOCK_EXTENSION))
|
1709
|
-
goto cleanup;
|
1710
|
-
|
1711
753
|
if ((segments_count == 1 ) && !(flags & GIT_REF_FORMAT_ALLOW_ONELEVEL))
|
1712
754
|
goto cleanup;
|
1713
755
|
|
@@ -1723,11 +765,14 @@ int git_reference__normalize_name(
|
|
1723
765
|
error = 0;
|
1724
766
|
|
1725
767
|
cleanup:
|
1726
|
-
if (error)
|
768
|
+
if (error == GIT_EINVALIDSPEC)
|
1727
769
|
giterr_set(
|
1728
770
|
GITERR_REFERENCE,
|
1729
771
|
"The given reference name '%s' is not valid", name);
|
1730
772
|
|
773
|
+
if (error && normalize)
|
774
|
+
git_buf_free(buf);
|
775
|
+
|
1731
776
|
return error;
|
1732
777
|
}
|
1733
778
|
|
@@ -1775,92 +820,69 @@ int git_reference__normalize_name_lax(
|
|
1775
820
|
|
1776
821
|
int git_reference_cmp(git_reference *ref1, git_reference *ref2)
|
1777
822
|
{
|
823
|
+
git_ref_t type1, type2;
|
1778
824
|
assert(ref1 && ref2);
|
1779
825
|
|
826
|
+
type1 = git_reference_type(ref1);
|
827
|
+
type2 = git_reference_type(ref2);
|
828
|
+
|
1780
829
|
/* let's put symbolic refs before OIDs */
|
1781
|
-
if (
|
1782
|
-
return (
|
830
|
+
if (type1 != type2)
|
831
|
+
return (type1 == GIT_REF_SYMBOLIC) ? -1 : 1;
|
1783
832
|
|
1784
|
-
if (
|
833
|
+
if (type1 == GIT_REF_SYMBOLIC)
|
1785
834
|
return strcmp(ref1->target.symbolic, ref2->target.symbolic);
|
1786
835
|
|
1787
836
|
return git_oid_cmp(&ref1->target.oid, &ref2->target.oid);
|
1788
837
|
}
|
1789
838
|
|
1790
|
-
|
1791
|
-
|
839
|
+
static int reference__update_terminal(
|
840
|
+
git_repository *repo,
|
841
|
+
const char *ref_name,
|
842
|
+
const git_oid *oid,
|
843
|
+
int nesting)
|
1792
844
|
{
|
1793
845
|
git_reference *ref;
|
1794
|
-
int
|
846
|
+
int error = 0;
|
1795
847
|
|
1796
|
-
|
848
|
+
if (nesting > MAX_NESTING_LEVEL)
|
849
|
+
return GIT_ENOTFOUND;
|
850
|
+
|
851
|
+
error = git_reference_lookup(&ref, repo, ref_name);
|
1797
852
|
|
1798
|
-
/* If we haven't found the reference at all,
|
1799
|
-
|
1800
|
-
if (res == GIT_ENOTFOUND) {
|
853
|
+
/* If we haven't found the reference at all, create a new reference. */
|
854
|
+
if (error == GIT_ENOTFOUND) {
|
1801
855
|
giterr_clear();
|
1802
|
-
return
|
856
|
+
return git_reference_create(NULL, repo, ref_name, oid, 0);
|
1803
857
|
}
|
1804
|
-
|
1805
|
-
if (
|
1806
|
-
return
|
1807
|
-
|
1808
|
-
/* If
|
1809
|
-
* the direct reference it points to */
|
858
|
+
|
859
|
+
if (error < 0)
|
860
|
+
return error;
|
861
|
+
|
862
|
+
/* If the ref is a symbolic reference, follow its target. */
|
1810
863
|
if (git_reference_type(ref) == GIT_REF_SYMBOLIC) {
|
1811
|
-
|
1812
|
-
|
1813
|
-
|
1814
|
-
/* The target pointed at by this reference */
|
1815
|
-
sym_target = git_reference_target(ref);
|
1816
|
-
|
1817
|
-
/* resolve the reference to the target it points to */
|
1818
|
-
res = git_reference_resolve(&aux, ref);
|
1819
|
-
|
1820
|
-
/*
|
1821
|
-
* if the symbolic reference pointed to an inexisting ref,
|
1822
|
-
* this is means we're creating a new branch, for example.
|
1823
|
-
* We need to create a new direct reference with that name
|
1824
|
-
*/
|
1825
|
-
if (res == GIT_ENOTFOUND) {
|
1826
|
-
giterr_clear();
|
1827
|
-
res = git_reference_create_oid(NULL, repo, sym_target, oid, 1);
|
1828
|
-
git_reference_free(ref);
|
1829
|
-
return res;
|
1830
|
-
}
|
1831
|
-
|
1832
|
-
/* free the original symbolic reference now; not before because
|
1833
|
-
* we're using the `sym_target` pointer */
|
864
|
+
error = reference__update_terminal(repo, git_reference_symbolic_target(ref), oid,
|
865
|
+
nesting+1);
|
1834
866
|
git_reference_free(ref);
|
1835
|
-
|
1836
|
-
|
1837
|
-
|
1838
|
-
|
1839
|
-
/* store the newly found direct reference in its place */
|
1840
|
-
ref = aux;
|
867
|
+
} else {
|
868
|
+
git_reference_free(ref);
|
869
|
+
error = git_reference_create(NULL, repo, ref_name, oid, 1);
|
1841
870
|
}
|
1842
|
-
|
1843
|
-
|
1844
|
-
* or the target of the symbolic reference we've looked up */
|
1845
|
-
res = git_reference_set_oid(ref, oid);
|
1846
|
-
git_reference_free(ref);
|
1847
|
-
return res;
|
871
|
+
|
872
|
+
return error;
|
1848
873
|
}
|
1849
874
|
|
1850
|
-
|
1851
|
-
|
1852
|
-
|
1853
|
-
|
1854
|
-
|
1855
|
-
|
1856
|
-
|
875
|
+
/*
|
876
|
+
* Starting with the reference given by `ref_name`, follows symbolic
|
877
|
+
* references until a direct reference is found and updated the OID
|
878
|
+
* on that direct reference to `oid`.
|
879
|
+
*/
|
880
|
+
int git_reference__update_terminal(
|
881
|
+
git_repository *repo,
|
882
|
+
const char *ref_name,
|
883
|
+
const git_oid *oid)
|
1857
884
|
{
|
1858
|
-
|
1859
|
-
|
1860
|
-
if (!p_fnmatch(data->glob, reference_name, 0))
|
1861
|
-
return data->callback(reference_name, data->payload);
|
1862
|
-
|
1863
|
-
return 0;
|
885
|
+
return reference__update_terminal(repo, ref_name, oid, 0);
|
1864
886
|
}
|
1865
887
|
|
1866
888
|
int git_reference_foreach_glob(
|
@@ -1872,16 +894,13 @@ int git_reference_foreach_glob(
|
|
1872
894
|
void *payload),
|
1873
895
|
void *payload)
|
1874
896
|
{
|
1875
|
-
|
897
|
+
git_refdb *refdb;
|
1876
898
|
|
1877
899
|
assert(repo && glob && callback);
|
1878
900
|
|
1879
|
-
|
1880
|
-
data.callback = callback;
|
1881
|
-
data.payload = payload;
|
901
|
+
git_repository_refdb__weakptr(&refdb, repo);
|
1882
902
|
|
1883
|
-
return
|
1884
|
-
repo, list_flags, fromglob_cb, &data);
|
903
|
+
return git_refdb_foreach_glob(refdb, glob, list_flags, callback, payload);
|
1885
904
|
}
|
1886
905
|
|
1887
906
|
int git_reference_has_log(
|
@@ -1892,7 +911,8 @@ int git_reference_has_log(
|
|
1892
911
|
|
1893
912
|
assert(ref);
|
1894
913
|
|
1895
|
-
if (git_buf_join_n(&path, '/', 3, ref->
|
914
|
+
if (git_buf_join_n(&path, '/', 3, ref->db->repo->path_repository,
|
915
|
+
GIT_REFLOG_DIR, ref->name) < 0)
|
1896
916
|
return -1;
|
1897
917
|
|
1898
918
|
result = git_path_isfile(git_buf_cstr(&path));
|
@@ -1901,16 +921,26 @@ int git_reference_has_log(
|
|
1901
921
|
return result;
|
1902
922
|
}
|
1903
923
|
|
924
|
+
int git_reference__is_branch(const char *ref_name)
|
925
|
+
{
|
926
|
+
return git__prefixcmp(ref_name, GIT_REFS_HEADS_DIR) == 0;
|
927
|
+
}
|
928
|
+
|
1904
929
|
int git_reference_is_branch(git_reference *ref)
|
1905
930
|
{
|
1906
931
|
assert(ref);
|
1907
|
-
return
|
932
|
+
return git_reference__is_branch(ref->name);
|
933
|
+
}
|
934
|
+
|
935
|
+
int git_reference__is_remote(const char *ref_name)
|
936
|
+
{
|
937
|
+
return git__prefixcmp(ref_name, GIT_REFS_REMOTES_DIR) == 0;
|
1908
938
|
}
|
1909
939
|
|
1910
940
|
int git_reference_is_remote(git_reference *ref)
|
1911
941
|
{
|
1912
942
|
assert(ref);
|
1913
|
-
return
|
943
|
+
return git_reference__is_remote(ref->name);
|
1914
944
|
}
|
1915
945
|
|
1916
946
|
static int peel_error(int error, git_reference *ref, const char* msg)
|
@@ -1921,15 +951,6 @@ static int peel_error(int error, git_reference *ref, const char* msg)
|
|
1921
951
|
return error;
|
1922
952
|
}
|
1923
953
|
|
1924
|
-
static int reference_target(git_object **object, git_reference *ref)
|
1925
|
-
{
|
1926
|
-
const git_oid *oid;
|
1927
|
-
|
1928
|
-
oid = git_reference_oid(ref);
|
1929
|
-
|
1930
|
-
return git_object_lookup(object, git_reference_owner(ref), oid, GIT_OBJ_ANY);
|
1931
|
-
}
|
1932
|
-
|
1933
954
|
int git_reference_peel(
|
1934
955
|
git_object **peeled,
|
1935
956
|
git_reference *ref,
|
@@ -1941,22 +962,37 @@ int git_reference_peel(
|
|
1941
962
|
|
1942
963
|
assert(ref);
|
1943
964
|
|
1944
|
-
if (
|
1945
|
-
|
965
|
+
if (ref->type == GIT_REF_OID) {
|
966
|
+
resolved = ref;
|
967
|
+
} else {
|
968
|
+
if ((error = git_reference_resolve(&resolved, ref)) < 0)
|
969
|
+
return peel_error(error, ref, "Cannot resolve reference");
|
970
|
+
}
|
971
|
+
|
972
|
+
if (!git_oid_iszero(&resolved->peel)) {
|
973
|
+
error = git_object_lookup(&target,
|
974
|
+
git_reference_owner(ref), &resolved->peel, GIT_OBJ_ANY);
|
975
|
+
} else {
|
976
|
+
error = git_object_lookup(&target,
|
977
|
+
git_reference_owner(ref), &resolved->target.oid, GIT_OBJ_ANY);
|
978
|
+
}
|
1946
979
|
|
1947
|
-
if (
|
980
|
+
if (error < 0) {
|
1948
981
|
peel_error(error, ref, "Cannot retrieve reference target");
|
1949
982
|
goto cleanup;
|
1950
983
|
}
|
1951
|
-
|
984
|
+
|
1952
985
|
if (target_type == GIT_OBJ_ANY && git_object_type(target) != GIT_OBJ_TAG)
|
1953
|
-
error =
|
1954
|
-
else
|
986
|
+
error = git_object_dup(peeled, target);
|
987
|
+
else
|
1955
988
|
error = git_object_peel(peeled, target, target_type);
|
1956
989
|
|
1957
990
|
cleanup:
|
1958
991
|
git_object_free(target);
|
1959
|
-
|
992
|
+
|
993
|
+
if (resolved != ref)
|
994
|
+
git_reference_free(resolved);
|
995
|
+
|
1960
996
|
return error;
|
1961
997
|
}
|
1962
998
|
|
@@ -1964,8 +1000,12 @@ int git_reference__is_valid_name(
|
|
1964
1000
|
const char *refname,
|
1965
1001
|
unsigned int flags)
|
1966
1002
|
{
|
1003
|
+
int error;
|
1004
|
+
|
1005
|
+
error = git_reference__normalize_name(NULL, refname, flags) == 0;
|
1967
1006
|
giterr_clear();
|
1968
|
-
|
1007
|
+
|
1008
|
+
return error;
|
1969
1009
|
}
|
1970
1010
|
|
1971
1011
|
int git_reference_is_valid_name(
|