1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4; coding: utf-8 -*- */
2 /* am-package.c
3  *
4  * Copyright (C) 2009  Sébastien Granjoux
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of the
9  * License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public
17  * License along with this program; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 
27 #include "amp-package.h"
28 
29 #include "amp-node.h"
30 #include "am-scanner.h"
31 #include "am-properties.h"
32 #include "ac-writer.h"
33 
34 
35 #include <libanjuta/interfaces/ianjuta-project.h>
36 #include <libanjuta/anjuta-utils.h>
37 #include <libanjuta/anjuta-pkg-config.h>
38 
39 #include <libanjuta/anjuta-debug.h>
40 
41 #include <glib/gi18n.h>
42 
43 #include <memory.h>
44 #include <string.h>
45 #include <ctype.h>
46 
47 /* Types
48  *---------------------------------------------------------------------------*/
49 
50 struct _AmpPackageNode {
51 	AnjutaProjectNode base;
52 	gchar *version;
53 	AnjutaToken *token;
54 };
55 
56 typedef struct _AmpPackageNodeClass AmpPackageNodeClass;
57 
58 struct _AmpPackageNodeClass {
59 	AmpNodeClass parent_class;
60 };
61 
62 G_DEFINE_DYNAMIC_TYPE (AmpPackageNode, amp_package_node, AMP_TYPE_NODE);
63 
64 
65 /* Package objects
66  *---------------------------------------------------------------------------*/
67 
68 AmpPackageNode*
amp_package_node_new(const gchar * name)69 amp_package_node_new (const gchar *name)
70 {
71 	AmpPackageNode *node = NULL;
72 
73 	node = g_object_new (AMP_TYPE_PACKAGE_NODE, NULL);
74 	node->base.name = g_strdup (name);
75 
76 	return node;
77 }
78 
79 AmpPackageNode*
amp_package_node_new_valid(const gchar * name,GError ** error)80 amp_package_node_new_valid (const gchar *name, GError **error)
81 {
82 	return amp_package_node_new (name);
83 }
84 
85 void
amp_package_node_free(AmpPackageNode * node)86 amp_package_node_free (AmpPackageNode *node)
87 {
88 	g_object_unref (G_OBJECT (node));
89 }
90 
91 void
amp_package_node_set_version(AmpPackageNode * node,const gchar * compare,const gchar * version)92 amp_package_node_set_version (AmpPackageNode *node, const gchar *compare, const gchar *version)
93 {
94 	g_return_if_fail (node != NULL);
95 	g_return_if_fail ((version == NULL) || (compare != NULL));
96 
97 	g_free (node->version);
98 	node->version = version != NULL ? g_strconcat (compare, version, NULL) : NULL;
99 }
100 
101 AnjutaToken *
amp_package_node_get_token(AmpPackageNode * node)102 amp_package_node_get_token (AmpPackageNode *node)
103 {
104 	return node->token;
105 }
106 
107 void
amp_package_node_add_token(AmpPackageNode * node,AnjutaToken * token)108 amp_package_node_add_token (AmpPackageNode *node, AnjutaToken *token)
109 {
110 	node->token = token;
111 }
112 
113 void
amp_package_node_update_node(AmpPackageNode * node,AmpPackageNode * new_node)114 amp_package_node_update_node (AmpPackageNode *node, AmpPackageNode *new_node)
115 {
116 	g_return_if_fail (new_node != NULL);
117 
118 	node->token = new_node->token;
119 	g_free (node->version);
120 	node->version = new_node->version;
121 	new_node->version = NULL;
122 }
123 
124 /* AmpNode implementation
125  *---------------------------------------------------------------------------*/
126 
127 static gboolean
amp_package_node_load(AmpNode * node,AmpNode * parent,AmpProject * project,GError ** error)128 amp_package_node_load (AmpNode *node, AmpNode *parent, AmpProject *project, GError **error)
129 {
130 	GList* deps;
131 	GList* dep;
132 	GList* include_dirs = NULL;
133 
134 	deps = anjuta_pkg_config_list_dependencies (anjuta_project_node_get_name (ANJUTA_PROJECT_NODE (node)),
135 	                                            error);
136 	for (dep = deps; dep != NULL; dep = g_list_next (dep))
137 	{
138 		/* Create a package node for the depedencies */
139 		AnjutaProjectNode *pkg;
140 
141 		pkg = ANJUTA_PROJECT_NODE (amp_package_node_new (dep->data));
142 		anjuta_project_node_append (ANJUTA_PROJECT_NODE (node), pkg);
143 	}
144 	anjuta_util_glist_strings_free (deps);
145 
146 	if (*error != NULL)
147 	{
148 		g_warning ("Error getting dependencies: %s", (*error)->message);
149 		g_error_free (*error);
150 		*error = NULL;
151 	}
152 
153 	if ((include_dirs = anjuta_pkg_config_get_directories (anjuta_project_node_get_name (ANJUTA_PROJECT_NODE (node)),
154 	                                                       TRUE, error)))
155 	{
156 		GList* include_dir;
157 
158 		for (include_dir = include_dirs; include_dir != NULL; include_dir = g_list_next (include_dir))
159 		{
160 			GList* children = NULL;
161 			GList* file = NULL;
162 			GFile* dir = g_file_new_for_path (include_dir->data);
163 
164 			anjuta_util_list_all_dir_children (&children, dir);
165 			for (file = g_list_first (children); file != NULL; file = g_list_next (file))
166 			{
167 				/* Create a source for files */
168 				AnjutaProjectNode *source;
169 
170 				source = amp_node_new_valid (ANJUTA_PROJECT_NODE (parent), ANJUTA_PROJECT_SOURCE, (GFile *)file->data, NULL, NULL);
171 				anjuta_project_node_append (ANJUTA_PROJECT_NODE (node), source);
172 				g_object_unref ((GObject *)file->data);
173 			}
174 			g_list_free (children);
175 			g_object_unref (dir);
176 		}
177 	}
178 	anjuta_util_glist_strings_free (include_dirs);
179 
180 	return TRUE;
181 }
182 
183 static gboolean
amp_package_node_update(AmpNode * node,AmpNode * new_node)184 amp_package_node_update (AmpNode *node, AmpNode *new_node)
185 {
186 	amp_package_node_update_node (AMP_PACKAGE_NODE (node), AMP_PACKAGE_NODE (new_node));
187 
188 	return TRUE;
189 }
190 
191 static AmpNode *
amp_package_node_copy(AmpNode * old_node)192 amp_package_node_copy (AmpNode *old_node)
193 {
194 	AmpNode *new_node;
195 
196 	new_node = AMP_NODE_CLASS (amp_package_node_parent_class)->copy (old_node);
197 	// FIXME: We should probably copy the version number too because it will not
198 	// be updated when the node is reloaded. So later when updating the old_node,
199 	// the value will be overwritten with the new node empty value.
200 	amp_package_node_add_token (AMP_PACKAGE_NODE (new_node), amp_package_node_get_token (AMP_PACKAGE_NODE (old_node)));
201 
202 	return new_node;
203 }
204 
205 static gboolean
amp_package_node_write(AmpNode * node,AmpNode * parent,AmpProject * project,GError ** error)206 amp_package_node_write (AmpNode *node, AmpNode *parent, AmpProject *project, GError **error)
207 {
208 	return amp_package_node_create_token (project, AMP_PACKAGE_NODE (node), error);
209 }
210 
211 static gboolean
amp_package_node_erase(AmpNode * node,AmpNode * parent,AmpProject * project,GError ** error)212 amp_package_node_erase (AmpNode *node, AmpNode *parent, AmpProject *project, GError **error)
213 {
214 			return amp_package_node_delete_token (project, AMP_PACKAGE_NODE (node), error);
215 }
216 
217 
218 /* GObjet implementation
219  *---------------------------------------------------------------------------*/
220 
221 static void
amp_package_node_init(AmpPackageNode * node)222 amp_package_node_init (AmpPackageNode *node)
223 {
224 	node->base.type = ANJUTA_PROJECT_PACKAGE;
225 	node->base.properties_info = amp_get_package_property_list();
226 	node->base.state =  ANJUTA_PROJECT_CAN_REMOVE;
227 	node->version = NULL;
228 }
229 
230 static void
amp_package_node_finalize(GObject * object)231 amp_package_node_finalize (GObject *object)
232 {
233 	AmpPackageNode *node = AMP_PACKAGE_NODE (object);
234 
235 	g_list_foreach (node->base.properties, (GFunc)amp_property_free, NULL);
236 
237 	G_OBJECT_CLASS (amp_package_node_parent_class)->finalize (object);
238 }
239 
240 static void
amp_package_node_class_init(AmpPackageNodeClass * klass)241 amp_package_node_class_init (AmpPackageNodeClass *klass)
242 {
243 	GObjectClass* object_class = G_OBJECT_CLASS (klass);
244 	AmpNodeClass* node_class;
245 
246 	object_class->finalize = amp_package_node_finalize;
247 
248 	node_class = AMP_NODE_CLASS (klass);
249 	node_class->load = amp_package_node_load;
250 	node_class->update = amp_package_node_update;
251 	node_class->copy = amp_package_node_copy;
252 	node_class->erase = amp_package_node_erase;
253 	node_class->write = amp_package_node_write;
254 }
255 
256 static void
amp_package_node_class_finalize(AmpPackageNodeClass * klass)257 amp_package_node_class_finalize (AmpPackageNodeClass *klass)
258 {
259 }
260 
261 void
amp_package_node_register(GTypeModule * module)262 amp_package_node_register (GTypeModule *module)
263 {
264 	amp_package_node_register_type (module);
265 }
266