Skip to content

Commit d601d23

Browse files
author
Dawa Ometto
committed
Add Repository#apply and tests.
1 parent 2870fce commit d601d23

File tree

4 files changed

+170
-1
lines changed

4 files changed

+170
-1
lines changed

ext/rugged/rugged.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ VALUE rb_merge_file_result_fromC(const git_merge_file_result *results);
8585

8686
void rugged_parse_diff_options(git_diff_options *opts, VALUE rb_options);
8787
void rugged_parse_merge_options(git_merge_options *opts, VALUE rb_options);
88+
void rugged_parse_apply_options(git_apply_options *opts, git_apply_location_t *location, VALUE rb_options);
8889
void rugged_parse_checkout_options(git_checkout_options *opts, VALUE rb_options);
8990
void rugged_parse_merge_file_options(git_merge_file_options *opts, VALUE rb_options);
9091

ext/rugged/rugged_repo.c

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <git2/sys/odb_backend.h>
1111
#include <git2/sys/refdb_backend.h>
1212
#include <git2/refs.h>
13+
#include <git2/apply.h>
1314

1415
extern VALUE rb_mRugged;
1516
extern VALUE rb_eRuggedError;
@@ -18,6 +19,7 @@ extern VALUE rb_cRuggedConfig;
1819
extern VALUE rb_cRuggedBackend;
1920
extern VALUE rb_cRuggedRemote;
2021
extern VALUE rb_cRuggedCommit;
22+
extern VALUE rb_cRuggedDiff;
2123
extern VALUE rb_cRuggedTag;
2224
extern VALUE rb_cRuggedTree;
2325
extern VALUE rb_cRuggedReference;
@@ -868,6 +870,42 @@ static VALUE rb_git_repo_revert_commit(int argc, VALUE *argv, VALUE self)
868870
return rugged_index_new(rb_cRuggedIndex, self, index);
869871
}
870872

873+
/*
874+
* call-seq:
875+
* repo.apply(diff, options = {}) -> true or false
876+
*
877+
* Applies the given diff to the repository.
878+
*/
879+
static VALUE rb_git_repo_apply(int argc, VALUE *argv, VALUE self)
880+
{
881+
VALUE rb_diff, rb_options;
882+
git_diff *diff;
883+
git_repository *repo;
884+
git_apply_options opts = GIT_APPLY_OPTIONS_INIT;
885+
git_apply_location_t location = GIT_APPLY_LOCATION_BOTH;
886+
int error;
887+
888+
rb_scan_args(argc, argv, "11", &rb_diff, &rb_options);
889+
890+
if (!rb_obj_is_kind_of(rb_diff, rb_cRuggedDiff)) {
891+
rb_raise(rb_eArgError, "Expected a Rugged::Diff.");
892+
}
893+
894+
if (!NIL_P(rb_options)) {
895+
Check_Type(rb_options, T_HASH);
896+
rugged_parse_apply_options(&opts, &location, rb_options);
897+
}
898+
899+
Data_Get_Struct(self, git_repository, repo);
900+
Data_Get_Struct(rb_diff, git_diff, diff);
901+
902+
error = git_apply(repo, diff, location, &opts);
903+
904+
rugged_exception_check(error);
905+
906+
return Qtrue;
907+
}
908+
871909
/*
872910
* call-seq:
873911
* repo.merge_commits(our_commit, their_commit, options = {}) -> index
@@ -2543,6 +2581,33 @@ static VALUE rb_git_repo_cherrypick_commit(int argc, VALUE *argv, VALUE self)
25432581
return rugged_index_new(rb_cRuggedIndex, self, index);
25442582
}
25452583

2584+
void rugged_parse_apply_options(git_apply_options *opts, git_apply_location_t *location, VALUE rb_options)
2585+
{
2586+
if (!NIL_P(rb_options)) {
2587+
VALUE rb_value;
2588+
Check_Type(rb_options, T_HASH);
2589+
2590+
rb_value = rb_hash_aref(rb_options, CSTR2SYM("location"));
2591+
if (!NIL_P(rb_value)) {
2592+
ID id_location;
2593+
2594+
Check_Type(rb_value, T_SYMBOL);
2595+
id_location = SYM2ID(rb_value);
2596+
2597+
if (id_location == rb_intern("both")) {
2598+
*location = GIT_APPLY_LOCATION_BOTH;
2599+
} else if (id_location == rb_intern("index")) {
2600+
*location = GIT_APPLY_LOCATION_INDEX;
2601+
} else if (id_location == rb_intern("workdir")) {
2602+
*location = GIT_APPLY_LOCATION_WORKDIR;
2603+
} else {
2604+
rb_raise(rb_eTypeError,
2605+
"Invalid location. Expected `:both`, `:index`, or `:workdir`");
2606+
}
2607+
}
2608+
}
2609+
}
2610+
25462611
void Init_rugged_repo(void)
25472612
{
25482613
id_call = rb_intern("call");
@@ -2598,6 +2663,8 @@ void Init_rugged_repo(void)
25982663
rb_define_method(rb_cRuggedRepo, "merge_analysis", rb_git_repo_merge_analysis, -1);
25992664
rb_define_method(rb_cRuggedRepo, "merge_commits", rb_git_repo_merge_commits, -1);
26002665

2666+
rb_define_method(rb_cRuggedRepo, "apply", rb_git_repo_apply, -1);
2667+
26012668
rb_define_method(rb_cRuggedRepo, "revert_commit", rb_git_repo_revert_commit, -1);
26022669

26032670
rb_define_method(rb_cRuggedRepo, "path_ignored?", rb_git_repo_is_path_ignored, 1);

test/repo_apply_test.rb

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
require 'test_helper'
2+
require 'base64'
3+
4+
module RepositoryApplyTestHelpers
5+
def blob_contents(repo, path)
6+
repo.lookup(repo.head.target.tree[path][:oid]).content
7+
end
8+
9+
def update_file(repo, path)
10+
original = blob_contents(repo, path)
11+
content = new_content(original)
12+
blob = repo.write(content, :blob)
13+
14+
index = repo.index
15+
index.read_tree(repo.head.target.tree)
16+
index.add(:path => path, :oid => blob, :mode => 0100644)
17+
new_tree = index.write_tree(repo)
18+
19+
oid = do_commit(repo, new_tree, "Update #{path}")
20+
21+
return repo.lookup(oid), content, original
22+
end
23+
24+
def do_commit(repo, tree, message)
25+
Rugged::Commit.create(repo,
26+
:tree => tree,
27+
:author => person,
28+
:committer => person,
29+
:message => message,
30+
:parents => repo.empty? ? [] : [ repo.head.target ].compact,
31+
:update_ref => 'HEAD',
32+
)
33+
end
34+
35+
def new_content(original)
36+
"#{original}Some new line\n"
37+
end
38+
39+
def person
40+
{:name => 'Scott', :email => '[email protected]', :time => Time.now }
41+
end
42+
end
43+
44+
class RepositoryApplyTest < Rugged::TestCase
45+
include RepositoryApplyTestHelpers
46+
47+
def setup
48+
@repo = FixtureRepo.from_libgit2("testrepo")
49+
end
50+
51+
def test_apply_index
52+
original_commit = @repo.head.target.oid
53+
new_commit, new_content, original_content = update_file(@repo, 'README')
54+
55+
assert_equal @repo.lookup(@repo.index["README"][:oid]).content, new_content
56+
57+
diff = @repo.diff(new_commit, original_commit)
58+
59+
assert_equal true, @repo.apply(diff, {:location => :index})
60+
assert_equal @repo.lookup(@repo.index["README"][:oid]).content, original_content
61+
end
62+
63+
def test_apply_workdir
64+
original_commit = @repo.head.target.oid
65+
new_commit, new_content, original_content = update_file(@repo, 'README')
66+
67+
@repo.checkout_head(:strategy => :force)
68+
assert_equal File.read(File.join(@repo.workdir, 'README')), new_content
69+
70+
diff = @repo.diff(new_commit, original_commit)
71+
72+
assert_equal true, @repo.apply(diff, {:location => :workdir})
73+
assert_equal File.read(File.join(@repo.workdir, 'README')), original_content
74+
end
75+
76+
def test_apply_both
77+
original_commit = @repo.head.target.oid
78+
new_commit, new_content, original_content = update_file(@repo, 'README')
79+
80+
@repo.checkout_head(:strategy => :force)
81+
assert_equal @repo.lookup(@repo.index["README"][:oid]).content, new_content
82+
assert_equal File.read(File.join(@repo.workdir, 'README')), new_content
83+
84+
diff = @repo.diff(new_commit, original_commit)
85+
86+
assert_equal true, @repo.apply(diff)
87+
assert_equal @repo.lookup(@repo.index["README"][:oid]).content, original_content
88+
assert_equal File.read(File.join(@repo.workdir, 'README')), original_content
89+
end
90+
91+
def test_location_option
92+
original_commit = @repo.head.target.oid
93+
new_commit, new_content, original_content = update_file(@repo, 'README')
94+
95+
diff = @repo.diff(new_commit, original_commit)
96+
97+
assert_raises TypeError do
98+
@repo.apply(diff, :location => :invalid)
99+
end
100+
end
101+
end

vendor/libgit2

Submodule libgit2 updated 5989 files

0 commit comments

Comments
 (0)