1 /*
2  * ggit-reflog.c
3  * This file is part of libgit2-glib
4  *
5  * Copyright (C) 2012 - Garrett Regier
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-reflog.h"
22 
23 #include "ggit-reflog-entry.h"
24 #include "ggit-native.h"
25 #include "ggit-error.h"
26 #include "ggit-signature.h"
27 #include "ggit-oid.h"
28 
29 struct _GgitReflog
30 {
31 	GgitRef *ref;
32 	git_reflog *reflog;
33 	gint ref_count;
34 };
35 
G_DEFINE_BOXED_TYPE(GgitReflog,ggit_reflog,ggit_reflog_ref,ggit_reflog_unref)36 G_DEFINE_BOXED_TYPE (GgitReflog, ggit_reflog, ggit_reflog_ref, ggit_reflog_unref)
37 
38 GgitReflog *
39 _ggit_reflog_wrap (GgitRef    *ref,
40                    git_reflog *reflog)
41 {
42 	GgitReflog *greflog;
43 
44 	greflog = g_slice_new (GgitReflog);
45 	greflog->reflog = reflog;
46 	greflog->ref = g_object_ref (ref);
47 	greflog->ref_count = 1;
48 
49 	return greflog;
50 }
51 
52 /**
53  * ggit_reflog_ref:
54  * @reflog: a #GgitReflog.
55  *
56  * Atomically increments the reference count of @reflog by one.
57  * This function is MT-safe and may be called from any thread.
58  *
59  * Returns: (transfer none) (nullable): the passed in #GgitReflog or %NULL.
60  */
61 GgitReflog *
ggit_reflog_ref(GgitReflog * reflog)62 ggit_reflog_ref (GgitReflog *reflog)
63 {
64 	g_return_val_if_fail (reflog != NULL, NULL);
65 
66 	g_atomic_int_inc (&reflog->ref_count);
67 
68 	return reflog;
69 }
70 
71 /**
72  * ggit_reflog_unref:
73  * @reflog: a #GgitReflog.
74  *
75  * Atomically decrements the reference count of @reflog by one.
76  * If the reference count drops to 0, @reflog is freed.
77  */
78 void
ggit_reflog_unref(GgitReflog * reflog)79 ggit_reflog_unref (GgitReflog *reflog)
80 {
81 	g_return_if_fail (reflog != NULL);
82 
83 	if (g_atomic_int_dec_and_test (&reflog->ref_count))
84 	{
85 		g_object_unref (reflog->ref);
86 
87 		git_reflog_free (reflog->reflog);
88 		g_slice_free (GgitReflog, reflog);
89 	}
90 }
91 
92 /**
93  * ggit_reflog_write:
94  * @reflog: a #GgitReflog.
95  * @error: a #GError.
96  *
97  * Write the reflog to disk.
98  *
99  * Returns: %TRUE if the reflog was successfully written, or %FALSE on error.
100  *
101  **/
102 gboolean
ggit_reflog_write(GgitReflog * reflog,GError ** error)103 ggit_reflog_write (GgitReflog  *reflog,
104                    GError     **error)
105 {
106 	gint ret;
107 
108 	g_return_val_if_fail (reflog != NULL, FALSE);
109 	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
110 
111 	ret = git_reflog_write (reflog->reflog);
112 
113 	if (ret != GIT_OK)
114 	{
115 		_ggit_error_set (error, ret);
116 		return FALSE;
117 	}
118 
119 	return TRUE;
120 }
121 
122 /**
123  * ggit_reflog_get_entry_count:
124  * @reflog: a #GgitReflog.
125  *
126  * Gets the number of log entries in @reflog.
127  *
128  * Returns: the number of log entries.
129  */
130 guint
ggit_reflog_get_entry_count(GgitReflog * reflog)131 ggit_reflog_get_entry_count (GgitReflog *reflog)
132 {
133 	g_return_val_if_fail (reflog != NULL, 0);
134 
135 	return git_reflog_entrycount (reflog->reflog);
136 }
137 
138 /**
139  * ggit_reflog_get_entry_from_index:
140  * @reflog: a #GgitReflog.
141  * @idx: the position to lookup.
142  *
143  * Gets the #GgitReflogEntry at @idx in @reflog, or %NULL if not found.
144  *
145  * Returns: (transfer full) (nullable): the reflog entry at the index, or %NULL if not found.
146  */
147 GgitReflogEntry *
ggit_reflog_get_entry_from_index(GgitReflog * reflog,guint idx)148 ggit_reflog_get_entry_from_index (GgitReflog *reflog,
149                                   guint       idx)
150 {
151 	const git_reflog_entry *reflog_entry;
152 
153 	g_return_val_if_fail (reflog != NULL, NULL);
154 
155 	reflog_entry = git_reflog_entry_byindex (reflog->reflog, idx);
156 
157 	if (reflog_entry == NULL)
158 	{
159 		return NULL;
160 	}
161 
162 	return _ggit_reflog_entry_wrap (reflog_entry);
163 }
164 
165 
166 /**
167  * ggit_reflog_rename:
168  * @reflog: a #GgitReflog.
169  * @new_name: the new name of the reference.
170  * @error: a #GError for error reporting, or %NULL.
171  *
172  * Renames the reflog for to @new_name, on error @error is set.
173  */
174 gboolean
ggit_reflog_rename(GgitReflog * reflog,const gchar * new_name,GError ** error)175 ggit_reflog_rename (GgitReflog  *reflog,
176                     const gchar *new_name,
177                     GError      **error)
178 {
179 	git_reference *nref;
180 	gint ret;
181 
182 	g_return_val_if_fail (reflog != NULL, FALSE);
183 	g_return_val_if_fail (new_name != NULL && *new_name != '\0', FALSE);
184 	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
185 
186 	nref = _ggit_native_get (reflog->ref);
187 
188 	ret = git_reflog_rename (git_reference_owner (nref),
189 	                         git_reference_name (nref),
190 	                         new_name);
191 
192 	if (ret != GIT_OK)
193 	{
194 		_ggit_error_set (error, ret);
195 		return FALSE;
196 	}
197 
198 	return TRUE;
199 }
200 
201 /**
202  * ggit_reflog_append:
203  * @reflog: a #GgitReflog.
204  * @oid: a #GgitOId.
205  * @committer: a #GgitSignature.
206  * @message: the message.
207  * @error: a #GError for error reporting, or %NULL.
208  *
209  * Creates a reflog entry.
210  *
211  * Returns: %TRUE if the reflog was successfully created, or %FALSE if error is set.
212  */
213 gboolean
ggit_reflog_append(GgitReflog * reflog,GgitOId * oid,GgitSignature * committer,const gchar * message,GError ** error)214 ggit_reflog_append (GgitReflog     *reflog,
215                     GgitOId        *oid,
216                     GgitSignature  *committer,
217                     const gchar    *message,
218                     GError        **error)
219 {
220 	gint ret;
221 
222 	g_return_val_if_fail (reflog != NULL, FALSE);
223 	g_return_val_if_fail (oid != NULL, FALSE);
224 	g_return_val_if_fail (GGIT_IS_SIGNATURE (committer), FALSE);
225 	g_return_val_if_fail (message != NULL && *message != '\0', FALSE);
226 	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
227 
228 	ret = git_reflog_append (reflog->reflog,
229 	                         _ggit_oid_get_oid (oid),
230 	                         _ggit_native_get (committer),
231 	                         message);
232 
233 	if (ret != GIT_OK)
234 	{
235 		_ggit_error_set (error, ret);
236 		return FALSE;
237 	}
238 
239 	return TRUE;
240 }
241 
242 /* ex:set ts=8 noet: */
243