rugged 0.24.0b12 → 0.24.0b13
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/rugged/rugged.c +1 -0
- data/ext/rugged/rugged.h +3 -0
- data/ext/rugged/rugged_commit.c +72 -12
- data/ext/rugged/rugged_rebase.c +355 -0
- data/ext/rugged/rugged_reference.c +12 -0
- data/ext/rugged/rugged_repo.c +57 -1
- data/ext/rugged/rugged_revwalk.c +24 -0
- data/lib/rugged/commit.rb +4 -0
- data/lib/rugged/tag.rb +19 -0
- data/lib/rugged/version.rb +1 -1
- data/vendor/libgit2/CMakeLists.txt +3 -2
- data/vendor/libgit2/include/git2/commit.h +12 -0
- data/vendor/libgit2/include/git2/diff.h +1 -1
- data/vendor/libgit2/include/git2/merge.h +0 -8
- data/vendor/libgit2/include/git2/rebase.h +32 -2
- data/vendor/libgit2/include/git2/stash.h +1 -1
- data/vendor/libgit2/src/attr_file.c +3 -2
- data/vendor/libgit2/src/checkout.c +6 -3
- data/vendor/libgit2/src/commit.c +103 -12
- data/vendor/libgit2/src/curl_stream.c +5 -1
- data/vendor/libgit2/src/diff.c +4 -4
- data/vendor/libgit2/src/index.c +2 -2
- data/vendor/libgit2/src/iterator.c +3 -2
- data/vendor/libgit2/src/iterator.h +1 -0
- data/vendor/libgit2/src/merge.c +9 -10
- data/vendor/libgit2/src/pack-objects.c +8 -4
- data/vendor/libgit2/src/pack.c +2 -3
- data/vendor/libgit2/src/pack.h +0 -7
- data/vendor/libgit2/src/pathspec.c +1 -2
- data/vendor/libgit2/src/rebase.c +262 -118
- data/vendor/libgit2/src/stash.c +4 -4
- data/vendor/libgit2/src/submodule.c +3 -3
- data/vendor/libgit2/src/transports/winhttp.c +7 -2
- metadata +3 -2
@@ -41,6 +41,18 @@ VALUE rugged_ref_new(VALUE klass, VALUE owner, git_reference *ref)
|
|
41
41
|
return rb_ref;
|
42
42
|
}
|
43
43
|
|
44
|
+
|
45
|
+
const char * rugged_refname_from_string_or_ref(VALUE rb_name_or_ref)
|
46
|
+
{
|
47
|
+
if (rb_obj_is_kind_of(rb_name_or_ref, rb_cRuggedReference))
|
48
|
+
rb_name_or_ref = rb_funcall(rb_name_or_ref, rb_intern("canonical_name"), 0);
|
49
|
+
|
50
|
+
if (TYPE(rb_name_or_ref) != T_STRING)
|
51
|
+
rb_raise(rb_eTypeError, "Expecting a String or Rugged::Reference instance");
|
52
|
+
|
53
|
+
return StringValueCStr(rb_name_or_ref);
|
54
|
+
}
|
55
|
+
|
44
56
|
/*
|
45
57
|
* call-seq:
|
46
58
|
* Reference.valid_name?(ref_name) -> true or false
|
data/ext/rugged/rugged_repo.c
CHANGED
@@ -1934,7 +1934,7 @@ static int rugged__checkout_notify_cb(
|
|
1934
1934
|
/**
|
1935
1935
|
* The caller has to free the returned git_checkout_options paths strings array.
|
1936
1936
|
*/
|
1937
|
-
|
1937
|
+
void rugged_parse_checkout_options(git_checkout_options *opts, VALUE rb_options)
|
1938
1938
|
{
|
1939
1939
|
VALUE rb_value;
|
1940
1940
|
|
@@ -2530,6 +2530,61 @@ static VALUE rb_git_repo_cherrypick(int argc, VALUE *argv, VALUE self)
|
|
2530
2530
|
return Qnil;
|
2531
2531
|
}
|
2532
2532
|
|
2533
|
+
/*
|
2534
|
+
* call-seq:
|
2535
|
+
* repo.cherrypick_commit(commit, our_commit, [mainline, options]) -> nil
|
2536
|
+
*
|
2537
|
+
* Cherry-pick the given commit on the given base in-memory and
|
2538
|
+
* return an index with the result.
|
2539
|
+
*
|
2540
|
+
* `commit` can be either a string containing a commit id or a
|
2541
|
+
* `Rugged::Commit` object.
|
2542
|
+
*
|
2543
|
+
* `our_commit` is the base commit, can be either a string containing
|
2544
|
+
* a commit id or a `Rugged::Commit` object.
|
2545
|
+
*
|
2546
|
+
* `mainline` when cherry-picking a merge, this is the parent number
|
2547
|
+
* (starting from 1) which should be considered the mainline.
|
2548
|
+
*/
|
2549
|
+
static VALUE rb_git_repo_cherrypick_commit(int argc, VALUE *argv, VALUE self)
|
2550
|
+
{
|
2551
|
+
VALUE rb_options, rb_commit, rb_our_commit, rb_mainline;
|
2552
|
+
|
2553
|
+
git_repository *repo;
|
2554
|
+
git_commit *commit, *our_commit;
|
2555
|
+
git_merge_options opts = GIT_MERGE_OPTIONS_INIT;
|
2556
|
+
git_index *index;
|
2557
|
+
int error, mainline;
|
2558
|
+
|
2559
|
+
rb_scan_args(argc, argv, "21:", &rb_commit, &rb_our_commit, &rb_mainline, &rb_options);
|
2560
|
+
|
2561
|
+
if (TYPE(rb_commit) == T_STRING) {
|
2562
|
+
rb_commit = rugged_object_rev_parse(self, rb_commit, 1);
|
2563
|
+
}
|
2564
|
+
if (TYPE(rb_our_commit) == T_STRING) {
|
2565
|
+
rb_our_commit = rugged_object_rev_parse(self, rb_our_commit, 1);
|
2566
|
+
}
|
2567
|
+
|
2568
|
+
if (!rb_obj_is_kind_of(rb_commit, rb_cRuggedCommit)) {
|
2569
|
+
rb_raise(rb_eArgError, "Expected a Rugged::Commit.");
|
2570
|
+
}
|
2571
|
+
if (!rb_obj_is_kind_of(rb_our_commit, rb_cRuggedCommit)) {
|
2572
|
+
rb_raise(rb_eArgError, "Expected a Rugged::Commit.");
|
2573
|
+
}
|
2574
|
+
|
2575
|
+
Data_Get_Struct(self, git_repository, repo);
|
2576
|
+
Data_Get_Struct(rb_commit, git_commit, commit);
|
2577
|
+
Data_Get_Struct(rb_our_commit, git_commit, our_commit);
|
2578
|
+
|
2579
|
+
rugged_parse_merge_options(&opts, rb_options);
|
2580
|
+
|
2581
|
+
mainline = NIL_P(rb_mainline) ? 0 : FIX2UINT(rb_mainline);
|
2582
|
+
error = git_cherrypick_commit(&index, repo, commit, our_commit, mainline, &opts);
|
2583
|
+
rugged_exception_check(error);
|
2584
|
+
|
2585
|
+
return rugged_index_new(rb_cRuggedIndex, self, index);
|
2586
|
+
}
|
2587
|
+
|
2533
2588
|
void Init_rugged_repo(void)
|
2534
2589
|
{
|
2535
2590
|
id_call = rb_intern("call");
|
@@ -2603,6 +2658,7 @@ void Init_rugged_repo(void)
|
|
2603
2658
|
rb_define_method(rb_cRuggedRepo, "checkout_head", rb_git_checkout_head, -1);
|
2604
2659
|
|
2605
2660
|
rb_define_method(rb_cRuggedRepo, "cherrypick", rb_git_repo_cherrypick, -1);
|
2661
|
+
rb_define_method(rb_cRuggedRepo, "cherrypick_commit", rb_git_repo_cherrypick_commit, -1);
|
2606
2662
|
rb_define_method(rb_cRuggedRepo, "fetch_attributes", rb_git_repo_attributes, -1);
|
2607
2663
|
|
2608
2664
|
rb_cRuggedOdbObject = rb_define_class_under(rb_mRugged, "OdbObject", rb_cObject);
|
data/ext/rugged/rugged_revwalk.c
CHANGED
@@ -190,6 +190,29 @@ static VALUE rb_git_walker_simplify_first_parent(VALUE self)
|
|
190
190
|
return Qnil;
|
191
191
|
}
|
192
192
|
|
193
|
+
/*
|
194
|
+
* call-seq:
|
195
|
+
* walker.count -> Fixnum
|
196
|
+
*
|
197
|
+
* Returns the amount of objects a walker iterated over.
|
198
|
+
*/
|
199
|
+
static VALUE rb_git_walker_count(VALUE self)
|
200
|
+
{
|
201
|
+
git_revwalk *walk;
|
202
|
+
git_oid commit_oid;
|
203
|
+
int error = 0;
|
204
|
+
uint64_t count = 0;
|
205
|
+
|
206
|
+
Data_Get_Struct(self, git_revwalk, walk);
|
207
|
+
|
208
|
+
while (((error = git_revwalk_next(&commit_oid, walk)) == 0) && ++count != UINT64_MAX);
|
209
|
+
|
210
|
+
if (error != GIT_ITEROVER)
|
211
|
+
rugged_exception_check(error);
|
212
|
+
|
213
|
+
return ULONG2NUM(count);
|
214
|
+
}
|
215
|
+
|
193
216
|
/*
|
194
217
|
* call-seq:
|
195
218
|
* walker.reset -> nil
|
@@ -492,4 +515,5 @@ void Init_rugged_revwalk(void)
|
|
492
515
|
rb_define_method(rb_cRuggedWalker, "reset", rb_git_walker_reset, 0);
|
493
516
|
rb_define_method(rb_cRuggedWalker, "sorting", rb_git_walker_sorting, 1);
|
494
517
|
rb_define_method(rb_cRuggedWalker, "simplify_first_parent", rb_git_walker_simplify_first_parent, 0);
|
518
|
+
rb_define_method(rb_cRuggedWalker, "count", rb_git_walker_count, 0);
|
495
519
|
}
|
data/lib/rugged/commit.rb
CHANGED
@@ -9,6 +9,10 @@ module Rugged
|
|
9
9
|
"#<Rugged::Commit:#{object_id} {message: #{message.inspect}, tree: #{tree.inspect}, parents: #{parent_oids}}>"
|
10
10
|
end
|
11
11
|
|
12
|
+
def header_field?(field)
|
13
|
+
!!header_field(field)
|
14
|
+
end
|
15
|
+
|
12
16
|
# Return a diff between this commit and its first parent or another commit or tree.
|
13
17
|
#
|
14
18
|
# See Rugged::Tree#diff for more details.
|
data/lib/rugged/tag.rb
CHANGED
@@ -1,5 +1,24 @@
|
|
1
1
|
module Rugged
|
2
2
|
class Tag < Rugged::Reference
|
3
|
+
GPG_SIGNATURE_PREFIX = "-----BEGIN PGP SIGNATURE-----".freeze
|
4
|
+
|
5
|
+
def self.extract_signature(repo, oid, prefix=GPG_SIGNATURE_PREFIX)
|
6
|
+
object = repo.read(oid)
|
7
|
+
|
8
|
+
unless object.type == :tag
|
9
|
+
raise GitRPC::InvalidObject, "Invalid object type #{object.type}, expected tag"
|
10
|
+
end
|
11
|
+
|
12
|
+
if index = object.data.index(prefix)
|
13
|
+
[
|
14
|
+
object.data.byteslice(index..-1),
|
15
|
+
object.data.byteslice(0...index)
|
16
|
+
]
|
17
|
+
else
|
18
|
+
[nil, object.data]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
3
22
|
def name
|
4
23
|
canonical_name.sub(%r{^refs/tags/}, "")
|
5
24
|
end
|
data/lib/rugged/version.rb
CHANGED
@@ -257,7 +257,7 @@ IF (WIN32 AND WINHTTP)
|
|
257
257
|
LINK_DIRECTORIES(${LIBWINHTTP_PATH})
|
258
258
|
ENDIF ()
|
259
259
|
|
260
|
-
LINK_LIBRARIES(winhttp rpcrt4 crypt32)
|
260
|
+
LINK_LIBRARIES(winhttp rpcrt4 crypt32 ole32)
|
261
261
|
LIST(APPEND LIBGIT2_PC_LIBS "-lwinhttp" "-lrpcrt4" "-lcrypt32" "-lole32")
|
262
262
|
ELSE ()
|
263
263
|
IF (CURL)
|
@@ -340,7 +340,8 @@ IF (LIBSSH2_FOUND)
|
|
340
340
|
ADD_DEFINITIONS(-DGIT_SSH)
|
341
341
|
INCLUDE_DIRECTORIES(${LIBSSH2_INCLUDE_DIRS})
|
342
342
|
LINK_DIRECTORIES(${LIBSSH2_LIBRARY_DIRS})
|
343
|
-
|
343
|
+
LIST(APPEND LIBGIT2_PC_LIBS ${LIBSSH2_LDFLAGS})
|
344
|
+
#SET(LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS} ${LIBSSH2_LDFLAGS}")
|
344
345
|
SET(SSH_LIBRARIES ${LIBSSH2_LIBRARIES})
|
345
346
|
|
346
347
|
CHECK_LIBRARY_EXISTS("${LIBSSH2_LIBRARIES}" libssh2_userauth_publickey_frommemory "${LIBSSH2_LIBRARY_DIRS}" HAVE_LIBSSH2_MEMORY_CREDENTIALS)
|
@@ -263,6 +263,18 @@ GIT_EXTERN(int) git_commit_nth_gen_ancestor(
|
|
263
263
|
*/
|
264
264
|
GIT_EXTERN(int) git_commit_header_field(git_buf *out, const git_commit *commit, const char *field);
|
265
265
|
|
266
|
+
/**
|
267
|
+
* Extract the signature from a commit
|
268
|
+
*
|
269
|
+
* @param signature the signature block
|
270
|
+
* @param signed_data signed data; this is the commit contents minus the signature block
|
271
|
+
* @param repo the repository in which the commit exists
|
272
|
+
* @param commit_id the commit from which to extract the data
|
273
|
+
* @param field the name of the header field containing the signature
|
274
|
+
* block; pass `NULL` to extract the default 'gpgsig'
|
275
|
+
*/
|
276
|
+
GIT_EXTERN(int) git_commit_extract_signature(git_buf *signature, git_buf *signed_data, git_repository *repo, git_oid *commit_id, const char *field);
|
277
|
+
|
266
278
|
/**
|
267
279
|
* Create new commit in the repository from a list of `git_object` pointers
|
268
280
|
*
|
@@ -1194,7 +1194,7 @@ typedef enum {
|
|
1194
1194
|
} git_diff_stats_format_t;
|
1195
1195
|
|
1196
1196
|
/**
|
1197
|
-
*
|
1197
|
+
* Accumulate diff statistics for all patches.
|
1198
1198
|
*
|
1199
1199
|
* @param out Structure containg the diff statistics.
|
1200
1200
|
* @param diff A git_diff generated by one of the above functions.
|
@@ -527,10 +527,6 @@ GIT_EXTERN(int) git_merge_trees(
|
|
527
527
|
* or checked out. If the index is to be converted to a tree, the caller
|
528
528
|
* should resolve any conflicts that arose as part of the merge.
|
529
529
|
*
|
530
|
-
* The merge performed uses the first common ancestor, unlike the
|
531
|
-
* `git-merge-recursive` strategy, which may produce an artificial common
|
532
|
-
* ancestor tree when there are multiple ancestors.
|
533
|
-
*
|
534
530
|
* The returned index must be freed explicitly with `git_index_free`.
|
535
531
|
*
|
536
532
|
* @param out pointer to store the index result in
|
@@ -553,10 +549,6 @@ GIT_EXTERN(int) git_merge_commits(
|
|
553
549
|
* to the index. Callers should inspect the repository's index after this
|
554
550
|
* completes, resolve any conflicts and prepare a commit.
|
555
551
|
*
|
556
|
-
* The merge performed uses the first common ancestor, unlike the
|
557
|
-
* `git-merge-recursive` strategy, which may produce an artificial common
|
558
|
-
* ancestor tree when there are multiple ancestors.
|
559
|
-
*
|
560
552
|
* For compatibility with git, the repository is put into a merging
|
561
553
|
* state. Once the commit is done (or if the uses wishes to abort),
|
562
554
|
* you should clear this state by calling
|
@@ -38,16 +38,30 @@ typedef struct {
|
|
38
38
|
*/
|
39
39
|
int quiet;
|
40
40
|
|
41
|
+
/**
|
42
|
+
* Used by `git_rebase_init`, this will begin an in-memory rebase,
|
43
|
+
* which will allow callers to step through the rebase operations and
|
44
|
+
* commit the rebased changes, but will not rewind HEAD or update the
|
45
|
+
* repository to be in a rebasing state. This will not interfere with
|
46
|
+
* the working directory (if there is one).
|
47
|
+
*/
|
48
|
+
int inmemory;
|
49
|
+
|
41
50
|
/**
|
42
51
|
* Used by `git_rebase_finish`, this is the name of the notes reference
|
43
52
|
* used to rewrite notes for rebased commits when finishing the rebase;
|
44
|
-
* if NULL, the contents of the
|
53
|
+
* if NULL, the contents of the configuration option `notes.rewriteRef`
|
45
54
|
* is examined, unless the configuration option `notes.rewrite.rebase`
|
46
55
|
* is set to false. If `notes.rewriteRef` is also NULL, notes will
|
47
56
|
* not be rewritten.
|
48
57
|
*/
|
49
58
|
const char *rewrite_notes_ref;
|
50
59
|
|
60
|
+
/**
|
61
|
+
* Options to control how trees are merged during `git_rebase_next`.
|
62
|
+
*/
|
63
|
+
git_merge_options merge_options;
|
64
|
+
|
51
65
|
/**
|
52
66
|
* Options to control how files are written during `git_rebase_init`,
|
53
67
|
* `git_checkout_next` and `git_checkout_abort`. Note that a minimum
|
@@ -101,7 +115,8 @@ typedef enum {
|
|
101
115
|
|
102
116
|
#define GIT_REBASE_OPTIONS_VERSION 1
|
103
117
|
#define GIT_REBASE_OPTIONS_INIT \
|
104
|
-
{GIT_REBASE_OPTIONS_VERSION, 0, NULL,
|
118
|
+
{ GIT_REBASE_OPTIONS_VERSION, 0, 0, NULL, GIT_MERGE_OPTIONS_INIT, \
|
119
|
+
GIT_CHECKOUT_OPTIONS_INIT}
|
105
120
|
|
106
121
|
/** Indicates that a rebase operation is not (yet) in progress. */
|
107
122
|
#define GIT_REBASE_NO_OPERATION SIZE_MAX
|
@@ -226,6 +241,21 @@ GIT_EXTERN(int) git_rebase_next(
|
|
226
241
|
git_rebase_operation **operation,
|
227
242
|
git_rebase *rebase);
|
228
243
|
|
244
|
+
/**
|
245
|
+
* Gets the index produced by the last operation, which is the result
|
246
|
+
* of `git_rebase_next` and which will be committed by the next
|
247
|
+
* invocation of `git_rebase_commit`. This is useful for resolving
|
248
|
+
* conflicts in an in-memory rebase before committing them. You must
|
249
|
+
* call `git_index_free` when you are finished with this.
|
250
|
+
*
|
251
|
+
* This is only applicable for in-memory rebases; for rebases within
|
252
|
+
* a working directory, the changes were applied to the repository's
|
253
|
+
* index.
|
254
|
+
*/
|
255
|
+
GIT_EXTERN(int) git_rebase_inmemory_index(
|
256
|
+
git_index **index,
|
257
|
+
git_rebase *rebase);
|
258
|
+
|
229
259
|
/**
|
230
260
|
* Commits the current patch. You must have resolved any conflicts that
|
231
261
|
* were introduced during the patch application from the `git_rebase_next`
|
@@ -150,7 +150,7 @@ typedef struct git_stash_apply_options {
|
|
150
150
|
* `GIT_STASH_APPLY_OPTIONS_INIT` here.
|
151
151
|
* @return Zero on success; -1 on failure.
|
152
152
|
*/
|
153
|
-
int git_stash_apply_init_options(
|
153
|
+
GIT_EXTERN(int) git_stash_apply_init_options(
|
154
154
|
git_stash_apply_options *opts, unsigned int version);
|
155
155
|
|
156
156
|
/**
|
@@ -123,7 +123,7 @@ int git_attr_file__load(
|
|
123
123
|
break;
|
124
124
|
}
|
125
125
|
case GIT_ATTR_FILE__FROM_FILE: {
|
126
|
-
int fd;
|
126
|
+
int fd = -1;
|
127
127
|
|
128
128
|
/* For open or read errors, pretend that we got ENOTFOUND. */
|
129
129
|
/* TODO: issue warning when warning API is available */
|
@@ -133,7 +133,8 @@ int git_attr_file__load(
|
|
133
133
|
(fd = git_futils_open_ro(entry->fullpath)) < 0 ||
|
134
134
|
(error = git_futils_readbuffer_fd(&content, fd, (size_t)st.st_size)) < 0)
|
135
135
|
nonexistent = true;
|
136
|
-
|
136
|
+
|
137
|
+
if (fd >= 0)
|
137
138
|
p_close(fd);
|
138
139
|
|
139
140
|
break;
|
@@ -1487,8 +1487,10 @@ static int blob_content_to_file(
|
|
1487
1487
|
if (!data->opts.disable_filters &&
|
1488
1488
|
(error = git_filter_list__load_ext(
|
1489
1489
|
&fl, data->repo, blob, hint_path,
|
1490
|
-
GIT_FILTER_TO_WORKTREE, &filter_opts)))
|
1490
|
+
GIT_FILTER_TO_WORKTREE, &filter_opts))) {
|
1491
|
+
p_close(fd);
|
1491
1492
|
return error;
|
1493
|
+
}
|
1492
1494
|
|
1493
1495
|
/* setup the writer */
|
1494
1496
|
memset(&writer, 0, sizeof(struct checkout_stream));
|
@@ -2519,7 +2521,8 @@ int git_checkout_iterator(
|
|
2519
2521
|
|
2520
2522
|
if (data.opts.baseline_index) {
|
2521
2523
|
if ((error = git_iterator_for_index(
|
2522
|
-
&baseline, data.opts.baseline_index,
|
2524
|
+
&baseline, git_index_owner(data.opts.baseline_index),
|
2525
|
+
data.opts.baseline_index, &baseline_opts)) < 0)
|
2523
2526
|
goto cleanup;
|
2524
2527
|
} else {
|
2525
2528
|
if ((error = git_iterator_for_tree(
|
@@ -2631,7 +2634,7 @@ int git_checkout_index(
|
|
2631
2634
|
return error;
|
2632
2635
|
GIT_REFCOUNT_INC(index);
|
2633
2636
|
|
2634
|
-
if (!(error = git_iterator_for_index(&index_i, index, NULL)))
|
2637
|
+
if (!(error = git_iterator_for_index(&index_i, repo, index, NULL)))
|
2635
2638
|
error = git_checkout_iterator(index_i, index, opts);
|
2636
2639
|
|
2637
2640
|
if (owned)
|
data/vendor/libgit2/src/commit.c
CHANGED
@@ -564,17 +564,97 @@ int git_commit_nth_gen_ancestor(
|
|
564
564
|
|
565
565
|
int git_commit_header_field(git_buf *out, const git_commit *commit, const char *field)
|
566
566
|
{
|
567
|
-
const char *buf = commit->raw_header;
|
568
|
-
const char *h, *eol;
|
567
|
+
const char *eol, *buf = commit->raw_header;
|
569
568
|
|
570
569
|
git_buf_sanitize(out);
|
570
|
+
|
571
|
+
while ((eol = strchr(buf, '\n'))) {
|
572
|
+
/* We can skip continuations here */
|
573
|
+
if (buf[0] == ' ') {
|
574
|
+
buf = eol + 1;
|
575
|
+
continue;
|
576
|
+
}
|
577
|
+
|
578
|
+
/* Skip until we find the field we're after */
|
579
|
+
if (git__prefixcmp(buf, field)) {
|
580
|
+
buf = eol + 1;
|
581
|
+
continue;
|
582
|
+
}
|
583
|
+
|
584
|
+
buf += strlen(field);
|
585
|
+
/* Check that we're not matching a prefix but the field itself */
|
586
|
+
if (buf[0] != ' ') {
|
587
|
+
buf = eol + 1;
|
588
|
+
continue;
|
589
|
+
}
|
590
|
+
|
591
|
+
buf++; /* skip the SP */
|
592
|
+
|
593
|
+
git_buf_put(out, buf, eol - buf);
|
594
|
+
if (git_buf_oom(out))
|
595
|
+
goto oom;
|
596
|
+
|
597
|
+
/* If the next line starts with SP, it's multi-line, we must continue */
|
598
|
+
while (eol[1] == ' ') {
|
599
|
+
git_buf_putc(out, '\n');
|
600
|
+
buf = eol + 2;
|
601
|
+
eol = strchr(buf, '\n');
|
602
|
+
if (!eol)
|
603
|
+
goto malformed;
|
604
|
+
|
605
|
+
git_buf_put(out, buf, eol - buf);
|
606
|
+
}
|
607
|
+
|
608
|
+
if (git_buf_oom(out))
|
609
|
+
goto oom;
|
610
|
+
|
611
|
+
return 0;
|
612
|
+
}
|
613
|
+
|
614
|
+
giterr_set(GITERR_OBJECT, "no such field '%s'", field);
|
615
|
+
return GIT_ENOTFOUND;
|
616
|
+
|
617
|
+
malformed:
|
618
|
+
giterr_set(GITERR_OBJECT, "malformed header");
|
619
|
+
return -1;
|
620
|
+
oom:
|
621
|
+
giterr_set_oom();
|
622
|
+
return -1;
|
623
|
+
}
|
624
|
+
|
625
|
+
int git_commit_extract_signature(git_buf *signature, git_buf *signed_data, git_repository *repo, git_oid *commit_id, const char *field)
|
626
|
+
{
|
627
|
+
git_odb_object *obj;
|
628
|
+
git_odb *odb;
|
629
|
+
const char *buf;
|
630
|
+
const char *h, *eol;
|
631
|
+
int error;
|
632
|
+
|
633
|
+
git_buf_sanitize(signature);
|
634
|
+
git_buf_sanitize(signed_data);
|
635
|
+
|
636
|
+
if (!field)
|
637
|
+
field = "gpgsig";
|
638
|
+
|
639
|
+
if ((error = git_repository_odb__weakptr(&odb, repo)) < 0)
|
640
|
+
return error;
|
641
|
+
|
642
|
+
if ((error = git_odb_read(&obj, odb, commit_id)) < 0)
|
643
|
+
return error;
|
644
|
+
|
645
|
+
buf = git_odb_object_data(obj);
|
646
|
+
|
571
647
|
while ((h = strchr(buf, '\n')) && h[1] != '\0' && h[1] != '\n') {
|
572
648
|
h++;
|
573
|
-
if (git__prefixcmp(
|
649
|
+
if (git__prefixcmp(buf, field)) {
|
650
|
+
if (git_buf_put(signed_data, buf, h - buf) < 0)
|
651
|
+
return -1;
|
652
|
+
|
574
653
|
buf = h;
|
575
654
|
continue;
|
576
655
|
}
|
577
656
|
|
657
|
+
h = buf;
|
578
658
|
h += strlen(field);
|
579
659
|
eol = strchr(h, '\n');
|
580
660
|
if (h[0] != ' ') {
|
@@ -586,33 +666,44 @@ int git_commit_header_field(git_buf *out, const git_commit *commit, const char *
|
|
586
666
|
|
587
667
|
h++; /* skip the SP */
|
588
668
|
|
589
|
-
git_buf_put(
|
590
|
-
if (git_buf_oom(
|
669
|
+
git_buf_put(signature, h, eol - h);
|
670
|
+
if (git_buf_oom(signature))
|
591
671
|
goto oom;
|
592
672
|
|
593
673
|
/* If the next line starts with SP, it's multi-line, we must continue */
|
594
674
|
while (eol[1] == ' ') {
|
595
|
-
git_buf_putc(
|
675
|
+
git_buf_putc(signature, '\n');
|
596
676
|
h = eol + 2;
|
597
677
|
eol = strchr(h, '\n');
|
598
678
|
if (!eol)
|
599
679
|
goto malformed;
|
600
680
|
|
601
|
-
git_buf_put(
|
681
|
+
git_buf_put(signature, h, eol - h);
|
602
682
|
}
|
603
683
|
|
604
|
-
if (git_buf_oom(
|
684
|
+
if (git_buf_oom(signature))
|
605
685
|
goto oom;
|
606
686
|
|
607
|
-
|
687
|
+
git_odb_object_free(obj);
|
688
|
+
return git_buf_puts(signed_data, eol+1);
|
608
689
|
}
|
609
690
|
|
610
|
-
|
691
|
+
giterr_set(GITERR_INVALID, "this commit is not signed");
|
692
|
+
error = GIT_ENOTFOUND;
|
693
|
+
goto cleanup;
|
611
694
|
|
612
695
|
malformed:
|
613
696
|
giterr_set(GITERR_OBJECT, "malformed header");
|
614
|
-
|
697
|
+
error = -1;
|
698
|
+
goto cleanup;
|
615
699
|
oom:
|
616
700
|
giterr_set_oom();
|
617
|
-
|
701
|
+
error = -1;
|
702
|
+
goto cleanup;
|
703
|
+
|
704
|
+
cleanup:
|
705
|
+
git_odb_object_free(obj);
|
706
|
+
git_buf_clear(signature);
|
707
|
+
git_buf_clear(signed_data);
|
708
|
+
return error;
|
618
709
|
}
|