source: libi4uccore/profilebuilder.vala @ 47b701a6646050bc639a18969b1ada4845b6e1c3

Revision 47b701a6646050bc639a18969b1ada4845b6e1c3, 8.3 KB checked in by Matias De la Puente <mfpuente.ar@…>, 2 years ago (diff)

Rework to use ViewFactory? and App

  • Property mode set to 100644
Line 
1/* profilebuilder.vala
2 *
3 * Copyright (C) 2010  Matias De la Puente
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 *
18 * Author:
19 *      Matias De la Puente <mfpuente.ar@gmail.com>
20 */
21using Gee;
22
23public class I4uc.Core.CommandContext : GLib.Object
24{
25        public string command;
26        public string output;
27        public string output_regex;
28        public string source_uri;
29}
30
31public class I4uc.Core.ProfileBuilder : GLib.Object
32{
33        private App _app;
34        private Command _command = create_command ();
35        private ArrayList<CommandContext> _commands = new ArrayList<CommandContext> ();
36        private int _command_index = 0;
37        private Profile _profile;
38       
39        public bool is_building { private set; get; }
40        public Project project { set; get; }
41
42        public string profile
43        {
44                set { _profile = _project.profiles[value]; }
45                get { return _profile.name; }
46        }
47
48        public signal void new_message (string message);
49        public signal void new_error (string error);
50        public signal void command_finished (CommandContext command_context);
51
52        public ProfileBuilder (App app)
53        {
54                _app = app;
55                _command.finished.connect (on_command_finished);
56        }
57
58        public void build () throws GLib.Error
59        {
60                if (_is_building)
61                        return;
62               
63                this.new_message (_("Start building \"%s\" profile of \"%s\" project...").printf (_profile.name, _project.name));
64               
65                var builder = _app.settings.builders[_profile.builder_id];
66                var device_type = builder.device_types[_profile.device_type];
67               
68                var objects = new ArrayList<string> ();
69               
70                _commands.clear ();
71                foreach (var source in _profile.files)
72                {
73                        var source_type = device_type.get_source_type_from_filename (source);
74                        if (source_type == null)
75                                continue;
76                       
77                        var object = source[0:-source_type.source_type.length] + "-" + _profile.name + source_type.object_type;
78                        objects.add (object);
79                       
80                        var source_uri = project.get_file_uri (source);
81                        var object_uri = project.get_file_uri (object);
82                       
83                        // Build the source file if the object file doesn't exists, is older than the
84                        // source or if the profile's parameters where changed
85                        if (!FileUtils.test (Filename.from_uri (object_uri), FileTest.EXISTS) ||
86                            check_mtime (source_uri, object_uri) ||
87                            _profile.parameters_changed)
88                        {
89                                var command = source_type.build_command;
90                                command = command.replace ("%device", _profile.device);
91                                command = command.replace ("%source", Shell.quote (source));
92                                command = command.replace ("%object", object.replace (" ", "_"));
93                                command = command.replace ("%project", _project.name.replace (" ", "_"));
94                                command = command.replace ("%profile", _profile.name.replace (" ", "_"));
95                               
96                                // Add compile options if the source has it
97                                if (_profile.compile_options.has_key (source))
98                                        command += " " + _profile.compile_options[source];
99                               
100                                var command_context = new CommandContext ();
101                                command_context.command = command;
102                                command_context.output_regex = source_type.output_regex;
103                                command_context.source_uri = source_uri;
104                               
105                                _commands.add (command_context);
106                        }
107                }
108               
109                // Restores parameters changed flag
110                _profile.parameters_changed = false;
111               
112                if (objects.size == 0)
113                        return;
114               
115                var hexfile = _project.name + "-" + _profile.name + ".hex";
116                var hexfile_file = File.new_for_uri (_project.get_file_uri (hexfile));
117
118                if (hexfile_file.query_exists (null) && _commands.size == 0)
119                {
120                        this.new_message (_("There's nothing to build"));
121                        return;
122                }
123
124                var objects_string = "";
125                foreach (var object in objects)
126                        objects_string +=  object.replace (" ", "_") + " ";
127               
128                var command = device_type.build_command;
129                command = command.replace ("%device", _profile.device);
130                command = command.replace ("%objects", objects_string);
131                command = command.replace ("%hexfile", hexfile.replace (" ", "_"));
132                command = command.replace ("%project", _project.name.replace (" ", "_"));
133                command = command.replace ("%profile", _profile.name.replace (" ", "_"));
134                command += " " + _profile.link_options;
135               
136                var command_context = new CommandContext ();
137                command_context.command = command;
138               
139                _commands.add (command_context);
140               
141                if (device_type.has_post_build_commands)
142                        foreach (var post_build_command in device_type.post_build_commands)
143                        {
144                                command = post_build_command;
145                                command = command.replace ("%device", _profile.device);
146                                command = command.replace ("%objects", objects_string);
147                                command = command.replace ("%hexfile", hexfile.replace (" ", "_"));
148                                command = command.replace ("%project", _project.name.replace (" ", "_"));
149                                command = command.replace ("%profile", _profile.name.replace (" ", "_"));
150                               
151                                command_context = new CommandContext ();
152                                command_context.command = command;
153                               
154                                _commands.add (command_context);
155                        }
156               
157                on_command_finished (true);
158        }
159       
160        public void clean () throws GLib.Error
161        {
162                if (_is_building)
163                        return;
164
165                this.new_message (_("Start cleaning \"%s\" profile of \"%s\" project...").printf (_profile.name, _project.name));
166               
167                var builder = _app.settings.builders[_profile.builder_id];
168                var device_type = builder.device_types[_profile.device_type];
169               
170                foreach (var source in _profile.files)
171                {
172                        var source_type = device_type.get_source_type_from_filename (source);
173                        if (source_type == null)
174                                continue;
175                       
176                        foreach (var clean_type in source_type.clean_types)
177                        {
178                                var filename = source[0:-source_type.source_type.length] + "-" + _profile.name + clean_type;
179                                var file = File.new_for_uri (_project.get_file_uri (filename.replace (" ", "_")));
180                                if (file.query_exists (null))
181                                {
182                                        this.new_message (_("Deleting %s").printf (file.get_path ()));
183                                        file.delete (null);
184                                }
185                        }
186                }
187               
188                foreach (var clean_type in device_type.clean_types)
189                {
190                        var filename = _project.name + "-" + _profile.name + clean_type;
191                        var file = File.new_for_uri (_project.get_file_uri (filename.replace (" ", "_")));
192                        if (file.query_exists (null))
193                        {
194                                this.new_message (_("Deleting %s").printf (file.get_path ()));
195                                file.delete (null);
196                        }
197                }
198               
199                this.new_message (_("The profile is clean"));
200        }
201
202        public void stop ()
203        {
204                _commands.clear ();
205                _command.stop ();
206        }
207
208        private void on_command_finished (bool exited_ok, string standard_output="", string standard_error="")
209        {
210                // When _command_index is different to 0, a command just finished
211                if (_command_index != 0)
212                {
213                        _commands[_command_index-1].output = standard_output + standard_error;
214                        this.command_finished (_commands[_command_index-1]);
215                }
216               
217                // Run the next command, exit when all the commands finished ok or with some error
218                if (_command_index < _commands.size && exited_ok)
219                {
220                        var folder_file = File.new_for_uri (_project.folder_uri);
221                        try
222                        {
223                                _command.run (_commands[_command_index].command, folder_file.get_path ());
224                                this.is_building = true;
225                                _command_index++;
226                        }
227                        catch (Error e)
228                        {
229                                this.is_building = false;
230                                _command_index = 0;
231                                this.new_error (e.message);
232                        }
233                }
234                else
235                {
236                        this.is_building = false;
237                        _command_index = 0;
238                        if (exited_ok)
239                                this.new_message (_("Build finished ok"));
240                        else
241                                this.new_error (_("Build finished with errors"));
242                }
243        }
244
245        private bool check_mtime (string newer_uri, string older_uri) throws GLib.Error
246        {
247                var newer_file = File.new_for_uri (newer_uri);
248                var older_file = File.new_for_uri (older_uri);
249               
250                var newer_info = newer_file.query_info ("time::*", FileQueryInfoFlags.NONE, null);
251                var older_info = older_file.query_info ("time::*", FileQueryInfoFlags.NONE, null);
252               
253                var newer_time = newer_info.get_attribute_uint64 (FILE_ATTRIBUTE_TIME_CHANGED);
254                var newer_time_usec = newer_info.get_attribute_uint32 (FILE_ATTRIBUTE_TIME_CHANGED_USEC);
255                var older_time = older_info.get_attribute_uint64 (FILE_ATTRIBUTE_TIME_CHANGED);
256                var older_time_usec = older_info.get_attribute_uint32 (FILE_ATTRIBUTE_TIME_CHANGED_USEC);
257               
258                return (newer_time > older_time) || (newer_time == older_time && newer_time_usec > older_time_usec);
259        }
260}
Note: See TracBrowser for help on using the repository browser.