rugged 0.24.0b12 → 0.24.0b13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
}
|