JsTemplate/Link.js
[gnome.introspection-doc-generator] / jhbuild.js
1 //<script type="text/javascript">
2 GLib= imports.gi.GLib;
3 Gio = imports.gi.Gio;
4
5 Roo = imports['Roo.js'].Roo;
6 File = imports['File.js'].File;
7 console = imports['console.js'].console;
8
9  
10 imports['Date.js'].load(Date);
11  
12
13 // these should come from args
14 var SRC='/disk2/checkout/gnome2/';
15
16 // perhaps we can just do a simple make for building the girs - no make install etc.?
17 var UPDATE_SOURCES = false;
18
19
20
21 var LOGFILE = "jhbuild-" + (new Date()).format("Y-m-d-H") + '.log';
22
23
24 // change src & deleteGirs when you add / remove girs..
25 /*
26
27 USAGE:
28 screen -d -m seed jhbuild.js
29 tail /tmp/builder.log
30
31 TODO:
32 continue - do not trash gir's...
33 use this to diff changes when we fix gobject introspection..
34 git diff on directories..
35 email me the results.
36 run the doc tool as well.
37
38
39 patching
40 --- before jhbuild..
41 --- git diff (current to /SRC/package-DATE.diff)
42 --- see if we have a patch list
43 --- if so: git reset --hard
44 ---    apply patch..
45 --- run jhbuild.
46
47 to add:
48 avahi + core.
49 babl
50 dbus
51  
52
53 sqlite3
54 libbonbo
55
56 to fix: - see the list of modules commented out.
57
58 */
59
60
61
62 var deleteGirs = [
63         'atk/atk/Atk-1.0.gir',
64     'clutter/clutter/json/ClutterJson-1.0.gir',
65         'clutter/clutter/cogl/Cogl-1.0.gir',
66         'clutter/clutter/Clutter-1.0.gir',
67         'clutter/clutter/Cogl-1.0.gir',
68         'clutter/clutter/ClutterJson-1.0.gir',
69     'epiphany/src/Epiphany-2.29.gir',
70     'libgda/libgda/Gda-4.0.gir',
71         'libgda/libgda-ui/Gdaui-4.0.gir',
72     'libgsf/gsf/Gsf-1.gir',
73     'gobject-introspection/gir/libxml2-2.0.gir', // needed!
74         'gobject-introspection/gir/Gio-2.0.gir',
75         'gobject-introspection/gir/GModule-2.0.gir',
76         'gobject-introspection/gir/GLib-2.0.gir',
77         'gobject-introspection/gir/GIRepository-2.0.gir',
78         'gobject-introspection/gir/GObject-2.0.gir',
79         
80         'gtk+/gdk-pixbuf/GdkPixbuf-2.0.gir',
81         'gtk+/gtk/Gtk-2.0.gir',
82         'gtk+/gdk/Gdk-2.0.gir',
83     'clutter-gtk/clutter-gtk/GtkClutter-0.10.gir',
84     'gconf/GConf-2.0.gir',
85     'gtksourceview/gtksourceview/GtkSource-2.0.gir',
86         'gstreamer/gst/Gst-0.10.gir',
87         'gstreamer/libs/gst/check/GstCheck-0.10.gir',
88         'gstreamer/libs/gst/net/GstNet-0.10.gir',
89         'gstreamer/libs/gst/controller/GstController-0.10.gir',
90         'gstreamer/libs/gst/base/GstBase-0.10.gir',
91     'gst-plugins-base/gst-libs/gst/video/GstVideo-0.10.gir',
92         'gst-plugins-base/gst-libs/gst/tag/GstTag-0.10.gir',
93         'gst-plugins-base/gst-libs/gst/interfaces/GstInterfaces-0.10.gir',
94         'gst-plugins-base/gst-libs/gst/pbutils/GstPbutils-0.10.gir',
95         'gst-plugins-base/gst-libs/gst/netbuffer/GstNetbuffer-0.10.gir',
96         'gst-plugins-base/gst-libs/gst/riff/GstRiff-0.10.gir',
97         'gst-plugins-base/gst-libs/gst/audio/GstAudio-0.10.gir',
98         'gst-plugins-base/gst-libs/gst/fft/GstFft-0.10.gir',
99         'gst-plugins-base/gst-libs/gst/rtsp/GstRtsp-0.10.gir',
100         'gst-plugins-base/gst-libs/gst/app/GstApp-0.10.gir',
101         'gst-plugins-base/gst-libs/gst/sdp/GstSdp-0.10.gir',
102         'gst-plugins-base/gst-libs/gst/rtp/GstRtp-0.10.gir',
103
104     'gssdp/libgssdp/GSSDP-1.0.gir',
105         'gdome2/libgdome/Gdome-2.0.gir',
106     'gnome-menus/libmenu/GMenu-2.0.gir',
107         
108         
109     
110         'pango/pango/PangoFT2-1.0.gir',
111         'pango/pango/PangoCairo-1.0.gir',
112         'pango/pango/PangoXft-1.0.gir',
113         'pango/pango/Pango-1.0.gir',
114         'PolicyKit/src/polkit/Polkit-1.0.gir',    
115         'unique/unique/Unique-1.0.gir',
116     'vte/src/Vte-0.gir',
117         
118         'WebKit/WebKit-1.0.gir',
119         //'WebKit/WebKit/gtk/JSCore-1.0.gir', -- not a generated file!
120         
121
122 ];
123
124 var all = {
125     
126     // package : directory
127     'atk' : 'atk',
128     'clutter': 'clutter', 
129         'clutter-gtk' :'clutter-gtk', 
130     'eggdbus' : 'eggdbus',
131         'glib' : 'glib' ,   
132         'epiphany' : 'epiphany',
133         'gtk+' : 'gtk+',
134         'gobject-introspection' : 'gobject-introspection',
135          
136         'gstreamer' : 'gstreamer',
137         'gst-plugins-base' : 'gst-plugins-base',
138         'gtksourceview' : 'gtksourceview',
139     'gnome-menus' :     'gnome-menus',
140     'gssdp' :'gssdp',
141         'libgda'  :'libgda',
142         'libgsf' :'libgsf',
143         'libunique' :'unique', 
144     'libsoup' : 'libsoup',
145         'pango' : 'pango',
146     'polkit' : 'PolicyKit', 
147         'vte' : 'vte',
148         'WebKit' :'WebKit',
149     'gconf' : 'gconf',
150     //'gupnp', -- needs patch
151         // 'gnome-keyring' -- ndeds patch
152     // gnome-vfs -- needs patch
153     // 'goocanvas' -- needs patch
154     //'libnotify' -- needs patch
155     // 'poppler' --- 
156     
157 };
158
159 // we dont use these at present..
160 var patches = {
161     'gconf' : [
162        'http://bugzilla-attachments.gnome.org/attachment.cgi?id=156459',
163        'http://bugzilla-attachments.gnome.org/attachment.cgi?id=156457',
164     ],
165     'gnome-keyring' : [
166         // not valid - against release..
167         //'http://bugzilla-attachments.gnome.org/attachment.cgi?id=145422'
168     ],
169     'gtksouceview' : [
170         'http://bugzilla-attachments.gnome.org/attachment.cgi?id=153062',
171     ],
172     'avahi' : [
173        'http://www.akbkhome.com/svn/seed/gir/avahi.diff',
174     ]
175 };
176 /**
177  * 
178  * spawnlog:
179  * spawn process, and print/monitor output.
180  * 
181  * usage scenarios:
182  *  - global log.. -> our global log just indicates what was done and what was the result?
183  *  - build log for a specific package?
184  *  - return data? - 
185  * 
186  * @arg string cwd working directory.
187  * @arg array  args 
188  * @
189  * 
190  */
191 var streams  = { };
192   
193 function  write(fn, str) {
194     if (!str) {
195         return;
196     }
197     
198     if (!fn) {
199         return;
200     }
201     console.log(str.replace(/\n/,''));
202     
203     if (typeof(streams[fn])=='undefined') {
204         GLib.unlink(fn);
205         var f = Gio.file_new_for_path(String(fn));
206         streams[fn] = new Gio.DataOutputStream({
207                 base_stream: f.replace(null, false, Gio.FileCreateFlags.REPLACE_DESTINATION, null)
208             });
209     }
210     streams[fn].put_string(str, null);
211 }
212 function  close(fn) {
213     if (!fn || typeof(streams[fn])=='undefined') {
214         return;
215     }
216     streams[fn].close(null);
217     delete streams[fn];
218 }
219
220
221 function spawnlog (cwd, s, outfile, errfile) {
222     var ret = { };
223     var retval =  { output: '' , error : '', cmd : s.join(' ') , done : false};
224     console.log(retval.cmd);
225     GLib.spawn_async_with_pipes(cwd, s, null, 
226         GLib.SpawnFlags.DO_NOT_REAP_CHILD + GLib.SpawnFlags.SEARCH_PATH , 
227         null, null, ret);
228         
229     var ctx = GLib.main_loop_new (null, false);
230     var started = false;
231     
232     GLib.child_watch_add(GLib.PRIORITY_DEFAULT, ret.child_pid, function(pid, status) {
233         console.log("GOT STATUS:" + status);
234         retval.status = status;
235         retval.done = true;
236         if (started) {
237             console.log("Ending LOOP");
238             GLib.main_loop_quit(ctx);
239         }
240         
241     });
242    //console.dump(ret);
243
244     var in_ch = GLib.io_channel_unix_new(ret.standard_input);
245     var out_ch = GLib.io_channel_unix_new(ret.standard_output);
246     var err_ch = GLib.io_channel_unix_new(ret.standard_error);
247     
248     function readstr(ch, fn, prop) {
249         
250         while (true) {
251             
252             var x = new GLib.String();
253             
254             
255             var cstatus = GLib.io_channel_get_buffer_condition(ch);
256             cstatus = GLib.io_channel_get_flags (ch)
257             
258
259             //Seed.print("WAITING INPUT?" + prop+':'+cstatus);
260             //var status = GLib.io_channel_read_line_string (ch, x, null);
261             
262                
263             var status = GLib.io_channel_read_line_string (ch, x);
264             
265             //Seed.print(prop + ":INPUT:" + status);
266         
267             switch(status) {
268                 case GLib.IOStatus.NORMAL:
269                     write(fn, x.str);
270                     retval[prop] += x.str;
271                    continue
272                 case GLib.IOStatus.AGAIN:   
273                     break;
274                 case GLib.IOStatus.ERROR:    
275                 case GLib.IOStatus.EOF:   
276                    break;
277                 
278             }
279             break;
280         }
281     }
282     
283     
284     
285     GLib.io_add_watch(in_ch, GLib.PRIORITY_DEFAULT, 
286         GLib.IOCondition.OUT + GLib.IOCondition.IN  + GLib.IOCondition.PRI, function()
287     {
288         //Seed.print("GOT INOUT ON IN");
289         readstr(out_ch, outfile, 'output');
290         
291     });
292     GLib.io_add_watch(err_ch, GLib.PRIORITY_DEFAULT, 
293         GLib.IOCondition.ERR + GLib.IOCondition.IN + GLib.IOCondition.PRI + GLib.IOCondition.OUT, 
294         function()
295     {
296         // Seed.print("GOT INOUT ON ERR");
297          readstr(er_ch, errfile, 'error');
298          
299     });
300     // let's just write some data... 
301     //var x = new GLib.String();
302     //var status = GLib.io_channel_write (out_ch, "\n", 1);
303     
304     //while (!retval.done) {
305             
306      
307     //}
308  
309     // do we need this?
310     if (!retval.done) {
311         started = true;
312         console.log("STARTING LOOP");
313         GLib.main_loop_run(ctx, false); // wait fore exit?
314     }
315     readstr(out_ch, outfile, 'output');
316     readstr(err_ch, errfile, 'error');
317      
318     
319     
320     
321     close(outfile);
322     close(errfile);
323     
324     //GLib.spawn_close_pid(ret.child_pid);
325     return retval;
326     
327
328 }
329   
330
331 function log(res) {
332     if (typeof(res) == 'string') {
333         if (!res.length) { // skip blan.
334             return;
335         }
336         
337         
338         write(SRC + LOGFILE, '[' + (new Date()).format("Y-m-d H:i:s") + '] ' + res);
339         return;
340     }
341     log("CMD:" + res.cmd +"\n");
342     log("RETURN:" + (res.status ? res.status : "OK")+"\n");
343     log(res.output ? "---OUT---\n" + res.output + "\n" : '');
344     log(res.error ? " ---ERROR---\n" + res.error + "\n" : '');
345    
346 }
347 function logresult(res) {
348    log("CMD: " + res.cmd +"\n");
349    log((res.status ? "RETURN: " + res.status : 'BUILD OK') +"\n");
350     if (res.status != 0 ) {
351        log(res.error ? "---ERROR---\n" + res.error + "\n" : '');
352     }
353      
354 }
355
356 var nojhbuild = {
357         gdome  : [ 'git', 'clean', 'make' , 'install' ], // fixme..
358          
359     
360     
361 }
362
363 function main() {
364         // delete old..
365     deleteGirs.map( function(g) {
366         try {
367             console.log("DELETE" + SRC + g);
368             GLib.unlink(SRC+g);
369         } catch(e) {
370             console.log(e);
371         }
372         
373     });
374
375     
376     
377     
378     var pkgs = [];
379     var cline = [];
380     for(var i in all) {
381         pkgs.push(i);
382         cline.push(i);
383     }
384     cline.unshift('list');
385     cline.unshift('jhbuild');
386     var order = spawnlog('/tmp', cline).output.split("\n");
387     // push introspection first...!!!
388     
389  
390     var buildorder = [];
391     for (var i=0; i < order.length; i++) {
392         if (!order[i].length || pkgs.indexOf(order[i]) < 0) {
393             //console.log("SKIP (not related to gir) " + order[i] );
394             log("SKIP (not related to gir) " + order[i] +"\n");
395             continue;    
396         }
397         
398         // special cases:
399         // just for our reference..
400         spawnlog('/tmp', ['jhbuild','info', order[i]]);
401         // add -a -c for a clean build..
402         
403         if (!UPDATE_SOURCES) {
404             // quick rebuild - probably to check introspection change results.
405             log("MAKE INSTALL: " + order[i] + "\n");
406             var res = spawnlog(
407                     SRC+all[order[i]], ['bash' , '-c' ,'make install 2>&1'],
408                     SRC+all[order[i]]+'/jhbuild.log', 
409                     SRC+all[order[i]]+'/jhbuild.err'
410             );
411             logresult(res); 
412             continue;
413             
414         }
415         
416         
417         // for git.. - do a diff before we start, and store it..
418         // just in case..
419         if (File.exists(SRC+all[order[i]]+'/.git')) {
420              
421             var gitres = spawnlog( SRC + all[order[i]], [ 'git', 'diff' ]);
422             
423             var fn = false;
424             if (gitres.output.length) {
425                 fn = SRC+all[order[i]]+'-' + (new Date()).format('Y-m-d-H') + '.diff';
426                 log("DIFF STORED: "+ fn+"\n");
427                 write(fn, gitres.output);
428                 close(fn);
429             }
430             log("RESET GIT / PULL\n");
431             spawnlog( SRC + all[order[i]], [ 'git', 'reset', '--hard' ]);
432             spawnlog( SRC + all[order[i]], [ 'git', 'pull' ]);
433             if (fn) {
434                 log("RE-APPLING DIFF\n");
435                 spawnlog( SRC + all[order[i]], [ 'patch', '-p1', '-i',  fn ]);
436             }
437             // we should apply patches here..
438             
439         }
440         
441         
442         
443         while(true) {
444             
445                
446             log("BUILDING : " + order[i] + "\n");
447             var res = spawnlog(
448                     '/tmp', ['jhbuild', '--no-interact', 'buildone',order[i]],
449                     SRC+all[order[i]]+'/jhbuild.log', 
450                     SRC+all[order[i]]+'/jhbuild.err'
451             );
452             logresult(res);
453             if (res.status == 256 && res.error.match(/The remote end hung up unexpectedly/)) {
454                 // try again - git connection failed..
455                 continue;
456             }
457             break;
458         }
459        
460    
461         
462         
463     }
464     close(SRC + LOGFILE);
465         
466         
467 }
468
469  
470 main();
471 // specials..
472 //polkit  -> PolicyKit
473 //WebKit -> svn 
474 //gdome -> manual..
475 //libxml2 -> last! and must manual..
476
477 // refresh build...
478 // we can just trash the gir's..
479 // usefull for checking changes in introspection..
480 // then run make on the whole lot..
481
482
483 // special treatment
484 //libxml (must be after introspecton)
485
486
487
488
489
490 // full build - needs jhbuild really...
491 // ideally:
492 // -- will not build stuff that's not changed.. (we need to store checkout id's to make this work..)
493 // otherwise do a -a -c 
494
495
496
497 // what this has to do.. (similar to jhbuild...?? why not use it???
498