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