rugged 0.22.0b5 → 0.22.1b1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +19 -3
  3. data/ext/rugged/extconf.rb +21 -5
  4. data/ext/rugged/rugged.c +1 -0
  5. data/ext/rugged/rugged.h +8 -0
  6. data/ext/rugged/rugged_backend.c +34 -0
  7. data/ext/rugged/rugged_branch_collection.c +1 -0
  8. data/ext/rugged/rugged_remote.c +37 -86
  9. data/ext/rugged/rugged_remote_collection.c +2 -1
  10. data/ext/rugged/rugged_repo.c +149 -24
  11. data/ext/rugged/rugged_revwalk.c +1 -2
  12. data/ext/rugged/rugged_submodule.c +1 -1
  13. data/ext/rugged/rugged_tree.c +69 -5
  14. data/lib/rugged/version.rb +1 -1
  15. data/vendor/libgit2/CMakeLists.txt +2 -1
  16. data/vendor/libgit2/include/git2.h +0 -1
  17. data/vendor/libgit2/include/git2/checkout.h +8 -0
  18. data/vendor/libgit2/include/git2/merge.h +8 -0
  19. data/vendor/libgit2/include/git2/push.h +0 -110
  20. data/vendor/libgit2/include/git2/remote.h +30 -1
  21. data/vendor/libgit2/include/git2/revert.h +1 -1
  22. data/vendor/libgit2/include/git2/submodule.h +80 -1
  23. data/vendor/libgit2/include/git2/sys/index.h +2 -2
  24. data/vendor/libgit2/include/git2/{threads.h → sys/openssl.h} +10 -12
  25. data/vendor/libgit2/include/git2/sys/refs.h +11 -0
  26. data/vendor/libgit2/include/git2/tree.h +1 -1
  27. data/vendor/libgit2/include/git2/version.h +3 -3
  28. data/vendor/libgit2/src/attr_file.c +3 -1
  29. data/vendor/libgit2/src/buffer.c +2 -1
  30. data/vendor/libgit2/src/checkout.c +135 -39
  31. data/vendor/libgit2/src/checkout.h +7 -0
  32. data/vendor/libgit2/src/config_file.c +5 -7
  33. data/vendor/libgit2/src/crlf.c +2 -0
  34. data/vendor/libgit2/src/describe.c +6 -2
  35. data/vendor/libgit2/src/diff.c +1 -0
  36. data/vendor/libgit2/src/fileops.c +87 -19
  37. data/vendor/libgit2/src/fileops.h +18 -0
  38. data/vendor/libgit2/src/global.c +1 -1
  39. data/vendor/libgit2/src/ident.c +2 -0
  40. data/vendor/libgit2/src/index.c +4 -4
  41. data/vendor/libgit2/src/merge.c +3 -1
  42. data/vendor/libgit2/src/notes.c +1 -1
  43. data/vendor/libgit2/src/pack.c +1 -0
  44. data/vendor/libgit2/src/path.c +17 -12
  45. data/vendor/libgit2/src/path.h +17 -3
  46. data/vendor/libgit2/src/push.h +110 -0
  47. data/vendor/libgit2/src/rebase.c +4 -2
  48. data/vendor/libgit2/src/remote.c +237 -16
  49. data/vendor/libgit2/src/remote.h +2 -0
  50. data/vendor/libgit2/src/repository.c +7 -3
  51. data/vendor/libgit2/src/submodule.c +229 -18
  52. data/vendor/libgit2/src/transports/local.c +61 -2
  53. data/vendor/libgit2/src/transports/smart_protocol.c +5 -3
  54. data/vendor/libgit2/src/tree.c +2 -2
  55. data/vendor/libgit2/src/util.h +13 -2
  56. data/vendor/libgit2/src/win32/mingw-compat.h +2 -0
  57. data/vendor/libgit2/src/win32/path_w32.h +2 -0
  58. metadata +4 -4
  59. data/vendor/libgit2/cmake/Modules/FindLIBSSH2.cmake +0 -44
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 096ce237a96fe39032ff6e26839007148fb90ea8
4
- data.tar.gz: 4a8b6154d4ef9c9be73f6c473d8edcd7eede1747
3
+ metadata.gz: a920e7f6ad886a0730f1b80b91990956469eb3c8
4
+ data.tar.gz: bc69152690eeea81ab3f2e0749a967de27b3107c
5
5
  SHA512:
6
- metadata.gz: 340fe46665f934cb4925d9ac63153107e322f06335753c753f09314515658ae8fd50d127084afc22904d9ee6730e9f933b27a9e8043fc8fc7df484ac722cc553
7
- data.tar.gz: ce7e75586a31232cda3b5a61c7742ba9a1d5f82b6f9fad14d6da8d346f73e44505195ee8a5d50a444ec04218f25701665133fe0a31b67ec378e5ca877dc2cdbe
6
+ metadata.gz: f26e34ae5df319b467d5348039255f0d4e1c8d885b6d11ec65511664b1e2a1d468369305dd383ab8084bc8566f12ab95caa2cade4698f9742d0d69ffff338323
7
+ data.tar.gz: e38f35f6abf4d6f08797c966c7e3a40508b771ed3f29c72e1dac56f4787c981ff9848a25142ff057924a2a53d139f22f33fa84f0b0e4a546951697e0c6917330
data/README.md CHANGED
@@ -27,7 +27,7 @@ If you want to build Rugged with HTTPS and SSH support, check out the list of op
27
27
  If you're using bundler and want to bundle `libgit2` with Rugged, you can use the `:submodules` option:
28
28
 
29
29
  ```ruby
30
- gem 'rugged', git: 'git://github.com/libgit2/rugged.git', branch: 'development', submodules: true
30
+ gem 'rugged', git: 'git://github.com/libgit2/rugged.git', submodules: true
31
31
  ```
32
32
 
33
33
  To load Rugged, you'll usually want to add something like this:
@@ -267,11 +267,11 @@ You can also write trees with the `TreeBuilder`:
267
267
 
268
268
  ```ruby
269
269
  oid = repo.write("This is a blob.", :blob)
270
- builder = Rugged::Tree::Builder.new
270
+ builder = Rugged::Tree::Builder.new(repo)
271
271
  builder << { :type => :blob, :name => "README.md", :oid => oid, :filemode => 0100644 }
272
272
 
273
273
  options = {}
274
- options[:tree] = builder.write(repo)
274
+ options[:tree] = builder.write
275
275
 
276
276
  options[:author] = { :email => "testuser@github.com", :name => 'Test Author', :time => Time.now }
277
277
  options[:committer] = { :email => "testuser@github.com", :name => 'Test Author', :time => Time.now }
@@ -569,6 +569,22 @@ Rugged.raw_to_hex("\277\336Y\315\320\337\254\035\211(\024\366j\225d\032\275\212\
569
569
 
570
570
  ---
571
571
 
572
+ ### Alternative backends
573
+
574
+ You can store bare repositories in alternative backends instead of storing on disk. (see
575
+ `redbadger/rugged-redis` for an example of how a rugged backend works).
576
+
577
+ ```ruby
578
+ a_backend = Rugged::InMemory::Backend.new(opt1: 'setting', opt2: 'setting')
579
+
580
+ repo = Rugged::Repository.init_at('repo_name', :bare, backend: a_backend)
581
+
582
+ # or
583
+
584
+ repo = Rugged::Repository.bare('repo_name', backend: a_backend)
585
+ ```
586
+ ---
587
+
572
588
  ## Contributing
573
589
 
574
590
  Fork libgit2/rugged on GitHub, make it awesomer (preferably in a branch named
@@ -19,15 +19,34 @@ if !(MAKE = find_executable('gmake') || find_executable('make'))
19
19
  abort "ERROR: GNU make is required to build Rugged."
20
20
  end
21
21
 
22
+ CWD = File.expand_path(File.dirname(__FILE__))
23
+ LIBGIT2_DIR = File.join(CWD, '..', '..', 'vendor', 'libgit2')
24
+
22
25
  if arg_config("--use-system-libraries", !!ENV['RUGGED_USE_SYSTEM_LIBRARIES'])
23
26
  puts "Building Rugged using system libraries.\n"
24
27
 
25
28
  dir_config('git2').any? or pkg_config('libgit2')
26
29
 
27
- try_compile(<<-SRC) or abort "libgit2 version is not compatible"
30
+ major = minor = nil
31
+
32
+ File.readlines(File.join(LIBGIT2_DIR, "include", "git2", "version.h")).each do |line|
33
+ if !major && (matches = line.match(/^#define LIBGIT2_VER_MAJOR ([0-9]+)$/))
34
+ major = matches[1]
35
+ next
36
+ end
37
+
38
+ if !minor && (matches = line.match(/^#define LIBGIT2_VER_MINOR ([0-9]+)$/))
39
+ minor = matches[1]
40
+ next
41
+ end
42
+
43
+ break if major && minor
44
+ end
45
+
46
+ try_compile(<<-SRC) or abort "libgit2 version is not compatible, expected ~> #{major}.#{minor}.0"
28
47
  #include <git2/version.h>
29
48
 
30
- #if LIBGIT2_SOVERSION != 21
49
+ #if LIBGIT2_VER_MAJOR != #{major} || LIBGIT2_VER_MINOR != #{minor}
31
50
  #error libgit2 version is not compatible
32
51
  #endif
33
52
  SRC
@@ -40,9 +59,6 @@ else
40
59
  abort "ERROR: pkg-config is required to build Rugged."
41
60
  end
42
61
 
43
- CWD = File.expand_path(File.dirname(__FILE__))
44
- LIBGIT2_DIR = File.join(CWD, '..', '..', 'vendor', 'libgit2')
45
-
46
62
  Dir.chdir(LIBGIT2_DIR) do
47
63
  Dir.mkdir("build") if !Dir.exists?("build")
48
64
 
@@ -456,6 +456,7 @@ void Init_rugged(void)
456
456
  Init_rugged_diff_line();
457
457
  Init_rugged_blame();
458
458
  Init_rugged_cred();
459
+ Init_rugged_backend();
459
460
 
460
461
  /*
461
462
  * Sort the repository contents in no particular ordering;
@@ -74,6 +74,7 @@ void Init_rugged_diff_hunk(void);
74
74
  void Init_rugged_diff_line(void);
75
75
  void Init_rugged_blame(void);
76
76
  void Init_rugged_cred(void);
77
+ void Init_rugged_backend(void);
77
78
 
78
79
  VALUE rb_git_object_init(git_otype type, int argc, VALUE *argv, VALUE self);
79
80
 
@@ -153,6 +154,7 @@ struct rugged_remote_cb_payload
153
154
  VALUE transfer_progress;
154
155
  VALUE update_tips;
155
156
  VALUE credentials;
157
+ VALUE result;
156
158
  int exception;
157
159
  };
158
160
 
@@ -174,4 +176,10 @@ static inline VALUE rugged_create_oid(const git_oid *oid)
174
176
  return rb_str_new(out, 40);
175
177
  }
176
178
 
179
+
180
+ typedef struct _rugged_backend {
181
+ int (* odb_backend)(git_odb_backend **backend_out, struct _rugged_backend *backend, const char* path);
182
+ int (* refdb_backend)(git_refdb_backend **backend_out, struct _rugged_backend *backend, const char* path);
183
+ } rugged_backend;
184
+
177
185
  #endif
@@ -0,0 +1,34 @@
1
+ /*
2
+ * The MIT License
3
+ *
4
+ * Copyright (c) 2014 GitHub, Inc
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ * of this software and associated documentation files (the "Software"), to deal
8
+ * in the Software without restriction, including without limitation the rights
9
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ * copies of the Software, and to permit persons to whom the Software is
11
+ * furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be included in
14
+ * all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ * THE SOFTWARE.
23
+ */
24
+
25
+ #include "rugged.h"
26
+
27
+ extern VALUE rb_mRugged;
28
+
29
+ VALUE rb_cRuggedBackend;
30
+
31
+ void Init_rugged_backend(void)
32
+ {
33
+ rb_cRuggedBackend = rb_define_class_under(rb_mRugged, "Backend", rb_cObject);
34
+ }
@@ -235,6 +235,7 @@ static VALUE each_branch(int argc, VALUE *argv, VALUE self, int branch_names_onl
235
235
  Data_Get_Struct(rb_repo, git_repository, repo);
236
236
 
237
237
  error = git_branch_iterator_new(&iter, repo, filter);
238
+ rugged_exception_check(error);
238
239
 
239
240
  if (branch_names_only) {
240
241
  git_reference *branch;
@@ -29,7 +29,7 @@ extern VALUE rb_cRuggedRepo;
29
29
  extern VALUE rb_eRuggedError;
30
30
  VALUE rb_cRuggedRemote;
31
31
 
32
- #define RUGGED_REMOTE_CALLBACKS_INIT {1, progress_cb, NULL, credentials_cb, NULL, transfer_progress_cb, update_tips_cb, NULL}
32
+ #define RUGGED_REMOTE_CALLBACKS_INIT {1, progress_cb, NULL, credentials_cb, NULL, transfer_progress_cb, update_tips_cb, NULL, NULL, push_update_reference_cb, NULL}
33
33
 
34
34
  static int progress_cb(const char *str, int len, void *data)
35
35
  {
@@ -69,6 +69,15 @@ static int transfer_progress_cb(const git_transfer_progress *stats, void *data)
69
69
  return payload->exception ? GIT_ERROR : GIT_OK;
70
70
  }
71
71
 
72
+ static int push_update_reference_cb(const char *refname, const char *status, void *data) {
73
+ struct rugged_remote_cb_payload *payload = data;
74
+
75
+ if (status != NULL)
76
+ rb_hash_aset(payload->result, rb_str_new_utf8(refname), rb_str_new_utf8(status));
77
+
78
+ return GIT_OK;
79
+ }
80
+
72
81
  static int update_tips_cb(const char *refname, const git_oid *src, const git_oid *dest, void *data)
73
82
  {
74
83
  struct rugged_remote_cb_payload *payload = data;
@@ -164,10 +173,12 @@ void rugged_remote_init_callbacks_and_payload_from_options(
164
173
  prefilled.payload = payload;
165
174
  memcpy(callbacks, &prefilled, sizeof(git_remote_callbacks));
166
175
 
167
- CALLABLE_OR_RAISE(payload->update_tips, rb_options, "update_tips");
168
- CALLABLE_OR_RAISE(payload->progress, rb_options, "progress");
169
- CALLABLE_OR_RAISE(payload->transfer_progress, rb_options, "transfer_progress");
170
- CALLABLE_OR_RAISE(payload->credentials, rb_options, "credentials");
176
+ if (!NIL_P(rb_options)) {
177
+ CALLABLE_OR_RAISE(payload->update_tips, rb_options, "update_tips");
178
+ CALLABLE_OR_RAISE(payload->progress, rb_options, "progress");
179
+ CALLABLE_OR_RAISE(payload->transfer_progress, rb_options, "transfer_progress");
180
+ CALLABLE_OR_RAISE(payload->credentials, rb_options, "credentials");
181
+ }
171
182
  }
172
183
 
173
184
  static void rb_git_remote__free(git_remote *remote)
@@ -237,7 +248,7 @@ static VALUE rb_git_remote_ls(int argc, VALUE *argv, VALUE self)
237
248
  git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
238
249
  const git_remote_head **heads;
239
250
 
240
- struct rugged_remote_cb_payload payload = { Qnil, Qnil, Qnil, Qnil, Qnil, 0 };
251
+ struct rugged_remote_cb_payload payload = { Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, 0 };
241
252
 
242
253
  VALUE rb_options;
243
254
 
@@ -251,8 +262,7 @@ static VALUE rb_git_remote_ls(int argc, VALUE *argv, VALUE self)
251
262
  if (!rb_block_given_p())
252
263
  return rb_funcall(self, rb_intern("to_enum"), 2, CSTR2SYM("ls"), rb_options);
253
264
 
254
- if (!NIL_P(rb_options))
255
- rugged_remote_init_callbacks_and_payload_from_options(rb_options, &callbacks, &payload);
265
+ rugged_remote_init_callbacks_and_payload_from_options(rb_options, &callbacks, &payload);
256
266
 
257
267
  if ((error = git_remote_set_callbacks(remote, &callbacks)) ||
258
268
  (error = git_remote_connect(remote, GIT_DIRECTION_FETCH)) ||
@@ -527,7 +537,7 @@ static VALUE rb_git_remote_check_connection(int argc, VALUE *argv, VALUE self)
527
537
  {
528
538
  git_remote *remote;
529
539
  git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
530
- struct rugged_remote_cb_payload payload = { Qnil, Qnil, Qnil, Qnil, Qnil, 0 };
540
+ struct rugged_remote_cb_payload payload = { Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, 0 };
531
541
  VALUE rb_direction, rb_options;
532
542
  ID id_direction;
533
543
  int error, direction;
@@ -544,8 +554,7 @@ static VALUE rb_git_remote_check_connection(int argc, VALUE *argv, VALUE self)
544
554
  else
545
555
  rb_raise(rb_eTypeError, "Invalid direction. Expected :fetch or :push");
546
556
 
547
- if (!NIL_P(rb_options))
548
- rugged_remote_init_callbacks_and_payload_from_options(rb_options, &callbacks, &payload);
557
+ rugged_remote_init_callbacks_and_payload_from_options(rb_options, &callbacks, &payload);
549
558
 
550
559
  if ((error = git_remote_set_callbacks(remote, &callbacks)) < 0)
551
560
  goto cleanup;
@@ -618,7 +627,7 @@ static VALUE rb_git_remote_fetch(int argc, VALUE *argv, VALUE self)
618
627
  git_signature *signature = NULL;
619
628
  git_strarray refspecs;
620
629
  git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
621
- struct rugged_remote_cb_payload payload = { Qnil, Qnil, Qnil, Qnil, Qnil, 0 };
630
+ struct rugged_remote_cb_payload payload = { Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, 0 };
622
631
 
623
632
  char *log_message = NULL;
624
633
  int error;
@@ -633,6 +642,8 @@ static VALUE rb_git_remote_fetch(int argc, VALUE *argv, VALUE self)
633
642
  rugged_check_repo(rb_repo);
634
643
  Data_Get_Struct(rb_repo, git_repository, repo);
635
644
 
645
+ rugged_remote_init_callbacks_and_payload_from_options(rb_options, &callbacks, &payload);
646
+
636
647
  if (!NIL_P(rb_options)) {
637
648
  VALUE rb_val = rb_hash_aref(rb_options, CSTR2SYM("signature"));
638
649
  if (!NIL_P(rb_val))
@@ -641,8 +652,6 @@ static VALUE rb_git_remote_fetch(int argc, VALUE *argv, VALUE self)
641
652
  rb_val = rb_hash_aref(rb_options, CSTR2SYM("message"));
642
653
  if (!NIL_P(rb_val))
643
654
  log_message = StringValueCStr(rb_val);
644
-
645
- rugged_remote_init_callbacks_and_payload_from_options(rb_options, &callbacks, &payload);
646
655
  }
647
656
 
648
657
  if ((error = git_remote_set_callbacks(remote, &callbacks)))
@@ -674,15 +683,6 @@ static VALUE rb_git_remote_fetch(int argc, VALUE *argv, VALUE self)
674
683
  return rb_result;
675
684
  }
676
685
 
677
- static int push_status_cb(const char *ref, const char *msg, void *payload)
678
- {
679
- VALUE rb_result_hash = (VALUE)payload;
680
- if (msg != NULL)
681
- rb_hash_aset(rb_result_hash, rb_str_new_utf8(ref), rb_str_new_utf8(msg));
682
-
683
- return GIT_OK;
684
- }
685
-
686
686
  /*
687
687
  * call-seq:
688
688
  * remote.push(refspecs = nil, options = {}) -> hash
@@ -721,36 +721,30 @@ static VALUE rb_git_remote_push(int argc, VALUE *argv, VALUE self)
721
721
  {
722
722
  VALUE rb_refspecs, rb_options, rb_val;
723
723
  VALUE rb_repo = rugged_owner(self);
724
- VALUE rb_exception = Qnil, rb_result = rb_hash_new();
725
724
 
726
725
  git_repository *repo;
727
- git_remote *remote, *tmp_remote = NULL;
726
+ git_remote *remote;
728
727
  git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
729
- git_push *push = NULL;
730
728
  git_signature *signature = NULL;
729
+ git_strarray refspecs;
730
+ git_push_options opts = GIT_PUSH_OPTIONS_INIT;
731
731
 
732
- int error = 0, i = 0;
732
+ int error = 0;
733
733
  char *log_message = NULL;
734
734
 
735
- struct rugged_remote_cb_payload payload = { Qnil, Qnil, Qnil, Qnil, 0 };
735
+ struct rugged_remote_cb_payload payload = { Qnil, Qnil, Qnil, Qnil, Qnil, rb_hash_new(), 0 };
736
736
 
737
737
  rb_scan_args(argc, argv, "01:", &rb_refspecs, &rb_options);
738
738
 
739
- if (!NIL_P(rb_refspecs)) {
740
- Check_Type(rb_refspecs, T_ARRAY);
741
- for (i = 0; i < RARRAY_LEN(rb_refspecs); ++i) {
742
- VALUE rb_refspec = rb_ary_entry(rb_refspecs, i);
743
- Check_Type(rb_refspec, T_STRING);
744
- }
745
- }
739
+ rugged_rb_ary_to_strarray(rb_refspecs, &refspecs);
746
740
 
747
741
  rugged_check_repo(rb_repo);
748
742
  Data_Get_Struct(rb_repo, git_repository, repo);
749
743
  Data_Get_Struct(self, git_remote, remote);
750
744
 
751
- if (!NIL_P(rb_options)) {
752
- rugged_remote_init_callbacks_and_payload_from_options(rb_options, &callbacks, &payload);
745
+ rugged_remote_init_callbacks_and_payload_from_options(rb_options, &callbacks, &payload);
753
746
 
747
+ if (!NIL_P(rb_options)) {
754
748
  rb_val = rb_hash_aref(rb_options, CSTR2SYM("message"));
755
749
  if (!NIL_P(rb_val))
756
750
  log_message = StringValueCStr(rb_val);
@@ -760,64 +754,21 @@ static VALUE rb_git_remote_push(int argc, VALUE *argv, VALUE self)
760
754
  signature = rugged_signature_get(rb_val, repo);
761
755
  }
762
756
 
763
- // Create a temporary remote that we use for pushing
764
- if ((error = git_remote_dup(&tmp_remote, remote)) ||
765
- (error = git_remote_set_callbacks(tmp_remote, &callbacks)))
757
+ if ((error = git_remote_set_callbacks(remote, &callbacks)))
766
758
  goto cleanup;
767
759
 
768
- if (!NIL_P(rb_refspecs)) {
769
- git_remote_clear_refspecs(tmp_remote);
770
-
771
- for (i = 0; !error && i < RARRAY_LEN(rb_refspecs); ++i) {
772
- VALUE rb_refspec = rb_ary_entry(rb_refspecs, i);
773
-
774
- if ((error = git_remote_add_push(tmp_remote, StringValueCStr(rb_refspec))))
775
- goto cleanup;
776
- }
777
- }
778
-
779
- if ((error = git_push_new(&push, tmp_remote)))
780
- goto cleanup;
781
-
782
- // TODO: Get rid of this once git_remote_push lands in libgit2.
783
- {
784
- git_strarray push_refspecs;
785
- size_t i;
786
-
787
- if ((error = git_remote_get_push_refspecs(&push_refspecs, tmp_remote)))
788
- goto cleanup;
789
-
790
- if (push_refspecs.count == 0) {
791
- rb_exception = rb_exc_new2(rb_eRuggedError, "no pushspecs are configured for the given remote");
792
- goto cleanup;
793
- }
794
-
795
- for (i = 0; !error && i < push_refspecs.count; ++i) {
796
- error = git_push_add_refspec(push, push_refspecs.strings[i]);
797
- }
798
-
799
- git_strarray_free(&push_refspecs);
800
- if (error) goto cleanup;
801
- }
802
-
803
- if ((error = git_push_finish(push)))
804
- goto cleanup;
805
-
806
- if ((error = git_push_status_foreach(push, &push_status_cb, (void *)rb_result)) ||
807
- (error = git_push_update_tips(push, signature, log_message)))
808
- goto cleanup;
760
+ error = git_remote_push(remote, &refspecs, &opts, signature, log_message);
809
761
 
810
762
  cleanup:
811
- git_push_free(push);
812
- git_remote_free(tmp_remote);
763
+ xfree(refspecs.strings);
813
764
  git_signature_free(signature);
814
765
 
815
- if (!NIL_P(rb_exception))
816
- rb_exc_raise(rb_exception);
766
+ if (payload.exception)
767
+ rb_jump_tag(payload.exception);
817
768
 
818
769
  rugged_exception_check(error);
819
770
 
820
- return rb_result;
771
+ return payload.result;
821
772
  }
822
773
 
823
774
  void Init_rugged_remote(void)
@@ -251,7 +251,8 @@ static VALUE rb_git_remote_collection_rename(VALUE self, VALUE rb_name_or_remote
251
251
  {
252
252
  VALUE rb_repo = rugged_owner(self);
253
253
  git_repository *repo;
254
- int i, error, exception;
254
+ size_t i;
255
+ int error, exception;
255
256
  git_strarray problems;
256
257
 
257
258
  if (!rb_block_given_p())
@@ -24,6 +24,9 @@
24
24
 
25
25
  #include "rugged.h"
26
26
  #include <git2/sys/repository.h>
27
+ #include <git2/sys/odb_backend.h>
28
+ #include <git2/sys/refdb_backend.h>
29
+ #include <git2/refs.h>
27
30
 
28
31
  extern VALUE rb_mRugged;
29
32
  extern VALUE rb_eRuggedError;
@@ -35,6 +38,7 @@ extern VALUE rb_cRuggedCommit;
35
38
  extern VALUE rb_cRuggedTag;
36
39
  extern VALUE rb_cRuggedTree;
37
40
  extern VALUE rb_cRuggedReference;
41
+ extern VALUE rb_cRuggedBackend;
38
42
 
39
43
  extern VALUE rb_cRuggedCredPlaintext;
40
44
  extern VALUE rb_cRuggedCredSshKey;
@@ -182,9 +186,78 @@ static void load_alternates(git_repository *repo, VALUE rb_alternates)
182
186
  rugged_exception_check(error);
183
187
  }
184
188
 
189
+ static void rugged_repo_new_with_backend(git_repository **repo, VALUE rb_path, VALUE rb_backend)
190
+ {
191
+ char *path;
192
+
193
+ git_odb *odb = NULL;
194
+ git_odb_backend *odb_backend = NULL;
195
+ git_refdb *refdb = NULL;
196
+ git_refdb_backend *refdb_backend = NULL;
197
+ git_reference *head = NULL;
198
+ rugged_backend *backend;
199
+
200
+ int error = 0;
201
+
202
+ Check_Type(rb_path, T_STRING);
203
+ path = StringValueCStr(rb_path);
204
+
205
+ if (rb_obj_is_kind_of(rb_backend, rb_cRuggedBackend) == Qfalse) {
206
+ rb_raise(rb_eRuggedError, "Backend must be an instance of Rugged::Backend");
207
+ }
208
+
209
+ Data_Get_Struct(rb_backend, rugged_backend, backend);
210
+
211
+ error = git_odb_new(&odb);
212
+ if (error) goto cleanup;
213
+
214
+ error = backend->odb_backend(&odb_backend, backend, path);
215
+ if (error) goto cleanup;
216
+
217
+ error = git_odb_add_backend(odb, odb_backend, 1);
218
+ if (error) goto cleanup;
219
+
220
+ error = git_repository_wrap_odb(repo, odb);
221
+ if (error) goto cleanup;
222
+
223
+ error = git_refdb_new(&refdb, *repo);
224
+ if (error) goto cleanup;
225
+
226
+ error = backend->refdb_backend(&refdb_backend, backend, path);
227
+ if (error) goto cleanup;
228
+
229
+ error = git_refdb_set_backend(refdb, refdb_backend);
230
+ if (error) goto cleanup;
231
+
232
+ git_repository_set_refdb(*repo, refdb);
233
+
234
+ error = git_reference_lookup(&head, *repo, "HEAD");
235
+
236
+ if (error == GIT_ENOTFOUND) {
237
+ giterr_clear();
238
+ error = git_reference_symbolic_create(&head, *repo, "HEAD", "refs/heads/master", 0, NULL, NULL);
239
+ }
240
+
241
+ if (!error) {
242
+ git_reference_free(head);
243
+ return;
244
+ }
245
+
246
+ cleanup:
247
+ git_repository_free(*repo);
248
+ git_odb_free(odb);
249
+ git_refdb_free(refdb);
250
+
251
+ if (odb_backend != NULL) odb_backend->free(odb_backend);
252
+ if (refdb_backend != NULL) refdb_backend->free(refdb_backend);
253
+
254
+ rugged_exception_check(error);
255
+ }
256
+
185
257
  /*
186
258
  * call-seq:
187
- * Repository.bare(path[, alternates]) -> repository
259
+ * Repository.bare(path[, alternates]) -> repository OR
260
+ * Repository.bare(path[, options]) -> repository
188
261
  *
189
262
  * Open a bare Git repository at +path+ and return a +Repository+
190
263
  * object representing it.
@@ -193,23 +266,52 @@ static void load_alternates(git_repository *repo, VALUE rb_alternates)
193
266
  * any +.git+ directory discovery, won't try to load the config options to
194
267
  * determine whether the repository is bare and won't try to load the workdir.
195
268
  *
196
- * Optionally, you can pass a list of alternate object folders.
269
+ * Optionally, you can pass a list of alternate object folders or an options Hash.
197
270
  *
198
271
  * Rugged::Repository.bare(path, ['./other/repo/.git/objects'])
272
+ * Rugged::Repository.bare(path, opts)
273
+ *
274
+ * The following options can be passed in the +options+ Hash:
275
+ *
276
+ * :backend ::
277
+ * A Rugged::Backend instance
278
+ * :alternates ::
279
+ * A list of alternate object folders.
280
+ * Rugged::Repository.bare(path, :alternates => ['./other/repo/.git/objects'])
199
281
  */
200
282
  static VALUE rb_git_repo_open_bare(int argc, VALUE *argv, VALUE klass)
201
283
  {
202
- git_repository *repo;
284
+ git_repository *repo = NULL;
203
285
  int error = 0;
204
- VALUE rb_path, rb_alternates;
286
+ VALUE rb_path, rb_options, rb_alternates = 0;
205
287
 
206
- rb_scan_args(argc, argv, "11", &rb_path, &rb_alternates);
207
- Check_Type(rb_path, T_STRING);
288
+ rb_scan_args(argc, argv, "11", &rb_path, &rb_options);
208
289
 
209
- error = git_repository_open_bare(&repo, StringValueCStr(rb_path));
210
- rugged_exception_check(error);
290
+ if (!NIL_P(rb_options) && TYPE(rb_options) == T_ARRAY)
291
+ rb_alternates = rb_options;
292
+
293
+ if (!NIL_P(rb_options) && TYPE(rb_options) == T_HASH) {
294
+ /* Check for `:backend` */
295
+ VALUE rb_backend = rb_hash_aref(rb_options, CSTR2SYM("backend"));
296
+
297
+ if (!NIL_P(rb_backend)) {
298
+ rugged_repo_new_with_backend(&repo, rb_path, rb_backend);
299
+ }
211
300
 
212
- load_alternates(repo, rb_alternates);
301
+ /* Check for `:alternates` */
302
+ rb_alternates = rb_hash_aref(rb_options, CSTR2SYM("alternates"));
303
+ }
304
+
305
+ if (!repo) {
306
+ Check_Type(rb_path, T_STRING);
307
+
308
+ error = git_repository_open_bare(&repo, StringValueCStr(rb_path));
309
+ rugged_exception_check(error);
310
+ }
311
+
312
+ if (rb_alternates) {
313
+ load_alternates(repo, rb_alternates);
314
+ }
213
315
 
214
316
  return rugged_repo_new(klass, repo);
215
317
  }
@@ -235,7 +337,7 @@ static VALUE rb_git_repo_open_bare(int argc, VALUE *argv, VALUE klass)
235
337
  *
236
338
  * Examples:
237
339
  *
238
- * Rugged::Repository.new('~/test/.git') #=> #<Rugged::Repository:0x108849488>
340
+ * Rugged::Repository.new('test/.git') #=> #<Rugged::Repository:0x108849488>
239
341
  * Rugged::Repository.new(path, :alternates => ['./other/repo/.git/objects'])
240
342
  */
241
343
  static VALUE rb_git_repo_new(int argc, VALUE *argv, VALUE klass)
@@ -260,7 +362,7 @@ static VALUE rb_git_repo_new(int argc, VALUE *argv, VALUE klass)
260
362
 
261
363
  /*
262
364
  * call-seq:
263
- * Repository.init_at(path, is_bare = false) -> repository
365
+ * Repository.init_at(path, is_bare = false, opts = {}) -> repository
264
366
  *
265
367
  * Initialize a Git repository in +path+. This implies creating all the
266
368
  * necessary files on the FS, or re-initializing an already existing
@@ -272,19 +374,36 @@ static VALUE rb_git_repo_new(int argc, VALUE *argv, VALUE klass)
272
374
  * of +path+. Non-bare repositories are created in a +.git+ folder and
273
375
  * use +path+ as working directory.
274
376
  *
275
- * Rugged::Repository.init_at('~/repository', :bare) #=> #<Rugged::Repository:0x108849488>
377
+ * The following options can be passed in the +options+ Hash:
378
+ *
379
+ * :backend ::
380
+ * A Rugged::Backend instance
381
+ *
382
+ *
383
+ * Rugged::Repository.init_at('repository', :bare) #=> #<Rugged::Repository:0x108849488>
276
384
  */
277
385
  static VALUE rb_git_repo_init_at(int argc, VALUE *argv, VALUE klass)
278
386
  {
279
- git_repository *repo;
280
- VALUE rb_path, rb_is_bare;
387
+ git_repository *repo = NULL;
388
+ VALUE rb_path, rb_is_bare, rb_options;
389
+ int error;
281
390
 
282
- rb_scan_args(argc, argv, "11", &rb_path, &rb_is_bare);
391
+ rb_scan_args(argc, argv, "11:", &rb_path, &rb_is_bare, &rb_options);
283
392
  Check_Type(rb_path, T_STRING);
284
393
 
285
- rugged_exception_check(
286
- git_repository_init(&repo, StringValueCStr(rb_path), RTEST(rb_is_bare))
287
- );
394
+ if (!NIL_P(rb_options)) {
395
+ /* Check for `:backend` */
396
+ VALUE rb_backend = rb_hash_aref(rb_options, CSTR2SYM("backend"));
397
+
398
+ if (rb_backend && !NIL_P(rb_backend)) {
399
+ rugged_repo_new_with_backend(&repo, rb_path, rb_backend);
400
+ }
401
+ }
402
+
403
+ if(!repo) {
404
+ error = git_repository_init(&repo, StringValueCStr(rb_path), RTEST(rb_is_bare));
405
+ rugged_exception_check(error);
406
+ }
288
407
 
289
408
  return rugged_repo_new(klass, repo);
290
409
  }
@@ -526,19 +645,21 @@ static VALUE rb_git_repo_merge_base(VALUE self, VALUE rb_args)
526
645
  */
527
646
  static VALUE rb_git_repo_merge_bases(VALUE self, VALUE rb_args)
528
647
  {
529
- int error = GIT_OK, i;
648
+ int error = GIT_OK;
649
+ size_t i, len = (size_t)RARRAY_LEN(rb_args);
530
650
  git_repository *repo;
531
651
  git_oidarray bases = {NULL, 0};
532
- git_oid *input_array = xmalloc(sizeof(git_oid) * RARRAY_LEN(rb_args));
533
- int len = (int)RARRAY_LEN(rb_args);
652
+ git_oid *input_array;
534
653
 
535
654
  VALUE rb_bases;
536
655
 
537
656
  if (len < 2)
538
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 2+)", len);
657
+ rb_raise(rb_eArgError, "wrong number of arguments (%ld for 2+)", RARRAY_LEN(rb_args));
539
658
 
540
659
  Data_Get_Struct(self, git_repository, repo);
541
660
 
661
+ input_array = xmalloc(sizeof(git_oid) * len);
662
+
542
663
  for (i = 0; !error && i < len; ++i) {
543
664
  error = rugged_oid_get(&input_array[i], repo, rb_ary_entry(rb_args, i));
544
665
  }
@@ -585,7 +706,7 @@ static VALUE rb_git_repo_merge_bases(VALUE self, VALUE rb_args)
585
706
  * :fastforward ::
586
707
  * The given commit is a fast-forward from HEAD and no merge needs to be
587
708
  * performed. HEAD can simply be set to the given commit.
588
- *
709
+ *
589
710
  * :unborn ::
590
711
  * The HEAD of the current repository is "unborn" and does not point to
591
712
  * a valid commit. No merge can be performed, but the caller may wish
@@ -1116,8 +1237,12 @@ static VALUE rb_git_repo_get_head(VALUE self)
1116
1237
  static VALUE rb_git_repo_path(VALUE self)
1117
1238
  {
1118
1239
  git_repository *repo;
1240
+ const char *path;
1241
+
1119
1242
  Data_Get_Struct(self, git_repository, repo);
1120
- return rb_str_new_utf8(git_repository_path(repo));
1243
+ path = git_repository_path(repo);
1244
+
1245
+ return path ? rb_str_new_utf8(path) : Qnil;
1121
1246
  }
1122
1247
 
1123
1248
  /*