1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3  * anjuta
4  * Copyright (C) James Liggett 2008 <jrliggett@cox.net>
5  *
6  * anjuta is free software.
7  *
8  * You may redistribute it and/or modify it under the terms of the
9  * GNU General Public License, as published by the Free Software
10  * Foundation; either version 2 of the License, or (at your option)
11  * any later version.
12  *
13  * anjuta is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  * See the GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with anjuta.  If not, write to:
20  * 	The Free Software Foundation, Inc.,
21  * 	51 Franklin Street, Fifth Floor
22  * 	Boston, MA  02110-1301, USA.
23  */
24 
25 #include "git-vcs-interface.h"
26 
27 void
git_ivcs_iface_init(IAnjutaVcsIface * iface)28 git_ivcs_iface_init (IAnjutaVcsIface *iface)
29 {
30 	iface->add = git_ivcs_add;
31 	iface->checkout = git_ivcs_checkout;
32 	iface->diff = git_ivcs_diff;
33 	iface->query_status = git_ivcs_query_status;
34 	iface->remove = git_ivcs_remove;
35 }
36 
37 void
git_ivcs_add(IAnjutaVcs * obj,GList * files,AnjutaAsyncNotify * notify,GError ** err)38 git_ivcs_add (IAnjutaVcs *obj, GList *files, AnjutaAsyncNotify *notify,
39 			  GError **err)
40 {
41 	gchar *project_root_directory;
42 	GList *path_list;
43 	GitAddCommand *add_command;
44 
45 	project_root_directory = ANJUTA_PLUGIN_GIT (obj)->project_root_directory;
46 
47 	if (project_root_directory)
48 	{
49 		path_list = anjuta_util_convert_gfile_list_to_relative_path_list (files,
50 		                                                                  project_root_directory);
51 		add_command = git_add_command_new_list (project_root_directory,
52 		                                        path_list, FALSE);
53 
54 		anjuta_util_glist_strings_free (path_list);
55 
56 		g_signal_connect (G_OBJECT (add_command), "command-finished",
57 		                  G_CALLBACK (g_object_unref),
58 		                  NULL);
59 
60 		if (notify)
61 		{
62 			g_signal_connect_swapped (G_OBJECT (add_command), "command-finished",
63 			                          G_CALLBACK (anjuta_async_notify_notify_finished),
64 			                          notify);
65 		}
66 
67 		anjuta_command_start (ANJUTA_COMMAND (add_command));
68 	}
69 
70 }
71 
72 void
git_ivcs_checkout(IAnjutaVcs * obj,const gchar * repository_location,GFile * dest,GCancellable * cancel,AnjutaAsyncNotify * notify,GError ** err)73 git_ivcs_checkout (IAnjutaVcs *obj,
74 				   const gchar *repository_location, GFile *dest,
75 				   GCancellable *cancel,
76 				   AnjutaAsyncNotify *notify, GError **err)
77 {
78 	GFile *parent;
79 	gchar *path, *dir_name;
80 	GitCloneCommand *clone_command;
81 	Git *plugin;
82 
83 	parent = g_file_get_parent (dest);
84 	path = g_file_get_path (parent);
85 	dir_name = g_file_get_basename (dest);
86 
87 	clone_command = git_clone_command_new (path, repository_location, dir_name);
88 	plugin = ANJUTA_PLUGIN_GIT (obj);
89 
90 	g_object_unref (parent);
91 	g_free (path);
92 	g_free (dir_name);
93 
94 	git_pane_create_message_view (plugin);
95 
96 	g_signal_connect (G_OBJECT (clone_command), "data-arrived",
97 	                  G_CALLBACK (git_pane_on_command_info_arrived),
98 	                  plugin);
99 
100 	g_signal_connect (G_OBJECT (clone_command), "command-finished",
101 	                  G_CALLBACK (g_object_unref),
102 	                  NULL);
103 
104 	if (cancel)
105 	{
106 		g_signal_connect_swapped (G_OBJECT (cancel), "cancelled",
107 		                          G_CALLBACK (anjuta_command_cancel),
108 		                          clone_command);
109 	}
110 
111 	if (notify)
112 	{
113 		g_signal_connect_swapped (G_OBJECT (clone_command),
114 		                          "command-finished",
115 		                          G_CALLBACK (anjuta_async_notify_notify_finished),
116 		                          notify);
117 	}
118 
119 	anjuta_command_start (ANJUTA_COMMAND (clone_command));
120 }
121 
122 static void
on_diff_command_data_arrived(AnjutaCommand * command,IAnjutaVcsDiffCallback callback)123 on_diff_command_data_arrived (AnjutaCommand *command,
124 							  IAnjutaVcsDiffCallback callback)
125 {
126 	GQueue *output;
127 	gchar *line;
128 
129 	output = git_raw_output_command_get_output (GIT_RAW_OUTPUT_COMMAND (command));
130 
131 	while (g_queue_peek_head (output))
132 	{
133 		line = g_queue_pop_head (output);
134 		callback (g_object_get_data (G_OBJECT (command), "file"), line,
135 				  g_object_get_data (G_OBJECT (command), "user-data"));
136 		g_free (line);
137 	}
138 }
139 
140 void
git_ivcs_diff(IAnjutaVcs * obj,GFile * file,IAnjutaVcsDiffCallback callback,gpointer user_data,GCancellable * cancel,AnjutaAsyncNotify * notify,GError ** err)141 git_ivcs_diff (IAnjutaVcs *obj, GFile* file,
142 			   IAnjutaVcsDiffCallback callback, gpointer user_data,
143 			   GCancellable* cancel, AnjutaAsyncNotify *notify,
144 			   GError **err)
145 {
146 	gchar *project_root_directory;
147 	GitDiffCommand *diff_command;
148 
149 	project_root_directory = ANJUTA_PLUGIN_GIT (obj)->project_root_directory;
150 
151 	if (project_root_directory)
152 	{
153 		diff_command = git_diff_command_new (project_root_directory, NULL, GIT_DIFF_WORKING_TREE);
154 
155 		g_object_set_data_full (G_OBJECT (diff_command), "file",
156 		                        g_object_ref (file),
157 		                        (GDestroyNotify) g_object_unref);
158 		g_object_set_data (G_OBJECT (diff_command), "user-data", user_data);
159 
160 		g_signal_connect (G_OBJECT (diff_command), "command-finished",
161 		                  G_CALLBACK (g_object_unref),
162 		                  NULL);
163 
164 		g_signal_connect (G_OBJECT (diff_command), "data-arrived",
165 		                  G_CALLBACK (on_diff_command_data_arrived),
166 		                  callback);
167 
168 /* FIXME: Reenable when canceling is implemented. */
169 #if 0
170 		if (cancel)
171 		{
172 			g_signal_connect_swapped (G_OBJECT (cancel), "cancelled",
173 			                          G_CALLBACK (anjuta_command_cancel),
174 			                          diff_command);
175 		}
176 #endif
177 
178 		if (notify)
179 		{
180 			g_signal_connect_swapped (G_OBJECT (diff_command), "command-finished",
181 			                          G_CALLBACK (anjuta_async_notify_notify_finished),
182 			                          notify);
183 		}
184 
185 		anjuta_command_start (ANJUTA_COMMAND (diff_command));
186 	}
187 }
188 
189 static void
on_status_command_data_arrived(AnjutaCommand * command,IAnjutaVcsStatusCallback callback)190 on_status_command_data_arrived (AnjutaCommand *command,
191 								IAnjutaVcsStatusCallback callback)
192 {
193 	GQueue *status_queue;
194 	GitStatus *status;
195 	const gchar *working_directory;
196 	gchar *path;
197 	gchar *full_path;
198 	GFile *file;
199 
200 	status_queue = git_status_command_get_status_queue (GIT_STATUS_COMMAND (command));
201 
202 	while (g_queue_peek_head (status_queue))
203 	{
204 		status = g_queue_pop_head (status_queue);
205 		working_directory = g_object_get_data (G_OBJECT (command),
206 		                                       "working-directory");
207 		path = git_status_get_path (status);
208 		full_path = g_strconcat (working_directory, G_DIR_SEPARATOR_S, path,
209 		                         NULL);
210 		file = g_file_new_for_path (full_path);
211 
212 		DEBUG_PRINT ("Working directory: %s\n", working_directory);
213 		DEBUG_PRINT ("File %s Status %i\n", full_path, git_status_get_vcs_status (status));
214 
215 		if (file)
216 		{
217 			callback (file,
218 			          git_status_get_vcs_status (status),
219 			          g_object_get_data (G_OBJECT (command), "user-data"));
220 
221 			g_object_unref (file);
222 		}
223 
224 		g_free (path);
225 		g_free (full_path);
226 
227 		g_object_unref (status);
228 	}
229 }
230 
231 void
git_ivcs_query_status(IAnjutaVcs * obj,GFile * file,IAnjutaVcsStatusCallback callback,gpointer user_data,GCancellable * cancel,AnjutaAsyncNotify * notify,GError ** err)232 git_ivcs_query_status (IAnjutaVcs *obj, GFile *file,
233 					   IAnjutaVcsStatusCallback callback,
234 					   gpointer user_data, GCancellable *cancel,
235 					   AnjutaAsyncNotify *notify, GError **err)
236 {
237 	gchar *path;
238 	GitStatusCommand *status_command;
239 
240 	path = g_file_get_path (file);
241 	status_command = git_status_command_new (path);
242 
243 	g_free (path);
244 
245 	g_object_set_data (G_OBJECT (status_command), "user-data", user_data);
246 	g_object_set_data (G_OBJECT (status_command), "working-directory",
247 	                   ANJUTA_PLUGIN_GIT (obj)->project_root_directory);
248 
249 	g_signal_connect (G_OBJECT (status_command), "data-arrived",
250 	                  G_CALLBACK (on_status_command_data_arrived),
251 	                  callback);
252 
253 	g_signal_connect (G_OBJECT (status_command), "command-finished",
254 	                  G_CALLBACK (g_object_unref),
255 	                  NULL);
256 
257 #if 0
258 	if (cancel)
259 	{
260 		g_signal_connect_swapped (G_OBJECT (cancel), "cancelled",
261 		                          G_CALLBACK (anjuta_command_cancel),
262 		                          status_command);
263 	}
264 #endif
265 
266 	if (notify)
267 	{
268 		g_signal_connect_swapped (G_OBJECT (status_command), "command-finished",
269 		                          G_CALLBACK (anjuta_async_notify_notify_finished),
270 		                          notify);
271 	}
272 
273 	anjuta_command_queue_push (ANJUTA_PLUGIN_GIT (obj)->command_queue,
274 	                           ANJUTA_COMMAND (status_command));
275 }
276 
277 void
git_ivcs_remove(IAnjutaVcs * obj,GList * files,AnjutaAsyncNotify * notify,GError ** err)278 git_ivcs_remove (IAnjutaVcs *obj, GList *files,
279 				 AnjutaAsyncNotify *notify, GError **err)
280 {
281 	gchar *project_root_directory;
282 	GList *path_list;
283 	GitRemoveCommand *remove_command;
284 
285 	project_root_directory = ANJUTA_PLUGIN_GIT (obj)->project_root_directory;
286 
287 	if (project_root_directory)
288 	{
289 		path_list = anjuta_util_convert_gfile_list_to_relative_path_list (files,
290 		                                                                  project_root_directory);
291 		remove_command = git_remove_command_new_list (project_root_directory,
292 		                                              path_list, FALSE);
293 
294 		anjuta_util_glist_strings_free (path_list);
295 
296 		g_signal_connect (G_OBJECT (remove_command), "command-finished",
297 		                  G_CALLBACK (g_object_unref),
298 		                  NULL);
299 
300 		if (notify)
301 		{
302 			g_signal_connect_swapped (G_OBJECT (remove_command), "command-finished",
303 			                          G_CALLBACK (anjuta_async_notify_notify_finished),
304 			                          notify);
305 		}
306 
307 		anjuta_command_start (ANJUTA_COMMAND (remove_command));
308 	}
309 }
310