1 /*
2 * ggit-tree.c
3 * This file is part of libgit2-glib
4 *
5 * Copyright (C) 2012 - Jesse van den Kieboom
6 *
7 * libgit2-glib is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * libgit2-glib is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with libgit2-glib. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include <git2.h>
22
23 #include "ggit-tree.h"
24 #include "ggit-oid.h"
25 #include "ggit-error.h"
26
27 /**
28 * GgitTree:
29 *
30 * Represents a tree object.
31 */
32
G_DEFINE_TYPE(GgitTree,ggit_tree,GGIT_TYPE_OBJECT)33 G_DEFINE_TYPE (GgitTree, ggit_tree, GGIT_TYPE_OBJECT)
34
35 static void
36 ggit_tree_class_init (GgitTreeClass *klass)
37 {
38 }
39
40 static void
ggit_tree_init(GgitTree * self)41 ggit_tree_init (GgitTree *self)
42 {
43 }
44
45 GgitTree *
_ggit_tree_wrap(git_tree * tree,gboolean owned)46 _ggit_tree_wrap (git_tree *tree,
47 gboolean owned)
48 {
49 GgitTree *gtree;
50
51 gtree = g_object_new (GGIT_TYPE_TREE,
52 "native", tree,
53 NULL);
54
55 if (owned)
56 {
57 _ggit_native_set_destroy_func (gtree,
58 (GDestroyNotify)git_object_free);
59 }
60
61 return gtree;
62 }
63
64 /**
65 * ggit_tree_get_id:
66 * @tree: a #GgitTree.
67 *
68 * Get the #GgitOId of the tree.
69 *
70 * Returns: (transfer full) (nullable): a #GgitOId or %NULL.
71 *
72 **/
73 GgitOId *
ggit_tree_get_id(GgitTree * tree)74 ggit_tree_get_id (GgitTree *tree)
75 {
76 git_tree *t;
77 const git_oid *oid;
78
79 g_return_val_if_fail (GGIT_IS_TREE (tree), NULL);
80
81 t = _ggit_native_get (tree);
82
83 oid = git_tree_id (t);
84
85 return _ggit_oid_wrap (oid);
86 }
87
88 /**
89 * ggit_tree_get:
90 * @tree: a #GgitTree.
91 * @i: the index of the entry.
92 *
93 * Get a tree entry by index.
94 *
95 * Returns: (transfer full) (nullable): a #GgitTreeEntry or %NULL.
96 *
97 **/
98 GgitTreeEntry *
ggit_tree_get(GgitTree * tree,guint i)99 ggit_tree_get (GgitTree *tree,
100 guint i)
101 {
102 git_tree *t;
103 const git_tree_entry *entry;
104
105 g_return_val_if_fail (GGIT_IS_TREE (tree), NULL);
106
107 t = _ggit_native_get (tree);
108
109 entry = git_tree_entry_byindex (t, i);
110
111 return _ggit_tree_entry_wrap ((git_tree_entry *)entry, FALSE);
112 }
113
114 /**
115 * ggit_tree_size:
116 * @tree: a #GgitTree.
117 *
118 * Get the number of entries in the tree.
119 *
120 * Returns: the number of entries in the tree.
121 *
122 **/
123 guint
ggit_tree_size(GgitTree * tree)124 ggit_tree_size (GgitTree *tree)
125 {
126 git_tree *t;
127
128 g_return_val_if_fail (GGIT_IS_TREE (tree), 0);
129
130 t = _ggit_native_get (tree);
131
132 return (guint)git_tree_entrycount (t);
133 }
134
135 /**
136 * ggit_tree_get_by_name:
137 * @tree: a #GgitTree.
138 * @name: a filename.
139 *
140 * Get a tree entry by name.
141 *
142 * Returns: (transfer full) (nullable): a #GgitTreeEntry or %NULL.
143 *
144 **/
145 GgitTreeEntry *
ggit_tree_get_by_name(GgitTree * tree,const gchar * name)146 ggit_tree_get_by_name (GgitTree *tree,
147 const gchar *name)
148 {
149 git_tree *t;
150 GgitTreeEntry *entry = NULL;
151 const git_tree_entry *tree_entry;
152
153 g_return_val_if_fail (GGIT_IS_TREE (tree), NULL);
154 g_return_val_if_fail (name != NULL, NULL);
155
156 t = _ggit_native_get (tree);
157
158 tree_entry = git_tree_entry_byname (t, name);
159
160 if (tree_entry != NULL)
161 {
162 entry = _ggit_tree_entry_wrap ((git_tree_entry *)tree_entry, FALSE);
163 }
164
165 return entry;
166 }
167
168 /**
169 * ggit_tree_get_by_path:
170 * @tree: a #GgitTree.
171 * @path: a path.
172 * @error: a #GError for error reporting, or %NULL.
173 *
174 * Retrieves a tree entry contained in a tree or in any of its subtrees,
175 * given its relative path.
176 *
177 * Returns: (transfer full) (nullable): a #GgitTreeEntry or %NULL.
178 *
179 **/
180 GgitTreeEntry *
ggit_tree_get_by_path(GgitTree * tree,const gchar * path,GError ** error)181 ggit_tree_get_by_path (GgitTree *tree,
182 const gchar *path,
183 GError **error)
184 {
185 git_tree *t;
186 GgitTreeEntry *entry = NULL;
187 git_tree_entry *tree_entry;
188 gint ret;
189
190 g_return_val_if_fail (GGIT_IS_TREE (tree), NULL);
191 g_return_val_if_fail (path != NULL, NULL);
192
193 t = _ggit_native_get (tree);
194
195 ret = git_tree_entry_bypath (&tree_entry, t, path);
196
197 if (ret == GIT_OK)
198 {
199 entry = _ggit_tree_entry_wrap (tree_entry, TRUE);
200 }
201 else
202 {
203 _ggit_error_set (error, ret);
204 }
205
206 return entry;
207 }
208
209 typedef struct
210 {
211 GgitTreeWalkCallback callback;
212 gpointer user_data;
213 } WalkInfo;
214
215 static int
walk_callback_wrapper(const char * root,const git_tree_entry * entry,gpointer payload)216 walk_callback_wrapper (const char *root,
217 const git_tree_entry *entry,
218 gpointer payload)
219 {
220 gint ret;
221 GgitTreeEntry *wentry;
222 WalkInfo *info = (WalkInfo *)payload;
223 git_tree_entry *dest;
224
225 ret = git_tree_entry_dup (&dest, entry);
226 if (ret == GIT_OK)
227 {
228 wentry = _ggit_tree_entry_wrap (dest, TRUE);
229
230 ret = info->callback(root, wentry, info->user_data);
231
232 ggit_tree_entry_unref (wentry);
233 }
234
235 return ret;
236 }
237
238 /**
239 * ggit_tree_walk:
240 * @tree: a #GgitTree.
241 * @mode: the walking order.
242 * @callback: (scope call): the callback to call for each entry.
243 * @user_data: (closure): user data for the callback.
244 * @error: a #GError for error reporting, or %NULL.
245 *
246 * Walk all the entries of a tree object recursively (resolving and walking
247 * subtrees of the tree as needed). The @error will be set to the error returned
248 * by @callback (if any).
249 *
250 **/
251 void
ggit_tree_walk(GgitTree * tree,GgitTreeWalkMode mode,GgitTreeWalkCallback callback,gpointer user_data,GError ** error)252 ggit_tree_walk (GgitTree *tree,
253 GgitTreeWalkMode mode,
254 GgitTreeWalkCallback callback,
255 gpointer user_data,
256 GError **error)
257 {
258 gint ret;
259 WalkInfo info = {0,};
260
261 g_return_if_fail (GGIT_IS_TREE (tree));
262 g_return_if_fail (callback != NULL);
263 g_return_if_fail (error == NULL || *error == NULL);
264
265 info.callback = callback;
266 info.user_data = user_data;
267
268 ret = git_tree_walk (_ggit_native_get (tree),
269 (git_treewalk_mode)mode,
270 (git_treewalk_cb)walk_callback_wrapper,
271 &info);
272
273 if (ret != GIT_OK)
274 {
275 _ggit_error_set (error, ret);
276 }
277 }
278
279 /* ex:set ts=8 noet: */
280