1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 Copyright (C) 2004 Sebastien Granjoux
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (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
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 * Handle installation of all files
24 *---------------------------------------------------------------------------*/
35 #include <libanjuta/interfaces/ianjuta-file-loader.h>
36 #include <libanjuta/anjuta-autogen.h>
37 #include <libanjuta/anjuta-launcher.h>
38 #include <libanjuta/anjuta-debug.h>
43 #include <sys/types.h>
46 /*---------------------------------------------------------------------------*/
48 #define FILE_BUFFER_SIZE 4096
50 #define AUTOGEN_START_MACRO_LEN 7
51 #define AUTOGEN_MARKER_1 "autogen5"
52 #define AUTOGEN_MARKER_2 "template"
54 /*---------------------------------------------------------------------------*/
59 NPWFileListParser
* file_parser
;
62 NPWActionListParser
* action_parser
;
65 AnjutaLauncher
* launcher
;
67 const gchar
* project_file
;
71 /*---------------------------------------------------------------------------*/
73 static void on_install_end_install_file (AnjutaAutogen
* gen
, gpointer data
);
74 static void on_run_terminated (AnjutaLauncher
* launcher
, gint pid
, gint status
, gulong time
, NPWInstall
* this);
75 static gboolean
npw_install_install_file (NPWInstall
* this);
76 static gboolean
npw_run_action (NPWInstall
* this);
77 static gboolean
npw_open_action (NPWInstall
* this);
80 *---------------------------------------------------------------------------*/
83 npw_is_autogen_template_file (FILE* tpl
)
86 const gchar
* marker
[] = {"", AUTOGEN_MARKER_1
, AUTOGEN_MARKER_2
, NULL
};
92 for (key
= marker
; *key
!= NULL
; ++key
)
94 /* Skip first whitespace */
98 if (c
== EOF
) return FALSE
;
102 /* Test start marker, then autogen5, then template */
104 len
= *ptr
== '\0' ? AUTOGEN_START_MACRO_LEN
: strlen (ptr
);
107 if (len
== 0) return FALSE
;
109 if ((*ptr
!= '\0') && (tolower (c
) != *ptr
++)) return FALSE
;
111 /* FIXME: Test this EOF test */
112 if (c
== EOF
) return FALSE
;
114 while (!isspace (c
));
115 if ((**key
!= '\0') && (len
!= 0)) return FALSE
;
122 npw_is_autogen_template (const gchar
* filename
)
127 tpl
= fopen (filename
, "rt");
128 if (tpl
== NULL
) return FALSE
;
130 autogen
= npw_is_autogen_template_file (tpl
);
137 npw_copy_file (const gchar
* destination
, const gchar
* source
)
145 buffer
= g_new (gchar
, FILE_BUFFER_SIZE
);
148 src
= fopen (source
, "rb");
154 dst
= fopen (destination
, "wb");
163 len
= fread (buffer
, 1, FILE_BUFFER_SIZE
, src
);
164 if ((len
!= FILE_BUFFER_SIZE
) && !feof (src
))
170 if (len
!= fwrite (buffer
, 1, len
, dst
))
186 *---------------------------------------------------------------------------*/
188 NPWInstall
* npw_install_new (NPWPlugin
* plugin
)
192 /* Skip if already created */
193 if (plugin
->install
!= NULL
) return plugin
->install
;
195 this = g_new0(NPWInstall
, 1);
196 this->gen
= anjuta_autogen_new ();
197 this->plugin
= plugin
;
198 this->success
= TRUE
;
199 npw_plugin_create_view (plugin
);
201 plugin
->install
= this;
206 void npw_install_free (NPWInstall
* this)
208 if (this->file_parser
!= NULL
)
210 npw_file_list_parser_free (this->file_parser
);
212 if (this->file_list
!= NULL
)
214 g_list_foreach (this->file_list
, (GFunc
)npw_file_free
, NULL
);
215 g_list_free (this->file_list
);
217 if (this->action_parser
!= NULL
)
219 npw_action_list_parser_free (this->action_parser
);
221 if (this->action_list
!= NULL
)
223 g_list_foreach (this->action_list
, (GFunc
)npw_action_free
, NULL
);
224 g_list_free (this->action_list
);
226 if (this->launcher
!= NULL
)
228 g_signal_handlers_disconnect_by_func (G_OBJECT (this->launcher
), G_CALLBACK (on_run_terminated
), this);
229 g_object_unref (this->launcher
);
231 g_object_unref (this->gen
);
232 this->plugin
->install
= NULL
;
237 npw_install_set_property (NPWInstall
* this, GHashTable
* values
)
239 anjuta_autogen_write_definition_file (this->gen
, values
, NULL
);
245 npw_install_set_wizard_file (NPWInstall
* this, const gchar
* filename
)
247 if (this->file_list
!= NULL
)
249 g_list_foreach (this->file_list
, (GFunc
)npw_file_free
, NULL
);
250 g_list_free (this->file_list
);
251 this->file_list
= NULL
;
253 if (this->file_parser
!= NULL
)
255 npw_file_list_parser_free (this->file_parser
);
257 this->file_parser
= npw_file_list_parser_new (filename
);
259 anjuta_autogen_set_input_file (this->gen
, filename
, "[+","+]");
265 npw_install_set_library_path (NPWInstall
* this, const gchar
*directory
)
267 anjuta_autogen_set_library_path (this->gen
, directory
);
273 on_install_read_action_list (const gchar
* output
, gpointer data
)
275 NPWInstall
* this = (NPWInstall
*)data
;
277 npw_action_list_parser_parse (this->action_parser
, output
, strlen (output
), NULL
);
281 on_install_end_action (gpointer data
)
283 NPWInstall
* this = (NPWInstall
*)data
;
289 if (this->action
== NULL
)
293 /* Run action on success only */
294 this->action
= g_list_first (this->action_list
);
299 this->action
= g_list_next (this->action
);
301 if (this->action
== NULL
)
303 DEBUG_PRINT ("Project wizard done");
304 /* The wizard could have been deactivated when loading the new
305 * project. Hence, the following check.
307 if (anjuta_plugin_is_active (ANJUTA_PLUGIN (this->plugin
)))
308 anjuta_plugin_deactivate (ANJUTA_PLUGIN (this->plugin
));
309 npw_install_free (this);
312 action
= (NPWAction
*)this->action
->data
;
314 switch (npw_action_get_type (action
))
317 npw_run_action (this);
319 case NPW_OPEN_ACTION
:
320 npw_open_action (this);
329 on_install_read_all_action_list (AnjutaAutogen
* gen
, gpointer data
)
331 NPWInstall
* this = (NPWInstall
*)data
;
333 this->action_list
= npw_action_list_parser_end_parse (this->action_parser
, NULL
);
335 on_install_end_install_file (NULL
, this);
339 on_install_read_file_list (const gchar
* output
, gpointer data
)
341 NPWInstall
* this = (NPWInstall
*)data
;
343 npw_file_list_parser_parse (this->file_parser
, output
, strlen (output
), NULL
);
347 on_install_read_all_file_list (AnjutaAutogen
* gen
, gpointer data
)
349 NPWInstall
* this = (NPWInstall
*)data
;
351 this->file_list
= npw_file_list_parser_end_parse (this->file_parser
, NULL
);
353 this->current_file
= NULL
;
354 this->project_file
= NULL
;
356 if (this->action_list
!= NULL
)
358 g_list_foreach (this->action_list
, (GFunc
)npw_action_free
, NULL
);
359 g_list_free (this->action_list
);
360 this->action_list
= NULL
;
362 if (this->action_parser
!= NULL
)
364 npw_action_list_parser_free (this->action_parser
);
366 this->action_parser
= npw_action_list_parser_new ();
367 anjuta_autogen_set_output_callback (this->gen
, on_install_read_action_list
, this, NULL
);
368 anjuta_autogen_execute (this->gen
, on_install_read_all_action_list
, this, NULL
);
372 on_install_end_install_file (AnjutaAutogen
* gen
, gpointer data
)
374 NPWInstall
* this = (NPWInstall
*)data
;
376 /* Warning gen could be invalid */
382 if (this->current_file
== NULL
)
384 this->current_file
= g_list_first (this->file_list
);
388 NPWFile
*file
= (NPWFile
*)this->current_file
->data
;
390 if (npw_file_get_execute (file
))
393 /* Make this file executable */
394 previous
= umask (0666);
395 chmod (npw_file_get_destination (file
), 0777 & ~previous
);
398 if (npw_file_get_project (file
))
400 /* Check if project is NULL */
401 this->project_file
= npw_file_get_destination (file
);
403 this->current_file
= g_list_next (this->current_file
);
405 if (this->current_file
== NULL
)
407 /* IAnjutaFileLoader* loader; */
408 /* All files have been installed */
411 npw_plugin_print_view (this->plugin
,
412 IANJUTA_MESSAGE_VIEW_TYPE_INFO
,
413 _("New project has been created successfully."),
418 npw_plugin_print_view (this->plugin
,
419 IANJUTA_MESSAGE_VIEW_TYPE_ERROR
,
420 _("New project creation has failed."),
423 on_install_end_action (this);
427 file
= (NPWFile
*)this->current_file
->data
;
428 switch (npw_file_get_type (file
))
431 npw_install_install_file (this);
434 g_warning("Unknown file type %d\n", npw_file_get_type (file
));
441 npw_install_launch (NPWInstall
* this)
443 anjuta_autogen_set_output_callback (this->gen
, on_install_read_file_list
, this, NULL
);
444 anjuta_autogen_execute (this->gen
, on_install_read_all_file_list
, this, NULL
);
450 npw_install_install_file (NPWInstall
* this)
455 const gchar
* destination
;
458 gboolean use_autogen
;
460 NPWFile
*file
= (NPWFile
*)this->current_file
->data
;
463 destination
= npw_file_get_destination (file
);
464 source
= npw_file_get_source (file
);
466 /* Check if file already exist */
467 if (g_file_test (destination
, G_FILE_TEST_EXISTS
))
469 msg
= g_strdup_printf (_("Skipping %s: file already exists"), destination
);
470 npw_plugin_print_view (this->plugin
, IANJUTA_MESSAGE_VIEW_TYPE_WARNING
, msg
, "");
472 on_install_end_install_file (this->gen
, this);
477 /* Check if autogen is needed */
478 switch (npw_file_get_autogen (file
))
487 use_autogen
= npw_is_autogen_template (source
);
493 len
= strlen (destination
) + 1;
494 buffer
= g_new (gchar
, MAX (FILE_BUFFER_SIZE
, len
));
495 strcpy (buffer
, destination
);
499 /* Get directory one by one */
500 sep
= strstr (sep
,G_DIR_SEPARATOR_S
);
501 if (sep
== NULL
) break;
502 /* Create directory if necessary */
504 if ((*buffer
!= '~') && (*buffer
!= '\0'))
506 if (!g_file_test (buffer
, G_FILE_TEST_EXISTS
))
508 if (mkdir (buffer
, 0755) == -1)
510 msg
= g_strdup_printf (_("Creating %s … Failed to create directory"), destination
);
516 *sep
++ = G_DIR_SEPARATOR_S
[0];
523 anjuta_autogen_set_input_file (this->gen
, source
, NULL
, NULL
);
524 anjuta_autogen_set_output_file (this->gen
, destination
);
525 ok
= anjuta_autogen_execute (this->gen
, on_install_end_install_file
, this, NULL
);
526 msg
= g_strdup_printf (_("Creating %s (using AutoGen)… %s"), destination
, ok
? "Ok" : "Fail to Execute");
530 ok
= npw_copy_file (destination
, source
);
531 msg
= g_strdup_printf (_("Creating %s … %s"), destination
, ok
? "Ok" : "Fail to copy file");
535 /* Record failure and display error message */
538 this->success
= FALSE
;
540 npw_plugin_print_view (this->plugin
, ok
? IANJUTA_MESSAGE_VIEW_TYPE_INFO
: IANJUTA_MESSAGE_VIEW_TYPE_ERROR
, msg
, "");
543 /* Next file is called automatically if autogen succeed */
544 if (!ok
|| !use_autogen
)
545 on_install_end_install_file (this->gen
, this);
551 on_run_terminated (AnjutaLauncher
* launcher
, gint pid
, gint status
, gulong time
, NPWInstall
* this)
553 on_install_end_action (this);
557 on_run_output (AnjutaLauncher
* launcher
, AnjutaLauncherOutputType type
, const gchar
* output
, gpointer data
)
559 NPWInstall
* this = (NPWInstall
*)data
;
561 npw_plugin_append_view (this->plugin
, output
);
565 npw_run_action (NPWInstall
* this)
568 NPWAction
*action
= (NPWAction
*)this->action
->data
;
570 if (this->launcher
== NULL
)
572 this->launcher
= anjuta_launcher_new ();
574 g_signal_connect (G_OBJECT (this->launcher
), "child-exited", G_CALLBACK (on_run_terminated
), this);
575 /* The %s is a name of a unix command line, by example
576 * cp foobar.c project */
577 msg
= g_strdup_printf (_("Executing: %s"), npw_action_get_command (action
));
578 npw_plugin_print_view (this->plugin
, IANJUTA_MESSAGE_VIEW_TYPE_INFO
, msg
, "");
581 return anjuta_launcher_execute (this->launcher
, npw_action_get_command (action
), on_run_output
, this);
585 npw_open_action (NPWInstall
* this)
587 IAnjutaFileLoader
* loader
;
588 NPWAction
*action
= (NPWAction
*)this->action
->data
;
590 loader
= anjuta_shell_get_interface (ANJUTA_PLUGIN (this->plugin
)->shell
, IAnjutaFileLoader
, NULL
);
593 GFile
* file
= g_file_new_for_path (npw_action_get_file (action
));
594 ianjuta_file_loader_load (loader
, file
, FALSE
, NULL
);
595 g_object_unref (file
);