1 /*
2  * ggit-index-entry-resolve_undo.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 "ggit-index-entry-resolve-undo.h"
22 #include "ggit-index.h"
23 #include <git2/sys/index.h>
24 
25 struct _GgitIndexEntriesResolveUndo
26 {
27 	GgitIndex *owner;
28 	gint ref_count;
29 };
30 
31 struct _GgitIndexEntryResolveUndo
32 {
33 	git_index_reuc_entry *entry;
34 	gint ref_count;
35 };
36 
G_DEFINE_BOXED_TYPE(GgitIndexEntriesResolveUndo,ggit_index_entries_resolve_undo,ggit_index_entries_resolve_undo_ref,ggit_index_entries_resolve_undo_unref)37 G_DEFINE_BOXED_TYPE (GgitIndexEntriesResolveUndo,
38                      ggit_index_entries_resolve_undo,
39                      ggit_index_entries_resolve_undo_ref,
40                      ggit_index_entries_resolve_undo_unref)
41 
42 G_DEFINE_BOXED_TYPE (GgitIndexEntryResolveUndo,
43                      ggit_index_entry_resolve_undo,
44                      ggit_index_entry_resolve_undo_ref,
45                      ggit_index_entry_resolve_undo_unref)
46 
47 static GgitIndexEntryResolveUndo *
48 ggit_index_entry_resolve_undo_wrap (git_index_reuc_entry *entry)
49 {
50 	GgitIndexEntryResolveUndo *ret;
51 
52 	ret = g_slice_new (GgitIndexEntryResolveUndo);
53 	ret->entry = entry;
54 	ret->ref_count = 1;
55 
56 	return ret;
57 }
58 
59 GgitIndexEntriesResolveUndo *
_ggit_index_entries_resolve_undo_wrap(GgitIndex * owner)60 _ggit_index_entries_resolve_undo_wrap (GgitIndex *owner)
61 {
62 	GgitIndexEntriesResolveUndo *ret;
63 
64 	ret = g_slice_new (GgitIndexEntriesResolveUndo);
65 	ret->owner = g_object_ref (owner);
66 	ret->ref_count = 1;
67 
68 	return ret;
69 }
70 
71 /**
72  * ggit_index_entry_resolve_undo_ref:
73  * @entry: a #GgitIndexEntryResolveUndo.
74  *
75  * Atomically increments the reference count of @entry by one.
76  * This function is MT-safe and may be called from any thread.
77  *
78  * Returns: (transfer none) (nullable): a #GgitIndexEntryResolveUndo or %NULL.
79  **/
80 GgitIndexEntryResolveUndo *
ggit_index_entry_resolve_undo_ref(GgitIndexEntryResolveUndo * entry)81 ggit_index_entry_resolve_undo_ref (GgitIndexEntryResolveUndo *entry)
82 {
83 	g_return_val_if_fail (entry != NULL, NULL);
84 
85 	g_atomic_int_inc (&entry->ref_count);
86 
87 	return entry;
88 }
89 
90 /**
91  * ggit_index_entry_resolve_undo_unref:
92  * @entry: a #GgitIndexEntryResolveUndo.
93  *
94  * Atomically decrements the reference count of @entry by one.
95  * If the reference count drops to 0, @entry is freed.
96  **/
97 void
ggit_index_entry_resolve_undo_unref(GgitIndexEntryResolveUndo * entry)98 ggit_index_entry_resolve_undo_unref (GgitIndexEntryResolveUndo *entry)
99 {
100 	g_return_if_fail (entry != NULL);
101 
102 	if (g_atomic_int_dec_and_test (&entry->ref_count))
103 	{
104 		g_slice_free (GgitIndexEntryResolveUndo, entry);
105 	}
106 }
107 
108 /**
109  * ggit_index_entries_resolve_undo_ref:
110  * @entries: a #GgitIndexEntriesResolveUndo.
111  *
112  * Atomically increments the reference count of @entries by one.
113  * This function is MT-safe and may be called from any thread.
114  *
115  * Returns: (transfer none) (nullable): a #GgitIndexEntriesResolveUndo or %NULL.
116  *
117  **/
118 GgitIndexEntriesResolveUndo *
ggit_index_entries_resolve_undo_ref(GgitIndexEntriesResolveUndo * entries)119 ggit_index_entries_resolve_undo_ref (GgitIndexEntriesResolveUndo *entries)
120 {
121 	g_return_val_if_fail (entries != NULL, NULL);
122 
123 	g_atomic_int_inc (&entries->ref_count);
124 
125 	return entries;
126 }
127 
128 /**
129  * ggit_index_entries_resolve_undo_unref:
130  * @entries: a #GgitIndexEntriesResolveUndo.
131  *
132  * Atomically decrements the reference count of @entries by one.
133  * If the reference count drops to 0, @entries is freed.
134  **/
135 void
ggit_index_entries_resolve_undo_unref(GgitIndexEntriesResolveUndo * entries)136 ggit_index_entries_resolve_undo_unref (GgitIndexEntriesResolveUndo *entries)
137 {
138 	g_return_if_fail (entries != NULL);
139 
140 	if (g_atomic_int_dec_and_test (&entries->ref_count))
141 	{
142 		g_clear_object (&entries->owner);
143 		g_slice_free (GgitIndexEntriesResolveUndo, entries);
144 	}
145 }
146 
147 /**
148  * ggit_index_entries_resolve_undo_get:
149  * @entries: a #GgitIndexEntriesResolveUndo.
150  * @idx: the index of the entry.
151  *
152  * Get a #GgitIndexEntryResolveUndo by index. Note that the returned
153  * #GgitIndexEntryResolveUndo is _only_ valid as long as:
154  *
155  * 1) The associated index has been closed
156  * 2) The entry has not been removed (see ggit_index_remove())
157  * 3) The index has not been refreshed (see ggit_index_read())
158  *
159  * Returns: (transfer full) (nullable): a #GgitIndexEntryResolveUndo or %NULL.
160  *
161  **/
162 GgitIndexEntryResolveUndo *
ggit_index_entries_resolve_undo_get(GgitIndexEntriesResolveUndo * entries,guint idx)163 ggit_index_entries_resolve_undo_get (GgitIndexEntriesResolveUndo *entries,
164                                      guint                        idx)
165 {
166 	git_index *gidx;
167 	const git_index_reuc_entry *ret;
168 
169 	g_return_val_if_fail (entries != NULL, NULL);
170 
171 	gidx = _ggit_index_get_index (entries->owner);
172 	ret = git_index_reuc_get_byindex (gidx, idx);
173 
174 	return ggit_index_entry_resolve_undo_wrap ((git_index_reuc_entry *)ret);
175 }
176 
177 /**
178  * ggit_index_entries_resolve_undo_size:
179  * @entries: a #GgitIndexEntriesResolveUndo.
180  *
181  * Get the number of #GgitIndexEntryResolveUndo entries.
182  *
183  * Returns: the number of entries.
184  *
185  **/
186 guint
ggit_index_entries_resolve_undo_size(GgitIndexEntriesResolveUndo * entries)187 ggit_index_entries_resolve_undo_size (GgitIndexEntriesResolveUndo *entries)
188 {
189 	git_index *gidx;
190 
191 	g_return_val_if_fail (entries != NULL, 0);
192 
193 	gidx = _ggit_index_get_index (entries->owner);
194 
195 	return git_index_reuc_entrycount (gidx);
196 }
197 
198 /**
199  * ggit_index_entries_resolve_undo_get_by_file:
200  * @entries: a #GgitIndexEntriesResolveUndo.
201  * @file: a #GFile.
202  *
203  * Get an resolve_undo entry specified by path. The returned entry is read
204  * only and should not be modified by the caller. If the entry could not be
205  * found, %NULL is returned.
206  *
207  * Returns: (transfer full) (nullable): a #GgitIndexEntryResolveUndo or %NULL.
208  *
209  **/
210 GgitIndexEntryResolveUndo *
ggit_index_entries_resolve_undo_get_by_file(GgitIndexEntriesResolveUndo * entries,GFile * file)211 ggit_index_entries_resolve_undo_get_by_file (GgitIndexEntriesResolveUndo  *entries,
212                                              GFile                        *file)
213 {
214 	git_index *gidx;
215 	const git_index_reuc_entry *ret;
216 	gchar *path;
217 
218 	g_return_val_if_fail (entries != NULL, NULL);
219 	g_return_val_if_fail (G_IS_FILE (file), NULL);
220 
221 	gidx = _ggit_index_get_index (entries->owner);
222 	path = g_file_get_path (file);
223 
224 	g_return_val_if_fail (path != NULL, NULL);
225 
226 	ret = git_index_reuc_get_bypath (gidx, path);
227 	g_free (path);
228 
229 	if (ret)
230 	{
231 		return ggit_index_entry_resolve_undo_wrap ((git_index_reuc_entry *)ret);
232 	}
233 	else
234 	{
235 		return NULL;
236 	}
237 }
238 
239 /**
240  * ggit_index_entry_resolve_undo_get_mode:
241  * @entry: a #GgitIndexEntryResolveUndo.
242  * @stage: the stage (0, 1 or 2).
243  *
244  * Get the mode of the index entry. The returned mode contains the modes from
245  * stage 1, 2 and 3.
246  *
247  * Returns: the mode.
248  *
249  **/
250 guint
ggit_index_entry_resolve_undo_get_mode(GgitIndexEntryResolveUndo * entry,gint stage)251 ggit_index_entry_resolve_undo_get_mode (GgitIndexEntryResolveUndo *entry,
252                                         gint                    stage)
253 {
254 	g_return_val_if_fail (entry != NULL, 0);
255 	g_return_val_if_fail (stage >= 0 && stage <= 3, 0);
256 
257 	return entry->entry->mode[stage];
258 }
259 
260 /**
261  * ggit_index_entry_resolve_undo_get_id:
262  * @entry: a #GgitIndexEntryResolveUndo.
263  * @stage: the stage (0, 1 or 2).
264  *
265  * Get the oid of the index entry.
266  *
267  * Returns: (transfer full) (nullable): the oid or %NULL.
268  *
269  **/
270 GgitOId *
ggit_index_entry_resolve_undo_get_id(GgitIndexEntryResolveUndo * entry,gint stage)271 ggit_index_entry_resolve_undo_get_id (GgitIndexEntryResolveUndo *entry,
272                                       gint                    stage)
273 {
274 	g_return_val_if_fail (entry != NULL, NULL);
275 	g_return_val_if_fail (stage >= 0 && stage <= 3, NULL);
276 
277 	return _ggit_oid_wrap (&entry->entry->oid[stage]);
278 }
279 
280 /**
281  * ggit_index_entry_resolve_undo_get_file:
282  * @entry: a #GgitIndexEntryResolveUndo.
283  *
284  * Get the file of the index entry.
285  *
286  * Returns: (transfer full) (nullable): a #GFile or %NULL.
287  *
288  **/
289 GFile *
ggit_index_entry_resolve_undo_get_file(GgitIndexEntryResolveUndo * entry)290 ggit_index_entry_resolve_undo_get_file (GgitIndexEntryResolveUndo *entry)
291 {
292 	g_return_val_if_fail (entry != NULL, 0);
293 
294 	if (entry->entry->path == NULL)
295 	{
296 		return NULL;
297 	}
298 
299 	return g_file_new_for_path (entry->entry->path);
300 }
301 
302 /* ex:set ts=8 noet: */
303