1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4; coding: utf-8 -*- */
4 * Copyright (C) 2009 Sébastien Granjoux
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.
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.
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., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
27 #include "am-project.h"
29 #include "am-project-private.h"
31 #include "amp-module.h"
32 #include "amp-package.h"
33 #include "amp-group.h"
34 #include "amp-target.h"
35 #include "amp-source.h"
36 #include "amp-object.h"
37 #include "command-queue.h"
39 #include <libanjuta/interfaces/ianjuta-project.h>
40 #include <libanjuta/anjuta-debug.h>
41 #include <libanjuta/anjuta-utils.h>
42 #include <libanjuta/anjuta-pkg-config.h>
50 #include <sys/types.h>
52 #include <glib/gi18n.h>
56 #include "ac-scanner.h"
57 #include "ac-writer.h"
58 #include "am-scanner.h"
59 #include "am-writer.h"
60 //#include "am-config.h"
61 #include "am-properties.h"
64 #define UNIMPLEMENTED G_STMT_START { g_warning (G_STRLOC": unimplemented"); } G_STMT_END
66 /* Constant strings for parsing perl script error output */
67 #define ERROR_PREFIX "ERROR("
68 #define WARNING_PREFIX "WARNING("
69 #define MESSAGE_DELIMITER ": "
71 const gchar
*valid_am_makefiles
[] = {"GNUmakefile.am", "makefile.am", "Makefile.am", NULL
};
74 #define STR_REPLACE(target, source) \
75 { g_free (target); target = source == NULL ? NULL : g_strdup (source);}
78 typedef struct _AmpConfigFile AmpConfigFile
;
80 struct _AmpConfigFile
{
86 *---------------------------------------------------------------------------*/
88 static AmpNodeInfo AmpNodeInformations
[] = {
89 {{ANJUTA_PROJECT_GROUP
| ANJUTA_PROJECT_ROOT_GROUP
,
92 "autotools-project-root-edit"},
97 {{ANJUTA_PROJECT_GROUP
,
100 "autotools-project-folder-edit"},
105 {{ANJUTA_PROJECT_SOURCE
,
113 {{ANJUTA_PROJECT_TARGET
| ANJUTA_PROJECT_UNKNOWN
| ANJUTA_PROJECT_READ_ONLY
,
114 /* Translator: Unknown here is a target type, if not unknown it can
115 * be a program or a shared library by example */
118 "autotools-project-target-edit"},
123 {{ANJUTA_PROJECT_TARGET
| ANJUTA_PROJECT_PRIMARY
| ANJUTA_PROJECT_SHAREDLIB
,
124 N_("Shared Library (Libtool)"),
125 "application/x-sharedlib",
126 "autotools-project-target-edit"},
127 AM_TOKEN__LTLIBRARIES
,
131 {{ANJUTA_PROJECT_TARGET
| ANJUTA_PROJECT_PRIMARY
| ANJUTA_PROJECT_LT_MODULE
,
132 N_("Module (Libtool)"),
133 "application/x-sharedlib",
134 "autotools-project-target-edit"},
135 AM_TOKEN__LTLIBRARIES
,
139 {{ANJUTA_PROJECT_TARGET
| ANJUTA_PROJECT_PRIMARY
| ANJUTA_PROJECT_STATICLIB
,
140 N_("Static Library (Libtool)"),
141 "application/x-archive",
142 "autotools-project-target-edit"},
147 {{ANJUTA_PROJECT_TARGET
| ANJUTA_PROJECT_PRIMARY
| ANJUTA_PROJECT_PROGRAM
| ANJUTA_PROJECT_EXECUTABLE
,
149 "application/x-executable",
150 "autotools-project-target-edit"},
155 {{ANJUTA_PROJECT_TARGET
| ANJUTA_PROJECT_PYTHON
,
157 "application/x-python",
158 "autotools-project-target-edit"},
163 {{ANJUTA_PROJECT_TARGET
| ANJUTA_PROJECT_JAVA
,
165 "application/x-java",
166 "autotools-project-target-edit"},
171 {{ANJUTA_PROJECT_TARGET
| ANJUTA_PROJECT_LISP
,
174 "autotools-project-target-edit"},
179 {{ANJUTA_PROJECT_TARGET
| ANJUTA_PROJECT_HEADER
,
182 "autotools-project-target-edit"},
187 {{ANJUTA_PROJECT_TARGET
| ANJUTA_PROJECT_MAN
,
188 N_("Man Documentation"),
190 "autotools-project-target-edit"},
195 {{ANJUTA_PROJECT_TARGET
| ANJUTA_PROJECT_INFO
,
196 N_("Info Documentation"),
197 "application/x-tex-info",
198 "autotools-project-target-edit"},
203 {{ANJUTA_PROJECT_TARGET
| ANJUTA_PROJECT_DATA
,
204 N_("Miscellaneous Data"),
205 "application/octet-stream",
206 "autotools-project-target-edit"},
211 {{ANJUTA_PROJECT_TARGET
| ANJUTA_PROJECT_SCRIPT
,
213 "text/x-shellscript",
214 "autotools-project-target-edit"},
219 {{ANJUTA_PROJECT_MODULE
,
227 {{ANJUTA_PROJECT_PACKAGE
,
235 {{ANJUTA_PROJECT_UNKNOWN
,
245 *---------------------------------------------------------------------------*/
247 static void iproject_iface_init(IAnjutaProjectIface
* iface
);
249 G_DEFINE_DYNAMIC_TYPE_EXTENDED (AmpProject
,
253 G_IMPLEMENT_INTERFACE_DYNAMIC (IANJUTA_TYPE_PROJECT
,
254 iproject_iface_init
));
259 *---------------------------------------------------------------------------*/
262 /* ----- Standard GObject types and variables ----- */
269 static GObject
*parent_class
;
272 *---------------------------------------------------------------------------*/
274 /* Work even if file is not a descendant of parent */
276 get_relative_path (GFile
*parent
, GFile
*file
)
280 relative
= g_file_get_relative_path (parent
, file
);
281 if (relative
== NULL
)
283 if (g_file_equal (parent
, file
))
285 relative
= g_strdup (".");
289 GFile
*grand_parent
= g_file_get_parent (parent
);
291 gchar
*grand_relative
;
296 for (level
= 1; !g_file_has_prefix (file
, grand_parent
); level
++)
298 GFile
*next
= g_file_get_parent (grand_parent
);
300 g_object_unref (grand_parent
);
304 grand_relative
= g_file_get_relative_path (grand_parent
, file
);
305 g_object_unref (grand_parent
);
307 len
= strlen (grand_relative
);
308 relative
= g_new (gchar
, len
+ level
* 3 + 1);
310 for (; level
; level
--)
312 memcpy(ptr
, ".." G_DIR_SEPARATOR_S
, 3);
315 memcpy (ptr
, grand_relative
, len
+ 1);
316 g_free (grand_relative
);
324 file_type (GFile
*file
, const gchar
*filename
)
330 child
= filename
!= NULL
? g_file_get_child (file
, filename
) : g_object_ref (file
);
332 info
= g_file_query_info (child
,
333 G_FILE_ATTRIBUTE_STANDARD_TYPE
,
334 G_FILE_QUERY_INFO_NONE
,
339 type
= g_file_info_get_file_type (info
);
340 g_object_unref (info
);
344 type
= G_FILE_TYPE_UNKNOWN
;
347 g_object_unref (child
);
352 /* Automake parsing function
353 *---------------------------------------------------------------------------*/
355 /* Remove invalid character according to automake rules */
357 canonicalize_automake_variable (const gchar
*name
)
359 gchar
*canon_name
= g_strdup (name
);
362 for (ptr
= canon_name
; *ptr
!= '\0'; ptr
++)
364 if (!g_ascii_isalnum (*ptr
) && (*ptr
!= '@'))
374 split_automake_variable (gchar
*name
, gint
*flags
, gchar
**module
, gchar
**primary
)
376 gboolean res
= FALSE
;
378 GMatchInfo
*match_info
;
382 regex
= g_regex_new ("(nobase_|notrans_)?"
384 "(noinst_|check_|man_|man[0-9al]_)?"
388 G_REGEX_MATCH_ANCHORED
,
391 if (!g_regex_match (regex
, name
, G_REGEX_MATCH_ANCHORED
, &match_info
))
397 g_match_info_fetch_pos (match_info
, 1, &start_pos
, &end_pos
);
400 if (*(name
+ start_pos
+ 2) == 'b') *flags
|= AM_TARGET_NOBASE
;
401 if (*(name
+ start_pos
+ 2) == 't') *flags
|= AM_TARGET_NOTRANS
;
404 g_match_info_fetch_pos (match_info
, 2, &start_pos
, &end_pos
);
407 if (*(name
+ start_pos
) == 'd') *flags
|= AM_TARGET_DIST
;
408 if (*(name
+ start_pos
) == 'n') *flags
|= AM_TARGET_NODIST
;
411 g_match_info_fetch_pos (match_info
, 3, &start_pos
, &end_pos
);
414 if (*(name
+ start_pos
) == 'n') *flags
|= AM_TARGET_NOINST
;
415 if (*(name
+ start_pos
) == 'c') *flags
|= AM_TARGET_CHECK
;
416 if (*(name
+ start_pos
) == 'm')
418 gchar section
= *(name
+ end_pos
- 1);
419 *flags
|= AM_TARGET_MAN
;
420 if (section
!= 'n') *flags
|= (section
& 0x1F) << 7;
427 g_match_info_fetch_pos (match_info
, 4, &start_pos
, &end_pos
);
430 *module
= name
+ start_pos
;
431 *(name
+ end_pos
- 1) = '\0';
441 g_match_info_fetch_pos (match_info
, 5, &start_pos
, &end_pos
);
444 *primary
= name
+ start_pos
;
455 g_match_info_unref (match_info
);
456 g_regex_unref (regex
);
462 ac_init_default_tarname (const gchar
*name
)
466 if (name
== NULL
) return NULL
;
468 /* Remove GNU prefix */
469 if (strncmp (name
, "GNU ", 4) == 0) name
+= 4;
471 tarname
= g_ascii_strdown (name
, -1);
472 g_strcanon (tarname
, "abcdefghijklmnopqrstuvwxyz0123456789", '-');
477 /* Config file objects
478 *---------------------------------------------------------------------------*/
480 static AmpConfigFile
*
481 amp_config_file_new (const gchar
*pathname
, GFile
*project_root
, AnjutaToken
*token
)
483 AmpConfigFile
*config
;
485 g_return_val_if_fail ((pathname
!= NULL
) && (project_root
!= NULL
), NULL
);
487 config
= g_slice_new0(AmpConfigFile
);
488 config
->file
= g_file_resolve_relative_path (project_root
, pathname
);
489 config
->token
= token
;
495 amp_config_file_free (AmpConfigFile
*config
)
499 g_object_unref (config
->file
);
500 g_slice_free (AmpConfigFile
, config
);
505 amp_project_clear (AmpProject
*project
)
507 if (project
->configure_file
!= NULL
) anjuta_token_file_free (project
->configure_file
);
508 project
->configure_file
= NULL
;
509 if (project
->configure_token
) anjuta_token_free (project
->configure_token
);
510 project
->configure_token
= NULL
;
514 on_project_monitor_changed (GFileMonitor
*monitor
,
517 GFileMonitorEvent event_type
,
520 AmpProject
*project
= AMP_PROJECT (data
);
522 switch (event_type
) {
523 case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT
:
524 case G_FILE_MONITOR_EVENT_CHANGED
:
525 case G_FILE_MONITOR_EVENT_DELETED
:
526 /* project can be NULL, if the node is dummy node because the
527 * original one is reloaded. */
528 g_signal_emit_by_name (G_OBJECT (project
), "file-changed", data
);
536 amp_project_set_configure (AmpProject
*project
, GFile
*configure
)
538 if (project
->configure
!= NULL
) g_object_unref (project
->configure
);
539 if (project
->configure_file
!= NULL
) anjuta_token_file_free (project
->configure_file
);
540 if (project
->monitor
) g_object_unref (project
->monitor
);
541 if (configure
!= NULL
)
543 project
->configure_file
= anjuta_token_file_new (configure
);
544 project
->configure
= g_object_ref (configure
);
546 project
->monitor
= g_file_monitor_file (configure
,
550 if (project
->monitor
!= NULL
)
552 g_signal_connect (G_OBJECT (project
->monitor
),
554 G_CALLBACK (on_project_monitor_changed
),
560 project
->configure_file
= NULL
;
561 project
->configure
= NULL
;
562 project
->monitor
= NULL
;
565 return project
->configure_file
;
569 amp_project_update_configure (AmpProject
*project
, AnjutaToken
*token
)
571 return anjuta_token_file_update (project
->configure_file
, token
);
575 amp_project_get_configure_token (AmpProject
*project
)
577 return project
->configure_token
;
581 amp_project_get_config_token (AmpProject
*project
, GFile
*file
)
583 AmpConfigFile
*config
;
585 config
= g_hash_table_lookup (project
->configs
, file
);
587 return config
!= NULL
? config
->token
: NULL
;
591 remove_config_file (gpointer data
, GObject
*object
)
593 AmpProject
*project
= (AmpProject
*)data
;
595 g_return_if_fail (project
->files
!= NULL
);
597 project
->files
= g_list_remove (project
->files
, object
);
601 amp_project_update_root (AmpProject
*project
, AmpProject
*new_project
)
605 AnjutaTokenStyle
*style
;
607 if (project
->configure
!= NULL
) g_object_unref (project
->configure
);
608 if (project
->configure_file
!= NULL
) anjuta_token_file_free (project
->configure_file
);
609 if (project
->monitor
) g_object_unref (project
->monitor
);
611 project
->configure
= new_project
->configure
;
612 if (project
->configure
!= NULL
)
614 project
->monitor
= g_file_monitor_file (project
->configure
,
618 if (project
->monitor
!= NULL
)
620 g_signal_connect (G_OBJECT (project
->monitor
),
622 G_CALLBACK (on_project_monitor_changed
),
628 project
->monitor
= NULL
;
630 new_project
->configure
= NULL
;
631 project
->configure_file
= new_project
->configure_file
;
632 new_project
->configure_file
= NULL
;
633 project
->configure_token
= new_project
->configure_token
;
634 new_project
->configure_token
= NULL
;
636 hash
= project
->groups
;
637 project
->groups
= new_project
->groups
;
638 new_project
->groups
= hash
;
640 list
= project
->files
;
641 project
->files
= new_project
->files
;
642 new_project
->files
= list
;
644 for (list
= project
->files
; list
!= NULL
; list
= g_list_next (list
))
646 GObject
*tfile
= (GObject
*)list
->data
;
648 g_object_weak_unref (tfile
, remove_config_file
, new_project
);
649 g_object_weak_ref (tfile
, remove_config_file
, project
);
651 for (list
= new_project
->files
; list
!= NULL
; list
= g_list_next (list
))
653 GObject
*tfile
= (GObject
*)list
->data
;
655 g_object_weak_unref (tfile
, remove_config_file
, project
);
656 g_object_weak_ref (tfile
, remove_config_file
, new_project
);
659 hash
= project
->configs
;
660 project
->configs
= new_project
->configs
;
661 new_project
->configs
= hash
;
664 style
= project
->ac_space_list
;
665 project
->ac_space_list
= new_project
->ac_space_list
;
666 new_project
->ac_space_list
= style
;
668 style
= project
->am_space_list
;
669 project
->am_space_list
= new_project
->am_space_list
;
670 new_project
->am_space_list
= style
;
672 style
= project
->arg_list
;
673 project
->arg_list
= new_project
->arg_list
;
674 new_project
->arg_list
= style
;
676 AMP_NODE_CLASS (parent_class
)->update (AMP_NODE (project
), AMP_NODE (new_project
));
681 *---------------------------------------------------------------------------*/
684 find_target (AnjutaProjectNode
*node
, gpointer data
)
686 if (anjuta_project_node_get_node_type (node
) == ANJUTA_PROJECT_TARGET
)
688 if (strcmp (anjuta_project_node_get_name (node
), *(gchar
**)data
) == 0)
690 /* Find target, return node value in pointer */
691 *(AnjutaProjectNode
**)data
= node
;
701 find_canonical_target (AnjutaProjectNode
*node
, gpointer data
)
703 if (anjuta_project_node_get_node_type (node
) == ANJUTA_PROJECT_TARGET
)
705 gchar
*canon_name
= canonicalize_automake_variable (anjuta_project_node_get_name (node
));
706 DEBUG_PRINT ("compare canon %s vs %s node %p", canon_name
, *(gchar
**)data
, node
);
707 if (strcmp (canon_name
, *(gchar
**)data
) == 0)
709 /* Find target, return node value in pointer */
710 *(AnjutaProjectNode
**)data
= node
;
722 * ---------------- Data structures managment
726 amp_project_load_properties (AmpProject
*project
, AnjutaToken
*macro
, AnjutaToken
*args
)
729 gint type
= anjuta_token_get_type (macro
);
731 for (item
= anjuta_project_node_get_properties_info (ANJUTA_PROJECT_NODE (project
)); item
!= NULL
; item
= g_list_next (item
))
733 AmpPropertyInfo
*info
= (AmpPropertyInfo
*)item
->data
;
735 if ((info
->token_type
== type
) && (info
->flags
& AM_PROPERTY_IN_CONFIGURE
))
737 AnjutaProjectProperty
*new_prop
;
739 new_prop
= anjuta_project_node_get_property (ANJUTA_PROJECT_NODE (project
), info
->base
.id
);
740 if ((new_prop
!= NULL
) && (new_prop
->info
->default_value
!= new_prop
))
742 amp_property_free (new_prop
);
744 new_prop
= amp_property_new (NULL
, info
->token_type
, info
->position
, NULL
, args
);
746 if (info
->position
>= 0)
748 /* Each parameter correspond to a different property */
751 arg
= anjuta_token_nth_word (args
, info
->position
);
752 g_free (new_prop
->value
);
753 new_prop
->value
= anjuta_token_evaluate_name (arg
);
757 /* Property value is whole argument */
760 new_prop
->value
= g_strdup(" ");
766 arg
= anjuta_token_nth_word (args
, 0);
767 new_prop
->value
= anjuta_token_evaluate_name (arg
);
768 if (new_prop
->value
== NULL
) new_prop
->value
= g_strdup(" ");
771 amp_node_property_add (ANJUTA_PROJECT_NODE (project
), new_prop
);
777 amp_project_load_module (AmpProject
*project
, AnjutaToken
*module_token
)
779 AmpAcScanner
*scanner
= NULL
;
781 if (module_token
!= NULL
)
787 AmpModuleNode
*module
;
788 AmpPackageNode
*package
;
792 arg
= anjuta_token_first_item (module_token
);
793 value
= anjuta_token_evaluate (arg
);
794 module
= amp_module_node_new (value
);
795 amp_module_node_add_token (module
, module_token
);
796 anjuta_project_node_append (ANJUTA_PROJECT_NODE (project
), ANJUTA_PROJECT_NODE (module
));
799 arg
= anjuta_token_next_word (arg
);
802 scanner
= amp_ac_scanner_new (project
);
803 list
= amp_ac_scanner_parse_token (scanner
, NULL
, arg
, AC_SPACE_LIST_STATE
, NULL
, NULL
);
804 anjuta_token_free_children (arg
);
805 list
= anjuta_token_delete_parent (list
);
806 anjuta_token_prepend_items (arg
, list
);
807 amp_ac_scanner_free (scanner
);
812 for (item
= anjuta_token_first_word (arg
); item
!= NULL
; item
= anjuta_token_next_word (item
))
814 value
= anjuta_token_evaluate (item
);
815 if (value
== NULL
) continue; /* Empty value, a comment of a quote by example */
822 if ((package
!= NULL
) && (compare
!= NULL
))
824 amp_package_node_set_version (package
, compare
, value
);
830 else if ((package
!= NULL
) && (anjuta_token_get_type (item
) == ANJUTA_TOKEN_OPERATOR
))
836 package
= amp_package_node_new (value
);
837 amp_package_node_add_token (package
, item
);
838 anjuta_project_node_append (ANJUTA_PROJECT_NODE (module
), ANJUTA_PROJECT_NODE (package
));
839 anjuta_project_node_set_state (ANJUTA_PROJECT_NODE (package
), ANJUTA_PROJECT_INCOMPLETE
);
848 amp_project_load_config (AmpProject
*project
, AnjutaToken
*arg_list
)
850 AmpAcScanner
*scanner
= NULL
;
852 if (arg_list
!= NULL
)
859 scanner
= amp_ac_scanner_new (project
);
861 arg
= anjuta_token_first_word (arg_list
);
862 list
= amp_ac_scanner_parse_token (scanner
, NULL
, arg
, AC_SPACE_LIST_STATE
, NULL
, NULL
);
863 anjuta_token_free_children (arg
);
864 list
= anjuta_token_delete_parent (list
);
865 amp_ac_scanner_free (scanner
);
867 /* list can be NULL is there is no argument to AC_OUTPUT or AC_CONFIG_FILES */
870 anjuta_token_prepend_items (arg
, list
);
871 for (item
= anjuta_token_first_word (arg
); item
!= NULL
; item
= anjuta_token_next_word (item
))
876 value
= anjuta_token_evaluate (item
);
877 if (value
== NULL
) continue;
879 cfg
= amp_config_file_new (value
, anjuta_project_node_get_file (ANJUTA_PROJECT_NODE (project
)), item
);
880 g_hash_table_replace (project
->configs
, cfg
->file
, cfg
);
888 project_load_target (AmpProject
*project
, AnjutaProjectNode
*parent
, AnjutaToken
*variable
, GHashTable
*orphan_properties
)
891 gchar
*install
= NULL
;
894 AmpNodeInfo
*info
= AmpNodeInformations
;
896 while (info
->base
.type
!= 0)
898 if (anjuta_token_get_type (variable
) == info
->token
)
905 value
= anjuta_token_evaluate (anjuta_token_first_word (variable
));
906 split_automake_variable (value
, &flags
, &install
, NULL
);
908 amp_group_node_add_token (AMP_GROUP_NODE (parent
), variable
, AM_GROUP_TARGET
);
910 for (arg
= anjuta_token_first_word (anjuta_token_last_item (variable
)); arg
!= NULL
; arg
= anjuta_token_next_word (arg
))
914 AmpTargetNode
*target
;
915 AmpTargetNode
*orphan
;
919 value
= anjuta_token_evaluate (arg
);
921 /* This happens for variable token which are considered as value */
922 if (value
== NULL
) continue;
923 canon_id
= canonicalize_automake_variable (value
);
925 /* Check if target already exists */
927 anjuta_project_node_children_traverse (parent
, find_target
, &find
);
928 if ((gchar
*)find
!= value
)
937 target
= amp_target_node_new (value
, info
->base
.type
, install
, flags
);
940 amp_target_node_add_token (target
, ANJUTA_TOKEN_ARGUMENT
, arg
);
941 anjuta_project_node_append (parent
, ANJUTA_PROJECT_NODE (target
));
942 DEBUG_PRINT ("create target %p name %s", target
, value
);
944 /* Check if there are sources or properties availables */
945 if (g_hash_table_lookup_extended (orphan_properties
, canon_id
, (gpointer
*)&orig_key
, (gpointer
*)&orphan
))
947 AnjutaTokenType type
;
949 AnjutaProjectNode
*child
;
951 g_hash_table_steal (orphan_properties
, canon_id
);
954 for (type
= amp_target_node_get_first_token_type (orphan
); type
!= 0; type
= amp_target_node_get_next_token_type (orphan
, type
))
957 tokens
= amp_target_node_get_token (orphan
, type
);
959 for (tokens
= g_list_first (tokens
); tokens
!= NULL
; tokens
= g_list_next (tokens
))
961 AnjutaToken
*token
= (AnjutaToken
*)tokens
->data
;
963 amp_target_node_add_token (target
, type
, token
);
967 /* Copy all properties */
968 while ((properties
= anjuta_project_node_get_properties (ANJUTA_PROJECT_NODE (orphan
))) != NULL
)
970 AnjutaProjectProperty
*prop
;
972 prop
= (AnjutaProjectProperty
*)anjuta_project_node_remove_property (ANJUTA_PROJECT_NODE (orphan
), (AnjutaProjectProperty
*)properties
->data
);
973 amp_node_property_add ((AnjutaProjectNode
*)target
, prop
);
976 /* Copy all sources */
977 while ((child
= anjuta_project_node_first_child (ANJUTA_PROJECT_NODE (orphan
))) != NULL
)
979 anjuta_project_node_remove (child
);
980 anjuta_project_node_append (ANJUTA_PROJECT_NODE (target
), child
);
981 g_object_unref (child
);
983 amp_target_changed (target
);
985 amp_target_node_free (orphan
);
988 /* Set target properties */
989 if (flags
& AM_TARGET_NOBASE
)
990 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 0, "1", arg
);
991 if (flags
& AM_TARGET_NOTRANS
)
992 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 1, "1", arg
);
993 if (flags
& AM_TARGET_DIST
)
994 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 2, "1", arg
);
995 if (flags
& AM_TARGET_NODIST
)
996 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 2, "0", arg
);
997 if (flags
& AM_TARGET_NOINST
)
999 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 3, "1", arg
);
1001 else if (install
!= NULL
)
1003 gchar
*instdir
= g_strconcat (install
, "dir", NULL
);
1004 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 6, instdir
, arg
);
1008 if (flags
& AM_TARGET_CHECK
)
1009 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 4, "1", arg
);
1010 if (flags
& AM_TARGET_MAN
)
1012 gchar section
[] = "0";
1014 section
[0] += (flags
>> 7) & 0x1F;
1015 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 4, section
, arg
);
1028 project_load_sources (AmpProject
*project
, AnjutaProjectNode
*group
, AnjutaToken
*variable
, GHashTable
*orphan_properties
)
1031 GFile
*group_file
= g_object_ref (anjuta_project_node_get_file (ANJUTA_PROJECT_NODE (group
)));
1032 gchar
*target_id
= NULL
;
1034 target_id
= anjuta_token_evaluate (anjuta_token_first_word (variable
));
1037 gchar
*end
= strrchr (target_id
, '_');
1047 AnjutaProjectNode
*target
;
1050 DEBUG_PRINT ("search for canonical %s", target_id
);
1051 anjuta_project_node_children_traverse (group
, find_canonical_target
, &find
);
1052 target
= (gchar
*)find
!= target_id
? (AnjutaProjectNode
*)find
: NULL
;
1054 /* Get orphan buffer if there is no target */
1059 if (g_hash_table_lookup_extended (orphan_properties
, target_id
, (gpointer
*)&orig_key
, (gpointer
*)&target
))
1061 g_hash_table_steal (orphan_properties
, target_id
);
1066 target
= ANJUTA_PROJECT_NODE (amp_target_node_new ("dummy", 0, NULL
, 0));
1068 g_hash_table_insert (orphan_properties
, target_id
, target
);
1074 amp_target_node_add_token (AMP_TARGET_NODE (target
), AM_TOKEN__SOURCES
, variable
);
1076 for (arg
= anjuta_token_first_word (anjuta_token_last_item (variable
)); arg
!= NULL
; arg
= anjuta_token_next_word (arg
))
1079 AnjutaProjectNode
*source
;
1080 AnjutaProjectNode
*parent
= target
;
1082 GFileInfo
* file_info
;
1084 value
= anjuta_token_evaluate (arg
);
1085 if (value
== NULL
) continue;
1087 src_file
= g_file_get_child (group_file
, value
);
1088 if (project
->lang_manager
!= NULL
)
1090 file_info
= g_file_query_info (src_file
,
1091 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE
,
1092 G_FILE_QUERY_INFO_NONE
,
1097 gint id
= ianjuta_language_get_from_mime_type (project
->lang_manager
,
1098 g_file_info_get_content_type (file_info
),
1102 const gchar
*obj_ext
= ianjuta_language_get_make_target (project
->lang_manager
, id
, NULL
);
1103 if (obj_ext
!= NULL
)
1105 /* Create object node */
1110 AnjutaProjectNode
*object
;
1112 ext
= strrchr (value
, '.');
1113 if ((ext
!= NULL
) && (ext
!= value
)) *ext
= '\0';
1114 object_name
= g_strconcat (value
, obj_ext
, NULL
);
1115 basename
= g_path_get_basename (object_name
);
1116 obj_file
= g_file_get_child (group_file
, basename
);
1118 g_free (object_name
);
1119 object
= amp_object_node_new (obj_file
, ANJUTA_PROJECT_PROJECT
);
1120 g_object_unref (obj_file
);
1121 anjuta_project_node_append (parent
, object
);
1125 g_object_unref (file_info
);
1130 source
= amp_source_node_new (src_file
, ANJUTA_PROJECT_PROJECT
);
1131 g_object_unref (src_file
);
1134 amp_source_node_add_token (AMP_SOURCE_NODE (source
), arg
);
1136 DEBUG_PRINT ("add target child %p", target
);
1137 /* Add as target child */
1138 anjuta_project_node_append (parent
, source
);
1143 amp_target_changed (AMP_TARGET_NODE (target
));
1146 g_object_unref (group_file
);
1152 project_load_data (AmpProject
*project
, AnjutaProjectNode
*parent
, AnjutaToken
*variable
, GHashTable
*orphan_properties
, gint data_flags
)
1154 gchar
*install
= NULL
;
1155 AmpTargetNode
*target
;
1159 AmpNodeInfo
*info
= AmpNodeInformations
;
1163 while (info
->base
.name
!= NULL
)
1165 if (anjuta_token_get_type (variable
) == info
->token
)
1172 target_id
= anjuta_token_evaluate (anjuta_token_first_word (variable
));
1173 split_automake_variable (target_id
, &flags
, &install
, NULL
);
1175 amp_group_node_add_token (AMP_GROUP_NODE (parent
), variable
, AM_GROUP_TARGET
);
1177 /* Check if target already exists */
1179 anjuta_project_node_children_traverse (parent
, find_target
, &find
);
1180 if ((gchar
*)find
== target_id
)
1183 target
= amp_target_node_new (target_id
, info
->base
.type
, install
, flags
);
1186 anjuta_project_node_append (parent
, ANJUTA_PROJECT_NODE (target
));
1187 DEBUG_PRINT ("create target %p name %s", target
, target_id
);
1192 target
= AMP_TARGET_NODE (find
);
1197 GFile
*parent_file
= g_object_ref (anjuta_project_node_get_file (parent
));
1199 amp_target_node_add_token (AMP_TARGET_NODE (target
), AM_TOKEN__DATA
, variable
);
1201 list
= anjuta_token_last_item (variable
);
1202 for (arg
= anjuta_token_first_word (list
); arg
!= NULL
; arg
= anjuta_token_next_word (arg
))
1205 AnjutaProjectNode
*source
;
1208 value
= anjuta_token_evaluate (arg
);
1209 if (value
== NULL
) continue;
1212 src_file
= g_file_get_child (parent_file
, value
);
1213 source
= amp_source_node_new (src_file
, ANJUTA_PROJECT_PROJECT
| data_flags
);
1214 g_object_unref (src_file
);
1217 amp_source_node_add_token (AMP_SOURCE_NODE(source
), arg
);
1219 /* Add as target child */
1220 DEBUG_PRINT ("add target child %p", target
);
1221 anjuta_project_node_append (ANJUTA_PROJECT_NODE (target
), source
);
1226 g_object_unref (parent_file
);
1228 /* Set target properties */
1229 if (flags
& AM_TARGET_NOBASE
)
1230 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 0, "1", arg
);
1231 if (flags
& AM_TARGET_NOTRANS
)
1232 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 1, "1", arg
);
1233 if (flags
& AM_TARGET_DIST
)
1234 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 2, "1", arg
);
1235 if (flags
& AM_TARGET_NODIST
)
1236 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 2, "0", arg
);
1237 if (flags
& AM_TARGET_NOINST
)
1239 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 3, "1", arg
);
1241 else if (install
!= NULL
)
1243 gchar
*instdir
= g_strconcat (install
, "dir", NULL
);
1244 amp_node_property_load (ANJUTA_PROJECT_NODE (target
), AM_TOKEN__PROGRAMS
, 6, instdir
, arg
);
1254 project_load_target_properties (AmpProject
*project
, AnjutaProjectNode
*parent
, AnjutaToken
*variable
, GHashTable
*orphan_properties
)
1256 gchar
*target_id
= NULL
;
1258 target_id
= anjuta_token_evaluate (anjuta_token_first_word (variable
));
1261 gchar
*end
= strrchr (target_id
, '_');
1272 AnjutaProjectProperty
*prop
;
1274 AnjutaTokenType type
;
1277 DEBUG_PRINT ("search for canonical %s", target_id
);
1278 anjuta_project_node_children_traverse (parent
, find_canonical_target
, &find
);
1279 parent
= (gchar
*)find
!= target_id
? (AnjutaProjectNode
*)find
: NULL
;
1281 /* Create property */
1282 list
= anjuta_token_last_item (variable
);
1283 type
= anjuta_token_get_type (variable
);
1284 value
= anjuta_token_evaluate_name (list
);
1285 prop
= amp_property_new (NULL
, type
, 0, value
, list
);
1289 /* Add property to non existing target, create a dummy target */
1292 if (g_hash_table_lookup_extended (orphan_properties
, target_id
, (gpointer
*)&orig_key
, (gpointer
*)&parent
))
1294 /* Dummy target already created */
1295 g_hash_table_steal (orphan_properties
, target_id
);
1300 /* Create dummy target */
1301 parent
= ANJUTA_PROJECT_NODE (amp_target_node_new ("dummy", 0, NULL
, 0));
1303 g_hash_table_insert (orphan_properties
, target_id
, parent
);
1311 /* Add property to target */
1312 amp_node_property_add (parent
, prop
);
1313 amp_target_node_add_token (AMP_TARGET_NODE (parent
), type
, variable
);
1314 amp_target_changed (AMP_TARGET_NODE (parent
));
1321 project_load_group_properties (AmpProject
*project
, AnjutaProjectNode
*parent
, AnjutaToken
*variable
)
1325 AnjutaProjectProperty
*prop
;
1328 /* Create property */
1329 list
= anjuta_token_last_item (variable
);
1330 name
= anjuta_token_evaluate (anjuta_token_first_word (variable
));
1331 value
= anjuta_token_evaluate_name (list
);
1333 prop
= amp_property_new (name
, anjuta_token_get_type (variable
), 0, value
, list
);
1335 amp_node_property_add (parent
, prop
);
1344 find_group (AnjutaProjectNode
*node
, gpointer data
)
1346 if (anjuta_project_node_get_node_type (node
) == ANJUTA_PROJECT_GROUP
)
1348 if (g_file_equal (anjuta_project_node_get_file (node
), (GFile
*)data
))
1350 /* Find group, return node value in pointer */
1359 project_load_subdirs (AmpProject
*project
, AnjutaToken
*list
, AnjutaProjectNode
*parent
, gboolean dist_only
)
1363 for (arg
= anjuta_token_first_word (list
); arg
!= NULL
; arg
= anjuta_token_next_word (arg
))
1367 value
= anjuta_token_evaluate (arg
);
1368 if (value
== NULL
) continue; /* Empty value, a comment of a quote by example */
1370 /* Skip ., it is a special case, used to defined build order */
1371 if (strcmp (value
, ".") != 0)
1374 AmpGroupNode
*group
;
1376 subdir
= g_file_resolve_relative_path (anjuta_project_node_get_file (parent
), value
);
1378 /* Look for already existing group */
1379 group
= AMP_GROUP_NODE (anjuta_project_node_children_traverse (parent
, find_group
, subdir
));
1383 /* Already existing group, mark for built if needed */
1384 if (!dist_only
) amp_group_node_set_dist_only (group
, FALSE
);
1388 /* Create new group */
1389 group
= amp_group_node_new (subdir
, value
, dist_only
);
1391 /* Group can be NULL if the name is not valid */
1394 g_hash_table_insert (project
->groups
, g_file_get_uri (subdir
), group
);
1395 anjuta_project_node_append (parent
, ANJUTA_PROJECT_NODE (group
));
1397 amp_node_load (AMP_NODE (group
), NULL
, project
, NULL
);
1400 if (group
) amp_group_node_add_token (group
, arg
, dist_only
? AM_GROUP_TOKEN_DIST_SUBDIRS
: AM_GROUP_TOKEN_SUBDIRS
);
1401 g_object_unref (subdir
);
1408 amp_project_set_am_variable (AmpProject
* project
, AmpGroupNode
* group
, AnjutaToken
*variable
, GHashTable
*orphan_properties
)
1412 switch (anjuta_token_get_type (variable
))
1414 case AM_TOKEN_SUBDIRS
:
1415 list
= anjuta_token_last_item (variable
);
1416 project_load_subdirs (project
, list
, ANJUTA_PROJECT_NODE (group
), FALSE
);
1418 case AM_TOKEN_DIST_SUBDIRS
:
1419 list
= anjuta_token_last_item (variable
);
1420 project_load_subdirs (project
, list
, ANJUTA_PROJECT_NODE (group
), TRUE
);
1422 case AM_TOKEN__DATA
:
1423 case AM_TOKEN__HEADERS
:
1424 case AM_TOKEN__LISP
:
1425 case AM_TOKEN__MANS
:
1426 case AM_TOKEN__PYTHON
:
1427 case AM_TOKEN__JAVA
:
1428 case AM_TOKEN__TEXINFOS
:
1429 project_load_data (project
, ANJUTA_PROJECT_NODE (group
), variable
, orphan_properties
, 0);
1431 case AM_TOKEN__SCRIPTS
:
1432 project_load_data (project
, ANJUTA_PROJECT_NODE (group
), variable
, orphan_properties
, ANJUTA_PROJECT_EXECUTABLE
);
1434 case AM_TOKEN__LIBRARIES
:
1435 case AM_TOKEN__LTLIBRARIES
:
1436 case AM_TOKEN__PROGRAMS
:
1437 project_load_target (project
, ANJUTA_PROJECT_NODE (group
), variable
, orphan_properties
);
1439 case AM_TOKEN__SOURCES
:
1440 project_load_sources (project
, ANJUTA_PROJECT_NODE (group
), variable
, orphan_properties
);
1443 case AM_TOKEN__LDFLAGS
:
1444 case AM_TOKEN__CPPFLAGS
:
1445 case AM_TOKEN__CFLAGS
:
1446 case AM_TOKEN__CXXFLAGS
:
1447 case AM_TOKEN__JAVACFLAGS
:
1448 case AM_TOKEN__VALAFLAGS
:
1449 case AM_TOKEN__FCFLAGS
:
1450 case AM_TOKEN__OBJCFLAGS
:
1451 case AM_TOKEN__LFLAGS
:
1452 case AM_TOKEN__YFLAGS
:
1453 project_load_group_properties (project
, ANJUTA_PROJECT_NODE (group
), variable
);
1455 case AM_TOKEN_TARGET_LDFLAGS
:
1456 case AM_TOKEN_TARGET_CPPFLAGS
:
1457 case AM_TOKEN_TARGET_CFLAGS
:
1458 case AM_TOKEN_TARGET_CXXFLAGS
:
1459 case AM_TOKEN_TARGET_JAVACFLAGS
:
1460 case AM_TOKEN_TARGET_VALAFLAGS
:
1461 case AM_TOKEN_TARGET_FCFLAGS
:
1462 case AM_TOKEN_TARGET_OBJCFLAGS
:
1463 case AM_TOKEN_TARGET_LFLAGS
:
1464 case AM_TOKEN_TARGET_YFLAGS
:
1465 case AM_TOKEN_TARGET_DEPENDENCIES
:
1466 case AM_TOKEN_TARGET_LIBADD
:
1467 case AM_TOKEN_TARGET_LDADD
:
1468 project_load_target_properties (project
, ANJUTA_PROJECT_NODE (group
), variable
, orphan_properties
);
1474 /* Keep the autotools variable as a normal variable too */
1475 amp_group_node_update_variable (group
, variable
);
1479 *---------------------------------------------------------------------------*/
1482 amp_project_compare_node (AnjutaProjectNode
*old_node
, AnjutaProjectNode
*new_node
)
1489 name1
= anjuta_project_node_get_name (old_node
);
1490 name2
= anjuta_project_node_get_name (new_node
);
1491 file1
= anjuta_project_node_get_file (old_node
);
1492 file2
= anjuta_project_node_get_file (new_node
);
1494 return (anjuta_project_node_get_full_type (old_node
) == anjuta_project_node_get_full_type (new_node
))
1495 && ((name1
== NULL
) || (name2
== NULL
) || (strcmp (name1
, name2
) == 0))
1496 && ((file1
== NULL
) || (file2
== NULL
) || g_file_equal (file1
, file2
)) ? 0 : 1;
1500 amp_project_map_children (GHashTable
*map
, AnjutaProjectNode
*old_node
, AnjutaProjectNode
*new_node
)
1502 GList
*children
= NULL
;
1504 if (new_node
!= NULL
)
1506 for (new_node
= anjuta_project_node_first_child (new_node
); new_node
!= NULL
; new_node
= anjuta_project_node_next_sibling (new_node
))
1508 children
= g_list_prepend (children
, new_node
);
1510 children
= g_list_reverse (children
);
1513 for (old_node
= anjuta_project_node_first_child (old_node
); old_node
!= NULL
; old_node
= anjuta_project_node_next_sibling (old_node
))
1517 same
= g_list_find_custom (children
, old_node
, (GCompareFunc
)amp_project_compare_node
);
1521 /* Add new to old node mapping */
1522 g_hash_table_insert (map
, (AnjutaProjectNode
*)same
->data
, old_node
);
1524 amp_project_map_children (map
, old_node
, (AnjutaProjectNode
*)same
->data
);
1525 children
= g_list_delete_link (children
, same
);
1529 /* Keep old_node to be deleted in the hash table as a key with a NULL
1531 g_hash_table_insert (map
, old_node
, NULL
);
1535 /* Add remaining node in hash table */
1536 for (; children
!= NULL
; children
= g_list_delete_link (children
, children
))
1538 /* Keep new node without a corresponding old node as a key and a identical
1540 g_hash_table_insert (map
, children
->data
, children
->data
);
1544 /* Find the correspondance between the new loaded node (new_node) and the
1545 * original node currently in the tree (old_node) */
1547 amp_project_map_node (AnjutaProjectNode
*old_node
, AnjutaProjectNode
*new_node
)
1551 map
= g_hash_table_new (g_direct_hash
, NULL
);
1553 g_hash_table_insert (map
, new_node
, old_node
);
1555 amp_project_map_children (map
, old_node
, new_node
);
1562 amp_project_update_node (AnjutaProjectNode
*key
, AnjutaProjectNode
*value
, GHashTable
*map
)
1564 AnjutaProjectNode
*old_node
= NULL
; /* The node that will be deleted */
1568 /* if value is NULL, delete the old node which is the key */
1573 AnjutaProjectNode
*node
= value
; /* The node that we keep in the tree */
1574 AnjutaProjectNode
*new_node
= key
; /* The node with the new data */
1576 if (new_node
&& new_node
!= node
)
1580 amp_node_update (AMP_NODE (node
), AMP_NODE (new_node
));
1582 /* Swap custom properties */
1583 properties
= node
->properties
;
1584 node
->properties
= new_node
->properties
;
1585 new_node
->properties
= properties
;
1587 if (new_node
->parent
== NULL
)
1589 /* This is the top loaded node, update only the children */
1590 node
->children
= new_node
->children
;
1594 /* Other node update all pointers */
1595 node
->parent
= new_node
->parent
;
1596 node
->children
= new_node
->children
;
1597 node
->next
= new_node
->next
;
1598 node
->prev
= new_node
->prev
;
1601 /* Destroy node with data */
1602 old_node
= new_node
;
1605 /* Update links, using original node address if they stay in the tree */
1606 new_node
= g_hash_table_lookup (map
, node
->parent
);
1607 if (new_node
!= NULL
) node
->parent
= new_node
;
1608 new_node
= g_hash_table_lookup (map
, node
->children
);
1609 if (new_node
!= NULL
) node
->children
= new_node
;
1610 new_node
= g_hash_table_lookup (map
, node
->next
);
1611 if (new_node
!= NULL
) node
->next
= new_node
;
1612 new_node
= g_hash_table_lookup (map
, node
->prev
);
1613 if (new_node
!= NULL
) node
->prev
= new_node
;
1617 /* Unlink old node and free it */
1618 if (old_node
!= NULL
)
1620 old_node
->parent
= NULL
;
1621 old_node
->children
= NULL
;
1622 old_node
->next
= NULL
;
1623 old_node
->prev
= NULL
;
1624 g_object_unref (old_node
);
1629 *---------------------------------------------------------------------------*/
1631 AnjutaProjectNodeInfo
*
1632 amp_project_get_type_info (AmpProject
*project
, AnjutaProjectNodeType type
)
1636 for (info
= AmpNodeInformations
; info
->base
.type
!= type
; info
++)
1638 if ((info
->base
.type
== type
) || (info
->base
.type
== 0)) break;
1641 return (AnjutaProjectNodeInfo
*)info
;
1645 amp_project_load_root (AmpProject
*project
, GError
**error
)
1647 AmpAcScanner
*scanner
;
1650 GFile
*configure_file
;
1651 AnjutaTokenFile
*configure_token_file
;
1652 AnjutaProjectNode
*source
;
1655 root_file
= anjuta_project_node_get_file (ANJUTA_PROJECT_NODE (project
));
1656 DEBUG_PRINT ("reload project %p root file %p", project
, root_file
);
1658 /* Unload current project */
1659 amp_project_unload (project
);
1661 /* Initialize list styles */
1662 project
->ac_space_list
= anjuta_token_style_new (NULL
, " ", "\n", NULL
, 0);
1663 project
->am_space_list
= anjuta_token_style_new (NULL
, " ", " \\\n\t", NULL
, 0);
1664 project
->arg_list
= anjuta_token_style_new (NULL
, ", ", ", ", ")", 0);
1666 /* Find configure file */
1667 if (file_type (root_file
, "configure.ac") == G_FILE_TYPE_REGULAR
)
1669 configure_file
= g_file_get_child (root_file
, "configure.ac");
1671 else if (file_type (root_file
, "configure.in") == G_FILE_TYPE_REGULAR
)
1673 configure_file
= g_file_get_child (root_file
, "configure.in");
1677 g_set_error (error
, IANJUTA_PROJECT_ERROR
,
1678 IANJUTA_PROJECT_ERROR_DOESNT_EXIST
,
1679 _("Project doesn't exist or invalid path"));
1684 /* Parse configure */
1685 configure_token_file
= amp_project_set_configure (project
, configure_file
);
1686 amp_project_add_file (project
, configure_file
, configure_token_file
);
1687 source
= amp_source_node_new (configure_file
, ANJUTA_PROJECT_PROJECT
| ANJUTA_PROJECT_FRAME
| ANJUTA_PROJECT_READ_ONLY
);
1688 anjuta_project_node_append (ANJUTA_PROJECT_NODE (project
), source
);
1689 arg
= anjuta_token_file_load (configure_token_file
, NULL
);
1690 g_hash_table_remove_all (project
->ac_variables
);
1691 scanner
= amp_ac_scanner_new (project
);
1692 project
->configure_token
= amp_ac_scanner_parse_token (scanner
, NULL
, arg
, 0, configure_file
, &err
);
1693 amp_ac_scanner_free (scanner
);
1695 if (project
->configure_token
== NULL
)
1699 g_set_error_literal (error
, IANJUTA_PROJECT_ERROR
,
1700 IANJUTA_PROJECT_ERROR_PROJECT_MALFORMED
,
1706 g_set_error (error
, IANJUTA_PROJECT_ERROR
,
1707 IANJUTA_PROJECT_ERROR_PROJECT_MALFORMED
,
1709 _("Unable to parse project file"));
1715 /* Load all makefiles recursively */
1716 if (!AMP_NODE_CLASS (parent_class
)->load (AMP_NODE (project
), NULL
, project
, NULL
))
1718 g_set_error (error
, IANJUTA_PROJECT_ERROR
,
1719 IANJUTA_PROJECT_ERROR_DOESNT_EXIST
,
1720 _("Project doesn't exist or has an invalid path"));
1729 amp_project_unload (AmpProject
*project
)
1732 amp_project_clear (project
);
1734 /* shortcut hash tables */
1735 if (project
->groups
) g_hash_table_remove_all (project
->groups
);
1736 if (project
->files
!= NULL
)
1740 for (list
= project
->files
; list
!= NULL
; list
= g_list_delete_link (list
, list
))
1742 g_object_weak_unref (G_OBJECT (list
->data
), remove_config_file
, project
);
1744 project
->files
= NULL
;
1746 if (project
->configs
) g_hash_table_remove_all (project
->configs
);
1749 if (project
->am_space_list
) anjuta_token_style_free (project
->am_space_list
);
1750 if (project
->ac_space_list
) anjuta_token_style_free (project
->ac_space_list
);
1751 if (project
->arg_list
) anjuta_token_style_free (project
->arg_list
);
1755 amp_project_is_loaded (AmpProject
*project
)
1757 return project
->loading
== 0;
1761 amp_project_probe (GFile
*file
,
1767 dir
= (file_type (file
, NULL
) == G_FILE_TYPE_DIRECTORY
);
1770 g_set_error (error
, IANJUTA_PROJECT_ERROR
,
1771 IANJUTA_PROJECT_ERROR_DOESNT_EXIST
,
1772 _("Project doesn't exist or invalid path"));
1778 const gchar
**makefile
;
1780 /* Look for makefiles */
1782 for (makefile
= valid_am_makefiles
; *makefile
!= NULL
; makefile
++)
1784 if (file_type (file
, *makefile
) == G_FILE_TYPE_REGULAR
)
1793 probe
= ((file_type (file
, "configure.ac") == G_FILE_TYPE_REGULAR
) ||
1794 (file_type (file
, "configure.in") == G_FILE_TYPE_REGULAR
));
1798 return probe
? IANJUTA_PROJECT_PROBE_PROJECT_FILES
: 0;
1802 amp_project_get_token_location (AmpProject
*project
, AnjutaTokenFileLocation
*location
, AnjutaToken
*token
)
1806 for (list
= project
->files
; list
!= NULL
; list
= g_list_next (list
))
1808 if (anjuta_token_file_get_token_location ((AnjutaTokenFile
*)list
->data
, location
, token
))
1818 amp_project_remove_group (AmpProject
*project
,
1819 AmpGroupNode
*group
,
1824 if (anjuta_project_node_get_node_type (ANJUTA_PROJECT_NODE (group
)) != ANJUTA_PROJECT_GROUP
) return;
1826 for (token_list
= amp_group_node_get_token (group
, AM_GROUP_TOKEN_CONFIGURE
); token_list
!= NULL
; token_list
= g_list_next (token_list
))
1828 anjuta_token_remove_word ((AnjutaToken
*)token_list
->data
);
1830 for (token_list
= amp_group_node_get_token (group
, AM_GROUP_TOKEN_SUBDIRS
); token_list
!= NULL
; token_list
= g_list_next (token_list
))
1832 anjuta_token_remove_word ((AnjutaToken
*)token_list
->data
);
1834 for (token_list
= amp_group_node_get_token (group
, AM_GROUP_TOKEN_DIST_SUBDIRS
); token_list
!= NULL
; token_list
= g_list_next (token_list
))
1836 anjuta_token_remove_word ((AnjutaToken
*)token_list
->data
);
1839 amp_group_node_free (group
);
1843 amp_project_remove_source (AmpProject
*project
,
1844 AmpSourceNode
*source
,
1847 if (anjuta_project_node_get_node_type (ANJUTA_PROJECT_NODE (source
)) != ANJUTA_PROJECT_SOURCE
) return;
1849 anjuta_token_remove_word (amp_source_node_get_token (source
));
1851 amp_source_node_free (source
);
1855 amp_project_get_node_info (AmpProject
*project
, GError
**error
)
1857 static GList
*info_list
= NULL
;
1859 if (info_list
== NULL
)
1863 for (node
= AmpNodeInformations
; node
->base
.type
!= 0; node
++)
1865 info_list
= g_list_prepend (info_list
, node
);
1868 info_list
= g_list_reverse (info_list
);
1875 *---------------------------------------------------------------------------*/
1877 typedef struct _AmpMovePacket
{
1878 AmpProject
*project
;
1879 GFile
*old_root_file
;
1880 GFile
*new_root_file
;
1884 foreach_node_move (AnjutaProjectNode
*g_node
, gpointer data
)
1886 AmpProject
*project
= ((AmpMovePacket
*)data
)->project
;
1887 GFile
*old_root_file
= ((AmpMovePacket
*)data
)->old_root_file
;
1888 GFile
*new_root_file
= ((AmpMovePacket
*)data
)->new_root_file
;
1892 switch (anjuta_project_node_get_node_type (g_node
))
1894 case ANJUTA_PROJECT_GROUP
:
1895 relative
= get_relative_path (old_root_file
, anjuta_project_node_get_file (g_node
));
1896 new_file
= g_file_resolve_relative_path (new_root_file
, relative
);
1898 amp_group_node_set_file (AMP_GROUP_NODE (g_node
), new_file
);
1899 g_object_unref (new_file
);
1901 g_hash_table_insert (project
->groups
, g_file_get_uri (new_file
), g_node
);
1903 case ANJUTA_PROJECT_SOURCE
:
1904 relative
= get_relative_path (old_root_file
, anjuta_project_node_get_file (g_node
));
1905 new_file
= g_file_resolve_relative_path (new_root_file
, relative
);
1907 amp_source_node_set_file (AMP_SOURCE_NODE (g_node
), new_file
);
1908 g_object_unref (new_file
);
1916 amp_project_move (AmpProject
*project
, const gchar
*path
)
1923 GHashTable
* old_hash
;
1924 GHashTableIter iter
;
1925 AmpMovePacket packet
= {project
, NULL
};
1927 /* Change project root directory */
1928 packet
.old_root_file
= g_object_ref (anjuta_project_node_get_file (ANJUTA_PROJECT_NODE (project
)));
1929 packet
.new_root_file
= g_file_new_for_path (path
);
1931 /* Change project root directory in groups */
1932 old_hash
= project
->groups
;
1933 project
->groups
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, NULL
);
1934 anjuta_project_node_foreach (ANJUTA_PROJECT_NODE (project
), G_POST_ORDER
, foreach_node_move
, &packet
);
1935 g_hash_table_destroy (old_hash
);
1937 /* Change all files */
1938 for (list
= project
->files
; list
!= NULL
; list
= g_list_next (list
))
1940 AnjutaTokenFile
*tfile
= (AnjutaTokenFile
*)list
->data
;
1942 relative
= get_relative_path (packet
.old_root_file
, anjuta_token_file_get_file (tfile
));
1943 new_file
= g_file_resolve_relative_path (packet
.new_root_file
, relative
);
1945 anjuta_token_file_move (tfile
, new_file
);
1948 /* Change all configs */
1949 old_hash
= project
->configs
;
1950 project
->configs
= g_hash_table_new_full (g_file_hash
, (GEqualFunc
)g_file_equal
, NULL
, (GDestroyNotify
)amp_config_file_free
);
1951 g_hash_table_iter_init (&iter
, old_hash
);
1952 while (g_hash_table_iter_next (&iter
, &key
, (gpointer
*)&cfg
))
1954 relative
= get_relative_path (packet
.old_root_file
, cfg
->file
);
1955 new_file
= g_file_resolve_relative_path (packet
.new_root_file
, relative
);
1957 g_object_unref (cfg
->file
);
1958 cfg
->file
= new_file
;
1960 g_hash_table_insert (project
->configs
, new_file
, cfg
);
1962 g_hash_table_steal_all (old_hash
);
1963 g_hash_table_destroy (old_hash
);
1965 g_object_unref (packet
.old_root_file
);
1966 g_object_unref (packet
.new_root_file
);
1971 /* Dump file content of corresponding node */
1973 amp_project_dump (AmpProject
*project
, AnjutaProjectNode
*node
, AmpFileType type
)
1975 gboolean ok
= FALSE
;
1977 if (anjuta_project_node_get_node_type (node
) == ANJUTA_PROJECT_GROUP
)
1982 anjuta_token_dump (amp_group_node_get_makefile_token (AMP_GROUP_NODE (node
)));
1984 case DUMP_CONFIGURE
:
1985 anjuta_token_dump (AMP_PROJECT (node
)->configure_token
);
1997 amp_project_new (GFile
*file
, IAnjutaLanguage
*language
, GError
**error
)
1999 AmpProject
*project
;
2002 project
= AMP_PROJECT (g_object_new (AMP_TYPE_PROJECT
, NULL
));
2003 new_file
= g_file_dup (file
);
2004 amp_root_node_set_file (AMP_ROOT_NODE (project
), new_file
);
2005 g_object_unref (new_file
);
2007 project
->lang_manager
= (language
!= NULL
) ? g_object_ref (language
) : NULL
;
2012 /* Project access functions
2013 *---------------------------------------------------------------------------*/
2016 amp_project_get_root (AmpProject
*project
)
2018 return AMP_PROJECT (project
);
2022 amp_project_get_group (AmpProject
*project
, const gchar
*id
)
2024 return (AmpGroupNode
*)g_hash_table_lookup (project
->groups
, id
);
2028 amp_project_get_target (AmpProject
*project
, const gchar
*id
)
2030 AmpTargetNode
**buffer
;
2031 AmpTargetNode
*target
;
2034 buffer
= (AmpTargetNode
**)g_base64_decode (id
, &dummy
);
2042 amp_project_get_source (AmpProject
*project
, const gchar
*id
)
2044 AmpSourceNode
**buffer
;
2045 AmpSourceNode
*source
;
2048 buffer
= (AmpSourceNode
**)g_base64_decode (id
, &dummy
);
2056 amp_project_get_uri (AmpProject
*project
)
2058 g_return_val_if_fail (project
!= NULL
, NULL
);
2060 return g_file_get_uri (anjuta_project_node_get_file (ANJUTA_PROJECT_NODE (project
)));
2064 amp_project_get_file (AmpProject
*project
)
2066 g_return_val_if_fail (project
!= NULL
, NULL
);
2068 return anjuta_project_node_get_file (ANJUTA_PROJECT_NODE (project
));
2072 amp_project_add_file (AmpProject
*project
, GFile
*file
, AnjutaTokenFile
* token
)
2074 project
->files
= g_list_prepend (project
->files
, token
);
2075 g_object_weak_ref (G_OBJECT (token
), remove_config_file
, project
);
2079 amp_project_add_subst_variable (AmpProject
*project
, const gchar
*name
, AnjutaToken
*value
)
2081 g_hash_table_insert (project
->ac_variables
, (gchar
*)name
, value
);
2085 amp_project_get_subst_variable_token (AmpProject
*project
, const gchar
*name
)
2087 return g_hash_table_lookup (project
->ac_variables
, name
);
2092 amp_project_is_busy (AmpProject
*project
)
2094 if (project
->queue
== NULL
) return FALSE
;
2096 return pm_command_queue_is_busy (project
->queue
);
2100 *---------------------------------------------------------------------------*/
2103 amp_load_setup (PmJob
*job
)
2105 //anjuta_project_node_check (job->node);
2106 pm_job_set_parent (job
, anjuta_project_node_parent (job
->node
));
2107 job
->proxy
= ANJUTA_PROJECT_NODE (amp_node_copy (AMP_NODE (job
->node
)));
2113 amp_load_work (PmJob
*job
)
2115 return amp_node_load (AMP_NODE (job
->proxy
), AMP_NODE (job
->parent
), AMP_PROJECT (job
->user_data
), &job
->error
);
2119 amp_load_complete (PmJob
*job
)
2122 //static GTimer *timer = NULL;
2124 g_return_val_if_fail (job
->proxy
!= NULL
, FALSE
);
2126 //anjuta_project_node_check (job->node);
2127 /*if (timer == NULL)
2129 timer = g_timer_new ();
2133 g_timer_continue (timer);
2135 map
= amp_project_map_node (job
->node
, job
->proxy
);
2136 g_object_ref (job
->proxy
);
2138 job
->proxy
->parent
= NULL
; // Mark loaded top node
2139 g_hash_table_foreach (map
, (GHFunc
)amp_project_update_node
, map
);
2140 //anjuta_project_node_check (job->node);
2141 g_hash_table_destroy (map
);
2142 g_object_unref (job
->proxy
);
2144 AMP_PROJECT (job
->user_data
)->loading
--;
2145 g_signal_emit_by_name (AMP_PROJECT (job
->user_data
), "node-loaded", job
->node
, job
->error
);
2146 //g_timer_stop (timer);
2147 //g_message ("amp_load_complete completed in %g", g_timer_elapsed (timer, NULL));
2152 static PmCommandWork amp_load_job
= {amp_load_setup
, amp_load_work
, amp_load_complete
};
2155 amp_save_setup (PmJob
*job
)
2161 amp_save_work (PmJob
*job
)
2163 /* It is difficult to save only a particular node, so the whole project is saved */
2164 amp_node_save (AMP_NODE (job
->user_data
), NULL
, AMP_PROJECT (job
->user_data
), &job
->error
);
2170 amp_save_complete (PmJob
*job
)
2172 g_signal_emit_by_name (AMP_PROJECT (job
->user_data
), "node-saved", job
->node
, job
->error
);
2177 static PmCommandWork amp_save_job
= {amp_save_setup
, amp_save_work
, amp_save_complete
};
2180 amp_add_before_setup (PmJob
*job
)
2182 /* If add is called to add the root group, the node is already existing */
2183 if (job
->parent
!= job
->node
)
2184 anjuta_project_node_insert_before (job
->parent
, job
->sibling
, job
->node
);
2190 amp_add_after_setup (PmJob
*job
)
2192 /* If add is called to add the root group, the node is already existing */
2193 if (job
->parent
!= job
->node
)
2194 anjuta_project_node_insert_after (job
->parent
, job
->sibling
, job
->node
);
2200 amp_add_work (PmJob
*job
)
2202 AmpNode
*parent
= AMP_NODE (job
->parent
);
2205 ok
= amp_node_write (AMP_NODE (job
->node
), parent
, AMP_PROJECT (job
->user_data
), &job
->error
);
2206 /* Add new node properties if existing */
2211 for (item
= anjuta_project_node_get_properties (ANJUTA_PROJECT_NODE (job
->node
)); item
!= NULL
; item
= g_list_next (item
))
2213 AnjutaProjectProperty
*property
= (AnjutaProjectProperty
*)item
->data
;
2216 flags
= ((AmpPropertyInfo
*)property
->info
)->flags
;
2217 if (flags
& AM_PROPERTY_IN_CONFIGURE
)
2219 ok
= ok
&& amp_project_update_ac_property (AMP_PROJECT (job
->user_data
), property
);
2221 else if (flags
& AM_PROPERTY_IN_MAKEFILE
)
2223 if (((AnjutaProjectPropertyInfo
*)property
->info
)->flags
& ANJUTA_PROJECT_PROPERTY_READ_WRITE
)
2225 ok
= ok
&& amp_project_update_am_property (AMP_PROJECT (job
->user_data
), job
->node
, property
);
2235 amp_add_complete (PmJob
*job
)
2237 g_signal_emit_by_name (AMP_PROJECT (job
->user_data
), "node-changed", job
->parent
, job
->error
);
2242 static PmCommandWork amp_add_before_job
= {amp_add_before_setup
, amp_add_work
, amp_add_complete
};
2243 static PmCommandWork amp_add_after_job
= {amp_add_after_setup
, amp_add_work
, amp_add_complete
};
2247 amp_remove_setup (PmJob
*job
)
2249 AnjutaProjectNode
*parent
;
2251 parent
= anjuta_project_node_parent (job
->node
);
2252 if (parent
== NULL
) parent
= job
->node
;
2253 pm_job_set_parent (job
, parent
);
2254 anjuta_project_node_set_state (job
->node
, ANJUTA_PROJECT_REMOVED
);
2260 amp_remove_work (PmJob
*job
)
2262 AmpNode
*parent
= AMP_NODE (job
->parent
);
2265 ok
= amp_node_erase (AMP_NODE (job
->node
), parent
, AMP_PROJECT (job
->user_data
), &job
->error
);
2271 amp_remove_complete (PmJob
*job
)
2273 g_signal_emit_by_name (AMP_PROJECT (job
->user_data
), "node-changed", job
->parent
, job
->error
);
2278 static PmCommandWork amp_remove_job
= {amp_remove_setup
, amp_remove_work
, amp_remove_complete
};
2281 amp_set_property_setup (PmJob
*job
)
2287 amp_set_property_work (PmJob
*job
)
2291 flags
= ((AmpPropertyInfo
*)job
->property
->info
)->flags
;
2293 if (flags
& AM_PROPERTY_IN_CONFIGURE
)
2295 amp_project_update_ac_property (AMP_PROJECT (job
->user_data
), job
->property
);
2297 else if (flags
& AM_PROPERTY_IN_MAKEFILE
)
2299 if (((AnjutaProjectPropertyInfo
*)job
->property
->info
)->flags
& ANJUTA_PROJECT_PROPERTY_READ_WRITE
)
2301 amp_project_update_am_property (AMP_PROJECT (job
->user_data
), job
->node
, job
->property
);
2309 amp_set_property_complete (PmJob
*job
)
2311 g_signal_emit_by_name (AMP_PROJECT (job
->user_data
), "node-changed", job
->node
, job
->error
);
2316 static PmCommandWork amp_set_property_job
= {amp_set_property_setup
, amp_set_property_work
, amp_set_property_complete
};
2319 amp_remove_property_setup (PmJob
*job
)
2325 amp_remove_property_work (PmJob
*job
)
2329 flags
= ((AmpPropertyInfo
*)job
->property
->info
)->flags
;
2331 if (flags
& AM_PROPERTY_IN_CONFIGURE
)
2333 amp_project_update_ac_property (AMP_PROJECT (job
->user_data
), job
->property
);
2335 else if (flags
& AM_PROPERTY_IN_MAKEFILE
)
2337 if (((AnjutaProjectPropertyInfo
*)job
->property
->info
)->flags
& ANJUTA_PROJECT_PROPERTY_READ_WRITE
)
2339 amp_project_update_am_property (AMP_PROJECT (job
->user_data
), job
->node
, job
->property
);
2347 amp_remove_property_complete (PmJob
*job
)
2349 g_signal_emit_by_name (AMP_PROJECT (job
->user_data
), "node-changed", job
->node
, job
->error
);
2354 static PmCommandWork amp_remove_property_job
= {amp_remove_property_setup
, amp_remove_property_work
, amp_remove_property_complete
};
2356 /* Implement IAnjutaProject
2357 *---------------------------------------------------------------------------*/
2360 iproject_load_node (IAnjutaProject
*obj
, AnjutaProjectNode
*node
, GError
**error
)
2364 if (node
== NULL
) node
= ANJUTA_PROJECT_NODE (obj
);
2365 if (AMP_PROJECT (obj
)->queue
== NULL
) AMP_PROJECT (obj
)->queue
= pm_command_queue_new ();
2367 AMP_PROJECT (obj
)->loading
++;
2368 load_job
= pm_job_new (&_load_job
, node
, NULL
, NULL
, ANJUTA_PROJECT_UNKNOWN
, NULL
, NULL
, obj
);
2370 pm_command_queue_push (AMP_PROJECT (obj
)->queue
, load_job
);
2376 iproject_save_node (IAnjutaProject
*obj
, AnjutaProjectNode
*node
, GError
**error
)
2380 if (node
== NULL
) node
= ANJUTA_PROJECT_NODE (obj
);
2381 if (AMP_PROJECT (obj
)->queue
== NULL
) AMP_PROJECT (obj
)->queue
= pm_command_queue_new ();
2383 save_job
= pm_job_new (&_save_job
, node
, NULL
, NULL
, ANJUTA_PROJECT_UNKNOWN
, NULL
, NULL
, obj
);
2384 pm_command_queue_push (AMP_PROJECT (obj
)->queue
, save_job
);
2389 static AnjutaProjectNode
*
2390 iproject_add_node_before (IAnjutaProject
*obj
, AnjutaProjectNode
*parent
, AnjutaProjectNode
*sibling
, AnjutaProjectNodeType type
, GFile
*file
, const gchar
*name
, GError
**err
)
2392 AnjutaProjectNode
*node
;
2395 if (AMP_PROJECT (obj
)->queue
== NULL
) AMP_PROJECT (obj
)->queue
= pm_command_queue_new ();
2397 node
= amp_node_new_valid (parent
, type
, file
, name
, err
);
2400 add_job
= pm_job_new (&_add_before_job
, node
, parent
, sibling
, ANJUTA_PROJECT_UNKNOWN
, NULL
, NULL
, obj
);
2401 pm_command_queue_push (AMP_PROJECT (obj
)->queue
, add_job
);
2407 static AnjutaProjectNode
*
2408 iproject_add_node_after (IAnjutaProject
*obj
, AnjutaProjectNode
*parent
, AnjutaProjectNode
*sibling
, AnjutaProjectNodeType type
, GFile
*file
, const gchar
*name
, GError
**err
)
2410 AnjutaProjectNode
*node
;
2413 if (AMP_PROJECT (obj
)->queue
== NULL
) AMP_PROJECT (obj
)->queue
= pm_command_queue_new ();
2415 node
= amp_node_new_valid (parent
, type
, file
, name
, err
);
2418 add_job
= pm_job_new (&_add_after_job
, node
, parent
, sibling
, ANJUTA_PROJECT_UNKNOWN
, NULL
, NULL
, obj
);
2419 pm_command_queue_push (AMP_PROJECT (obj
)->queue
, add_job
);
2426 iproject_remove_node (IAnjutaProject
*obj
, AnjutaProjectNode
*node
, GError
**err
)
2430 if (AMP_PROJECT (obj
)->queue
== NULL
) AMP_PROJECT (obj
)->queue
= pm_command_queue_new ();
2432 remove_job
= pm_job_new (&_remove_job
, node
, NULL
, NULL
, ANJUTA_PROJECT_UNKNOWN
, NULL
, NULL
, obj
);
2433 pm_command_queue_push (AMP_PROJECT (obj
)->queue
, remove_job
);
2438 static AnjutaProjectProperty
*
2439 iproject_set_property (IAnjutaProject
*obj
, AnjutaProjectNode
*node
, const gchar
*id
, const gchar
*name
, const gchar
*value
, GError
**error
)
2441 AnjutaProjectProperty
*new_prop
;
2442 PmJob
*set_property_job
;
2444 if (AMP_PROJECT (obj
)->queue
== NULL
) AMP_PROJECT (obj
)->queue
= pm_command_queue_new ();
2446 new_prop
= name
== NULL
? amp_node_property_set (node
, id
, value
) : amp_node_map_property_set (node
, id
, name
, value
);
2447 set_property_job
= pm_job_new (&_set_property_job
, node
, NULL
, NULL
, ANJUTA_PROJECT_UNKNOWN
, NULL
, NULL
, obj
);
2448 set_property_job
->property
= new_prop
;
2449 pm_command_queue_push (AMP_PROJECT (obj
)->queue
, set_property_job
);
2455 iproject_remove_property (IAnjutaProject
*obj
, AnjutaProjectNode
*node
, const gchar
*id
, const gchar
*name
, GError
**error
)
2457 AnjutaProjectProperty
*new_prop
;
2458 PmJob
*remove_property_job
;
2460 if (AMP_PROJECT (obj
)->queue
== NULL
) AMP_PROJECT (obj
)->queue
= pm_command_queue_new ();
2463 new_prop
= amp_node_map_property_set (node
, id
, name
, NULL
);
2464 remove_property_job
= pm_job_new (&_set_property_job
, node
, NULL
, NULL
, ANJUTA_PROJECT_UNKNOWN
, NULL
, NULL
, obj
);
2465 remove_property_job
->property
= new_prop
;
2466 pm_command_queue_push (AMP_PROJECT (obj
)->queue
, remove_property_job
);
2471 static AnjutaProjectNode
*
2472 iproject_get_root (IAnjutaProject
*obj
, GError
**err
)
2474 return ANJUTA_PROJECT_NODE (obj
);
2478 iproject_get_node_info (IAnjutaProject
*obj
, GError
**err
)
2480 return amp_project_get_node_info (AMP_PROJECT (obj
), err
);
2484 iproject_is_loaded (IAnjutaProject
*obj
, GError
**err
)
2486 return amp_project_is_loaded (AMP_PROJECT (obj
));
2490 iproject_iface_init(IAnjutaProjectIface
* iface
)
2492 iface
->load_node
= iproject_load_node
;
2493 iface
->save_node
= iproject_save_node
;
2494 iface
->add_node_before
= iproject_add_node_before
;
2495 iface
->add_node_after
= iproject_add_node_after
;
2496 iface
->remove_node
= iproject_remove_node
;
2497 iface
->set_property
= iproject_set_property
;
2498 iface
->remove_property
= iproject_remove_property
;
2499 iface
->get_root
= iproject_get_root
;
2500 iface
->get_node_info
= iproject_get_node_info
;
2501 iface
->is_loaded
= iproject_is_loaded
;
2504 /* AmpNode implementation
2505 *---------------------------------------------------------------------------*/
2508 amp_project_load (AmpNode
*root
, AmpNode
*parent
, AmpProject
*project
, GError
**error
)
2510 return amp_project_load_root (AMP_PROJECT (root
), error
);
2514 amp_project_save (AmpNode
*root
, AmpNode
*parent
, AmpProject
*project
, GError
**error
)
2516 AnjutaTokenFile
*tfile
;
2517 AnjutaProjectNode
*child
;
2520 tfile
= AMP_PROJECT (root
)->configure_file
;
2521 if (anjuta_token_file_is_dirty (tfile
))
2523 if (!anjuta_token_file_save (tfile
, error
)) return FALSE
;
2526 if (!AMP_NODE_CLASS (parent_class
)->save (root
, parent
, project
, error
))
2531 /* Save all children */
2532 for (child
= anjuta_project_node_first_child (ANJUTA_PROJECT_NODE (root
)); child
!= NULL
; child
= anjuta_project_node_next_sibling (child
))
2534 if (!amp_node_save (AMP_NODE (child
), root
, project
, error
)) return FALSE
;
2542 amp_project_update (AmpNode
*node
, AmpNode
*new_node
)
2544 amp_project_update_root (AMP_PROJECT (node
), AMP_PROJECT (new_node
));
2550 amp_project_copy (AmpNode
*old_node
)
2554 new_node
= AMP_NODE_CLASS (amp_project_parent_class
)->copy (old_node
);
2555 ((AmpProject
*)new_node
)->lang_manager
= (((AmpProject
*)old_node
)->lang_manager
!= NULL
) ? g_object_ref (((AmpProject
*)old_node
)->lang_manager
) : NULL
;
2561 /* GObject implementation
2562 *---------------------------------------------------------------------------*/
2565 amp_project_dispose (GObject
*object
)
2567 AmpProject
*project
;
2569 g_return_if_fail (AMP_IS_PROJECT (object
));
2571 project
= AMP_PROJECT (object
);
2572 amp_project_unload (project
);
2574 amp_project_clear (project
);
2576 if (project
->groups
) g_hash_table_destroy (project
->groups
);
2577 project
->groups
= NULL
;
2578 if (project
->configs
) g_hash_table_destroy (project
->configs
);
2579 project
->configs
= NULL
;
2580 if (project
->ac_variables
) g_hash_table_destroy (project
->ac_variables
);
2581 project
->ac_variables
= NULL
;
2583 if (project
->queue
) pm_command_queue_free (project
->queue
);
2584 project
->queue
= NULL
;
2586 if (project
->monitor
) g_object_unref (project
->monitor
);
2587 project
->monitor
= NULL
;
2589 if (project
->lang_manager
) g_object_unref (project
->lang_manager
);
2590 project
->lang_manager
= NULL
;
2592 G_OBJECT_CLASS (parent_class
)->dispose (object
);
2596 amp_project_init (AmpProject
*project
)
2598 g_return_if_fail (project
!= NULL
);
2599 g_return_if_fail (AMP_IS_PROJECT (project
));
2602 project
->configure_file
= NULL
;
2603 project
->configure_token
= NULL
;
2606 project
->groups
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, NULL
);
2607 project
->files
= NULL
;
2608 project
->configs
= g_hash_table_new_full (g_file_hash
, (GEqualFunc
)g_file_equal
, NULL
, (GDestroyNotify
)amp_config_file_free
);
2609 project
->ac_variables
= g_hash_table_new_full (g_str_hash
, g_str_equal
, (GDestroyNotify
)g_free
, NULL
);
2612 project
->am_space_list
= NULL
;
2613 project
->ac_space_list
= NULL
;
2614 project
->arg_list
= NULL
;
2616 project
->queue
= NULL
;
2617 project
->loading
= 0;
2621 amp_project_class_init (AmpProjectClass
*klass
)
2623 GObjectClass
*object_class
;
2624 AmpNodeClass
*node_class
;
2626 parent_class
= g_type_class_peek_parent (klass
);
2628 object_class
= G_OBJECT_CLASS (klass
);
2629 object_class
->dispose
= amp_project_dispose
;
2631 node_class
= AMP_NODE_CLASS (klass
);
2632 node_class
->load
= amp_project_load
;
2633 node_class
->save
= amp_project_save
;
2634 node_class
->update
= amp_project_update
;
2635 node_class
->copy
= amp_project_copy
;
2639 amp_project_class_finalize (AmpProjectClass
*klass
)
2644 amp_project_register (GTypeModule
*module
)
2646 amp_node_register (module
);
2647 amp_project_register_type (module
);