1 /*
2 * git2r, R bindings to the libgit2 library.
3 * Copyright (C) 2013-2019 The git2r contributors
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License, version 2,
7 * as published by the Free Software Foundation.
8 *
9 * git2r is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19 #include <git2.h>
20
21 #include "git2r_arg.h"
22 #include "git2r_blob.h"
23 #include "git2r_commit.h"
24 #include "git2r_deprecated.h"
25 #include "git2r_error.h"
26 #include "git2r_repository.h"
27 #include "git2r_S3.h"
28 #include "git2r_tag.h"
29 #include "git2r_tree.h"
30
31 /**
32 * Lookup an object in a repository
33 *
34 * @param repo S3 class git_repository
35 * @param sha 4 to 40 char hexadecimal string
36 * @return S3 object with lookup
37 */
git2r_object_lookup(SEXP repo,SEXP sha)38 SEXP git2r_object_lookup(SEXP repo, SEXP sha)
39 {
40 int error, nprotect = 0;
41 size_t len;
42 SEXP result = R_NilValue;
43 git_object *object = NULL;
44 git_oid oid;
45 git_repository *repository = NULL;
46
47 if (git2r_arg_check_sha(sha))
48 git2r_error(__func__, NULL, "'sha'", git2r_err_sha_arg);
49
50 repository = git2r_repository_open(repo);
51 if (!repository)
52 git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL);
53
54 len = LENGTH(STRING_ELT(sha, 0));
55 if (GIT_OID_HEXSZ == len) {
56 git_oid_fromstr(&oid, CHAR(STRING_ELT(sha, 0)));
57 error = git_object_lookup(&object, repository, &oid, GIT2R_OBJECT_ANY);
58 if (error)
59 goto cleanup;
60 } else {
61 git_oid_fromstrn(&oid, CHAR(STRING_ELT(sha, 0)), len);
62 error = git_object_lookup_prefix(&object, repository, &oid, len, GIT2R_OBJECT_ANY);
63 if (error)
64 goto cleanup;
65 }
66
67 switch (git_object_type(object)) {
68 case GIT2R_OBJECT_COMMIT:
69 PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_commit));
70 nprotect++;
71 Rf_setAttrib(result, R_ClassSymbol,
72 Rf_mkString(git2r_S3_class__git_commit));
73 git2r_commit_init((git_commit*)object, repo, result);
74 break;
75 case GIT2R_OBJECT_TREE:
76 PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_tree));
77 nprotect++;
78 Rf_setAttrib(result, R_ClassSymbol,
79 Rf_mkString(git2r_S3_class__git_tree));
80 git2r_tree_init((git_tree*)object, repo, result);
81 break;
82 case GIT2R_OBJECT_BLOB:
83 PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_blob));
84 nprotect++;
85 Rf_setAttrib(result, R_ClassSymbol,
86 Rf_mkString(git2r_S3_class__git_blob));
87 git2r_blob_init((git_blob*)object, repo, result);
88 break;
89 case GIT2R_OBJECT_TAG:
90 PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_tag));
91 nprotect++;
92 Rf_setAttrib(result, R_ClassSymbol,
93 Rf_mkString(git2r_S3_class__git_tag));
94 git2r_tag_init((git_tag*)object, repo, result);
95 break;
96 default:
97 git2r_error(__func__, NULL, git2r_err_object_type, NULL);
98 }
99
100 cleanup:
101 git_object_free(object);
102 git_repository_free(repository);
103
104 if (nprotect)
105 UNPROTECT(nprotect);
106
107 if (error)
108 git2r_error(__func__, GIT2R_ERROR_LAST(), NULL, NULL);
109
110 return result;
111 }
112