sync gitlive origin.gitlive
authorAlan Knowles <alan@akbkhome.com>
Wed, 30 Mar 2011 16:43:59 +0000 (00:43 +0800)
committerAlan Knowles <alan@akbkhome.com>
Wed, 30 Mar 2011 16:43:59 +0000 (00:43 +0800)
Spawn.js [new file with mode: 0644]
StatusIcon.js [new file with mode: 0644]
sqlite3 [new file with mode: 0644]

diff --git a/Spawn.js b/Spawn.js
new file mode 100644 (file)
index 0000000..8f46360
--- /dev/null
+++ b/Spawn.js
@@ -0,0 +1,325 @@
+///<script type="text/javascript">
+
+var Gio      = imports.gi.Gio;
+var GLib      = imports.gi.GLib;
+
+
+/**
+* @namespace Spawn
+* 
+* Library to wrap GLib.spawn_async_with_pipes
+* 
+* usage:
+* 
+* Spawn = import.Spawn;
+* 
+* simple version..
+* var output = Spawn.run({
+*   cwd : '/home',
+*   args : [ 'ls', '-l' ],
+*   env : [], // optional
+*   listeners : {
+        output : function (line) { Seed.print(line); },
+*       stderr :  function (line) {Seed.print("ERROR" + line);  },
+*       input : function() { return 'xxx' },
+*   }
+*  });
+* 
+* 
+*/
+
+
+/**
+ * @class Spawn
+ * @param cfg {Object} settings - see properties.
+ * 
+ * @arg cwd {String}            working directory. (defaults to home directory)
+ * @arg args {Array}            arguments eg. [ 'ls', '-l' ]
+ * @arg listeners {Object} (optional) handlers for output, stderr, input
+ *     stderr/output both receive output line as argument
+ *     input should return any standard input
+ *     finish recieves result as argument.
+ * @arg env {Array}             enviroment eg. [ 'GITDIR=/home/test' ]
+ * @arg async {Boolean} (optional)return instantly, or wait for exit. (default no)
+ * @arg exceptions {Boolean}    throw exception on failure (default no)
+ * @arg debug {Boolean}    print out what's going on.. (default no)
+ * 
+ */
+function Spawn(cfg) {
+    for(var i in cfg) {
+        this[i] = cfg[i];
+    }
+    // set defaults?
+    this.listeners = this.listeners || {};
+    this.cwd =  this.cwd || GLib.get_home_dir();
+    if (!this.args || !this.args.length) {
+        throw "No arguments";
+    }
+    
+}
+
+
+Spawn.prototype = {
+    
+    listeners : false,
+    async : false,
+    env : null,
+    cwd: false,
+    args: false,
+    exceptions : false,
+    debug : false,
+    /**
+     * @property output {String} resulting output
+     */
+    output  : '',
+    /**
+     * @property stderr {String} resulting output from stderr
+     */
+    stderr  : '',
+     /**
+     * @property result {Number} execution result.
+     */
+    result: 0,
+    /**
+     * @property pid {Number} pid of child process (of false if it's not running)
+     */
+    pid : false,
+    
+   
+    
+    /**
+     * @property in_ch {GLib.IOChannel} input io channel
+     */
+    in_ch : false,
+    /**
+     * @property out_ch {GLib.IOChannel} output io channel
+     */
+    out_ch : false,
+    /**
+     * @property err_ch {GLib.IOChannel} stderr io channel
+     */
+    err_ch : false,
+    
+    /**
+     * 
+     * @method run
+     * Run the configured command.
+     * 
+     */
+    
+    
+    run : function()
+    {
+        
+        var _this = this;
+        
+        var err_src = false;
+        var out_src = false;
+        var ctx = false; 
+        var ret = {};
+        
+        if (this.debug) {
+            print("spawn : " + this.args.join(" "));
+        }
+        
+        GLib.spawn_async_with_pipes(this.cwd, this.args, this.env, 
+            GLib.SpawnFlags.DO_NOT_REAP_CHILD + GLib.SpawnFlags.SEARCH_PATH , 
+            null, null, ret);
+            
+        this.pid = ret.child_pid;
+        
+        if (this.debug) {
+            print("PID: " + this.pid);
+        }
+        
+        function tidyup()
+        {
+            if (_this.pid) {
+                GLib.spawn_close_pid(_this.pid); // hopefully kills it..
+                _this.pid = false;
+            }
+            if (_this.in_ch)  _this.in_ch.close();
+            if (_this.out_ch)  _this.out_ch.close();
+            if (_this.err_ch)  _this.err_ch.close();
+            // blank out channels
+            _this.in_ch = false;
+            _this.err_ch = false;
+            _this.out_ch = false;
+            // rmeove listeners !! important otherwise we kill the CPU
+            if (err_src !== false) GLib.source_remove(err_src);
+            if (out_src !== false) GLib.source_remove(out_src);
+            err_src = false;
+            out_src = false;
+            
+        }
+        
+        
+        
+        GLib.child_watch_add(GLib.PRIORITY_DEFAULT, this.pid, function(pid, result) {
+            _this.result = result;
+            if (_this.debug) {
+                print("result: " + result);
+            }
+            _this.read(_this.out_ch);
+            _this.read(_this.err_ch);
+            
+            GLib.spawn_close_pid(_this.pid);
+            _this.pid = false;
+            if (ctx) {
+                ctx.quit();
+            }
+            tidyup();
+            if (_this.listeners.finish) {
+                _this.listeners.finish.call(this, _this.result);
+            }
+        });
+        
+        
+        this.in_ch = GLib.io_channel_unix_new(ret.standard_input);
+        this.out_ch = GLib.io_channel_unix_new(ret.standard_output);
+        this.err_ch = GLib.io_channel_unix_new(ret.standard_error);
+       
+        // make everything non-blocking!
+        this.in_ch.set_flags (GLib.IOFlags.NONBLOCK);
+        this.out_ch.set_flags (GLib.IOFlags.NONBLOCK);
+        this.err_ch.set_flags (GLib.IOFlags.NONBLOCK);
+
+      
+        // add handlers for output and stderr.
+        out_src= GLib.io_add_watch(this.out_ch, GLib.PRIORITY_DEFAULT, 
+            GLib.IOCondition.OUT + GLib.IOCondition.IN  + GLib.IOCondition.PRI, function()
+        {
+            _this.read(_this.out_ch);
+            
+        });
+        err_src= GLib.io_add_watch(this.err_ch, GLib.PRIORITY_DEFAULT, 
+            GLib.IOCondition.ERR + GLib.IOCondition.IN + GLib.IOCondition.PRI + GLib.IOCondition.OUT, 
+            function()
+        {
+            _this.read(_this.err_ch);
+             
+        });
+        
+      
+        
+        // call input.. 
+        if (this.pid !== false) {
+            // child can exit before we get this far..
+            if (this.listeners.input) {
+                try {
+                    this.write(this.listeners.input.call(this));
+                } catch (e) {
+                    tidyup();
+                    throw e;
+                    
+                }
+                
+            }
+        }
+        // async - if running - return..
+        if (this.async && this.pid) {
+            return this;
+        }
+        
+        
+        // start mainloop if not async..
+        
+        if (this.pid !== false) {
+            if (this.debug) {
+                print("starting main loop");
+            }
+            ctx = new GLib.MainLoop.c_new (null, false);
+            ctx.run(false); // wait fore exit?
+            
+        } else {
+            tidyup(); // tidyup get's called in main loop. 
+        }
+        
+        if (this.exceptions && this.result != 0) {
+            this.toString = function() { return this.stderr; };
+            throw this; // we throw self...
+        }
+        
+        // finally throw, or return self..
+        
+        return this;
+    
+    },
+    /**
+     * write to stdin of process
+     * @arg str {String} string to write to stdin of process
+     * @returns GLib.IOStatus (0 == error, 1= NORMAL)
+     */
+    write : function(str) // write a line to 
+    {
+        if (!this.in_ch) {
+            return 0; // input is closed
+        }
+        var ret = {};
+        var res = this.in_ch.write_chars(str, str.length);
+        if (res != GLib.IOStatus.NORMAL) {
+            throw "Write failed";
+        }
+        return ret.bytes_written;
+        
+    },
+    
+    /**
+     * read from pipe and call appropriate listerner and add to output or stderr string.
+     * @arg giochannel to read from.
+     * @returns none
+     */
+    read: function(ch) 
+    {
+        var prop = ch == this.out_ch ? 'output' : 'stderr';
+        var _this = this;
+        while (true) {
+            var x = new GLib.String();
+            var status = ch.read_line_string( x);
+            switch(status) {
+                case GLib.IOStatus.NORMAL:
+                    //write(fn, x.str);
+                    if (this.listeners[prop]) {
+                        this.listeners[prop].call(this, x.str);
+                    }
+                    _this[prop] += x.str;
+                    if (_this.debug) {
+                        print(prop + ':' + x.str);
+                    }
+                   continue;
+                case GLib.IOStatus.AGAIN:   
+                    break;
+                case GLib.IOStatus.ERROR:    
+                case GLib.IOStatus.EOF:   
+                   break;
+                
+            }
+            break;
+        }
+    }
+    
+};
+/**
+ * @function run 
+ * 
+ * simple run a process - returns result, or throws stderr result...
+ * @param cfg {Object}  see spawn
+ * @return {string} stdout output.
+ */
+function run(cfg) {
+    cfg.exceptions = true;
+    cfg.async = false;
+    var s = new Spawn(cfg);
+    var ret = s.run();
+    return s.output;
+}
+
+// test
+
+
+//Seed.print(run({
+//    args: ['ls', '/tmp'],
+//    //debug : true
+//}));
+
+     
\ No newline at end of file
diff --git a/StatusIcon.js b/StatusIcon.js
new file mode 100644 (file)
index 0000000..5f363a1
--- /dev/null
@@ -0,0 +1,232 @@
+//<script type="text/javascript">
+
+
+/**
+ * Status icon and menu for component of gitlive.
+ * 
+ * Implements XObject - however we want to control initialization.
+ * 
+ * 
+ * 
+ * Currently only does a few things
+ * a) Quit
+ * 
+ * b) Pause!??!
+ */
+var Gtk      = imports.gi.Gtk;
+var Gdk      = imports.gi.Gdk;
+var Gio      = imports.gi.Gio;
+var GLib     = imports.gi.GLib;
+var Notify   = imports.gi.Notify;
+
+var Git = imports.Git;
+var XObject = imports.XObject.XObject;
+
+//var gitlive = imports.gitlive;
+
+var StatusIcon  = new XObject({
+    
+    paused : false, // on!
+    xtype : Gtk.StatusIcon,
+    stock : Gtk.STOCK_MEDIA_PLAY,
+    tooltip_text : 'GitLive',
+    listeners : {
+        //'popup-menu' : function( w, event, event_time) {
+        'activate' : function( w, event, event_time) {
+            print(Array.prototype.slice.call(arguments).join(','));
+            
+            menu = this.get('menu');
+            
+            menu.el.show_all();
+            
+            this.get(!this.paused ? 'resume' : 'pause' ).el.hide();
+            
+            menu.el.popup(null, null,Gtk.StatusIcon.position_menu , this.el , 1, Gtk.get_current_event_time());
+            //menu.el.popup(null, null,null, null, 1, Gtk.get_current_event_time());
+            
+            return;
+            
+            var g = { };
+            var a = new Gdk.Rectangle();
+            //  needs direction=inout setting in gir to work (in bugzilla @present)
+            this.el.get_geometry(g,a,null);
+             
+            // should check to see if @ top or bottom I guess..
+            menu.el.get_toplevel().move(a.x, a.y +a.height);
+             
+        }
+    },
+    items : [
+       {
+            xtype: Gtk.Menu,
+            id : 'menu',
+            pack: false,
+            items : [
+                {
+                    init : function() {
+                        this.el = new Gtk.ImageMenuItem.from_stock(Gtk.STOCK_MEDIA_PAUSE);
+                        XObject.prototype.init.call(this);
+                    },
+                    label: 'Pause Commits',
+                   
+                    always_show_image : true,
+                    accel_group : null,
+                    id : 'pause',
+                    //label: 'Pause',
+                    pack:  'append',
+                    listeners : {
+                        activate : function () {
+                            this.parent.parent.paused = true;
+                            imports.gitlive.monitor.stop();
+                           // this.el.label  = status ? 'Resume' : 'Pause';
+                            this.parent.parent.el.set_from_stock( Gtk.STOCK_MEDIA_PAUSE );
+                            
+                        }
+                    }
+                },
+                
+                {
+                    init : function() {
+                        this.el = new Gtk.ImageMenuItem.from_stock(Gtk.STOCK_MEDIA_PLAY);
+                        XObject.prototype.init.call(this);
+                    },
+                    label: 'Resume Commits',
+                    always_show_image : true,
+                    accel_group : null,
+                    id : 'resume',
+                    //label: 'Pause',
+                    pack:  'append',
+                    listeners : {
+                        activate : function () {
+                            this.parent.parent.paused = false;
+                            imports.gitlive.monitor.start();
+                            //var status = this.el.label == 'Pause' ? 1 : 0
+                           // this.el.label  = status ? 'Resume' : 'Pause';
+                            this.parent.parent.el.set_from_stock(   Gtk.STOCK_MEDIA_PLAY);
+                            
+                        }
+                    }
+                },
+                
+                {
+                    init : function() {
+                        this.el = new Gtk.ImageMenuItem.from_stock(Gtk.STOCK_RELOAD);
+                        XObject.prototype.init.call(this);
+                    },
+                    label: 'Pull (Refresh) All',
+                    always_show_image : true,
+                    accel_group : null,
+                    //label: 'Pause',
+                    pack:  'append',
+                    listeners : {
+                        activate : function () {
+                            imports.gitlive.monitor.stop();
+                            
+                            var f = Gio.file_new_for_path(imports.gitlive.gitlive);
+                            var file_enum = f.enumerate_children(
+                                Gio.FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, Gio.FileQueryInfoFlags.NONE, null);
+
+                            var next_file = null;
+                            
+                            while ((next_file = file_enum.next_file(null)) != null) {
+                                
+                                var fn = imports.gitlive.gitlive + '/' + next_file.get_display_name();
+                                if (! GLib.file_test(fn + '/.git', GLib.FileTest.IS_DIR)) {
+                                    continue;
+                                }
+                                
+                                
+                                var res = Git.run(fn,  'pull' );
+                                if (res.result * 1  == 0) {
+                                        
+                                    var notification = new Notify.Notification({
+                                        summary: "Updated " + fn,
+                                        body : res.output
+                                    });
+                                    notification.set_timeout(1000);
+                                    notification.show();
+                                    continue;
+                                }
+                                imports.gitlive.errorDialog(res.stderr);
+                                    // should also update modules ideally.
+                                
+                            }
+                            
+                                
+                            file_enum.close(null);
+
+                            
+                            imports.gitlive.monitor.start();
+                            
+                        }
+                    }
+                },
+                {
+                    init : function() {
+                        this.el = new Gtk.ImageMenuItem.from_stock(Gtk.STOCK_RELOAD);
+                        XObject.prototype.init.call(this);
+                    },
+                    label: 'Manage Clones',
+                    always_show_image : true,
+                    accel_group : null,
+                    
+                    //label: 'Pause',
+                    pack:  'append',
+                    listeners : {
+                        activate : function () {
+                             
+                            
+                        }
+                    }
+                },
+                
+                
+                
+            
+                {
+                    init : function() {
+                        this.el = new Gtk.ImageMenuItem.from_stock(Gtk.STOCK_ABOUT);
+                        XObject.prototype.init.call(this);
+                    },
+                    label: 'About GitLive',
+                    pack:  'append',
+                    listeners : {
+                        activate : function () {
+                            var msg = new Gtk.AboutDialog({
+                                program_name : "Git Live",
+                                version: '0.1',
+                                website: 'http://git.akbkhome.com',
+                                website_label: 'AK BK Consulting (git repo)',
+                                license : 'LGPL'
+                            });
+                            msg.set_authors([ "Alan Knowles <alan@akbkhome.com>" ]);
+                            msg.run();
+                            msg.destroy();
+                        }
+                    }
+                },
+                
+                {
+                    init : function() {
+                        this.el = new Gtk.ImageMenuItem.from_stock(Gtk.STOCK_QUIT);
+                        XObject.prototype.init.call(this);
+                    },
+                    label: 'Quit',
+                    pack:  'append',
+                    listeners : {
+                        activate : function () {
+                            Seed.quit();
+                        }
+                    }
+                }
+                
+                
+            ]
+        }
+    ]
+    
+});
+
+
diff --git a/sqlite3 b/sqlite3
new file mode 100644 (file)
index 0000000..793eb07
--- /dev/null
+++ b/sqlite3
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<!-- This file was automatically generated from C sources - DO NOT EDIT!
+To affect the contents of this file, edit the original C definitions,
+and/or use gtk-doc annotations.  -->
+<repository version="1.0"
+            xmlns="http://www.gtk.org/introspection/core/1.0"
+            xmlns:c="http://www.gtk.org/introspection/c/1.0"
+            xmlns:glib="http://www.gtk.org/introspection/glib/1.0">
+  <namespace name="sqlite3"
+             version="1.0"
+             shared-library="libsqlite3.so.0"
+             c:prefix="sqlite3">
+    <callback name="callback" c:type="sqlite3_callback" doc="Test docs">
+      <return-value transfer-ownership="none">
+        <type name="int" c:type="int"/>
+      </return-value>
+      <parameters>
+        <parameter name="user_data" transfer-ownership="none" closure="0">
+          <type name="any" c:type="void*"/>
+        </parameter>
+        <parameter name="connection" transfer-ownership="none">
+          <type name="int" c:type="int"/>
+        </parameter>
+        <parameter name="data1" transfer-ownership="none">
+          <array c:type="char**">
+            <type name="utf8"/>
+          </array>
+        </parameter>
+        <parameter name="data2" transfer-ownership="none">
+          <array c:type="char**">
+            <type name="utf8"/>
+          </array>
+        </parameter>
+      </parameters>
+    </callback>
+  </namespace>
+</repository>