File Coverage

xs/Repository.xs
Criterion Covered Total %
statement 413 449 91.9
branch 153 196 78.0
condition n/a
subroutine n/a
pod n/a
total 566 645 87.7


line stmt bran cond sub pod time code
1             MODULE = Git::Raw PACKAGE = Git::Raw::Repository
2              
3             Repository
4             init(class, path, is_bare)
5             SV *class
6             SV *path
7             unsigned is_bare
8              
9             PREINIT:
10             int rc;
11 5           git_repository *r = NULL;
12 5           Repository repo = NULL;
13              
14             CODE:
15 5           rc = git_repository_init(
16             &r, git_ensure_pv(path, "path"), is_bare
17             );
18 5           git_check_error(rc);
19              
20 5           Newxz(repo, 1, git_raw_repository);
21 5           repo -> repository = r;
22 5           repo -> owned = 1;
23              
24 5           RETVAL = repo;
25              
26             OUTPUT: RETVAL
27              
28             Repository
29             clone(class, url, path, opts, ...)
30             SV *class
31             SV *url
32             SV *path
33             HV *opts
34              
35             PREINIT:
36             int rc;
37              
38             SV *opt;
39             HV *callbacks;
40 0           git_repository *r = NULL;
41 0           Repository repo = NULL;
42              
43 0           git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT;
44              
45             CODE:
46             /* Clone options */
47 0           git_hv_to_clone_opts(opts, &clone_opts);
48              
49             /* Fetch options */
50 0 0         if (items >= 5) {
51 0           git_hv_to_fetch_opts(
52 0           git_ensure_hv(ST(4), "fetch_opts"),
53             &clone_opts.fetch_opts
54             );
55             }
56              
57             /* Checkout options */
58 0 0         if (items >= 6) {
59 0           git_hv_to_checkout_opts(
60 0           git_ensure_hv(ST(5), "checkout_opts"),
61             &clone_opts.checkout_opts
62             );
63             }
64              
65 0           rc = git_clone(
66             &r, git_ensure_pv(url, "url"), git_ensure_pv(path, "path"),
67             &clone_opts
68             );
69 0           Safefree(clone_opts.checkout_opts.paths.strings);
70 0           git_check_error(rc);
71              
72 0           Newxz(repo, 1, git_raw_repository);
73 0           repo -> repository = r;
74 0           repo -> owned = 1;
75              
76 0           RETVAL = repo;
77              
78             OUTPUT: RETVAL
79              
80             Repository
81             open(class, path)
82             SV *class
83             SV *path
84              
85             PREINIT:
86             int rc;
87 29           git_repository *r = NULL;
88 29           Repository repo = NULL;
89              
90             CODE:
91 29           rc = git_repository_open(&r, git_ensure_pv(path, "path"));
92 29           git_check_error(rc);
93              
94 29           Newxz(repo, 1, git_raw_repository);
95 29           repo -> repository = r;
96 29           repo -> owned = 1;
97              
98 29           RETVAL = repo;
99              
100             OUTPUT: RETVAL
101              
102             Repository
103             discover(class, path)
104             SV *class
105             SV *path
106              
107             PREINIT:
108             int rc;
109              
110 1           git_repository *r = NULL;
111 1           Repository repo = NULL;
112              
113             CODE:
114 1           git_buf buf = GIT_BUF_INIT_CONST(NULL, 0);
115              
116 1           rc = git_buf_grow(&buf, GIT_PATH_MAX);
117 1           git_check_error(rc);
118              
119 1           rc = git_repository_discover(
120             &buf, git_ensure_pv(path, "path"), 1, NULL
121             );
122              
123 1 50         if (rc == GIT_OK)
124 1           rc = git_repository_open(&r, (const char*) buf.ptr);
125              
126 1           git_buf_dispose(&buf);
127 1           git_check_error(rc);
128              
129 1           Newxz(repo, 1, git_raw_repository);
130 1           repo -> repository = r;
131 1           repo -> owned = 1;
132              
133 1           RETVAL = repo;
134              
135             OUTPUT: RETVAL
136              
137             Repository
138             new(class)
139             SV *class
140              
141             PREINIT:
142             int rc;
143 0           git_repository *r = NULL;
144 0           Repository repo = NULL;
145              
146             CODE:
147 0           rc = git_repository_new(&r);
148 0           git_check_error(rc);
149              
150 0           Newxz(repo, 1, git_raw_repository);
151 0           repo -> repository = r;
152 0           repo -> owned = 1;
153              
154 0           RETVAL = repo;
155              
156             OUTPUT: RETVAL
157              
158             Config
159             config(self)
160             Repository self
161              
162             PREINIT:
163             int rc;
164             Config cfg;
165              
166             CODE:
167 14           rc = git_repository_config(&cfg, self -> repository);
168 14           git_check_error(rc);
169              
170 14           RETVAL = cfg;
171              
172             OUTPUT: RETVAL
173              
174             SV *
175             commondir(self)
176             Repository self
177              
178             PREINIT:
179             const char *path;
180              
181             CODE:
182 3           path = git_repository_commondir(self -> repository);
183 3           RETVAL = newSVpv(path, 0);
184              
185             OUTPUT: RETVAL
186              
187             SV *
188             index(self, ...)
189             SV *self
190              
191             PREINIT:
192             int rc;
193             Index index;
194              
195 18           Repository repo = NULL;
196              
197             CODE:
198 18           repo = GIT_SV_TO_PTR(Repository, self);
199 18 100         if (items >= 2) {
200             /* it is possible to remove the index by passing undef */
201 2 100         if (!SvOK(ST(1))) {
    50          
    50          
202 1           git_repository_set_index(repo -> repository, NULL);
203 1           XSRETURN_UNDEF;
204             }
205              
206 1           index = GIT_SV_TO_PTR(Index, ST(1));
207 1           git_repository_set_index(repo -> repository, index);
208 1           rc = git_repository_index(&index, repo -> repository);
209 1           git_check_error(rc);
210              
211             /* replace the underlying index pointer and associate it with this repository */
212 1           git_index_free(index);
213 1           GIT_SV_SET_PTR(Index, ST(1), index);
214 1           GIT_OBJ_SET_MAGIC(ST(1), SvRV(self));
215             }
216              
217 17           rc = git_repository_index(&index, repo -> repository);
218 17           git_check_error(rc);
219              
220 17           GIT_NEW_OBJ_WITH_MAGIC(
221             RETVAL, "Git::Raw::Index", index, SvRV(self)
222             );
223              
224             OUTPUT: RETVAL
225              
226             SV *
227             odb(self, ...)
228             SV *self
229              
230             PROTOTYPE: $;$$
231              
232             PREINIT:
233             int rc;
234             Odb out;
235             git_odb *odb;
236              
237 6           Repository repo = NULL;
238              
239             CODE:
240 6           repo = GIT_SV_TO_PTR(Repository, self);
241 6 100         if (items >= 2) {
242 2           Odb o = GIT_SV_TO_PTR(Odb, ST(1));
243 2           git_repository_set_odb(repo -> repository, o -> odb);
244              
245             /* associate with this repository */
246 2           SvREFCNT_dec(GIT_SV_TO_MAGIC(ST(1)));
247 2           GIT_OBJ_SET_MAGIC(ST(1), SvRV(self));
248             }
249              
250 6           rc = git_repository_odb(&odb, repo -> repository);
251 6           git_check_error(rc);
252              
253 6           Newxz(out, 1, git_raw_odb);
254 6           out -> odb = odb;
255              
256 6           GIT_NEW_OBJ_WITH_MAGIC(
257             RETVAL, "Git::Raw::Odb", out, SvRV(self)
258             );
259              
260             OUTPUT: RETVAL
261              
262             SV *
263             head(self, ...)
264             SV *self
265              
266             PROTOTYPE: $;$$
267              
268             PREINIT:
269             int rc;
270              
271             Reference head;
272             Repository repo;
273              
274             CODE:
275 78           repo = GIT_SV_TO_PTR(Repository, self);
276              
277 78 100         if (items >= 2) {
278 19           Reference new_head = GIT_SV_TO_PTR(Reference, ST(1));
279              
280 19           rc = git_repository_set_head(
281             repo -> repository, git_reference_name(new_head)
282             );
283 19           git_check_error(rc);
284             }
285              
286 78           rc = git_repository_head(&head, repo -> repository);
287 78           git_check_error(rc);
288              
289 77           GIT_NEW_OBJ_WITH_MAGIC(
290             RETVAL, "Git::Raw::Reference", head, SvRV(self)
291             );
292              
293             OUTPUT: RETVAL
294              
295             SV *
296             head_for_worktree(self, worktree)
297             SV *self
298             SV *worktree
299              
300             PREINIT:
301             int rc;
302              
303             Reference head;
304             Repository repo;
305              
306             CODE:
307 1           repo = GIT_SV_TO_PTR(Repository, self);
308              
309 1           rc = git_repository_head_for_worktree(&head,
310             repo -> repository, git_ensure_pv(worktree, "worktree"));
311 1           git_check_error(rc);
312              
313 1           GIT_NEW_OBJ_WITH_MAGIC(
314             RETVAL, "Git::Raw::Reference", head, SvRV(self)
315             );
316              
317             OUTPUT: RETVAL
318              
319             void
320             detach_head(self, commitish)
321             SV *self
322             SV *commitish
323              
324             PROTOTYPE: $$;$
325             PREINIT:
326             int rc;
327              
328             Repository repo;
329             git_oid id;
330              
331             CODE:
332 1           repo = GIT_SV_TO_PTR(Repository, self);
333              
334 1 50         if (git_sv_to_commitish(repo -> repository, commitish, &id) == NULL)
335 0           croak_resolve("Could not resolve 'commitish' to a commit id");
336              
337 1           rc = git_repository_set_head_detached(repo -> repository,
338             &id);
339 1           git_check_error(rc);
340              
341             SV *
342             lookup(self, id)
343             SV *self
344             SV *id
345              
346             PREINIT:
347             int rc;
348              
349             git_oid oid;
350             git_object *obj;
351              
352             STRLEN len;
353             const char *id_str;
354              
355 3           Repository repo = NULL;
356              
357             CODE:
358 3           id_str = git_ensure_pv_with_len(id, "id", &len);
359              
360 3           rc = git_oid_fromstrn(&oid, id_str, len);
361 3           git_check_error(rc);
362              
363 3           repo = GIT_SV_TO_PTR(Repository, self);
364 3           rc = git_object_lookup_prefix(
365             &obj, repo -> repository, &oid, len, GIT_OBJ_ANY
366             );
367              
368 3 100         if (rc == GIT_ENOTFOUND) {
369 1           RETVAL = &PL_sv_undef;
370             } else {
371 2           git_check_error(rc);
372 2           RETVAL = git_obj_to_sv(obj, SvRV(self));
373             }
374              
375             OUTPUT: RETVAL
376              
377             void
378             checkout(self, target, opts)
379             Repository self
380             SV *target
381             HV *opts
382              
383             PREINIT:
384             int rc;
385              
386 24           git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
387              
388             CODE:
389 24           git_hv_to_checkout_opts(opts, &checkout_opts);
390              
391 24           rc = git_checkout_tree(
392 24           self -> repository, git_sv_to_obj(target), &checkout_opts
393             );
394              
395 24           Safefree(checkout_opts.paths.strings);
396 24           git_check_error(rc);
397              
398             void
399             reset(self, target, opts)
400             Repository self
401             SV *target
402             HV *opts
403              
404             PREINIT:
405             int rc;
406              
407             SV *opt;
408             AV *lopt;
409              
410             CODE:
411 3 100         if ((lopt = git_hv_list_entry(opts, "paths"))) {
412             SV **path;
413              
414 1           size_t i = 0, count = 0;
415 1           git_strarray paths = {0, 0};
416              
417 3 100         while ((path = av_fetch(lopt, i++, 0))) {
418 2 100         if (!SvOK(*path))
    50          
    50          
419 1           continue;
420              
421 1 50         Renew(paths.strings, count + 1, char *);
422 1 50         paths.strings[count++] = SvPVbyte_nolen(*path);
423             }
424              
425 1           paths.count = count;
426              
427 1           rc = git_reset_default(self -> repository, git_sv_to_obj(target), &paths);
428 1           Safefree(paths.strings);
429 1           git_check_error(rc);
430 2 50         } else if ((opt = git_hv_string_entry(opts, "type"))) {
431 2           git_reset_t reset = GIT_RESET_SOFT;
432 2 50         const char *type_str = SvPVbyte_nolen(opt);
433              
434 2 50         if (strcmp(type_str, "soft") == 0)
435 0           reset = GIT_RESET_SOFT;
436 2 50         else if (strcmp(type_str, "mixed") == 0)
437 0           reset = GIT_RESET_MIXED;
438 2 100         else if (strcmp(type_str, "hard") == 0)
439 1           reset = GIT_RESET_HARD;
440             else
441 1           croak_usage("Invalid type '%s'. "
442             "Valid values: 'soft', 'mixed' or 'hard'",
443             type_str);
444              
445 1           rc = git_reset(self -> repository, git_sv_to_obj(target), reset, NULL);
446 1           git_check_error(rc);
447             }
448              
449             HV *
450             status(self, opts, ...)
451             Repository self
452             HV *opts
453              
454             PROTOTYPE: $$;@
455              
456             PREINIT:
457             int rc, i, count;
458              
459             SV *opt;
460             HV *status_hv, *hopt;
461              
462             git_status_list *list;
463 57           git_status_options status_opts = GIT_STATUS_OPTIONS_INIT;
464              
465             CODE:
466 57 100         if ((hopt = git_hv_hash_entry(opts, "flags")))
467 15           status_opts.flags = git_hv_to_status_flag(hopt);
468              
469 57 100         if ((opt = git_hv_string_entry(opts, "show"))) {
470 4 50         const char *show_str = SvPVbyte_nolen(opt);
471              
472 4 100         if (strcmp(show_str, "index_and_worktree") == 0)
473 1           status_opts.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
474 3 100         else if (strcmp(show_str, "index") == 0)
475 1           status_opts.show = GIT_STATUS_SHOW_INDEX_ONLY;
476 2 100         else if (strcmp(show_str, "worktree") == 0)
477 1           status_opts.show = GIT_STATUS_SHOW_WORKDIR_ONLY;
478             else
479 1           croak_usage("Invalid show value '%s'. "
480             "Valid values: 'index_and_worktree', 'index' or 'worktree'",
481             show_str);
482             }
483              
484 56 100         if (items > 2) {
485 6 50         Newx(status_opts.pathspec.strings, items - 2, char *);
486              
487 12 100         for (i = 2; i < items; i++) {
488 6           size_t index = (size_t) i - 2;
489 12           status_opts.pathspec.strings[index] =
490 6 50         SvPVbyte_nolen(ST(i));
491 6           status_opts.pathspec.count = index + 1;
492             }
493             }
494              
495 56           rc = git_status_list_new(&list, self -> repository, &status_opts);
496 56           Safefree(status_opts.pathspec.strings);
497 56           git_check_error(rc);
498              
499 56           count = (int) git_status_list_entrycount(list);
500              
501 56           status_hv = newHV();
502 110 100         for (i = 0; i < count; i++) {
503             AV *flags;
504             HV *file_status_hv;
505              
506 54           const char *path = NULL;
507 54           const git_status_entry *entry =
508 54           git_status_byindex(list, i);
509              
510 54           flags = newAV();
511              
512 54 100         if (entry -> status & GIT_STATUS_INDEX_NEW)
513 12           av_push(flags, newSVpv("index_new", 0));
514              
515 54 100         if (entry -> status & GIT_STATUS_INDEX_MODIFIED)
516 10           av_push(flags, newSVpv("index_modified", 0));
517              
518 54 100         if (entry -> status & GIT_STATUS_INDEX_DELETED)
519 1           av_push(flags, newSVpv("index_deleted", 0));
520              
521 54 100         if (entry -> status & GIT_STATUS_INDEX_RENAMED)
522 2           av_push(flags, newSVpv("index_renamed", 0));
523              
524 54 100         if (entry -> status & GIT_STATUS_WT_NEW)
525 21           av_push(flags, newSVpv("worktree_new", 0));
526              
527 54 100         if (entry -> status & GIT_STATUS_WT_MODIFIED)
528 9           av_push(flags, newSVpv("worktree_modified", 0));
529              
530 54 100         if (entry -> status & GIT_STATUS_WT_DELETED)
531 1           av_push(flags, newSVpv("worktree_deleted", 0));
532              
533 54 100         if (entry -> status & GIT_STATUS_WT_RENAMED)
534 1           av_push(flags, newSVpv("worktree_renamed", 0));
535              
536 54 50         if (entry -> status & GIT_STATUS_WT_UNREADABLE)
537 0           av_push(flags, newSVpv("worktree_unreadable", 0));
538              
539 54 100         if (entry -> status & GIT_STATUS_IGNORED)
540 4           av_push(flags, newSVpv("ignored", 0));
541              
542 54 50         if (entry -> status & GIT_STATUS_CONFLICTED)
543 0           av_push(flags, newSVpv("conflicted", 0));
544              
545 54           file_status_hv = newHV();
546              
547 54 100         if (entry -> index_to_workdir) {
548 36 100         if (entry -> status & GIT_STATUS_WT_RENAMED) {
549 1           HV *worktree_status_hv = newHV();
550              
551 1           hv_stores(worktree_status_hv, "old_file",
552             newSVpv(entry -> index_to_workdir -> old_file.path, 0));
553 1           hv_stores(file_status_hv, "worktree", newRV_noinc((SV *) worktree_status_hv));
554             }
555              
556 36           path = entry -> index_to_workdir -> new_file.path;
557             }
558              
559 54 100         if (entry -> head_to_index) {
560 25 100         if (entry -> status & GIT_STATUS_INDEX_RENAMED) {
561 2           HV *index_status_hv = newHV();
562              
563 2           hv_stores(index_status_hv, "old_file",
564             newSVpv(entry -> head_to_index -> old_file.path, 0));
565 2           hv_stores(file_status_hv, "index", newRV_noinc((SV *) index_status_hv));
566             }
567              
568 25 100         if (!path)
569 18           path = entry -> head_to_index -> new_file.path;
570             }
571              
572 54           hv_stores(file_status_hv, "flags", newRV_noinc((SV *) flags));
573 54           hv_store(status_hv, path, strlen(path), newRV_noinc((SV *) file_status_hv), 0);
574             }
575              
576 56           git_status_list_free(list);
577              
578 56           RETVAL = status_hv;
579              
580             OUTPUT: RETVAL
581              
582             void
583             is_worktree(self)
584             Repository self
585              
586             PPCODE:
587 2 100         if (git_repository_is_worktree (self -> repository))
588 1           XSRETURN_YES;
589              
590 1           XSRETURN_NO;
591              
592             SV *
593             path_is_ignored(self, path)
594             Repository self
595             const char *path
596              
597             PREINIT:
598             int rc, ignore;
599              
600             CODE:
601 3           rc = git_ignore_path_is_ignored(&ignore, self -> repository, path);
602 3           git_check_error(rc);
603              
604 3           RETVAL = newSViv(ignore);
605              
606             OUTPUT: RETVAL
607              
608             void
609             ignore(self, rules)
610             Repository self
611             SV *rules
612              
613             PREINIT:
614             int rc;
615              
616             CODE:
617 2           rc = git_ignore_add_rule(self -> repository, git_ensure_pv(rules, "rules"));
618 2           git_check_error(rc);
619              
620             SV *
621             diff(self, ...)
622             SV *self
623              
624             PROTOTYPE: $;$
625              
626             PREINIT:
627             int rc;
628              
629             Repository repo_ptr;
630             Diff diff;
631             Index index;
632              
633 7           Tree tree = NULL;
634              
635 7           git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT;
636              
637             CODE:
638 7           repo_ptr = GIT_SV_TO_PTR(Repository, self);
639              
640 7           rc = git_repository_index(&index, repo_ptr -> repository);
641 7           git_check_error(rc);
642              
643 7 50         if (items == 2) {
644 7           HV *opts = git_ensure_hv(ST(1), "diff_opts");
645 7           git_hv_to_diff_opts(opts, &diff_opts, &tree);
646             }
647              
648 7 50         if (tree) {
649 7           rc = git_diff_tree_to_index(
650             &diff, repo_ptr -> repository, tree, index, &diff_opts
651             );
652             } else {
653 0           rc = git_diff_index_to_workdir(
654             &diff, repo_ptr -> repository, index, &diff_opts
655             );
656             }
657              
658 7           git_index_free(index);
659 7 100         if (diff_opts.pathspec.count > 0)
660 4           Safefree(diff_opts.pathspec.strings);
661 7           git_check_error(rc);
662              
663 7           GIT_NEW_OBJ_WITH_MAGIC(
664             RETVAL, "Git::Raw::Diff", diff, SvRV(self)
665             );
666              
667             OUTPUT: RETVAL
668              
669             SV *
670             merge_base(repo, ...)
671             SV *repo
672              
673             PROTOTYPE: $;@
674              
675             PREINIT:
676             int i, rc, count;
677              
678             Repository repo_ptr;
679 12           git_oid merge_base, *oids = NULL;
680              
681             CODE:
682 12 100         if (items < 3)
683 1           croak_usage("At least 2 arguments needed");
684              
685 11           repo_ptr = GIT_SV_TO_PTR(Repository, repo);
686              
687 11           count = items - 1;
688 11 50         Renew(oids, count, git_oid);
689 30 100         for (i = 0; i < count; ++i) {
690 22 100         if (git_sv_to_commitish(repo_ptr -> repository, ST(i + 1), oids + i) == NULL) {
691 3           Safefree(oids);
692 3           croak_resolve("Could not resolve 'object' to a commit id");
693             }
694             }
695              
696 8           rc = git_merge_base_many(
697             &merge_base, repo_ptr -> repository, (size_t) count, oids);
698 8           Safefree(oids);
699              
700 8           RETVAL = &PL_sv_undef;
701 8 50         if (rc != GIT_ENOTFOUND) {
702             Commit commit;
703 8           git_check_error(rc);
704              
705 8           rc = git_commit_lookup(&commit, repo_ptr -> repository, &merge_base);
706 8           git_check_error(rc);
707              
708 8           GIT_NEW_OBJ_WITH_MAGIC(
709             RETVAL, "Git::Raw::Commit",
710             commit, repo
711             );
712             }
713              
714             OUTPUT: RETVAL
715              
716             SV *
717             merge_analysis(self, ref)
718             Repository self
719             Reference ref
720              
721             PREINIT:
722             int rc;
723              
724             git_annotated_commit *merge_head;
725             git_merge_preference_t pref;
726             git_merge_analysis_t analysis;
727              
728             AV *result;
729             CODE:
730 5           rc = git_annotated_commit_from_ref(&merge_head, self -> repository, ref);
731 5           git_check_error(rc);
732              
733 5           rc = git_merge_analysis(&analysis, &pref,
734             self -> repository, (const git_annotated_commit **) &merge_head, 1);
735 5           git_annotated_commit_free(merge_head);
736 5           git_check_error(rc);
737              
738 5           result = newAV();
739 5 100         if (analysis & GIT_MERGE_ANALYSIS_NORMAL)
740 4           av_push(result, newSVpv("normal", 0));
741 5 100         if (analysis & GIT_MERGE_ANALYSIS_UP_TO_DATE)
742 1           av_push(result, newSVpv("up_to_date", 0));
743 5 100         if (analysis & GIT_MERGE_ANALYSIS_FASTFORWARD)
744 1           av_push(result, newSVpv("fast_forward", 0));
745 5 50         if (analysis & GIT_MERGE_ANALYSIS_UNBORN)
746 0           av_push(result, newSVpv("unborn", 0));
747              
748 5           RETVAL = newRV_noinc((SV *) result);
749              
750             OUTPUT: RETVAL
751              
752             void
753             merge(self, ref, ...)
754             Repository self
755             Reference ref
756              
757             PROTOTYPE: $$;$;$
758             PREINIT:
759             int rc;
760              
761             git_annotated_commit *merge_head;
762              
763 8           git_merge_options merge_opts = GIT_MERGE_OPTIONS_INIT;
764 8           git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
765              
766             CODE:
767 8           rc = git_annotated_commit_from_ref(&merge_head, self -> repository, ref);
768 8           git_check_error(rc);
769              
770 8 100         if (items >= 3) {
771 6           HV *opts = git_ensure_hv(ST(2), "merge_opts");
772 6           git_hv_to_merge_opts(opts, &merge_opts);
773             }
774              
775 5 100         if (items >= 4) {
776 2           HV *opts = git_ensure_hv(ST(3), "checkout_opts");
777 2           git_hv_to_checkout_opts(opts, &checkout_opts);
778             }
779              
780 5           rc = git_merge(
781             self -> repository, (const git_annotated_commit **) &merge_head,
782             1, &merge_opts, &checkout_opts
783             );
784 5           Safefree(checkout_opts.paths.strings);
785 5           git_annotated_commit_free(merge_head);
786 5           git_check_error(rc);
787              
788             void
789             branches(self, ...)
790             SV *self
791              
792             PROTOTYPE: $;$
793             PREINIT:
794             int rc;
795              
796             Branch branch;
797 3           int num_branches = 0;
798              
799             git_branch_t type;
800             git_branch_iterator *itr;
801              
802             Repository repo;
803              
804             PPCODE:
805 3           type = GIT_BRANCH_ALL;
806              
807 3 100         if (items == 2) {
808 2           const char *type_str = git_ensure_pv(ST(1), "type");
809              
810 2 100         if (strcmp(type_str, "local") == 0)
811 1           type = GIT_BRANCH_LOCAL;
812 1 50         else if (strcmp(type_str, "remote") == 0)
813 0           type = GIT_BRANCH_REMOTE;
814 1 50         else if (strcmp(type_str, "all") == 0)
815 0           type = GIT_BRANCH_ALL;
816             else
817 1           croak_usage("Invalid branch type '%s'. ",
818             "Valid values: 'local', 'remote' or 'all'",
819             type_str);
820             }
821              
822 2           repo = GIT_SV_TO_PTR(Repository, self);
823              
824 2           rc = git_branch_iterator_new(&itr, repo -> repository, type);
825 2           git_check_error(rc);
826              
827 6 100         while ((rc = git_branch_next(&branch, &type, itr)) == 0) {
828             SV *perl_ref;
829              
830 4           GIT_NEW_OBJ_WITH_MAGIC(
831             perl_ref, "Git::Raw::Branch", branch, SvRV(self)
832             );
833              
834 4 50         mXPUSHs(perl_ref);
835              
836 4           num_branches++;
837             }
838              
839 2           git_branch_iterator_free(itr);
840 2           git_check_error(rc);
841              
842 2           XSRETURN(num_branches);
843              
844             void
845             remotes(self)
846             SV *self
847              
848             PREINIT:
849             int rc;
850             size_t i;
851              
852 3           int num_remotes = 0;
853             git_strarray remotes;
854              
855             Repository repo;
856              
857             PPCODE:
858 3           repo = GIT_SV_TO_PTR(Repository, self);
859              
860 3           rc = git_remote_list(&remotes, repo -> repository);
861 3           git_check_error(rc);
862              
863 10 100         for (i = 0; i < remotes.count; i++) {
864             SV *perl_ref;
865 7           git_remote *r = NULL;
866 7           Remote remote = NULL;
867              
868 7           rc = git_remote_lookup(&r, repo -> repository, remotes.strings[i]);
869 7           git_check_error(rc);
870              
871 7           Newxz(remote, 1, git_raw_remote);
872 7           remote -> remote = r;
873              
874 7           GIT_NEW_OBJ_WITH_MAGIC(
875             perl_ref, "Git::Raw::Remote", remote, SvRV(self)
876             );
877              
878 7 50         mXPUSHs(perl_ref);
879              
880 7           num_remotes++;
881             }
882              
883 3           git_strarray_free(&remotes);
884              
885 3           XSRETURN(num_remotes);
886              
887             void
888             refs(self)
889             SV *self
890              
891             PREINIT:
892             int rc;
893              
894             Reference ref;
895 3           int num_refs = 0;
896              
897             git_reference_iterator *itr;
898              
899 3           Repository repo = NULL;
900              
901             PPCODE:
902 3           repo = GIT_SV_TO_PTR(Repository, self);
903 3           rc = git_reference_iterator_new(&itr, repo -> repository);
904 3           git_check_error(rc);
905              
906 7 100         while ((rc = git_reference_next(&ref, itr)) == 0) {
907             SV *perl_ref;
908              
909 4           GIT_NEW_OBJ_WITH_MAGIC(
910             perl_ref, "Git::Raw::Reference", ref, SvRV(self)
911             );
912              
913 4 50         mXPUSHs(perl_ref);
914              
915 4           num_refs++;
916             }
917              
918 3           git_reference_iterator_free(itr);
919 3           git_check_error(rc);
920              
921 3           XSRETURN(num_refs);
922              
923             SV *
924             path(self)
925             Repository self
926              
927             PREINIT:
928             const char *path;
929              
930             CODE:
931 30           path = git_repository_path(self -> repository);
932 30           RETVAL = newSVpv(path, 0);
933              
934             OUTPUT: RETVAL
935              
936             SV *
937             workdir(self, ...)
938             Repository self
939              
940             PROTOTYPE: $;$
941              
942             PREINIT:
943             int rc;
944             const char *path;
945              
946             CODE:
947 34 100         if (items == 2) {
948 2           const char *new_dir = git_ensure_pv(ST(1), "new_dir");
949              
950 2           rc = git_repository_set_workdir(self -> repository, new_dir, 1);
951 2           git_check_error(rc);
952             }
953              
954 34           path = git_repository_workdir(self -> repository);
955 34           RETVAL = newSVpv(path, 0);
956              
957             OUTPUT: RETVAL
958              
959             SV *
960             blame(self, file)
961             SV *self
962             const char *file
963              
964             PREINIT:
965             int rc;
966             Blame blame;
967              
968 1           Repository repo = NULL;
969 1           git_blame_options options = GIT_BLAME_OPTIONS_INIT;
970              
971             CODE:
972 1           repo = GIT_SV_TO_PTR(Repository, self);
973 1           rc = git_blame_file(
974             &blame, repo -> repository, file, &options);
975 1           git_check_error(rc);
976              
977 1           GIT_NEW_OBJ_WITH_MAGIC(
978             RETVAL, "Git::Raw::Blame", blame, SvRV(self)
979             );
980              
981             OUTPUT: RETVAL
982              
983             void
984             cherry_pick(self, commit, ...)
985             SV *self
986             Commit commit
987              
988             PROTOTYPE: $$;$;$;$
989             PREINIT:
990             int rc;
991              
992 7           Repository repo = NULL;
993 7           git_cherrypick_options opts = GIT_CHERRYPICK_OPTIONS_INIT;
994              
995             CODE:
996 7 100         if (items >= 3) {
997 2           HV *hopts = git_ensure_hv(ST(2), "merge_opts");
998 2           git_hv_to_merge_opts(hopts, &opts.merge_opts);
999             }
1000              
1001 7 100         if (items >= 4) {
1002 2           HV *hopts = git_ensure_hv(ST(3), "checkout_opts");
1003 2           git_hv_to_checkout_opts(hopts, &opts.checkout_opts);
1004             }
1005              
1006 7 100         if (items >= 5) {
1007 2           unsigned int parents = git_commit_parentcount(commit);
1008 2           int mainline = git_ensure_iv(ST(4), "mainline");
1009              
1010 2 50         if (mainline < 0 || mainline > (int) git_commit_parentcount(commit) - 1)
    100          
1011 1           croak_usage("'mainline' out of range, should be between 0 and %d",
1012 1           (int) parents - 1);
1013              
1014 1           opts.mainline = (unsigned int) mainline;
1015             }
1016              
1017 6           repo = GIT_SV_TO_PTR(Repository, self);
1018 6           rc = git_cherrypick(
1019             repo -> repository,
1020             commit,
1021             &opts
1022             );
1023 6           Safefree(opts.checkout_opts.paths.strings);
1024 6           git_check_error(rc);
1025              
1026             void
1027             revert(self, commit, ...)
1028             SV *self
1029             Commit commit
1030              
1031             PROTOTYPE: $$;$;$;$
1032             PREINIT:
1033             int rc;
1034              
1035 2           Repository repo = NULL;
1036 2           git_revert_options opts = GIT_REVERT_OPTIONS_INIT;
1037              
1038             CODE:
1039 2 50         if (items >= 3) {
1040 2           HV *hopts = git_ensure_hv(ST(2), "merge_opts");
1041 2           git_hv_to_merge_opts(hopts, &opts.merge_opts);
1042             }
1043              
1044 2 50         if (items >= 4) {
1045 2           HV *hopts = git_ensure_hv(ST(3), "checkout_opts");
1046 2           git_hv_to_checkout_opts(hopts, &opts.checkout_opts);
1047             }
1048              
1049 2 50         if (items >= 5) {
1050 2           unsigned int parents = git_commit_parentcount(commit);
1051 2           int mainline = git_ensure_iv(ST(4), "mainline");
1052              
1053 2 50         if (mainline < 0 || mainline > (int) git_commit_parentcount(commit) - 1)
    100          
1054 1           croak_usage("'mainline' out of range, should be between 0 and %d",
1055 1           (int) parents - 1);
1056              
1057 1           opts.mainline = (unsigned int) mainline;
1058             }
1059              
1060 1           repo = GIT_SV_TO_PTR(Repository, self);
1061 1           rc = git_revert(
1062             repo -> repository,
1063             commit,
1064             &opts
1065             );
1066 1           Safefree(opts.checkout_opts.paths.strings);
1067 1           git_check_error(rc);
1068              
1069             void
1070             revparse(self, spec)
1071             SV *self
1072             SV *spec
1073              
1074             PREINIT:
1075             int rc;
1076 11           int ctx, count = 0;
1077 11           git_revspec rs = {NULL, NULL, 0};
1078              
1079             PPCODE:
1080 11 50         ctx = GIMME_V;
1081              
1082 11           Repository repo = GIT_SV_TO_PTR(Repository, self);
1083 11           rc = git_revparse(&rs, repo -> repository,
1084             git_ensure_pv(spec, "spec"));
1085 11           git_check_error(rc);
1086              
1087 10 100         if (ctx != G_VOID) {
1088 9 100         if (ctx == G_ARRAY) {
1089 7 50         mXPUSHs(git_obj_to_sv(rs.from, SvRV(self)));
1090 7 100         if (rs.flags & GIT_REVPARSE_SINGLE) {
1091 4           count = 1;
1092             } else {
1093 3 50         mXPUSHs(git_obj_to_sv(rs.to, SvRV(self)));
1094 7           count = 2;
1095             }
1096             } else {
1097 2 100         if (rs.flags & GIT_REVPARSE_SINGLE)
1098 1 50         mXPUSHs(newSViv(1));
1099             else
1100 1 50         mXPUSHs(newSViv(2));
1101              
1102 2           count = 1;
1103             }
1104             }
1105              
1106 10 100         if (count == 0) {
1107 1           git_object_free(rs.from);
1108 1           git_object_free(rs.to);
1109 1           XSRETURN_EMPTY;
1110             }
1111              
1112 10           XSRETURN(count);
1113              
1114             SV *
1115             state(self)
1116             Repository self
1117              
1118             PREINIT:
1119             int rc;
1120 37           const char *s = NULL;
1121              
1122             CODE:
1123 37           rc = git_repository_state(self -> repository);
1124              
1125 37           switch (rc) {
1126             case GIT_REPOSITORY_STATE_NONE:
1127 20           s = "none";
1128 20           break;
1129              
1130             case GIT_REPOSITORY_STATE_MERGE:
1131 4           s = "merge";
1132 4           break;
1133              
1134             case GIT_REPOSITORY_STATE_REVERT:
1135 2           s = "revert";
1136 2           break;
1137              
1138             case GIT_REPOSITORY_STATE_CHERRYPICK:
1139 3           s = "cherry_pick";
1140 3           break;
1141              
1142             case GIT_REPOSITORY_STATE_BISECT:
1143 1           s = "bisect";
1144 1           break;
1145              
1146             case GIT_REPOSITORY_STATE_REBASE:
1147 1           s = "rebase";
1148 1           break;
1149              
1150             case GIT_REPOSITORY_STATE_REBASE_INTERACTIVE:
1151 1           s = "rebase_interactive";
1152 1           break;
1153              
1154             case GIT_REPOSITORY_STATE_REBASE_MERGE:
1155 3           s = "rebase_merge";
1156 3           break;
1157              
1158             case GIT_REPOSITORY_STATE_APPLY_MAILBOX:
1159 1           s = "apply_mailbox";
1160 1           break;
1161              
1162             case GIT_REPOSITORY_STATE_APPLY_MAILBOX_OR_REBASE:
1163 1           s = "mailbox_or_rebase";
1164 1           break;
1165              
1166             default:
1167 0           croak_assert("Unknown state: %i", rc);
1168             }
1169              
1170 37           RETVAL = newSVpv(s, 0);
1171              
1172             OUTPUT: RETVAL
1173              
1174             void
1175             state_cleanup(self)
1176             Repository self
1177              
1178             PREINIT:
1179             int rc;
1180              
1181             CODE:
1182 17           rc = git_repository_state_cleanup(self -> repository);
1183 17           git_check_error(rc);
1184              
1185             SV *
1186             message(self)
1187             Repository self
1188              
1189             PREINIT:
1190             int rc;
1191              
1192 1           git_buf buf = GIT_BUF_INIT_CONST(NULL, 0);
1193              
1194             CODE:
1195 1           RETVAL = &PL_sv_undef;
1196              
1197 1           rc = git_repository_message(&buf, self -> repository);
1198 1 50         if (rc == GIT_OK)
1199 1           RETVAL = newSVpv(buf.ptr, 0);
1200              
1201 1           git_buf_dispose(&buf);
1202 1           git_check_error(rc);
1203              
1204             OUTPUT: RETVAL
1205              
1206             SV *
1207             is_bare(self)
1208             Repository self
1209              
1210             CODE:
1211 1           RETVAL = newSViv(git_repository_is_bare(self -> repository));
1212              
1213             OUTPUT: RETVAL
1214              
1215             SV *
1216             is_empty(self)
1217             Repository self
1218              
1219             CODE:
1220 2           RETVAL = newSViv(git_repository_is_empty(self -> repository));
1221              
1222             OUTPUT: RETVAL
1223              
1224             SV *
1225             is_shallow(self)
1226             Repository self
1227              
1228             CODE:
1229 0           RETVAL = newSViv(git_repository_is_shallow(self -> repository));
1230              
1231             OUTPUT: RETVAL
1232              
1233             SV *
1234             is_head_detached(self)
1235             Repository self
1236              
1237             CODE:
1238 6           RETVAL = newSViv(git_repository_head_detached(self -> repository));
1239              
1240             OUTPUT: RETVAL
1241              
1242             void
1243             DESTROY(self)
1244             Repository self
1245              
1246             CODE:
1247 36 50         if (self -> owned)
1248 36           git_repository_free(self -> repository);
1249 36           Safefree(self);