--- /dev/null
+<?xml version="1.0"?>
+<anjuta>
+ <plugin name="Git" mandatory="no">
+ <require group="Anjuta Plugin"
+ attribute="Location"
+ value="anjuta-git:Git"/>
+ </plugin>
+</anjuta>
--- /dev/null
+[Anjuta]
+Geometry=976x744+448+143
+
+[Document Manager]
+bookmarks=<?xml version="1.0" encoding="UTF-8"?>\n<bookmarks/>\n
+
+[Execution]
+Run in terminal=2
+Working directories=../../.
+
+[Build]
+Configuration list=1:Default:%%%1:Debug:Debug%%%1:Profiling:Profiling%%%1:Optimized:Optimized
+Selected Configuration=Default
+BuildArgs/Default=--enable-maintainer-mode
+BuildArgs/Debug=--enable-maintainer-mode 'CFLAGS=-g -O0' 'CXXFLAGS=-g -O0' 'JFLAGS=-g -O0' 'FFLAGS=-g -O0'
+BuildArgs/Profiling=--enable-maintainer-mode 'CFLAGS=-g -pg' 'CXXFLAGS=-g -pg' 'JFLAGS=-g -pg' 'FFLAGS=-g -pg'
+BuildArgs/Optimized=--enable-maintainer-mode 'CFLAGS=-O2' 'CXXFLAGS=-O2' 'JFLAGS=-O2' 'FFLAGS=-O2'
+
+[Debugger]
+Stop at beginning=2
--- /dev/null
+<?xml version="1.0"?>
+<dock-layout>
+
+<layout name="__default__"><dock name="__dock_1" floating="no" width="-1" height="-1" floatx="0" floaty="0" skip-taskbar="yes"><paned orientation="vertical" locked="no" iconified="no" closed="no" position="326"><paned orientation="horizontal" locked="no" iconified="no" closed="no" position="249"><notebook orientation="vertical" locked="no" iconified="no" closed="no" page="1"><item name="AnjutaFileManager" orientation="vertical" locked="no" iconified="no" closed="no"/><item name="AnjutaProjectManager" orientation="vertical" locked="no" iconified="no" closed="no"/><item name="AnjutaSymbolBrowser" orientation="horizontal" locked="no" iconified="no" closed="yes"/><item name="AnjutaSymbolDB" orientation="vertical" locked="no" iconified="no" closed="no"/><item name="AnjutaDevhelpIndex" orientation="horizontal" locked="no" iconified="no" closed="yes"/><item name="AnjutaGladeTree" orientation="horizontal" locked="no" iconified="no" closed="yes"/><item name="AnjutaGladePalette" orientation="horizontal" locked="no" iconified="no" closed="yes"/><item name="AnjutaDebuggerRegisters" orientation="horizontal" locked="no" iconified="no" closed="yes"/></notebook><paned orientation="horizontal" locked="no" iconified="no" closed="no" position="500"><paned orientation="vertical" locked="no" iconified="no" closed="no" position="200"><notebook orientation="vertical" locked="no" iconified="no" closed="yes" page="-1"/><notebook orientation="vertical" locked="no" iconified="no" closed="no" page="1"><item name="AnjutaStarter" orientation="horizontal" locked="no" iconified="no" closed="yes"/><item name="AnjutaDocumentManager" orientation="vertical" locked="no" iconified="no" closed="no"/><item name="AnjutaDevhelpDisplay" orientation="horizontal" locked="no" iconified="no" closed="yes"/><item name="AnjutaTodoPlugin" orientation="horizontal" locked="no" iconified="no" closed="yes"/><item name="AnjutaClassInheritance" orientation="horizontal" locked="no" iconified="no" closed="yes"/><item name="AnjutaSamplePlugin" orientation="horizontal" locked="no" iconified="no" closed="yes"/><item name="AnjutaGladeEditor" orientation="horizontal" locked="no" iconified="no" closed="yes"/><item name="AnjutaDebuggerMemory" orientation="horizontal" locked="no" iconified="no" closed="yes"/><item name="AnjutaSubversionLogViewer" orientation="horizontal" locked="no" iconified="no" closed="yes"/></notebook></paned><notebook orientation="vertical" locked="no" iconified="no" closed="yes" page="-1"/></paned></paned><notebook orientation="vertical" locked="no" iconified="no" closed="yes" page="-1"><item name="AnjutaTerminal" orientation="horizontal" locked="no" iconified="no" closed="yes"/><item name="AnjutaMessageView" orientation="horizontal" locked="no" iconified="no" closed="yes"/><item name="AnjutaDebuggerStack" orientation="horizontal" locked="no" iconified="no" closed="yes"/><item name="AnjutaDebuggerLocals" orientation="horizontal" locked="no" iconified="no" closed="yes"/><item name="AnjutaDebuggerWatch" orientation="vertical" locked="no" iconified="no" closed="yes"/><item name="AnjutaDebuggerBreakpoints" orientation="vertical" locked="no" iconified="no" closed="yes"/></notebook></paned></dock></layout></dock-layout>
--- /dev/null
+*.c
+*.o
+c/*.o
+Makefile
+Gitlive
+*.stamp
+*.stamp-t
+
+Makefile
+Makefile.in
+aclocal.m4
+autom4te.cache
+config.*
+configure
+depcomp
+install-sh
+libtool
+ltmain.sh
+m4/
+missing
+stamp-h?
+.deps/
+.dirstamp
+.libs/
+*.l[ao]
+*~
+compile
+fontconfig/*
+
--- /dev/null
+Gtk = imports.gi.Gtk;
+Gdk = imports.gi.Gdk;
+Pango = imports.gi.Pango;
+GLib = imports.gi.GLib;
+Gio = imports.gi.Gio;
+GObject = imports.gi.GObject;
+GtkSource = imports.gi.GtkSource;
+WebKit = imports.gi.WebKit;
+Vte = imports.gi.Vte;
+console = imports.console;
+XObject = imports.XObject.XObject;
+Branches=new XObject({
+ xtype: Gtk.Dialog,
+ listeners : {
+ destroy_event : function (self, event) {
+ this.el.hide();
+ return false;
+ },
+ response : function (self, id) {
+ // hide
+ //if (id < 1) {
+ this.el.hide();
+ return;
+ //}
+ if (typeof(this.get('bug').getValue()) != 'object') {
+ print("ERROR");
+ return;
+ }
+
+ this.el.hide();
+
+ //var val = this.get('bug').getValue();
+ // Seed.print(val);
+ }
+ },
+ ' modal' : true,
+ border_width : 3,
+ default_height : 300,
+ default_width : 500,
+ title : "Branches",
+ deletable : true,
+ modal : true,
+ show : function(c) {
+
+ if (!this.el) {
+ this.init();
+ }
+ var _this = this;
+ this.get('/branchStore').load();
+ this.el.show_all();
+
+ var run_ret = this.el.run();
+ if (run_ret < 1 ) {
+ return "DONE";
+ }
+ print("RUN RETURN : " + run_ret);
+ return "DONE";
+
+ },
+ items : [
+ {
+ xtype: Gtk.VBox,
+ pack : function(p,e) {
+ p.el.get_content_area().pack_start(e.el,true,true,0)
+ },
+ items : [
+ {
+ xtype: Gtk.HBox,
+ pack : "pack_start,false,true",
+ items : [
+ {
+ xtype: Gtk.Button,
+ listeners : {
+ clicked : function (self) {
+
+ return;
+ var RemoteEdit= imports.RemoteEdit.RemoteEdit
+ RemoteEdit.repo = Remotes.repo;
+ RemoteEdit.el.set_transient_for(Remotes.el);
+
+ var res = RemoteEdit.show();
+
+ if (res != false) {
+ Remotes.repo.remotes(res);
+ }
+
+ this.get('/remotesStore').load();
+
+
+ }
+ },
+ label : "Pull",
+ pack : "add"
+ }
+ ]
+ },
+ {
+ xtype: Gtk.ScrolledWindow,
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.set_policy (Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
+ },
+ items : [
+ {
+ xtype: Gtk.TreeView,
+ listeners : {
+ cursor_changed : function (self)
+ {
+
+ return;
+ // SEE SELECTION.CHANGED
+ if (this.el.get_selection().count_selected_rows() < 1) {
+ //nothing? - clea it?
+ return;
+ }
+ var ret = {};
+ var model = this.get('/changedFilesStore');
+
+ var s = this.el.get_selection();
+ var files = [];
+ s.selected_foreach(function(model,p,iter) {
+
+ files.push( model.get_value(iter, 0).value.get_string());
+
+ });
+ this.get('/patchview').showDiff(files);
+ //var value = ''+ ret.model.get_value(ret.iter, 1).value.get_string();
+ //print("OUT?" + value);// id..
+ // load the list in the right grid..
+
+ return true;
+
+ }
+ },
+ id : "branchView",
+ pack : "add",
+ init : function() {
+ XObject.prototype.init.call(this);
+ var description = new Pango.FontDescription.c_new();
+ description.set_size(8000);
+ this.el.modify_font(description);
+
+ this.selection = this.el.get_selection();
+ this.selection.set_mode( Gtk.SelectionMode.MULTIPLE);
+ var _this = this;
+ this.selection.signal['changed'].connect(function() {
+ _this.listeners.cursor_changed.apply(
+ _this, [ _this, '']
+ );
+ });
+ },
+ items : [
+ {
+ xtype: Gtk.ListStore,
+ id : "branchStore",
+ pack : "set_model",
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.set_column_types ( 3, [
+ GObject.TYPE_STRING, // file
+ GObject.TYPE_STRING, // added
+ GObject.TYPE_STRING, // removed
+ ] );
+ },
+ load : function(tr)
+ {
+ //this.insert(citer,iter,0);
+ this.el.clear();
+
+ var tr = Branches.repo.getBranches();
+
+
+ for(var i =0 ; i < tr.length; i++) {
+ var ret = { };
+
+ this.el.append(ret);
+
+ //print(JSON.stringify(ret,null,4));
+ var lastrev = tr[i].lastrev;
+ var remoterev = tr[i].remoterev;
+
+ var lastrev = lastrev.length ? lastrev : remoterev;
+
+ if (lastrev != remoterev) {
+ lastrev = "Out of sync: remote=" + remoterev + ", local=" + lastrev;
+ }
+
+
+
+ this.el.set_value(ret.iter, 0, '' + tr[i].name );
+ this.el.set_value(ret.iter, 1, '' + tr[i].remote );
+ this.el.set_value(ret.iter, 2, '' + lastrev );
+
+
+ }
+ }
+ },
+ {
+ xtype: Gtk.TreeViewColumn,
+ min_width : 70,
+ pack : "append_column",
+ resizable : true,
+ title : "Local",
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.add_attribute(this.items[0].el , 'markup', 0 );
+
+ },
+ items : [
+ {
+ xtype: Gtk.CellRendererText,
+ pack : "pack_start"
+ }
+ ]
+ },
+ {
+ xtype: Gtk.TreeViewColumn,
+ min_width : 70,
+ pack : "append_column",
+ resizable : true,
+ title : "Remote",
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.add_attribute(this.items[0].el , 'markup', 1 );
+
+ },
+ items : [
+ {
+ xtype: Gtk.CellRendererText,
+ pack : "pack_start"
+ }
+ ]
+ },
+ {
+ xtype: Gtk.TreeViewColumn,
+ min_width : 200,
+ pack : "append_column",
+ title : "Status",
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.add_attribute(this.items[0].el , 'markup', 2 );
+
+ },
+ items : [
+ {
+ xtype: Gtk.CellRendererText,
+ pack : "pack_start"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ xtype: Gtk.TreeView,
+ pack : false,
+ items : [
+ {
+ xtype: Gtk.ListStore,
+ pack : false
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ xtype: Gtk.Button,
+ label : "Cancel",
+ pack : "add_action_widget,0"
+ },
+ {
+ xtype: Gtk.Button,
+ id : "ok_button",
+ label : "OK",
+ pack : "add_action_widget,1"
+ }
+ ]
+});
+Branches.init();
+XObject.cache['/Branches'] = Branches;
--- /dev/null
+Gtk = imports.gi.Gtk;
+Gdk = imports.gi.Gdk;
+Pango = imports.gi.Pango;
+GLib = imports.gi.GLib;
+Gio = imports.gi.Gio;
+GObject = imports.gi.GObject;
+GtkSource = imports.gi.GtkSource;
+WebKit = imports.gi.WebKit;
+Vte = imports.gi.Vte;
+console = imports.console;
+XObject = imports.XObject.XObject;
+Clones=new XObject({
+ xtype: Gtk.Dialog,
+ listeners : {
+ destroy_event : function (self, event) {
+ print("DESTROY?!");
+ return true;
+ },
+ response : function (self, id) {
+ // hide
+ //if (id < 1) {
+ this.el.hide();
+ return;
+ //}
+ if (typeof(this.get('bug').getValue()) != 'object') {
+ print("ERROR");
+ return;
+ }
+
+ this.el.hide();
+
+ //var val = this.get('bug').getValue();
+ // Seed.print(val);
+ }
+ },
+ border_width : 3,
+ default_height : 500,
+ default_width : 600,
+ title : "Manage Clones",
+ deletable : true,
+ modal : true,
+ show : function(c) {
+
+ if (!this.el) {
+ this.init();
+ }
+ var _this = this;
+ /*[ 'xtype' ].forEach(function(k) {
+ _this.get(k).setValue(typeof(c[k]) == 'undefined' ? '' : c[k]);
+ });
+ // shouild set path..
+ */
+ this.el.set_deletable(false);
+ this.el.show_all();
+ // load clones..
+ this.get('/reposStore').load();
+
+ //this.get('/ok_button').el.set_sensitive(false);
+
+ // block until we return.
+ var run_ret = this.el.run();
+ if (run_ret < 1 ) {
+ return "DONE";
+ }
+ print("RUN RETURN : " + run_ret);
+ return "DONE";
+ //print(JSON.stringify(this.get('bug').getValue()));
+ // return this.get('bug').getValue();
+ //this.success = c.success;
+ },
+ items : [
+ {
+ xtype: Gtk.VBox,
+ id : "Clones",
+ pack : function(p,e) {
+ p.el.get_content_area().pack_start(e.el,true,true,0)
+ },
+ items : [
+ {
+ xtype: Gtk.HBox,
+ pack : "pack_start,false,true",
+ items : [
+ {
+ xtype: Gtk.Button,
+ listeners : {
+ clicked : function (self) {
+
+ var rv = this.get('/reposView');
+ var rs = this.get('/reposStore');
+ if (rv.el.get_selection().count_selected_rows() != 1) {
+ //nothing?
+ // error condition.
+ return;
+ }
+ var Remotes = imports.Remotes.Remotes;
+
+
+ var ret = {};
+ var s = rv.el.get_selection();
+ var path = '';
+ s.selected_foreach(function(model,p,iter) {
+
+ path = model.get_value(iter, 6).value.get_string();
+
+ });
+
+ var repo = false;
+ rs.repos.forEach(function(r) {
+ if (r.repopath == path) {
+ repo = r;
+
+ }
+
+ });
+ Remotes.repo = repo;
+ Remotes.el.set_transient_for(Clones.el);
+ Clones.el.set_title("Manage Clones - " + repo.repopath);
+ Remotes.show();
+ Clones.el.set_title("Manage Clones");
+
+
+
+
+
+
+
+
+
+ }
+ },
+ label : "Remotes / Clones",
+ pack : "add"
+ },
+ {
+ xtype: Gtk.Button,
+ listeners : {
+ clicked : function (self) {
+
+ var rv = this.get('/reposView');
+ var rs = this.get('/reposStore');
+ if (rv.el.get_selection().count_selected_rows() != 1) {
+ //nothing?
+ // error condition.
+ return;
+ }
+ var Branches = imports.Branches.Branches;
+
+
+ var ret = {};
+ var s = rv.el.get_selection();
+ var path = '';
+ s.selected_foreach(function(model,p,iter) {
+
+ path = model.get_value(iter, 6).value.get_string();
+
+ });
+
+ var repo = false;
+ rs.repos.forEach(function(r) {
+ if (r.repopath == path) {
+ repo = r;
+
+ }
+
+ });
+ Branches.repo = repo;
+ Branches.el.set_transient_for(Clones.el);
+ Clones.el.set_title("Manage Clones - " + repo.repopath);
+ Branches.show();
+ Clones.el.set_title("Manage Clones");
+
+
+
+
+
+
+
+
+
+ }
+ },
+ label : "Branches",
+ pack : "add"
+ },
+ {
+ xtype: Gtk.Button,
+ listeners : {
+ clicked : function (self) {
+
+ var rv = this.get('/reposView');
+ var rs = this.get('/reposStore');
+ if (rv.el.get_selection().count_selected_rows() != 1) {
+ //nothing?
+ // error condition.
+ return;
+ }
+ var Merger = imports.Merger.Merger;
+
+
+ var ret = {};
+ var s = rv.el.get_selection();
+ var path = '';
+ s.selected_foreach(function(model,p,iter) {
+
+ path = model.get_value(iter, 6).value.get_string();
+
+ });
+
+ var repo = false;
+ rs.repos.forEach(function(r) {
+ if (r.repopath == path) {
+ repo = r;
+
+ }
+
+ });
+ Merger.repo = repo;
+ Merger.el.set_transient_for(Clones.el);
+ Clones.el.set_title("Manage Clones - " + repo.repopath);
+ Merger.show();
+ Clones.el.set_title("Manage Clones");
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+ },
+ label : "Run Merger",
+ pack : "add"
+ },
+ {
+ xtype: Gtk.Button,
+ listeners : {
+ clicked : function (self) {
+
+
+
+
+
+
+ }
+ },
+ label : "Switch Branch",
+ pack : "add"
+ },
+ {
+ xtype: Gtk.Button,
+ listeners : {
+ clicked : function (self) {
+
+
+
+
+
+
+ }
+ },
+ label : "Pull",
+ pack : "add"
+ }
+ ]
+ },
+ {
+ xtype: Gtk.ScrolledWindow,
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.set_policy (Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
+ },
+ items : [
+ {
+ xtype: Gtk.TreeView,
+ listeners : {
+ cursor_changed : function (self) {
+ // SEE SELECTION.CHANGED
+
+
+ return;
+
+ if (this.el.get_selection().count_selected_rows() < 1) {
+ //nothing? - clea it?
+ return;
+ }
+ var ret = {};
+ var model = this.get('/changedFilesStore');
+
+ var s = this.el.get_selection();
+ var files = [];
+ s.selected_foreach(function(model,p,iter) {
+
+ files.push( model.get_value(iter, 0).value.get_string());
+
+ });
+ this.get('/patchview').showDiff(files);
+ //var value = ''+ ret.model.get_value(ret.iter, 1).value.get_string();
+ //print("OUT?" + value);// id..
+ // load the list in the right grid..
+
+ return true;
+
+ }
+ },
+ id : "reposView",
+ pack : "add",
+ init : function() {
+ XObject.prototype.init.call(this);
+ var description = new Pango.FontDescription.c_new();
+ description.set_size(10000);
+ this.el.modify_font(description);
+
+ this.selection = this.el.get_selection();
+ this.selection.set_mode( Gtk.SelectionMode.MULTIPLE);
+ var _this = this;
+
+
+ this.selection.signal['changed'].connect(function() {
+ _this.listeners.cursor_changed.apply(
+ _this, [ _this, '']
+ );
+ });
+ },
+ items : [
+ {
+ xtype: Gtk.ListStore,
+ id : "reposStore",
+ pack : "set_model",
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.set_column_types ( 8, [
+ GObject.TYPE_STRING, // repo
+ GObject.TYPE_STRING, // current branch
+ GObject.TYPE_STRING, // all branch
+ GObject.TYPE_STRING, // updated
+ GObject.TYPE_BOOLEAN, // auto-commit
+ GObject.TYPE_BOOLEAN, // auto-push
+ GObject.TYPE_STRING, // repopath
+ GObject.TYPE_STRING // color highighling
+ ] );
+ },
+ load : function()
+ {
+ //this.insert(citer,iter,0);
+ print("getting list");
+ this.repos = imports.Scm.Repo.Repo.list();
+ var tr= this.repos;
+ this.el.clear();
+
+ for(var i =0 ; i < tr.length; i++) {
+ var ret = { };
+
+ this.el.append(ret);
+
+ //print(JSON.stringify(ret,null,4));
+ tr[i].getBranches();
+ tr[i].getStatus();
+ var hi;
+ try {
+ //tr[i].debug=1;
+ hi = tr[i].history('/', 1, 'branch', tr[i].currentBranch.name );
+ // print(JSON.stringify(hi,null,4));
+ } catch(e) { print(e);}
+
+ this.el.set_value(ret.iter, 0, '' + tr[i].repopath.split('/').pop() );
+ this.el.set_value(ret.iter, 1, '' + tr[i].currentBranch.name );
+ this.el.set_value(ret.iter, 2, '' + tr[i].branches.map(
+ function(e) { return e.name;
+ }).join(', ')
+ );
+ this.el.set_value(ret.iter, 3, '' + (!hi ? '??' : hi[0].changed_raw));
+ this.el.set_value(ret.iter, 4, tr[i].autocommit() );
+ this.el.set_value(ret.iter, 5, tr[i].autopush() );
+ this.el.set_value(ret.iter, 6, tr[i].repopath );
+ // highlight color.
+ var cb = tr[i].currentBranch;
+ //print(JSON.stringify(cb,null,4));
+ var col = '#ffffff';
+ if (cb.lastrev != cb.remoterev) {
+ col = '#ff0000';
+ }
+ if (tr[i].hasLocalChanges) {
+ col = '#0000ff';
+ }
+ if ((cb.lastrev != cb.remoterev) && (tr[i].hasLocalChanges)) {
+ col = '#ff00ff';
+ }
+
+ this.el.set_value(ret.iter, 7, col );
+
+ }
+ },
+ pathToRepo : function(path) {
+
+ var tr= this.repos;
+
+
+ for(var i =0 ; i < tr.length; i++) {
+ if (tr[i].repopath == path) {
+ return tr[i];
+ }
+ }
+ return false;
+ }
+ },
+ {
+ xtype: Gtk.TreeViewColumn,
+ min_width : 50,
+ pack : "append_column",
+ title : "Auto Commit",
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.add_attribute(this.items[0].el , 'active', 4 );
+ this.items[0].el.set_activatable(true);
+
+ },
+ items : [
+ {
+ xtype: Gtk.CellRendererToggle,
+ listeners : {
+ toggled : function (self, path) {
+ var ret ={} ;
+ var store = this.get('/reposStore');
+ store.el.get_iter_from_string(ret, path);
+
+ var value = store.el.get_value(ret.iter,4).value.get_boolean();
+
+ //print(JSON.stringify(value));
+ store.el.set_value(ret.iter,4, !value);
+
+ var path = store.el.get_value(ret.iter, 6).value.get_string();
+ var repo = imports.Scm.Repo.Repo.get(path);
+ repo.autocommit(!value);
+
+
+
+ }
+ },
+ pack : "pack_start",
+ mode : Gtk.CellRendererMode.ACTIVATABLE
+ }
+ ]
+ },
+ {
+ xtype: Gtk.TreeViewColumn,
+ min_width : 50,
+ pack : "append_column",
+ title : "Auto Push",
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.add_attribute(this.items[0].el , 'active', 5 );
+ this.items[0].el.set_activatable(true);
+ },
+ items : [
+ {
+ xtype: Gtk.CellRendererToggle,
+ listeners : {
+ toggled : function (self, path) {
+ var ret ={} ;
+ var store = this.get('/reposStore');
+ store.el.get_iter_from_string(ret, path);
+
+ var value = store.el.get_value(ret.iter,5).value.get_boolean();
+
+ //print(JSON.stringify(value));
+ store.el.set_value(ret.iter,5, !value);
+ var path = store.el.get_value(ret.iter, 6).value.get_string();
+ var repo = imports.Scm.Repo.Repo.get(path);
+ repo.autopush(!value);
+
+ }
+ },
+ pack : "pack_start",
+ mode : Gtk.CellRendererMode.ACTIVATABLE
+ }
+ ]
+ },
+ {
+ xtype: Gtk.TreeViewColumn,
+ min_width : 200,
+ pack : "append_column",
+ resizable : true,
+ title : "Repo",
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.add_attribute(this.items[0].el , 'markup', 0 );
+
+ },
+ items : [
+ {
+ xtype: Gtk.CellRendererText,
+ pack : "pack_start"
+ }
+ ]
+ },
+ {
+ xtype: Gtk.TreeViewColumn,
+ min_width : 50,
+ pack : "append_column",
+ title : "Current Branch",
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.add_attribute(this.items[0].el , 'markup', 1 );
+ this.el.add_attribute(this.items[0].el , 'cell-background', 7 );
+
+ },
+ items : [
+ {
+ xtype: Gtk.CellRendererText,
+ pack : "pack_start"
+ }
+ ]
+ },
+ {
+ xtype: Gtk.TreeViewColumn,
+ min_width : 50,
+ pack : "append_column",
+ title : "Last updated",
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.add_attribute(this.items[0].el , 'markup', 3 );
+
+ },
+ items : [
+ {
+ xtype: Gtk.CellRendererText,
+ pack : "pack_start"
+ }
+ ]
+ },
+ {
+ xtype: Gtk.TreeViewColumn,
+ min_width : 50,
+ pack : "append_column",
+ resizable : false,
+ title : "All Branches",
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.add_attribute(this.items[0].el , 'markup', 2 );
+
+ },
+ items : [
+ {
+ xtype: Gtk.CellRendererText,
+ pack : "pack_start"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ xtype: Gtk.TreeView,
+ pack : false,
+ items : [
+ {
+ xtype: Gtk.ListStore,
+ pack : false
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ xtype: Gtk.Button,
+ id : "ok_button",
+ label : "Close",
+ pack : "add_action_widget,1"
+ }
+ ]
+});
+Clones.init();
+XObject.cache['/Clones'] = Clones;
--- /dev/null
+Gtk = imports.gi.Gtk;
+Gdk = imports.gi.Gdk;
+Pango = imports.gi.Pango;
+GLib = imports.gi.GLib;
+Gio = imports.gi.Gio;
+GObject = imports.gi.GObject;
+GtkSource = imports.gi.GtkSource;
+WebKit = imports.gi.WebKit;
+Vte = imports.gi.Vte;
+console = imports.console;
+XObject = imports.XObject.XObject;
+Commit=new XObject({
+ xtype: Gtk.Dialog,
+ listeners : {
+ destroy_event : function (self, event) {
+ this.el.hide();
+ return false;
+ },
+ response : function (self, id) {
+ // hide
+ //if (id < 1) {
+ this.el.hide();
+ return;
+ //}
+ if (typeof(this.get('bug').getValue()) != 'object') {
+ print("ERROR");
+ return;
+ }
+
+ this.el.hide();
+
+ //var val = this.get('bug').getValue();
+ // Seed.print(val);
+ }
+ },
+ ' modal' : true,
+ border_width : 3,
+ default_height : 500,
+ default_width : 800,
+ title : "Commit",
+ deletable : true,
+ modal : true,
+ show : function(c) {
+
+ if (!this.el) {
+ this.init();
+ }
+ var _this = this;
+
+
+ this.files = c.files;
+ this.release = c.release;
+ this.rev = c.rev;
+
+ this.repo = c.repo;
+
+ this.get('/commitDate').el.set_text(c.changed);
+ this.get('/commitAuthor').el.set_text(c.author);
+ this.get('/commitMsg').el.get_buffer().set_text('');
+ this.get('/commitPatch').showDiff(c.files);
+
+ this.el.show_all();
+
+ var run_ret = this.el.run();
+ if (run_ret < 1 ) {
+ return false;
+ }
+ var buf = this.get('/commitMsg').el.get_buffer();
+ var e = {};
+ var s = {};
+ buf.get_start_iter(s);
+ buf.get_end_iter(e);
+
+ var ret= {
+ date : this.get('/commitDate').el.get_text(),
+ author : this.get('/commitAuthor').el.get_text(),
+ message : buf.get_text(s.value, e.value, false)
+ };
+
+ return ret;
+
+
+
+ },
+ items : [
+ {
+ xtype: Gtk.VBox,
+ pack : function(p,e) {
+ p.el.get_content_area().pack_start(e.el,true,true,10);
+ },
+ items : [
+ {
+ xtype: Gtk.HBox,
+ pack : "pack_start,false,true,2",
+ items : [
+ {
+ xtype: Gtk.Label,
+ label : "Fixes",
+ pack : "pack_start,false,false,10",
+ width_request : 50
+ },
+ {
+ xtype: Gtk.ComboBox,
+ listeners : {
+ changed : function (self) {
+ var val = this.el.get_child().get_text();
+ print(JSON.stringify(val));
+ if (!val.length) {
+ return;
+ }
+
+ var name = this.get('/remoteName').el.get_text();
+ if (name.length) {
+ return;
+ }
+ // fill in name
+ var val = imports.Scm.Git.Repo.Repo.parseURL(val);
+ if ((typeof(val.host) != 'undefined') && val.host.length) {
+ var host = val.host;
+ // need to add github owner...
+ if (host.match(/github.com$/)) {
+ host += '.' + val.path.split('/').shift();
+ }
+
+
+ this.get('/remoteName').el.set_text(host);
+ }
+
+
+ }
+ },
+ id : "commitFixes",
+ init : function() {
+ this.el = new Gtk.ComboBox.with_entry();
+
+
+ this.model = new XObject(this.model);
+ this.model.init();
+ this.el.set_model(this.model.el);
+ this.el.set_entry_text_column (0);
+ XObject.prototype.init.call(this);
+
+ },
+ load : function(tr)
+ {
+ //this.insert(citer,iter,0);
+ this.model.el.clear();
+
+ var master = false;
+ var working = false;
+
+ for(var i =0 ; i < tr.length; i++) {
+ var ret = { };
+ this.model.el.append(ret);
+ //print(JSON.stringify(ret,null,4));
+ if (tr[i].name == 'master') {
+ master = i;
+ }
+ if (tr[i].name == 'working') {
+ working = i;
+ }
+ this.model.el.set_value(ret.iter, 0, '' + tr[i].name );
+ this.model.el.set_value(ret.iter, 1, '' + tr[i].rev );
+
+
+ }
+ if (master !== false) {
+ this.el.set_active(master);
+ }
+ if (working !== false) {
+ this.el.set_active(working);
+ }
+
+ },
+ model : {
+ xtype: Gtk.ListStore,
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.set_column_types ( 3, [
+ GObject.TYPE_STRING, // file
+ GObject.TYPE_STRING, // added
+ GObject.TYPE_STRING, // removed
+ ] );
+ }
+ }
+ }
+ ]
+ },
+ {
+ xtype: Gtk.HBox,
+ pack : "pack_start,false,true,2",
+ items : [
+ {
+ xtype: Gtk.Label,
+ label : "Date",
+ pack : "pack_start,false,false,10",
+ width_request : 50,
+ xalign : 1
+ },
+ {
+ xtype: Gtk.Entry,
+ id : "commitDate"
+ }
+ ]
+ },
+ {
+ xtype: Gtk.HBox,
+ pack : "pack_start,false,true,2",
+ items : [
+ {
+ xtype: Gtk.Label,
+ label : "Author",
+ pack : "pack_start,false,false,10",
+ width_request : 50,
+ xalign : 1
+ },
+ {
+ xtype: Gtk.Entry,
+ id : "commitAuthor"
+ }
+ ]
+ },
+ {
+ xtype: Gtk.HBox,
+ pack : "pack_start,false,false,2",
+ items : [
+ {
+ xtype: Gtk.Label,
+ label : "Message",
+ pack : "pack_start,false,false,10",
+ width_request : 50,
+ xalign : 1
+ },
+ {
+ xtype: Gtk.TextView,
+ height_request : 100,
+ id : "commitMsg",
+ pack : "add"
+ }
+ ]
+ },
+ {
+ xtype: Gtk.ScrolledWindow,
+ height_request : 200,
+ pack : "pack_end,true,true,0",
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.set_policy (Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
+ },
+ items : [
+ {
+ xtype: WebKit.WebView,
+ id : "commitPatch",
+ pack : "add",
+ clear : function() {
+
+
+
+
+ // remove..
+ var s = "document.body.textContent='';"
+
+ this.el.execute_script(s);
+
+
+
+
+
+ },
+ showDiff : function(files) {
+ this.clear();
+
+
+
+ if (Commit.release === false) {
+ return;
+ }
+
+ var diff = Commit.repo.diff(files, Commit.release, Commit.rev);
+
+ // remove..
+ var s = "var pre = document.createElement('pre'); document.body.appendChild(pre);";
+ s += "pre.textContent = " +
+ JSON.stringify(Commit.repo.lastCmd + "\n") + '+ ' +
+ JSON.stringify(diff) + ";";
+
+ this.el.execute_script(s);
+
+
+
+
+
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ xtype: Gtk.Button,
+ label : "Cancel",
+ pack : "add_action_widget,0"
+ },
+ {
+ xtype: Gtk.Button,
+ id : "ok_button",
+ label : "Add",
+ pack : "add_action_widget,1"
+ }
+ ]
+});
+Commit.init();
+XObject.cache['/Commit'] = Commit;
--- /dev/null
+/*
+ * Based on:
+ * Ext JS Library 1.1.1
+ * Copyright(c) 2006-2007, Ext JS, LLC.
+ *
+ * Originally Released Under LGPL - original licence link has changed is not relivant.
+ *
+ * Fork - LGPL
+ * <script type="text/javascript">
+ */
+
+/**
+ * @class Date
+ *
+ * The date parsing and format syntax is a subset of
+ * <a href="http://www.php.net/date">PHP's date() function</a>, and the formats that are
+ * supported will provide results equivalent to their PHP versions.
+ *
+ * Following is the list of all currently supported formats:
+ *<pre>
+Sample date:
+'Wed Jan 10 2007 15:05:01 GMT-0600 (Central Standard Time)'
+
+Format Output Description
+------ ---------- --------------------------------------------------------------
+ d 10 Day of the month, 2 digits with leading zeros
+ D Wed A textual representation of a day, three letters
+ j 10 Day of the month without leading zeros
+ l Wednesday A full textual representation of the day of the week
+ S th English ordinal day of month suffix, 2 chars (use with j)
+ w 3 Numeric representation of the day of the week
+ z 9 The julian date, or day of the year (0-365)
+ W 01 ISO-8601 2-digit week number of year, weeks starting on Monday (00-52)
+ F January A full textual representation of the month
+ m 01 Numeric representation of a month, with leading zeros
+ M Jan Month name abbreviation, three letters
+ n 1 Numeric representation of a month, without leading zeros
+ t 31 Number of days in the given month
+ L 0 Whether it's a leap year (1 if it is a leap year, else 0)
+ Y 2007 A full numeric representation of a year, 4 digits
+ y 07 A two digit representation of a year
+ a pm Lowercase Ante meridiem and Post meridiem
+ A PM Uppercase Ante meridiem and Post meridiem
+ g 3 12-hour format of an hour without leading zeros
+ G 15 24-hour format of an hour without leading zeros
+ h 03 12-hour format of an hour with leading zeros
+ H 15 24-hour format of an hour with leading zeros
+ i 05 Minutes with leading zeros
+ s 01 Seconds, with leading zeros
+ O -0600 Difference to Greenwich time (GMT) in hours
+ P -06:00 Difference to Greenwich time (GMT) with colon between hours and minutes
+ T CST Timezone setting of the machine running the code
+ Z -21600 Timezone offset in seconds (negative if west of UTC, positive if east)
+</pre>
+ *
+ * Example usage (note that you must escape format specifiers with '\\' to render them as character literals):
+ * <pre><code>
+var dt = new Date('1/10/2007 03:05:01 PM GMT-0600');
+document.write(dt.format('Y-m-d')); //2007-01-10
+document.write(dt.format('F j, Y, g:i a')); //January 10, 2007, 3:05 pm
+document.write(dt.format('l, \\t\\he dS of F Y h:i:s A')); //Wednesday, the 10th of January 2007 03:05:01 PM
+ </code></pre>
+ *
+ * Here are some standard date/time patterns that you might find helpful. They
+ * are not part of the source of Date.js, but to use them you can simply copy this
+ * block of code into any script that is included after Date.js and they will also become
+ * globally available on the Date object. Feel free to add or remove patterns as needed in your code.
+ * <pre><code>
+Date.patterns = {
+ ISO8601Long:"Y-m-d H:i:s",
+ ISO8601Short:"Y-m-d",
+ ShortDate: "n/j/Y",
+ LongDate: "l, F d, Y",
+ FullDateTime: "l, F d, Y g:i:s A",
+ MonthDay: "F d",
+ ShortTime: "g:i A",
+ LongTime: "g:i:s A",
+ SortableDateTime: "Y-m-d\\TH:i:s",
+ UniversalSortableDateTime: "Y-m-d H:i:sO",
+ YearMonth: "F, Y"
+};
+</code></pre>
+ *
+ * Example usage:
+ * <pre><code>
+var dt = new Date();
+document.write(dt.format(Date.patterns.ShortDate));
+ </code></pre>
+ */
+
+/*
+ * Most of the date-formatting functions below are the excellent work of Baron Schwartz.
+ * They generate precompiled functions from date formats instead of parsing and
+ * processing the pattern every time you format a date. These functions are available
+ * on every Date object (any javascript function).
+ *
+ * The original article and download are here:
+ * http://www.xaprb.com/blog/2005/12/12/javascript-closures-for-runtime-efficiency/
+ *
+ */
+
+
+ // was in core
+/**
+ Returns the number of milliseconds between this date and date
+ @param {Date} date (optional) Defaults to now
+ @return {Number} The diff in milliseconds
+ @member Date getElapsed
+ */
+Date.prototype.getElapsed = function(date) {
+ return Math.abs((date || new Date()).getTime()-this.getTime());
+};
+// was in date file..
+
+
+// private
+Date.parseFunctions = {count:0};
+// private
+Date.parseRegexes = [];
+// private
+Date.formatFunctions = {count:0};
+
+
+
+Date.escape = function(string) {
+ return string.replace(/('|\\)/g, "\\$1");
+};
+
+
+Date.leftPad = function (val, size, ch) {
+ var result = new String(val);
+ if(ch === null || ch === undefined || ch === '') {
+ ch = " ";
+ }
+ while (result.length < size) {
+ result = ch + result;
+ }
+ return result;
+}
+
+
+
+
+
+
+
+
+
+
+
+// private
+Date.prototype.dateFormat = function(format) {
+ if (Date.formatFunctions[format] == null) {
+ Date.createNewFormat(format);
+ }
+ var func = Date.formatFunctions[format];
+ return this[func]();
+};
+
+
+/**
+ * Formats a date given the supplied format string
+ * @param {String} format The format string
+ * @return {String} The formatted date
+ * @method
+ */
+Date.prototype.format = Date.prototype.dateFormat;
+
+// private
+Date.createNewFormat = function(format) {
+ var funcName = "format" + Date.formatFunctions.count++;
+ Date.formatFunctions[format] = funcName;
+ var code = "Date.prototype." + funcName + " = function(){return ";
+ var special = false;
+ var ch = '';
+ for (var i = 0; i < format.length; ++i) {
+ ch = format.charAt(i);
+ if (!special && ch == "\\") {
+ special = true;
+ }
+ else if (special) {
+ special = false;
+ code += "'" + Date.escape(ch) + "' + ";
+ }
+ else {
+ code += Date.getFormatCode(ch);
+ }
+ }
+ /** eval:var:zzzzzzzzzzzzz */
+ eval(code.substring(0, code.length - 3) + ";}");
+};
+
+// private
+Date.getFormatCode = function(character) {
+ switch (character) {
+ case "d":
+ return "Date.leftPad(this.getDate(), 2, '0') + ";
+ case "D":
+ return "Date.dayNames[this.getDay()].substring(0, 3) + ";
+ case "j":
+ return "this.getDate() + ";
+ case "l":
+ return "Date.dayNames[this.getDay()] + ";
+ case "S":
+ return "this.getSuffix() + ";
+ case "w":
+ return "this.getDay() + ";
+ case "z":
+ return "this.getDayOfYear() + ";
+ case "W":
+ return "this.getWeekOfYear() + ";
+ case "F":
+ return "Date.monthNames[this.getMonth()] + ";
+ case "m":
+ return "Date.leftPad(this.getMonth() + 1, 2, '0') + ";
+ case "M":
+ return "Date.monthNames[this.getMonth()].substring(0, 3) + ";
+ case "n":
+ return "(this.getMonth() + 1) + ";
+ case "t":
+ return "this.getDaysInMonth() + ";
+ case "L":
+ return "(this.isLeapYear() ? 1 : 0) + ";
+ case "Y":
+ return "this.getFullYear() + ";
+ case "y":
+ return "('' + this.getFullYear()).substring(2, 4) + ";
+ case "a":
+ return "(this.getHours() < 12 ? 'am' : 'pm') + ";
+ case "A":
+ return "(this.getHours() < 12 ? 'AM' : 'PM') + ";
+ case "g":
+ return "((this.getHours() % 12) ? this.getHours() % 12 : 12) + ";
+ case "G":
+ return "this.getHours() + ";
+ case "h":
+ return "Date.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0') + ";
+ case "H":
+ return "Date.leftPad(this.getHours(), 2, '0') + ";
+ case "i":
+ return "Date.leftPad(this.getMinutes(), 2, '0') + ";
+ case "s":
+ return "Date.leftPad(this.getSeconds(), 2, '0') + ";
+ case "O":
+ return "this.getGMTOffset() + ";
+ case "P":
+ return "this.getGMTColonOffset() + ";
+ case "T":
+ return "this.getTimezone() + ";
+ case "Z":
+ return "(this.getTimezoneOffset() * -60) + ";
+ default:
+ return "'" + Date.escape(character) + "' + ";
+ }
+};
+
+/**
+ * Parses the passed string using the specified format. Note that this function expects dates in normal calendar
+ * format, meaning that months are 1-based (1 = January) and not zero-based like in JavaScript dates. Any part of
+ * the date format that is not specified will default to the current date value for that part. Time parts can also
+ * be specified, but default to 0. Keep in mind that the input date string must precisely match the specified format
+ * string or the parse operation will fail.
+ * Example Usage:
+<pre><code>
+//dt = Fri May 25 2007 (current date)
+var dt = new Date();
+
+//dt = Thu May 25 2006 (today's month/day in 2006)
+dt = Date.parseDate("2006", "Y");
+
+//dt = Sun Jan 15 2006 (all date parts specified)
+dt = Date.parseDate("2006-1-15", "Y-m-d");
+
+//dt = Sun Jan 15 2006 15:20:01 GMT-0600 (CST)
+dt = Date.parseDate("2006-1-15 3:20:01 PM", "Y-m-d h:i:s A" );
+</code></pre>
+ * @param {String} input The unparsed date as a string
+ * @param {String} format The format the date is in
+ * @return {Date} The parsed date
+ * @static
+ */
+Date.parseDate = function(input, format) {
+ if (Date.parseFunctions[format] == null) {
+ Date.createParser(format);
+ }
+ var func = Date.parseFunctions[format];
+ return Date[func](input);
+};
+/**
+ * @private
+ */
+Date.createParser = function(format) {
+ var funcName = "parse" + Date.parseFunctions.count++;
+ var regexNum = Date.parseRegexes.length;
+ var currentGroup = 1;
+ Date.parseFunctions[format] = funcName;
+
+ var code = "Date." + funcName + " = function(input){\n"
+ + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1, o, z, v;\n"
+ + "var d = new Date();\n"
+ + "y = d.getFullYear();\n"
+ + "m = d.getMonth();\n"
+ + "d = d.getDate();\n"
+ + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n"
+ + "if (results && results.length > 0) {";
+ var regex = "";
+
+ var special = false;
+ var ch = '';
+ for (var i = 0; i < format.length; ++i) {
+ ch = format.charAt(i);
+ if (!special && ch == "\\") {
+ special = true;
+ }
+ else if (special) {
+ special = false;
+ regex += Date.escape(ch);
+ }
+ else {
+ var obj = Date.formatCodeToRegex(ch, currentGroup);
+ currentGroup += obj.g;
+ regex += obj.s;
+ if (obj.g && obj.c) {
+ code += obj.c;
+ }
+ }
+ }
+
+ code += "if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n"
+ + "{v = new Date(y, m, d, h, i, s);}\n"
+ + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n"
+ + "{v = new Date(y, m, d, h, i);}\n"
+ + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0)\n"
+ + "{v = new Date(y, m, d, h);}\n"
+ + "else if (y >= 0 && m >= 0 && d > 0)\n"
+ + "{v = new Date(y, m, d);}\n"
+ + "else if (y >= 0 && m >= 0)\n"
+ + "{v = new Date(y, m);}\n"
+ + "else if (y >= 0)\n"
+ + "{v = new Date(y);}\n"
+ + "}return (v && (z || o))?\n" // favour UTC offset over GMT offset
+ + " ((z)? v.add(Date.SECOND, (v.getTimezoneOffset() * 60) + (z*1)) :\n" // reset to UTC, then add offset
+ + " v.add(Date.HOUR, (v.getGMTOffset() / 100) + (o / -100))) : v\n" // reset to GMT, then add offset
+ + ";}";
+
+ Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$");
+ /** eval:var:zzzzzzzzzzzzz */
+ eval(code);
+};
+
+// private
+Date.formatCodeToRegex = function(character, currentGroup) {
+ switch (character) {
+ case "D":
+ return {g:0,
+ c:null,
+ s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"};
+ case "j":
+ return {g:1,
+ c:"d = parseInt(results[" + currentGroup + "], 10);\n",
+ s:"(\\d{1,2})"}; // day of month without leading zeroes
+ case "d":
+ return {g:1,
+ c:"d = parseInt(results[" + currentGroup + "], 10);\n",
+ s:"(\\d{2})"}; // day of month with leading zeroes
+ case "l":
+ return {g:0,
+ c:null,
+ s:"(?:" + Date.dayNames.join("|") + ")"};
+ case "S":
+ return {g:0,
+ c:null,
+ s:"(?:st|nd|rd|th)"};
+ case "w":
+ return {g:0,
+ c:null,
+ s:"\\d"};
+ case "z":
+ return {g:0,
+ c:null,
+ s:"(?:\\d{1,3})"};
+ case "W":
+ return {g:0,
+ c:null,
+ s:"(?:\\d{2})"};
+ case "F":
+ return {g:1,
+ c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "].substring(0, 3)], 10);\n",
+ s:"(" + Date.monthNames.join("|") + ")"};
+ case "M":
+ return {g:1,
+ c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "]], 10);\n",
+ s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"};
+ case "n":
+ return {g:1,
+ c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
+ s:"(\\d{1,2})"}; // Numeric representation of a month, without leading zeros
+ case "m":
+ return {g:1,
+ c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
+ s:"(\\d{2})"}; // Numeric representation of a month, with leading zeros
+ case "t":
+ return {g:0,
+ c:null,
+ s:"\\d{1,2}"};
+ case "L":
+ return {g:0,
+ c:null,
+ s:"(?:1|0)"};
+ case "Y":
+ return {g:1,
+ c:"y = parseInt(results[" + currentGroup + "], 10);\n",
+ s:"(\\d{4})"};
+ case "y":
+ return {g:1,
+ c:"var ty = parseInt(results[" + currentGroup + "], 10);\n"
+ + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
+ s:"(\\d{1,2})"};
+ case "a":
+ return {g:1,
+ c:"if (results[" + currentGroup + "] == 'am') {\n"
+ + "if (h == 12) { h = 0; }\n"
+ + "} else { if (h < 12) { h += 12; }}",
+ s:"(am|pm)"};
+ case "A":
+ return {g:1,
+ c:"if (results[" + currentGroup + "] == 'AM') {\n"
+ + "if (h == 12) { h = 0; }\n"
+ + "} else { if (h < 12) { h += 12; }}",
+ s:"(AM|PM)"};
+ case "g":
+ case "G":
+ return {g:1,
+ c:"h = parseInt(results[" + currentGroup + "], 10);\n",
+ s:"(\\d{1,2})"}; // 12/24-hr format format of an hour without leading zeroes
+ case "h":
+ case "H":
+ return {g:1,
+ c:"h = parseInt(results[" + currentGroup + "], 10);\n",
+ s:"(\\d{2})"}; // 12/24-hr format format of an hour with leading zeroes
+ case "i":
+ return {g:1,
+ c:"i = parseInt(results[" + currentGroup + "], 10);\n",
+ s:"(\\d{2})"};
+ case "s":
+ return {g:1,
+ c:"s = parseInt(results[" + currentGroup + "], 10);\n",
+ s:"(\\d{2})"};
+ case "O":
+ return {g:1,
+ c:[
+ "o = results[", currentGroup, "];\n",
+ "var sn = o.substring(0,1);\n", // get + / - sign
+ "var hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60);\n", // get hours (performs minutes-to-hour conversion also)
+ "var mn = o.substring(3,5) % 60;\n", // get minutes
+ "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n", // -12hrs <= GMT offset <= 14hrs
+ " (sn + Date.leftPad(hr, 2, 0) + Date.leftPad(mn, 2, 0)) : null;\n"
+ ].join(""),
+ s:"([+\-]\\d{4})"};
+ case "P":
+ return {g:1,
+ c:[
+ "o = results[", currentGroup, "];\n",
+ "var sn = o.substring(0,1);\n",
+ "var hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60);\n",
+ "var mn = o.substring(4,6) % 60;\n",
+ "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n",
+ " (sn + Date.leftPad(hr, 2, 0) + Date.leftPad(mn, 2, 0)) : null;\n"
+ ].join(""),
+ s:"([+\-]\\d{4})"};
+ case "T":
+ return {g:0,
+ c:null,
+ s:"[A-Z]{1,4}"}; // timezone abbrev. may be between 1 - 4 chars
+ case "Z":
+ return {g:1,
+ c:"z = results[" + currentGroup + "];\n" // -43200 <= UTC offset <= 50400
+ + "z = (-43200 <= z*1 && z*1 <= 50400)? z : null;\n",
+ s:"([+\-]?\\d{1,5})"}; // leading '+' sign is optional for UTC offset
+ default:
+ return {g:0,
+ c:null,
+ s:Date.escape(character)};
+ }
+};
+
+/**
+ * Get the timezone abbreviation of the current date (equivalent to the format specifier 'T').
+ * @return {String} The abbreviated timezone name (e.g. 'CST')
+ */
+Date.prototype.getTimezone = function() {
+ return this.toString().replace(/^.*? ([A-Z]{1,4})[\-+][0-9]{4} .*$/, "$1");
+};
+
+/**
+ * Get the offset from GMT of the current date (equivalent to the format specifier 'O').
+ * @return {String} The 4-character offset string prefixed with + or - (e.g. '-0600')
+ */
+Date.prototype.getGMTOffset = function() {
+ return (this.getTimezoneOffset() > 0 ? "-" : "+")
+ + Date.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
+ + Date.leftPad(this.getTimezoneOffset() % 60, 2, "0");
+};
+
+/**
+ * Get the offset from GMT of the current date (equivalent to the format specifier 'P').
+ * @return {String} 2-characters representing hours and 2-characters representing minutes
+ * seperated by a colon and prefixed with + or - (e.g. '-06:00')
+ */
+Date.prototype.getGMTColonOffset = function() {
+ return (this.getTimezoneOffset() > 0 ? "-" : "+")
+ + Date.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
+ + ":"
+ + Date.leftPad(this.getTimezoneOffset() %60, 2, "0");
+}
+
+/**
+ * Get the numeric day number of the year, adjusted for leap year.
+ * @return {Number} 0 through 364 (365 in leap years)
+ */
+Date.prototype.getDayOfYear = function() {
+ var num = 0;
+ Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
+ for (var i = 0; i < this.getMonth(); ++i) {
+ num += Date.daysInMonth[i];
+ }
+ return num + this.getDate() - 1;
+};
+
+/**
+ * Get the string representation of the numeric week number of the year
+ * (equivalent to the format specifier 'W').
+ * @return {String} '00' through '52'
+ */
+Date.prototype.getWeekOfYear = function() {
+ // Skip to Thursday of this week
+ var now = this.getDayOfYear() + (4 - this.getDay());
+ // Find the first Thursday of the year
+ var jan1 = new Date(this.getFullYear(), 0, 1);
+ var then = (7 - jan1.getDay() + 4);
+ return Date.leftPad(((now - then) / 7) + 1, 2, "0");
+};
+
+/**
+ * Whether or not the current date is in a leap year.
+ * @return {Boolean} True if the current date is in a leap year, else false
+ */
+Date.prototype.isLeapYear = function() {
+ var year = this.getFullYear();
+ return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
+};
+
+/**
+ * Get the first day of the current month, adjusted for leap year. The returned value
+ * is the numeric day index within the week (0-6) which can be used in conjunction with
+ * the {@link #monthNames} array to retrieve the textual day name.
+ * Example:
+ *<pre><code>
+var dt = new Date('1/10/2007');
+document.write(Date.dayNames[dt.getFirstDayOfMonth()]); //output: 'Monday'
+</code></pre>
+ * @return {Number} The day number (0-6)
+ */
+Date.prototype.getFirstDayOfMonth = function() {
+ var day = (this.getDay() - (this.getDate() - 1)) % 7;
+ return (day < 0) ? (day + 7) : day;
+};
+
+/**
+ * Get the last day of the current month, adjusted for leap year. The returned value
+ * is the numeric day index within the week (0-6) which can be used in conjunction with
+ * the {@link #monthNames} array to retrieve the textual day name.
+ * Example:
+ *<pre><code>
+var dt = new Date('1/10/2007');
+document.write(Date.dayNames[dt.getLastDayOfMonth()]); //output: 'Wednesday'
+</code></pre>
+ * @return {Number} The day number (0-6)
+ */
+Date.prototype.getLastDayOfMonth = function() {
+ var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
+ return (day < 0) ? (day + 7) : day;
+};
+
+
+/**
+ * Get the first date of this date's month
+ * @return {Date}
+ */
+Date.prototype.getFirstDateOfMonth = function() {
+ return new Date(this.getFullYear(), this.getMonth(), 1);
+};
+
+/**
+ * Get the last date of this date's month
+ * @return {Date}
+ */
+Date.prototype.getLastDateOfMonth = function() {
+ return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
+};
+/**
+ * Get the number of days in the current month, adjusted for leap year.
+ * @return {Number} The number of days in the month
+ */
+Date.prototype.getDaysInMonth = function() {
+ Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
+ return Date.daysInMonth[this.getMonth()];
+};
+
+/**
+ * Get the English ordinal suffix of the current day (equivalent to the format specifier 'S').
+ * @return {String} 'st, 'nd', 'rd' or 'th'
+ */
+Date.prototype.getSuffix = function() {
+ switch (this.getDate()) {
+ case 1:
+ case 21:
+ case 31:
+ return "st";
+ case 2:
+ case 22:
+ return "nd";
+ case 3:
+ case 23:
+ return "rd";
+ default:
+ return "th";
+ }
+};
+
+// private
+Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];
+
+/**
+ * An array of textual month names.
+ * Override these values for international dates, for example...
+ * Date.monthNames = ['JanInYourLang', 'FebInYourLang', ...];
+ * @type Array
+ * @static
+ */
+Date.monthNames =
+ ["January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"];
+
+/**
+ * An array of textual day names.
+ * Override these values for international dates, for example...
+ * Date.dayNames = ['SundayInYourLang', 'MondayInYourLang', ...];
+ * @type Array
+ * @static
+ */
+Date.dayNames =
+ ["Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"];
+
+// private
+Date.y2kYear = 50;
+// private
+Date.monthNumbers = {
+ Jan:0,
+ Feb:1,
+ Mar:2,
+ Apr:3,
+ May:4,
+ Jun:5,
+ Jul:6,
+ Aug:7,
+ Sep:8,
+ Oct:9,
+ Nov:10,
+ Dec:11};
+
+/**
+ * Creates and returns a new Date instance with the exact same date value as the called instance.
+ * Dates are copied and passed by reference, so if a copied date variable is modified later, the original
+ * variable will also be changed. When the intention is to create a new variable that will not
+ * modify the original instance, you should create a clone.
+ *
+ * Example of correctly cloning a date:
+ * <pre><code>
+//wrong way:
+var orig = new Date('10/1/2006');
+var copy = orig;
+copy.setDate(5);
+document.write(orig); //returns 'Thu Oct 05 2006'!
+
+//correct way:
+var orig = new Date('10/1/2006');
+var copy = orig.clone();
+copy.setDate(5);
+document.write(orig); //returns 'Thu Oct 01 2006'
+</code></pre>
+ * @return {Date} The new Date instance
+ */
+Date.prototype.clone = function() {
+ return new Date(this.getTime());
+};
+
+/**
+ * Clears any time information from this date
+ @param {Boolean} clone true to create a clone of this date, clear the time and return it
+ @return {Date} this or the clone
+ */
+Date.prototype.clearTime = function(clone){
+ if(clone){
+ return this.clone().clearTime();
+ }
+ this.setHours(0);
+ this.setMinutes(0);
+ this.setSeconds(0);
+ this.setMilliseconds(0);
+ return this;
+};
+
+// private
+// safari setMonth is broken
+/*
+if(Roo.isSafari){
+ Date.brokenSetMonth = Date.prototype.setMonth;
+ Date.prototype.setMonth = function(num){
+ if(num <= -1){
+ var n = Math.ceil(-num);
+ var back_year = Math.ceil(n/12);
+ var month = (n % 12) ? 12 - n % 12 : 0 ;
+ this.setFullYear(this.getFullYear() - back_year);
+ return Date.brokenSetMonth.call(this, month);
+ } else {
+ return Date.brokenSetMonth.apply(this, arguments);
+ }
+ };
+}
+*/
+
+/** Date interval constant
+* @static
+* @type String */
+Date.MILLI = "ms";
+/** Date interval constant
+* @static
+* @type String */
+Date.SECOND = "s";
+/** Date interval constant
+* @static
+* @type String */
+Date.MINUTE = "mi";
+/** Date interval constant
+* @static
+* @type String */
+Date.HOUR = "h";
+/** Date interval constant
+* @static
+* @type String */
+Date.DAY = "d";
+/** Date interval constant
+* @static
+* @type String */
+Date.MONTH = "mo";
+/** Date interval constant
+* @static
+* @type String */
+Date.YEAR = "y";
+
+/**
+ * Provides a convenient method of performing basic date arithmetic. This method
+ * does not modify the Date instance being called - it creates and returns
+ * a new Date instance containing the resulting date value.
+ *
+ * Examples:
+ * <pre><code>
+//Basic usage:
+var dt = new Date('10/29/2006').add(Date.DAY, 5);
+document.write(dt); //returns 'Fri Oct 06 2006 00:00:00'
+
+//Negative values will subtract correctly:
+var dt2 = new Date('10/1/2006').add(Date.DAY, -5);
+document.write(dt2); //returns 'Tue Sep 26 2006 00:00:00'
+
+//You can even chain several calls together in one line!
+var dt3 = new Date('10/1/2006').add(Date.DAY, 5).add(Date.HOUR, 8).add(Date.MINUTE, -30);
+document.write(dt3); //returns 'Fri Oct 06 2006 07:30:00'
+ </code></pre>
+ *
+ * @param {String} interval A valid date interval enum value
+ * @param {Number} value The amount to add to the current date
+ * @return {Date} The new Date instance
+ */
+Date.prototype.add = function(interval, value){
+ var d = this.clone();
+ if (!interval || value === 0) return d;
+ switch(interval.toLowerCase()){
+ case Date.MILLI:
+ d.setMilliseconds(this.getMilliseconds() + value);
+ break;
+ case Date.SECOND:
+ d.setSeconds(this.getSeconds() + value);
+ break;
+ case Date.MINUTE:
+ d.setMinutes(this.getMinutes() + value);
+ break;
+ case Date.HOUR:
+ d.setHours(this.getHours() + value);
+ break;
+ case Date.DAY:
+ d.setDate(this.getDate() + value);
+ break;
+ case Date.MONTH:
+ var day = this.getDate();
+ if(day > 28){
+ day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
+ }
+ d.setDate(day);
+ d.setMonth(this.getMonth() + value);
+ break;
+ case Date.YEAR:
+ d.setFullYear(this.getFullYear() + value);
+ break;
+ }
+ return d;
+};
+
+
+function newDate() {
+ return new Date();
+}
\ No newline at end of file
--- /dev/null
+// <script type ="text/Javascript">
+GLib = imports.gi.GLib;
+Gio = imports.gi.Gio;
+
+
+
+/**
+* @namespace File
+*
+* Library to wrap GLib and Gio basic File related methods
+*
+* usage:
+*
+* File = import.File.File;
+*
+* var contents = File.read("/tmp/test.txt");
+*
+*
+*
+*/
+var File = {
+
+ SEPARATOR : '/',
+
+ // fixme - this needs a bitter location..
+ // they where in a string class before, but overriding String methods is not a good normally a good idea..
+
+ rtrim : function (s,toTrim) {
+ if (s.substr(s.length - toTrim.length) == toTrim) {
+ return s.slice(0, s.length - toTrim.length);
+ }
+
+ return s;
+ },
+ trim : function (s,toTrim) {
+ var out = s.ltrim(toTrim);
+ out = out.rtrim(toTrim);
+ return out;
+ },
+
+ ltrim : function (s, toTrim) {
+ if (s.substr(0, toTrim.length) == toTrim) {
+ return s.slice(toTrim.length);
+ }
+
+ return s;
+ },
+
+ join : function () {
+ var out = "";
+ for (var i = 0; i < arguments.length; i++) {
+ if (i == 0) {
+ out += this.rtrim(arguments[i], File.SEPARATOR);
+ }
+ else if (i == arguments.length - 1) {
+ out += File.SEPARATOR + this.ltrim(arguments[i], File.SEPARATOR);
+ }
+ else {
+ out += File.SEPARATOR + this.trim(arguments[i], File.SEPARATOR);
+ }
+ }
+ return out;
+ },
+
+ read : function (path) {
+ var out = {};
+ GLib.file_get_contents(path, out, null, null);
+
+ return out['value'];
+ },
+
+ isFile : function (path) {
+ return GLib.file_test(path, GLib.FileTest.IS_REGULAR);
+ },
+ exists : function (path) {
+ return GLib.file_test(path, GLib.FileTest.EXISTS);
+ },
+ isDirectory : function (path) {
+ return GLib.file_test(path, GLib.FileTest.IS_DIR);
+ },
+
+ list : function (path) {
+ var listing = [];
+
+ var f = Gio.file_new_for_path(String(path));
+ 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) {
+ listing.push(next_file.get_display_name());
+ }
+
+ file_enum.close(null);
+
+ listing.sort();
+ return listing;
+ },
+
+ mtime : function (path) {
+ var f = Gio.file_new_for_path(String(path));
+ var mtime = new GLib.TimeVal();
+
+ var info = f.query_info(Gio.FILE_ATTRIBUTE_TIME_MODIFIED, Gio.FileQueryInfoFlags.NONE, null);
+ info.get_modification_time(mtime);
+
+ return new Date(mtime.tv_sec * 1000);
+ },
+
+ /**
+ * resolve the real path
+ * @arg path {String} Path to resolve
+ * @returns {String} the resolved path path.
+ *
+ */
+ realpath : function (path) {
+ return imports.os.realpath(path);
+ },
+ canonical : function (path) {
+ var f = Gio.file_new_for_path(String(path));
+ var can = f.resolve_relative_path('');
+ return can.get_path();
+ },
+ /**
+ * write a string to a file
+ * @arg path {String} File to write to alwasy overwrites.
+ * @arg string {String} Contents of file.
+ *
+ */
+ write : function (path, string) {
+ var d = new Date();
+ var f = Gio.file_new_for_path(String(path));
+ var data_out = new Gio.DataOutputStream({base_stream:f.replace(null, false, Gio.FileCreateFlags.NONE, null)});
+ data_out.put_string(string, null);
+ data_out.close(null);
+ print("WRITE : " + path + " in " + ((new Date()) - d) + 'ms');
+
+ },
+ /**
+ * append
+ * @arg path {String} File to write to
+ * @arg string {String} string to append to file.
+ *
+ */
+ append : function (path, string) {
+ var f = Gio.file_new_for_path(String(path));
+ var data_out = new Gio.DataOutputStream({
+ base_stream:f.append_to(Gio.FileCreateFlags.NONE, null)
+ });
+ data_out.put_string(string, null);
+ data_out.close(null);
+ },
+ /**
+ * remove
+ * Delete a file.
+ * @arg path {String} File to remove
+ *
+ *
+ */
+ remove : function (path)
+ {
+ var f = Gio.file_new_for_path(String(path));
+ return f['delete']();
+ },
+ // copy files recursively from fromDir, silently ignore them if they already exist in toDir
+ silentRecursiveCopy : function (fromDir, toDir) {
+ var filesToCopy = File.recursiveListing(fromDir);
+ var srcPath, destPath, src, dest;
+
+ for (var index in filesToCopy) {
+ srcPath = File.join(String(fromDir), filesToCopy[index]);
+ destPath = File.join(String(toDir), filesToCopy[index]);
+
+ if (File.isFile(srcPath) && !File.isFile(destPath)) {
+ File.copyFile(srcPath, destPath);
+ }
+ else if (File.isDirectory(srcPath) && !File.isDirectory(destPath)) {
+ File.mkdir(destPath);
+ }
+
+ }
+ },
+ /**
+ * Make a symbolic link
+ * @arg new_link {String} The new link
+ * @arg target {String} Where it links to.
+ */
+ link : function (new_link, target) {
+ var dest = Gio.file_new_for_path(String(new_link));
+ return dest.make_symbolic_link(target, null);
+ },
+ /**
+ * Make a directory
+ * FIXME - needs perms setting..
+ *
+ * @arg directory {String} Directory to make
+ * @arg recursive {Boolean}
+ */
+
+ mkdir : function (destPath, rec) {
+ //print("mkdir: " + destPath);
+ rec = rec || false;
+ if (rec && !File.isDirectory(GLib.path_get_dirname(destPath))) {
+ File.mkdir(GLib.path_get_dirname(destPath),true);
+ }
+
+ var dest = Gio.file_new_for_path(String(destPath));
+ return dest.make_directory(null);
+ },
+
+ /**
+ * Copy a file or (directory maybe?)
+ * @arg srcPath {String} source file
+ * @arg destPath {String} destination file
+ * @arg flags {Gio.FileCopyFlags} to overwrite etc... Gio.FileCopyFlags.OVERWRITE
+ */
+ copy : function (srcPath, destPath, flags) {
+ return this.copyFile(srcPath, destPath, flags);
+ },
+ copyFile : function (srcPath, destPath, flags) {
+
+ flags = typeof(flags) == 'undefined' ? Gio.FileCopyFlags.NONE : flags;
+ var dest = Gio.file_new_for_path(String(destPath));
+ var src = Gio.file_new_for_path(String(srcPath));
+
+ // a bit of a hack for the fact that Gio.File.copy arguments
+ // can be nulled, but not according to the GIR file
+ return src.copy(dest, flags);
+ },
+
+
+
+
+ recursiveListing : function (dir) {
+
+ function recursiveListingInternal(prefix, listing, dir) {
+ var entries = File.list(dir);
+ var next, fullPath;
+
+ for (var index in entries) {
+ next = entries[index];
+ fullPath = File.join(prefix, dir, next);
+
+ if (File.isDirectory(fullPath)) {
+ listing.push(next);
+ listing = listing.concat(recursiveListingInternal(next, [], fullPath));
+ }
+ else {
+ if (prefix) {
+ next = File.join(prefix, next);
+ }
+ listing.push(next);
+ }
+ }
+
+ return listing;
+ }
+
+ return recursiveListingInternal('', [], dir);
+ }
+
+};
--- /dev/null
+Gtk = imports.gi.Gtk;
+Gdk = imports.gi.Gdk;
+Pango = imports.gi.Pango;
+GLib = imports.gi.GLib;
+Gio = imports.gi.Gio;
+GObject = imports.gi.GObject;
+GtkSource = imports.gi.GtkSource;
+WebKit = imports.gi.WebKit;
+Vte = imports.gi.Vte;
+console = imports.console;
+XObject = imports.XObject.XObject;
+FixBug=new XObject({
+ xtype: Gtk.Window,
+ listeners : {
+ destroy_event : function (self, event) {
+ this.el.hide();
+ return false;
+ },
+ show : function (self) {
+ print("ON SHOW!");
+
+ this.el.fullscreen();
+ this.el.grab_focus();
+ this.el.set_keep_above(true);
+
+ this.get('/today-vew').load();
+
+ }
+ },
+ border_width : 3,
+ default_height : 400,
+ default_width : 1200,
+ title : "Select Active Bug",
+ deletable : true,
+ modal : true,
+ show : function(c) {
+
+ if (!this.el) {
+ this.init();
+ }
+ var _this = this;
+ /*[ 'xtype' ].forEach(function(k) {
+ _this.get(k).setValue(typeof(c[k]) == 'undefined' ? '' : c[k]);
+ });
+ // shouild set path..
+ */
+
+
+ this.el.show_all();
+ // this.get('/ok_button').el.set_sensitive(false);
+
+ // block until we return.
+ // var run_ret = this.el.run();
+ // if (run_ret < 1 ) {
+ // return false;
+ // }
+ // print("RUN RETURN : " + run_ret);
+
+ //print(JSON.stringify(this.get('bug').getValue()));
+ //return this.get('bug').getValue();
+ //this.success = c.success;
+ },
+ items : [
+ {
+ xtype: Gtk.VBox,
+ pack : "add",
+ items : [
+ {
+ xtype: Gtk.HBox,
+ pack : "pack_start,false,true,3",
+ items : [
+ {
+ xtype: Gtk.Label,
+ label : "On this project:"
+ },
+ {
+ xtype: Gtk.ComboBox,
+ listeners : {
+ changed : function (self) {
+ print("store: active id = " + this.el.get_active_id());
+ this.get('/ticket-store').reload();
+
+
+ }
+ },
+ id : "project-select",
+ init : function() {
+ this.el = new Gtk.ComboBox.with_entry();
+
+
+ this.model = new XObject(this.model);
+ this.model.init();
+ this.el.set_model(this.model.el);
+ this.el.set_entry_text_column (0);
+ XObject.prototype.init.call(this);
+
+ var t = this;
+ imports.Projects.Projects.fetch( function(res) {
+ t.load(res);
+ });
+ },
+ load : function(tr) {
+ this.model.el.clear();
+ this.raw_data = tr;
+ for(var i =0 ; i < tr.length; i++) {
+ var ret = { };
+ this.model.el.append(ret);
+ //print(JSON.stringify(ret,null,4));
+
+ this.model.el.set_value(ret.iter, 0, '' + tr[i].code + " - " + tr[i].name );
+ this.model.el.set_value(ret.iter, 1, '' + tr[i].id );
+
+
+ }
+
+ },
+ model : {
+ xtype: Gtk.ListStore,
+ id : "project-store",
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.set_column_types ( 3, [
+ GObject.TYPE_STRING, // file
+ GObject.TYPE_STRING, // added
+ GObject.TYPE_STRING, // removed
+ ] );
+ }
+ }
+ },
+ {
+ xtype: Gtk.Button,
+ listeners : {
+ button_press_event : function (self, event) {
+
+ FixBug.el.hide();
+ }
+ },
+ height_request : 90,
+ label : "Not working on Project",
+ pack : "add"
+ },
+ {
+ xtype: Gtk.Button,
+ listeners : {
+ button_press_event : function (self, event) {
+
+ FixBug.el.hide();
+ }
+ },
+ id : "ok_button",
+ label : "Working on Selected Ticket",
+ pack : "add"
+ }
+ ]
+ },
+ {
+ xtype: Gtk.HPaned,
+ pack : "pack_end,true,true,3",
+ items : [
+ {
+ xtype: Gtk.VBox,
+ pack : "add",
+ width_request : 400,
+ items : [
+ {
+ xtype: Gtk.HBox,
+ pack : "pack_start,false,true,3",
+ items : [
+ {
+ xtype: Gtk.Entry,
+ listeners : {
+ key_release_event : function (self, event) {
+ if (event.key.keyval == Gdk.KEY_Return) {;
+ // same code as button press..
+ var active_id = this.get('/project-select').el.get_active();
+
+ var project_id = this.get('/project-select').raw_data[active_id].id;
+
+ var str = this.get('/search-entry').el.get_text();
+
+ print(str);
+
+ var _t = this;
+
+ imports.Tasks.Tasks.query({
+ project_id : project_id,
+ 'query[filter]' : 'me',
+ 'query[search]' : str
+ }, function(res) {
+ // print(JSON.stringify(res,null,4));
+ _t.get('/ticket-store').loadData(res);
+ });
+ }
+ return true;
+ }
+ },
+ id : "search-entry",
+ pack : "pack_start,true,true,3"
+ },
+ {
+ xtype: Gtk.Button,
+ listeners : {
+ clicked : function (self) {
+ var active_id = this.get('/project-select').el.get_active();
+
+ var project_id = this.get('/project-select').raw_data[active_id].id;
+
+ var str = this.get('/search-entry').el.get_text();
+
+ print(str);
+
+ var _t = this;
+
+ imports.Tasks.Tasks.query({
+ project_id : project_id,
+ 'query[filter]' : 'me',
+ 'query[search]' : str
+ }, function(res) {
+ // print(JSON.stringify(res,null,4));
+ _t.get('/ticket-store').loadData(res);
+ });
+ }
+ },
+ label : "Search",
+ pack : "pack_end,false,true,3",
+ use_stock : true
+ }
+ ]
+ },
+ {
+ xtype: Gtk.ScrolledWindow,
+ pack : "pack_end,true,true,3",
+ shadow_type : Gtk.ShadowType.IN,
+ items : [
+ {
+ xtype: Gtk.TreeView,
+ listeners : {
+ cursor_changed : function (self) {
+
+ var ret = {};
+ this.selection.get_selected(ret);
+
+ // var val = "";
+ var value = ''+ret.model.get_value(ret.iter, 0).value.get_string();
+
+ print(value);
+ var rec = false;
+ this.get('/ticket-store').data.forEach( function(e) {
+ if (e.id == value) {
+ rec = e;
+ return false;
+ }
+ });
+ // update the text box with the ticket data..
+ this.get('/view').show(rec);
+ //print(rec);
+
+ }
+ },
+ id : "ticket-view",
+ pack : "add",
+ can_focus : true,
+ fixed_height_mode : false,
+ headers_visible : false,
+ init : function() {
+ XObject.prototype.init.call(this);
+ var description = new Pango.FontDescription.c_new();
+ description.set_size(10000);
+ this.el.modify_font(description);
+
+ this.selection = this.el.get_selection();
+ this.selection.set_mode( Gtk.SelectionMode.SINGLE);
+ var _t = this;
+
+ // is this really needed??
+ this.selection.signal['changed'].connect(function() {
+ print('selection changed');
+
+
+ });
+
+ },
+ items : [
+ {
+ xtype: Gtk.ListStore,
+ id : "ticket-store",
+ pack : "set_model",
+ columns : [
+ GObject.TYPE_STRING, // title
+ GObject.TYPE_STRING, // tip
+ GObject.TYPE_STRING // source..
+ ],
+ init : function() {
+ XObject.prototype.init.call(this);
+
+ this.el.set_column_types ( 2, [
+ GObject.TYPE_STRING, // real key
+ GObject.TYPE_STRING // real type
+
+
+ ] );
+
+
+
+ // var t = this;
+ //imports.Projects.Projects.fetch( function(res) {
+ // t.loadData(res);
+ // });
+
+
+ },
+ loadData : function (data) {
+ print("loading data");
+
+
+ this.data = data;
+
+ var el = this.el;
+ this.el.clear();
+ data.forEach(function(p) {
+ var ret = {};
+ el.append(ret);
+ //print("ADD " + p.name);
+
+ var line = '[' + p.status_name + '] <b>' +
+ GLib.markup_escape_text(p.summary, p.summary.length) + "</b>\n" +
+ '<span color="#666">' +
+ GLib.markup_escape_text(p.description,p.description.length).split("\n").slice(0,3).join("\n") +
+ '</span>';
+ print(line);
+
+ el.set_value(ret.iter, 0, p.id);
+ el.set_value(ret.iter, 1, '<b>#' + p.id + '</b>' + line );
+
+ });
+
+
+ },
+ reload : function() {
+
+ var active_id = this.get('/project-select').el.get_active();
+
+ var project_id = this.get('/project-select').raw_data[active_id].id;
+
+ var _t = this;
+
+ imports.Tasks.Tasks.query({
+ project_id : project_id,
+ 'query[filter]' : 'me'
+ }, function(res) {
+ print(JSON.stringify(res,null,4));
+ _t.loadData(res);
+ });
+
+
+ }
+ },
+ {
+ xtype: Gtk.TreeViewColumn,
+ pack : "append_column",
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.add_attribute(this.items[0].el , 'markup', 1 );
+ },
+ items : [
+ {
+ xtype: Gtk.CellRendererText,
+ pack : "pack_start"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ xtype: Gtk.HPaned,
+ pack : "add",
+ items : [
+ {
+ xtype: Gtk.VBox,
+ pack : "pack1,true,true",
+ items : [
+ {
+ xtype: Gtk.HBox,
+ pack : "pack_start,false,true,3",
+ items : [
+ {
+ xtype: Gtk.Label,
+ label : "I am doing this:",
+ pack : "pack_start,false,true,3"
+ },
+ {
+ xtype: Gtk.Entry,
+ pack : "pack_start,true,true,3"
+ }
+ ]
+ },
+ {
+ xtype: Gtk.HBox,
+ pack : "pack_start,false,true,3",
+ items : [
+ {
+ xtype: Gtk.Label,
+ label : "Since:",
+ pack : "pack_start,false,true,3"
+ },
+ {
+ xtype: Gtk.Entry,
+ pack : "pack_start,false,false,3",
+ width_request : 80
+ },
+ {
+ xtype: Gtk.Label,
+ label : "Until",
+ pack : "pack_start,false,true,3"
+ },
+ {
+ xtype: Gtk.Entry,
+ pack : "pack_start,true,true,3"
+ }
+ ]
+ },
+ {
+ xtype: Gtk.ScrolledWindow,
+ pack : "add",
+ id : "RightEditor",
+ items : [
+ {
+ xtype: Gtk.TextView,
+ id : "view",
+ indent_width : 4,
+ pack : "add",
+ auto_indent : true,
+ editable : false,
+ init : function() {
+ XObject.prototype.init.call(this);
+ var description = Pango.font_description_from_string("monospace");
+
+ description.set_size(8000);
+ this.el.modify_font(description);
+
+ },
+ load : function(str) {
+
+ // show the help page for the active node..
+
+
+
+
+ this.el.get_buffer().set_text(str, str.length);
+
+
+ var buf = this.el.get_buffer();
+
+
+
+ },
+ show : function(p) {
+ var line = [
+ 'Status : ' + p.status_name,
+ 'ID : ' + p.id,
+ '',
+ 'Summary : ' + p.summary,
+ '' +
+ p.description,
+ ].join("\n") ;
+ print(line);
+
+
+ // can not do rich text due to so many missing features..
+ this.el.get_buffer().set_text(line, line.length);
+
+ },
+ show_line_numbers : true,
+ items : [
+ {
+ xtype: GtkSource.Buffer,
+ listeners : {
+ changed : function (self) {
+ /*
+ var s = new Gtk.TextIter();
+ var e = new Gtk.TextIter();
+ this.el.get_start_iter(s);
+ this.el.get_end_iter(e);
+ var str = this.el.get_text(s,e,true);
+ try {
+ Seed.check_syntax('var e = ' + str);
+ } catch (e) {
+ this.get('/RightEditor.view').el.modify_base(Gtk.StateType.NORMAL, new Gdk.Color({
+ red: 0xFFFF, green: 0xCCCC , blue : 0xCCCC
+ }));
+ //print("SYNTAX ERROR IN EDITOR");
+ //print(e);
+ //console.dump(e);
+ return;
+ }
+ this.get('/RightEditor.view').el.modify_base(Gtk.StateType.NORMAL, new Gdk.Color({
+ red: 0xFFFF, green: 0xFFFF , blue : 0xFFFF
+ }));
+
+ this.get('/LeftPanel.model').changed( str , false);
+ */
+ }
+ },
+ pack : "set_buffer"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ xtype: Gtk.VBox,
+ pack : "pack2,false,false",
+ width_request : 200,
+ items : [
+ {
+ xtype: Gtk.HBox,
+ pack : "pack_start,false,true,3",
+ items : [
+ {
+ xtype: Gtk.Button,
+ listeners : {
+ clicked : function (self) {
+
+ }
+ },
+ label : "Next/Back",
+ pack : "pack_end,false,true,3",
+ use_stock : true
+ }
+ ]
+ },
+ {
+ xtype: Gtk.ScrolledWindow,
+ pack : "pack_end,true,true,3",
+ shadow_type : Gtk.ShadowType.IN,
+ items : [
+ {
+ xtype: Gtk.TreeView,
+ id : "today-view",
+ pack : "add",
+ can_focus : true,
+ fixed_height_mode : true,
+ headers_visible : false,
+ init : function() {
+ XObject.prototype.init.call(this);
+ var description = new Pango.FontDescription.c_new();
+ description.set_size(10000);
+ this.el.modify_font(description);
+
+ this.selection = this.el.get_selection();
+ this.selection.set_mode( Gtk.SelectionMode.SINGLE);
+ var _t = this;
+
+ // is this really needed??
+ this.selection.signal['changed'].connect(function() {
+ print('selection changed');
+
+
+ });
+
+ },
+ items : [
+ {
+ xtype: Gtk.ListStore,
+ id : "today-store",
+ pack : "set_model",
+ columns : [
+ GObject.TYPE_STRING, // title
+ GObject.TYPE_STRING, // tip
+ GObject.TYPE_STRING // source..
+ ],
+ init : function() {
+ XObject.prototype.init.call(this);
+
+ this.el.set_column_types ( 2, [
+ GObject.TYPE_STRING, // real key
+ GObject.TYPE_STRING // real type
+
+
+ ] );
+
+
+
+ // var t = this;
+ //imports.Projects.Projects.fetch( function(res) {
+ // t.loadData(res);
+ // });
+
+
+ },
+ loadData : function (data) {
+ print("loading data");
+
+ var el = this.el;
+ this.el.clear();
+ data.forEach(function(p) {
+ var ret = {};
+ el.append(ret);
+ //print("ADD " + p.name);
+
+ el.set_value(ret.iter, 0, p.id);
+ el.set_value(ret.iter, 1, '<b>#' + p.id + '</b>' +
+ '[' + p.status_name + '] <b>' + p.summary + "</b>\n" +
+ '<span color="#666">' + p.description.split("\n").slice(0,3).join("\n") +
+ '</span>'
+
+ );
+
+ });
+
+
+ },
+ reload : function() {
+
+ var active_id = this.get('/project-select').el.get_active();
+
+ var project_id = this.get('/project-select').raw_data[active_id].id;
+
+ var _t = this;
+
+ var DT = imports.Date.Date;
+
+ new imports.Request.Request( {
+ url : '/cash_invoice_entry',
+ params : {
+ 'query[action_dt_from]' : (new DT()).format('Y-m-d'),
+ 'query[action_dt_to]' : (new DT()).add(DT.DAY,1).format('Y-m-d'),
+ limit: 999,
+ 'sort' : 'action_dt',
+ dir : 'ASC',
+ action : 'Hours'
+ },
+
+ success : function(res) {
+ this.loadData();
+ },
+ scope : this
+
+
+ });
+
+
+
+ }
+ },
+ {
+ xtype: Gtk.TreeViewColumn,
+ pack : "append_column",
+ sizing : Gtk.TreeViewColumnSizing.FIXED,
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.add_attribute(this.items[0].el , 'markup', 1 );
+ },
+ items : [
+ {
+ xtype: Gtk.CellRendererText,
+ pack : "pack_start"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+});
+FixBug.init();
+XObject.cache['/FixBug'] = FixBug;
--- /dev/null
+
+var File = imports.File.File;
+xDate = imports.Date;
+
+
+
+
+
+GitLogParser = {
+ shours : false,
+ date : false,
+ parse : function(date)
+ {
+ var filename = date;
+ if (typeof(date) == 'object') {
+ this.date = date;
+ var home = GLib.get_home_dir();
+ //print( "READING FILE");
+ filename = home + '/.gitlog' + date.format('/Y/m/d') + '.log';
+
+
+ }
+
+ var flines = File.read( filename ).split("\n");
+ //print("loaded");
+ // first just convert them..
+ // we had an old bug that did not put line breaks in there..
+ // however 00:00:00: is pretty distinct, so let'st try and split on it..
+
+
+
+ lines = [];
+
+ // read the lines, and fill in the 'spans'
+
+ for (var i = 0; i < flines.length; i++) {
+
+ var xl = flines[i].split(/([0-9]{2}:[0-9]{2}:[0-9]{2})/);
+
+ //print(JSON.stringify(xl));
+ for (var ii=1; ii< xl.length; ii+=2) {
+ var p = lines.length;
+ lines.push( this.parseLine(xl[ii] + ' ' + xl[ii+1]));
+ if (p > 0) {
+ lines[p-1].span = lines[p].start - lines[p-1].start; // should be seconds..?
+ lines[p-1].spanMin = lines[p-1].span/60000;
+
+
+ }
+
+ }
+
+
+ }
+ //print("parsed");
+ //print(JSON.stringify(lines,null,4));
+
+ // summarize data...
+ var hours = {};
+ var shours = {};
+
+ // shours should be:
+ // hour : [ ]
+
+
+ for (var i = 0; i < lines.length; i++) {
+ var line = lines[i];
+ var hour = line.start.format('H');
+
+ if (line.project == 'IDLE' && line.spanMin >= 5 ) {
+ line.project = 'LONGIDLE';
+ }
+ if (line.project == 'IDLE' || line.project == 'LONGIDLE') {
+ line.desc = line.project;
+ }
+
+ var project = line.project;
+ hours[hour] = (typeof(hours[hour]) == 'undefined') ? {} : hours[hour];
+ hours[hour][project] = (typeof(hours[hour][project]) == 'undefined') ?
+ { total : 0, items : [] }
+ : hours[hour][project];
+ hours[hour][project].total += line.span;
+ hours[hour][project].items.push(line);
+
+ hours[-1] = (typeof(hours[-1]) == 'undefined') ? {} : hours[-1];
+ hours[-1][project] = (typeof(hours[-1][project]) == 'undefined') ?
+ { total : 0, items : {} }
+ : hours[-1][project];
+
+ hours[-1][project].total += line.span;
+ hours[-1][project].items[line.desc] = (typeof(hours[-1][project].items[line.desc]) == 'undefined' ?
+ 0 : hours[-1][project].items[line.desc]) + line.span;
+
+ shours[hour] = (typeof(shours[hour]) == 'undefined') ? {} : shours[hour];
+ shours[hour][line.desc] = (typeof(shours[hour][line.desc] ) == 'undefined') ? 0 : shours[hour][line.desc] ;
+ shours[hour][line.desc] += line.span;
+
+
+
+ }
+ this.shours = shours;
+ return hours;
+
+ },
+ parseLine : function(l)
+ {
+ var ret = { cmd : false, line : l, span : 0 };
+ var ar = l.split(/\s+/);
+ //print(JSON.stringify(ar));
+
+
+ var time = ar.shift();
+
+ ret.desc = ar.join(' ');
+
+ //print("time: " + time);
+
+ //ret.start = xDate.Date.parseDate(this.date.format('Y-m-d') + ' ' + time, 'Y-m-d H:i:s');
+ ret.start = xDate.Date.parseDate(
+ (this.date ? this.date.format('Y-m-d') :'2013-01-01') +
+ ' ' + time, 'Y-m-d H:i:s');
+
+ while (ret.cmd === false) {
+ var ta = ar.pop();
+ //print("TA:"+ta)
+ if (ta[0] != '-') { //hopfully withc catch stuff.
+ ret.cmd = ta;
+ break;
+ }
+ if (!ar.length) {
+ // just assume it's the last bit..
+ //print(line);
+ throw "invalid line: " + l;
+ }
+
+ }
+ //print(ret.cmd);
+
+
+ ret.title = ar.join(' ');
+ if (ret.title == 'IDLE') {
+ ret.project = 'IDLE';
+ return ret;
+ }
+ ret.project = 'Unknown';
+
+ for(var proj in this.regexes) {
+ for(var r in this.regexes[proj]) {
+ if (ret.line.match(this.regexes[proj][r])) {
+ //print("Match " + proj + " on " + r + ret.line + )
+ ret.project = proj;
+ break;
+ }
+ }
+ if (ret.project != 'Unknown') {
+ break;
+ }
+ }
+ return ret;
+ /*
+
+ if (typeof(this[ret.cmd])=='undefined') {
+ ret.project = 'Unknown';
+ return ret;
+ print( "Unknown application: " + ret.line);
+ throw { error : "TEST"};
+ }
+
+ //print(ret.cmd);
+ //print(ret.title);
+ if (typeof(this[ret.cmd])=='string') {
+ ret.project = this[ret.cmd]
+ } else {
+
+ this[ret.cmd](ret);
+ }
+
+
+ return ret;
+ */
+
+ },
+
+ regexes : {
+ 'HPA' : [ /web.hpasite/, /Roo Application Builder - Site/, /HP Intranet/, /Hpasite/ ],
+ 'MediaOut' : [ /app\.WorkerBee/, /web\.MediaOut/, /workerbee/,
+ /media-outreach/ , /Press Release Image Portal/, /Media Outreach Feed/ , /PressRelease/,
+ /Clipping Portal/, /Media OutReach/,
+ /Auto Searching/ , // These are the excel files they send over..
+ /sitemap\.xml/,
+ /Builder - Clipping/
+ ],
+ 'Habito' : [ /Interspire/ ],
+ 'Hebe' :[ /web.hhyc_membership_system/ ,/Builder - Hebe/, /Hebe Haven Membership Managment/],
+
+ 'RIS' : [ /Project web.Ris/ , /RIS HK/ , /Hydra/, /hydrajobs/ ],
+ // for who thoug...
+ 'Mailfort' : [ /web.FlexySpam/ ],
+ 'Emily' : [ /greengarden/ ,/Inventory \| Warehouse/, /Emily/ ],
+ 'GPUK' : [/gp-wordpress/, /Greenpeace UK/],
+
+ 'COBA' : [/Veridate/, /web\.coba/, /COBA/ ,/Pipeline - DS view/ ],
+ 'Regulation Asia' : [/Regulation Asia/, /comocracy/],
+ 'Unknown Project' : [ /PAC/ , /Guake/ , /WhatsApp/ ,/Mozilla Thunderbird/],
+ 'Admin Work' : [ /roojs.com\/admin/, /RooJSolutions Management Portal/ ]
+
+
+ },
+
+ match_project : function(line) {
+ for(var proj in this.regexes) {
+ for(var r in this.regexes[proj]) {
+ if (line.match(this.regexes[proj][r])) {
+ //print("Match " + proj + " on " + r + ret.line + )
+ return proj;
+
+ }
+ }
+
+ }
+ return "Unknown";
+ },
+
+
+ '/usr/bin/perl' : function(ret) {
+ if (ret.title.match(/^PAC/)) {
+ ret.project = 'Unknown';
+ return 'Unknown';
+ }
+ return 'Unknown';
+ throw "Unknown match: " + ret.line;
+ },
+ '/usr/lib/icedove/icedove-bin' : 'Checking Mail',
+ '/usr/lib/chromium/chromium' : function (ret) {
+
+ switch(true) {
+
+ case (ret.title.match(/Media Clipping Portal/)):
+ ret.project = 'Media Outreach';
+ return;
+
+ default:
+ ret.project = 'Browsing';
+ return;
+ }
+
+ },
+ '/usr/lib/Komodo-Edit-7/lib/mozilla/komodo' : function(ret) {
+ var l = ret.title.match(/Project\s+(^\)+)/);
+ if (!l) {
+ ret.project="Unknown";
+ return;
+ }
+ throw "Unknown match: " + ret.line;
+ },
+ 'guake' : 'Local Terminal',
+ 'mono' : 'mono?'
+
+
+}
+//print(Seed.argv[2]);Seed.quit();
+if (typeof(Seed.argv[2]) == 'undefined') {
+ print("pick a date");
+ Seed.quit();
+}
+
+var res = GitLogParser.parse( Seed.argv[2][0] == '/' ? Seed.argv[2] : xDate.Date.parseDate(Seed.argv[2], 'Y-m-d'));
+var totals = { work : 0 , idle: 0, shortidle : 0};
+var unknown = [];
+for (var h in res) {
+ for (var p in res[h]) {
+ if (p == 'LONGIDLE') {
+ var idletime = Math.floor(res[h][p].total/60000) ;
+ //print(h + ' ' + Math.floor(res[h][p].total/60000) +'m LONGIDLE' );
+ totals.idle += idletime;
+
+
+ continue;
+ }
+ if (p == 'IDLE') {
+ var idletime = Math.floor(res[h][p].total/60000) ;
+ //print(h + ' ' + Math.floor(res[h][p].total/60000) +'m SHORT IDLE' );
+ totals.shortidle += idletime;
+
+
+ continue;
+ }
+
+
+ //print(h + ' ' + Math.floor(res[h][p].total/60000) +'m ' + p );
+ totals.work += Math.floor(res[h][p].total/60000) ;
+
+ if (h == -1) {
+
+ print( "\n" + p + ':' + Math.floor(res[h][p].total/60000) + 'm');
+
+ if (p != 'Unknown') {
+
+ for (var k in res[h][p].items) {
+
+ print( ' ' + Math.floor(res[h][p].items[k]/60000) +'m ' + k );
+
+ }
+ } else {
+
+ for (var k in res[h][p].items) {
+ unknown.push({ desc : k , tot : (res[h][p].items[k]/60000).toFixed(2)*1 }) ;
+
+
+ }
+ }
+ }
+
+ }
+
+}
+
+
+print("\nLONGIDLE : " +(totals.idle/60).toFixed(2) +"h" );
+print("\nShort Idle : " +(totals.shortidle/60).toFixed(2) +"h" );
+
+print("Worked: " + (totals.work/60).toFixed(2) +"h\n" );
+
+var totals = {};
+
+for (var h in GitLogParser.shours) {
+ var hsum = [];
+ var htot = 0;
+ for (var desc in GitLogParser.shours[h]) {
+ htot += (GitLogParser.shours[h][desc]/60000).toFixed(2)*1;
+ hsum.push({ desc : desc, tot : (GitLogParser.shours[h][desc]/60000).toFixed(2)*1 })
+ totals[desc] = (typeof(totals[desc]) == 'undefined' ? 0 : totals[desc]) + ((GitLogParser.shours[h][desc]/60000).toFixed(2)*1);
+ }
+ hsum.sort(function(a,b) { if (a.tot == b.tot) { return 0; } return a.tot < b.tot ? 1 : -1 });
+ print("\n\n" + h+': Total (' + htot +')');
+ hsum.forEach(function(r) {
+ var pr = r.desc.match(/IDLE/) ? '' : (GitLogParser.match_project(r.desc) == "Unknown" ? '??? - ' : '');
+
+ print (" " + r.tot + " : " + pr + r.desc);
+ });
+}
+
+
+unknown.sort(function(a,b) { if (a.tot == b.tot) { return 0; } return a.tot < b.tot ? 1 : -1 });
+print("\n\nUnclassified");
+unknown.forEach(function(r) {
+ print (" " + (r.tot.toFixed(2)*1) + " : " + r.desc);
+});
+
+//print(JSON.stringify(GitLogParser.shours,null,4));
+
+
+
+// open file..
+
+// read lines
+
+// summarize each hour
+
+//convert line into 'Project / filename'
+
+
--- /dev/null
+
+var Gio = imports.gi.Gio;
+var Gtk = imports.gi.Gtk;
+var Notify = imports.gi.Notify;
+var GLib = imports.gi.GLib;
+
+var Spawn = imports.Spawn;
+var StatusIcon = imports.StatusIcon.StatusIcon;
+var Monitor = imports.Monitor.Monitor;
+
+
+
+var GitMonitor = new Monitor({
+
+ /**
+ * @property {String} the "gitlive" directory, normally ~/gitlive
+ * dset by OWNER... - we should do this as a CTOR.
+ *
+ */
+ gitlive : false,
+
+
+ queue : [],
+ queueRunning : false,
+
+
+
+ pause : function() {
+ this.paused = true;
+ this.queue = [];
+ imports.StatusIcon.StatusIcon.el.set_from_stock( Gtk.STOCK_MEDIA_PAUSE );
+ },
+
+ resume : function() {
+ this.paused = false;
+ this.queue = [];
+ imports.StatusIcon.StatusIcon.el.set_from_stock( Gtk.STOCK_MEDIA_PLAY );
+
+
+ },
+
+ /**
+ * Start the monitoring
+ * and run the queue every 500 milliseconds..
+ *
+ */
+ start: function() {
+ imports.StatusIcon.StatusIcon.el.set_from_stock( Gtk.STOCK_REFRESH );
+ var _this = this;
+ this.lastAdd = new Date();
+
+ GLib.timeout_add(GLib.PRIORITY_LOW, 500, function() {
+ _this.top.forEach(_this.monitor, _this);
+ imports.StatusIcon.StatusIcon.el.set_from_stock( Gtk.STOCK_MEDIA_PLAY );
+
+ try {
+ var notification = new Notify.Notification({
+ summary: "Git Live",
+ body : this.gitlive + "\nMonitoring " + _this.monitors.length + " Directories",
+ timeout : 5
+ });
+
+ notification.set_timeout(5);
+ notification.show();
+ } catch(e) {
+ print(e.toString());
+ }
+
+ });
+
+ GLib.timeout_add(GLib.PRIORITY_LOW, 1000, function() {
+ //TIMEOUT", _this.queue.length , _this.queueRunning].join(', '));
+ if (!_this.queue.length || _this.queueRunning) {
+ return 1;
+ }
+ var last = Math.floor(((new Date()) - _this.lastAdd) / 100);
+
+ //print("LAST RUN?" + last);
+
+ if (last < 5) { // wait 1/2 a seconnd before running.
+ return 1;
+ }
+ //_this.lastAdd = new Date();
+ //return 1;
+
+ _this.runQueue();
+ return 1;
+ },null,null);
+
+
+ },
+
+
+ stop: function() {
+ imports.StatusIcon.StatusIcon.el.set_from_stock( Gtk.STOCK_MEDIA_PAUSE );
+ Monitor.prototype.stop.call(this);
+ },
+
+
+ monitor : function(path, fn, depth)
+ {
+ depth = typeof(depth) == 'number' ? depth *1 : 0;
+
+
+ // if we are not at top level.. and there is a .git directory (it's a submodule .. ignore)
+ if (depth > 1 && GLib.file_test(path + '/.git' , GLib.FileTest.IS_DIR)) {
+ return;
+ }
+
+ if (depth == 1) {
+ var repo = imports.Scm.Repo.Repo.get(path);
+ if (!repo || !repo.autocommit()) {
+ return;
+ }
+ }
+
+
+ // check if the repo is to be monitored.
+ //print("PATH : " + path);
+
+
+ Monitor.prototype.monitor.call(this, path,fn, depth);
+ },
+
+ /**
+ * run the queue.
+ * - pulls the items off the queue
+ * (as commands run concurrently and new items may get added while it's running)
+ * - runs the queue items
+ * - pushes upstream.
+ *
+ */
+ runQueue: function()
+ {
+
+ if (this.paused) {
+ return;
+ }
+ this.queueRunning = true;
+ var cmds = [];
+ this.queue.forEach(function (q) {
+ cmds.push(q);
+ });
+ this.queue = []; // empty queue!
+
+ var success = [];
+ var failure = [];
+ var repos = [];
+ var done = [];
+
+ // first build a array of repo's to work with
+ var repo_list = {};
+
+ // pull and group.
+
+ //print(JSON.stringify(cmds));
+ this.paused = true;
+ cmds.forEach(function(cmd) {
+ var gitpath = cmd.shift();
+ if (typeof(repo_list[gitpath]) == 'undefined') {
+ repo_list[gitpath] = new imports.Scm.Git.Repo.Repo( { repopath : gitpath });
+ repo_list[gitpath].cmds = [];
+ repo_list[gitpath].pull();
+ }
+ repo_list[gitpath].cmds.push(cmd);
+ });
+ this.paused = false;
+ // build add, remove and commit message list..
+
+
+
+ for (var gitpath in repo_list) {
+ var repo = repo_list[gitpath];
+ var add_files = [];
+ var remove_files = [];
+ var messages = [];
+ //print(JSON.stringify(repo.cmds,null,4));
+
+ repo.cmds.forEach(function(cmd) {
+
+ var name = cmd.shift();
+ var arg = cmd.shift();
+
+ switch(name) {
+ case 'add' :
+
+ if (add_files.indexOf(arg) > -1) {
+ break;
+ }
+
+ // if file does not exist.. s,ip
+
+ //if (!GLib.file_test(arg, GLib.FileTest.EXISTS)) {
+
+ // break;
+ // }
+
+
+ add_files.push(arg);
+ break;
+
+ case 'rm':
+
+ if (add_files.indexOf(arg) > -1) {
+ break;
+ }
+
+ // if file exists, do not try and delete it.
+ if (GLib.file_test(arg, GLib.FileTest.EXISTS)) {
+ break;
+ }
+
+ remove_files.push(arg);
+ break;
+
+ case 'commit' :
+
+ if (messages.indexOf(arg.message) < 0) {
+ messages.push(arg.message);
+ }
+ break;
+ }
+ });
+
+ //repo.debug = 1;
+ // these can fail... at present... as we wildcard stuff.
+ print("ADD : " + JSON.stringify(add_files));
+
+ // make sure added files do not get removed..
+ remove_files = remove_files.filter(function(v) {
+ return add_files.indexOf(v) < 0;
+ });
+ print("REMOVE : " + JSON.stringify(remove_files));
+
+
+ // make sure monitoring is paused so it does not recursively pick up
+ // deletions
+
+ // -- DO STUFF..
+
+ repo.add(add_files);
+
+ repo.remove(remove_files);
+ this.paused = false;
+
+
+ try {
+ success.push(repo.commit({
+ reason : messages.join("\n"),
+ files : add_files
+ }));
+ success.push(repo.push());
+
+ } catch(e) {
+ failure.push(e.message);
+
+ }
+ }
+
+ // finally merge all the commit messages.
+
+ try {
+ // catch notification failures.. so we can carry on..
+ if (success.length) {
+ print(success.join("\n"));
+
+ var notification = new Notify.Notification({
+ summary: "Git Live Commited",
+ body : success.join("\n"),
+ timeout : 5
+
+ });
+
+ notification.set_timeout(5);
+ notification.show();
+ }
+
+ if (failure.length) {
+
+ var notification = new Notify.Notification({
+ summary: "Git Live ERROR!!",
+ body : failure.join("\n"),
+ timeout : 5
+
+ });
+
+ notification.set_timeout(5); // show errros for longer
+ notification.show();
+ }
+ } catch(e) {
+ print(e.toString());
+
+ }
+ this.queueRunning = false;
+ },
+
+ shouldIgnore: function(f)
+ {
+
+ if (this.paused) {
+ return true;
+ }
+
+
+ // vim.. what a seriously brain dead program..
+ if (f.name == '4913') {
+ return true;
+ }
+
+ if (f.name[0] == '.') {
+ // except!
+ if (f.name == '.htaccess') {
+ return false;
+ }
+
+ return true;
+ }
+ if (f.name.match(/~$/)) {
+ return true;
+ }
+ if (f.name.match(/^nbproject/)) {
+ return true;
+ }
+ // ignore anything in top level!!!!
+ if (!f.vpath.length) {
+ return true;
+ }
+
+ return false;
+ },
+
+ /**
+ * parsePath:
+ * Fill in gitlive, vpath and repo
+ *
+ */
+ parsePath: function(f)
+ {
+
+ var vpath_ar = f.path.substring(this.gitlive.length +1).split('/');
+
+ f.gitpath = this.gitlive + '/' + vpath_ar.shift();
+ f.vpath = vpath_ar.join('/');
+ //f.repo = new imports.Scm.Git.Repo({ repopath: f.gitpath })
+
+
+ },
+
+ just_created : {},
+
+ onChanged : function(src)
+ {
+ return; // always ignore this..?
+ //this.parsePath(src);
+ },
+
+
+
+
+ /**
+ * results in git add + git commit..
+ *
+ */
+ onChangesDoneHint : function(src)
+ {
+ this.lastAdd = new Date();
+ this.parsePath(src);
+ if (this.shouldIgnore(src)) {
+ return;
+ }
+
+
+ var add_it = false;
+ if (typeof(this.just_created[src.path]) !='undefined') {
+ delete this.just_created[src.path];
+
+ this.queue.push(
+ [ src.gitpath, 'add', src.vpath ],
+ [ src.gitpath, 'commit', { message: src.vpath} ]
+
+ );
+
+ return;
+ }
+
+ this.queue.push(
+ [ src.gitpath, 'add', src.vpath ],
+ [ src.gitpath, 'commit', { message: src.vpath} ]
+
+
+ );
+ },
+ onDeleted : function(src)
+ {
+ this.lastAdd = new Date();
+ this.parsePath(src);
+ if (this.shouldIgnore(src)) {
+ return;
+ }
+ // should check if monitor needs removing..
+ // it should also check if it was a directory.. - so we dont have to commit all..
+
+
+ this.queue.push(
+ [ src.gitpath, 'rm' , src.vpath ],
+ [ src.gitpath, 'commit', { all: true, message: src.vpath} ]
+
+ );
+
+
+ },
+ onCreated : function(src)
+ {
+ this.lastAdd = new Date();
+ this.parsePath(src);
+ if (this.shouldIgnore(src)) {
+ return;
+ }
+
+ if (!GLib.file_test(src.path, GLib.FileTest.IS_DIR)) {
+ this.just_created[src.path] = true;
+ return; // we do not handle file create flags... - use done hint.
+ }
+ // director has bee created
+ this.monitor(src.path);
+
+ this.queue.push(
+ [ src.gitpath, 'add' , src.vpath, { all: true } ],
+ [ src.gitpath, 'commit' , { all: true, message: src.vpath} ]
+
+ );
+
+
+ },
+ onAttributeChanged : function(src)
+ {
+ this.lastAdd = new Date();
+ this.parsePath(src);
+ if (this.shouldIgnore(src)) {
+ return;
+ }
+
+ this.queue.push(
+
+ //[ src.gitpath, 'commit' , src.vpath, { message: src.vpath} ]
+ [ src.gitpath, 'add' , src.vpath ],
+ [ src.gitpath, 'commit' , { message: "Attribute Changed :" + src.vpath} ]
+ );
+
+
+ },
+
+ onMoved : function(src,dest)
+ {
+ this.lastAdd = new Date();
+ this.parsePath(src);
+ this.parsePath(dest);
+
+ if (src.gitpath != dest.gitpath) {
+ this.onDeleted(src);
+ this.onCreated(dest);
+ this.onChangedDoneHint(dest);
+ return;
+ }
+ // needs to handle move to/from unsupported types..
+
+ if (this.shouldIgnore(src)) {
+ return;
+ }
+ if (this.shouldIgnore(dest)) {
+ return;
+ }
+
+ this.queue.push(
+ // [ src.gitpath, 'mv', '-k', src.vpath, dest.vpath ],
+ [ src.gitpath, 'add', dest.vpath ],
+ [ src.gitpath, 'rm', src.vpath ],
+
+ [ src.gitpath, 'commit' ,
+ { message: 'MOVED ' + src.vpath +' to ' + dest.vpath}
+ ]
+ );
+
+ }
+
+
+});
+
+
--- /dev/null
+Gtk = imports.gi.Gtk;
+Gdk = imports.gi.Gdk;
+Pango = imports.gi.Pango;
+GLib = imports.gi.GLib;
+Gio = imports.gi.Gio;
+GObject = imports.gi.GObject;
+GtkSource = imports.gi.GtkSource;
+WebKit = imports.gi.WebKit;
+Vte = imports.gi.Vte;
+console = imports.console;
+XObject = imports.XObject.XObject;
+Merger=new XObject({
+ xtype: Gtk.Dialog,
+ listeners : {
+ destroy_event : function (self, event) {
+ this.el.hide();
+ return false;
+ },
+ response : function (self, id) {
+ // hide
+ //if (id < 1) {
+ this.el.hide();
+ return;
+ //}
+ if (typeof(this.get('bug').getValue()) != 'object') {
+ print("ERROR");
+ return;
+ }
+
+ this.el.hide();
+
+ //var val = this.get('bug').getValue();
+ // Seed.print(val);
+ }
+ },
+ border_width : 3,
+ default_height : 700,
+ default_width : 800,
+ id : "Merger",
+ title : "Merger",
+ deletable : true,
+ show : function(c) {
+
+ if (!this.el) {
+ this.init();
+ }
+ var _this = this;
+
+ //this.el.set_title("Merger - ??? ");
+ // this.el.set_title("Merger - " + this.repo.repopath);
+
+
+ Merger.loading = true; // stop change firing on combos.
+ /// load up branches
+
+ this.get('/historyTreeStore').el.clear();
+ this.get('/changedFilesStore').el.clear();
+ this.get('/patchview').clear();
+
+
+
+ this.get('/workingCombo').load(Merger.repo.branches);
+
+ this.get('/releaseCombo').load(Merger.repo.branches);
+
+
+
+
+ Merger.loading = false;
+
+ this.el.show_all();
+ //this.get('/ok_button').el.set_sensitive(false);
+
+ // block until we return.
+ var run_ret = this.el.run();
+ if (run_ret < 1 ) {
+ return "DONE";
+ }
+ print("RUN RETURN : " + run_ret);
+ return "DONE";
+ //print(JSON.stringify(this.get('bug').getValue()));
+ // return this.get('bug').getValue();
+ //this.success = c.success;
+ },
+ items : [
+ {
+ xtype: Gtk.VBox,
+ pack : function(p,e) {
+ p.el.get_content_area().pack_start(e.el,true,true,0)
+ },
+ items : [
+ {
+ xtype: Gtk.HBox,
+ pack : "pack_start,false,true",
+ items : [
+ {
+ xtype: Gtk.Label,
+ label : "Working Branch"
+ },
+ {
+ xtype: Gtk.ComboBox,
+ listeners : {
+ changed : function (self) {
+ this.get('/historyTreeStore').loadTree();
+ }
+ },
+ id : "workingCombo",
+ init : function() {
+ this.el = new Gtk.ComboBox.with_entry();
+
+
+ this.model = new XObject(this.model);
+ this.model.init();
+ this.el.set_model(this.model.el);
+ this.el.set_entry_text_column (0);
+ XObject.prototype.init.call(this);
+
+ },
+ load : function(tr)
+ {
+ //this.insert(citer,iter,0);
+ this.model.el.clear();
+
+ var master = false;
+ var working = false;
+
+ for(var i =0 ; i < tr.length; i++) {
+ if (!tr[i].name.length) {
+ continue;
+ }
+ var ret = { };
+ this.model.el.append(ret);
+ //print(JSON.stringify(ret,null,4));
+ if (tr[i].name == 'master') {
+ master = i;
+ }
+ if (tr[i].name == 'working') {
+ working = i;
+ }
+ this.model.el.set_value(ret.iter, 0, '' + tr[i].name );
+ this.model.el.set_value(ret.iter, 1, '' + tr[i].rev );
+
+
+ }
+ if (master !== false) {
+ this.el.set_active(master);
+ }
+ if (working !== false) {
+ this.el.set_active(working);
+ }
+
+ },
+ model : {
+ xtype: Gtk.ListStore,
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.set_column_types ( 3, [
+ GObject.TYPE_STRING, // file
+ GObject.TYPE_STRING, // added
+ GObject.TYPE_STRING, // removed
+ ] );
+ }
+ }
+ },
+ {
+ xtype: Gtk.Label,
+ label : "Release Branch"
+ },
+ {
+ xtype: Gtk.ComboBox,
+ listeners : {
+ changed : function (self) {
+ this.get('/historyTreeStore').loadTree();
+ }
+ },
+ id : "releaseCombo",
+ init : function() {
+ this.el = new Gtk.ComboBox.with_entry();
+
+
+ this.model = new XObject(this.model);
+ this.model.init();
+ this.el.set_model(this.model.el);
+ this.el.set_entry_text_column (0);
+ XObject.prototype.init.call(this);
+
+ },
+ load : function(tr)
+ {
+ //this.insert(citer,iter,0);
+ this.model.el.clear();
+
+ var master = false;
+ var release = false;
+
+ for(var i =0 ; i < tr.length; i++) {
+ var ret = { };
+ if (!tr[i].name.length) {
+ continue;
+ }
+
+ this.model.el.append(ret);
+ //print(JSON.stringify(ret,null,4));
+ if (tr[i].name == 'master') {
+ master = i;
+ }
+ if (tr[i].name == 'release') {
+ release = i;
+ }
+
+ this.model.el.set_value(ret.iter, 0, '' + tr[i].name );
+ this.model.el.set_value(ret.iter, 1, '' + tr[i].rev );
+
+
+ }
+ if (master !== false) {
+ this.el.set_active(master);
+ }
+ if (release !== false) {
+ this.el.set_active(release);
+ }
+
+ },
+ model : {
+ xtype: Gtk.ListStore,
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.set_column_types ( 3, [
+ GObject.TYPE_STRING, // file
+ GObject.TYPE_STRING, // added
+ GObject.TYPE_STRING, // removed
+ ] );
+ }
+ }
+ }
+ ]
+ },
+ {
+ xtype: Gtk.VPaned,
+ pack : "pack_end,true,true,0",
+ position : 400,
+ items : [
+ {
+ xtype: Gtk.HPaned,
+ pack : "add",
+ position : 200,
+ items : [
+ {
+ xtype: Gtk.ScrolledWindow,
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.set_policy (Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
+ },
+ items : [
+ {
+ xtype: Gtk.TreeView,
+ listeners : {
+ cursor_changed : function (self) {
+
+ if (this.el.get_selection().count_selected_rows() < 1) {
+ //nothing?
+ return;
+ }
+ var model = this.get('/historyTreeStore');
+ var ret = {};
+ var s = this.el.get_selection();
+ s.get_selected(ret);
+
+ var value = ''+ ret.model.get_value(ret.iter, 1).value.get_string();
+ print("OUT?" + value);// id..
+ // load the list in the right grid..
+ var Repo = imports.Scm.Git.Repo.Repo;
+
+
+
+ if (model.release === false) {
+ return;
+ }
+ model.rev = value;
+
+ var files = Merger.repo.changedFiles('/', 'rev', model.release + '..' + value);
+ this.get('/changedFilesStore').load(files);
+ return true;
+
+ }
+ },
+ pack : "add",
+ init : function() {
+ XObject.prototype.init.call(this);
+ var description = new Pango.FontDescription.c_new();
+ description.set_size(8000);
+ this.el.modify_font(description);
+
+ this.selection = this.el.get_selection();
+ this.selection.set_mode( Gtk.SelectionMode.SINGLE);
+ var _this = this;
+ /*
+ 780
+ 781 // is this really needed??
+ 782 this.selection.signal['changed'].connect(function() {
+ 783 _this.get('/LeftTree.view').listeners.cursor_changed.apply(
+ 784 _this.get('/LeftTree.view'), [ _this.get('/LeftTree.view'), '']
+ 785 );
+ 786 });
+ 787
+ */
+ },
+ items : [
+ {
+ xtype: Gtk.TreeStore,
+ id : "historyTreeStore",
+ pack : "set_model",
+ release : false,
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.set_column_types ( 3, [
+ GObject.TYPE_STRING, // title
+ GObject.TYPE_STRING, // rev
+ ] );
+ },
+ load : function(tr,iter)
+ {
+ //this.insert(citer,iter,0);
+ if (!iter) {
+ this.el.clear();
+ }
+
+ for(var i =0 ; i < tr.length; i++) {
+ var ret = { };
+ if (iter) {
+ this.el.insert(ret ,iter,-1);
+ } else {
+ this.el.append(ret);
+ }
+ //print(JSON.stringify(ret,null,4));
+
+
+ this.el.set_value(ret.iter, 0, '' + tr[i].text );
+ this.el.set_value(ret.iter, 1, '' + tr[i].rev );
+
+ if (tr[i].children && tr[i].children.length) {
+ this.load(tr[i].children, ret.iter);
+ }
+ }
+ },
+ loadTree : function() {
+
+ this.working = false;
+ if (Merger.loading) {
+ return;
+ }
+
+
+ var wid = this.get('/workingCombo').el.get_active();
+ var rid = this.get('/releaseCombo').el.get_active();
+ if (wid < 0 || rid < 0 || rid == wid) {
+ return;
+ }
+
+ var w = Merger.repo.branches[wid];
+ var r = Merger.repo.branches[rid];
+
+
+
+ var rev = r.name + '..' + w.name;
+ this.release = r.name;
+ this.working = w.name;
+
+ // this takes some time, lets. try and dialog it..
+
+
+
+
+ var msg = new Gtk.MessageDialog( {
+ buttons : Gtk.ButtonsType.NONE,
+ text: "Loading History"
+
+ });
+
+ msg.set_transient_for(Merger.el);
+ msg.set_modal(true);
+ msg.show_all();
+
+ var hist = Merger.repo.dayTree('/', false, 'rev', rev);
+ msg.hide();
+
+ this.load(hist);
+
+
+ }
+ },
+ {
+ xtype: Gtk.TreeViewColumn,
+ pack : "append_column",
+ title : "Changes",
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.add_attribute(this.items[0].el , 'markup', 0 );
+
+ },
+ items : [
+ {
+ xtype: Gtk.CellRendererText,
+ pack : "pack_start"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ xtype: Gtk.ScrolledWindow,
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.set_policy (Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
+ },
+ items : [
+ {
+ xtype: Gtk.TreeView,
+ listeners : {
+ cursor_changed : function (self) {
+ // SEE SELECTION.CHANGED
+ var files = this.files();
+ this.get('/patchview').showDiff(files);
+ //var value = ''+ ret.model.get_value(ret.iter, 1).value.get_string();
+ //print("OUT?" + value);// id..
+ // load the list in the right grid..
+
+ return true;
+
+ }
+ },
+ id : "changedFilesView",
+ pack : "add",
+ files : function() {
+ if (this.el.get_selection().count_selected_rows() < 1) {
+ //nothing? - clea it?
+ return [];
+ }
+
+ var ret = {};
+
+
+ var s = this.el.get_selection();
+ var files = [];
+ s.selected_foreach(function(model,p,iter) {
+
+ files.push( model.get_value(iter, 0).value.get_string());
+
+ });
+ return files;
+ },
+ init : function() {
+ XObject.prototype.init.call(this);
+ var description = new Pango.FontDescription.c_new();
+ description.set_size(8000);
+ this.el.modify_font(description);
+
+ this.selection = this.el.get_selection();
+ this.selection.set_mode( Gtk.SelectionMode.MULTIPLE);
+ var _this = this;
+ this.selection.signal['changed'].connect(function() {
+ _this.listeners.cursor_changed.apply(
+ _this, [ _this, '']
+ );
+ });
+ },
+ items : [
+ {
+ xtype: Gtk.ListStore,
+ id : "changedFilesStore",
+ pack : "set_model",
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.set_column_types ( 3, [
+ GObject.TYPE_STRING, // file
+ GObject.TYPE_STRING, // added
+ GObject.TYPE_STRING, // removed
+ ] );
+ },
+ load : function(tr)
+ {
+ //this.insert(citer,iter,0);
+ this.el.clear();
+ for(var i =0 ; i < tr.length; i++) {
+ var ret = { };
+
+ this.el.append(ret);
+
+ //print(JSON.stringify(ret,null,4));
+
+
+ this.el.set_value(ret.iter, 0, '' + tr[i].filename );
+ this.el.set_value(ret.iter, 1, '' + tr[i].added );
+ this.el.set_value(ret.iter, 2, '' + tr[i].removed );
+
+
+ }
+ }
+ },
+ {
+ xtype: Gtk.TreeViewColumn,
+ resizable : true,
+ min_width : 200,
+ pack : "append_column",
+ title : "Filename",
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.add_attribute(this.items[0].el , 'markup', 0 );
+
+ },
+ items : [
+ {
+ xtype: Gtk.CellRendererText,
+ pack : "pack_start"
+ }
+ ]
+ },
+ {
+ xtype: Gtk.TreeViewColumn,
+ min_width : 50,
+ pack : "append_column",
+ title : "Added",
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.add_attribute(this.items[0].el , 'markup', 1 );
+
+ },
+ items : [
+ {
+ xtype: Gtk.CellRendererText,
+ pack : "pack_start"
+ }
+ ]
+ },
+ {
+ xtype: Gtk.TreeViewColumn,
+ min_width : 50,
+ pack : "append_column",
+ title : "Removed",
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.add_attribute(this.items[0].el , 'markup', 2 );
+
+ },
+ items : [
+ {
+ xtype: Gtk.CellRendererText,
+ pack : "pack_start"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ xtype: Gtk.TreeView,
+ pack : false,
+ items : [
+ {
+ xtype: Gtk.ListStore,
+ pack : false
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ xtype: Gtk.VBox,
+ items : [
+ {
+ xtype: Gtk.HBox,
+ pack : "pack_start,false,false,0",
+ items : [
+ {
+ xtype: Gtk.Button,
+ listeners : {
+ clicked : function (self) {
+
+
+ var model = this.get('/historyTreeStore');
+
+ if (model.release === false) {
+ return;
+ }
+
+
+ var files = this.get('/changedFilesView').files();
+
+ if (!files.length) {
+ return; // error.!
+ }
+ var diff = Merger.repo.diff(files, model.release, model.rev);
+
+
+ print("history?");
+
+
+ var history = Merger.repo.history(files, 1, 'rev', model.rev);
+
+ print("History" + JSON.stringify(history, null,4));
+
+ Commit = imports.Commit.Commit;
+
+ Commit.el.set_modal(true);
+ Commit.el.set_transient_for(Merger.el);
+
+ var ce = Commit.show({
+ repo : Merger.repo,
+ files : files,
+ release : model.release,
+ rev : model.rev,
+ author : history[0].changeby,
+ changed : history[0].changed_raw
+
+
+ });
+ if (ce === false ) {
+ return;
+ }
+
+
+ var diff = Merger.repo.diff(files, model.release, model.rev);
+
+
+ print(JSON.stringify(ce,null,4));
+ //.... commit!!!
+
+ imports.GitMonitor.GitMonitor.pause();
+
+
+
+ var msg = new Gtk.MessageDialog( {
+ buttons : Gtk.ButtonsType.NONE,
+ text: "Committing Changes"
+ });
+
+ msg.set_transient_for(Merger.el);
+ msg.set_modal(true);
+ msg.show_all();
+
+
+
+ try {
+
+ Merger.repo.checkout(model.release);
+
+ print("Call apply patch");
+
+ Merger.repo.applyPatch(diff);
+
+ var author = Merger.repo.parseAuthor(ce.author);
+
+ print("Add new files.");
+ // add all the files..
+ Merger.repo.add(files);
+
+ print("Commit changes.");
+ Merger.repo.commit({
+ name : author.name,
+ email : author.email,
+ author : ce.author,
+ changed : ce.changed,
+ reason : ce.message,
+ files : files
+
+ });
+
+
+ } catch (e) {
+ //message..
+ msg.hide();
+
+ var emsg = new Gtk.MessageDialog({
+ message_type: Gtk.MessageType.ERROR,
+ buttons : Gtk.ButtonsType.OK,
+ text: e.message
+ });
+ emsg.set_transient_for(Merger.el);
+ emsg.set_modal(true);
+ emsg.run();
+ emsg.destroy();
+ Merger.repo.stash(); // revert change.. - so we can go back...
+ }
+ msg.show_all();
+ msg.set_markup("Changing to previous branch");
+ Merger.repo.checkout(model.working);
+
+
+ // if gitlive was previously running warn the user that it is now paused..
+ /*
+ var cmsg = new Gtk.MessageDialog({
+ message_type: Gtk.MessageType.ERROR,
+ buttons : Gtk.ButtonsType.OK,
+ text: "Git Live is now paused "
+ });
+ cmsg.run();
+ cmsg.destroy();
+ */
+ var _t = this;
+ GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 5, function() {
+ imports.GitMonitor.GitMonitor.resume();
+ msg.hide();
+ msg.destroy();
+ _t.get('/historyTreeStore').loadTree();
+ _t.get('/changedFilesStore').el.clear();
+ _t.get('/patchview').showDiff(files);
+ return false; //only once.
+ });
+
+
+
+
+ }
+ },
+ label : "Commit diff (no merge)"
+ }
+ ]
+ },
+ {
+ xtype: Gtk.ScrolledWindow,
+ pack : "pack_end,true,true,0",
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.set_policy (Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
+ },
+ items : [
+ {
+ xtype: WebKit.WebView,
+ id : "patchview",
+ pack : "add",
+ clear : function() {
+
+
+
+
+ // remove..
+ var s = "document.body.textContent='';"
+
+ this.el.execute_script(s);
+
+
+
+
+
+ },
+ showDiff : function(files) {
+ this.clear();
+
+
+ var model = this.get('/historyTreeStore');
+
+ if (model.release === false) {
+ return;
+ }
+
+ var diff = Merger.repo.diff(files, model.release, model.rev);
+
+ // remove..
+ var s = "var pre = document.createElement('pre'); document.body.appendChild(pre);";
+ s += "pre.textContent = " +
+ JSON.stringify(Merger.repo.lastCmd + "\n") + '+ ' +
+ JSON.stringify(diff) + ";";
+ print(s);
+
+ this.el.execute_script(s);
+
+
+
+
+
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ xtype: Gtk.Button,
+ id : "ok_button",
+ label : "Close",
+ pack : "add_action_widget,1"
+ }
+ ]
+});
+Merger.init();
+XObject.cache['/Merger'] = Merger;
--- /dev/null
+//<Script type="text/javascript">
+var Gio = imports.gi.Gio;
+var GLib = imports.gi.GLib;
+
+var XObject = imports.XObject.XObject;
+var File = imports.File.File;
+
+/**
+ * Monitor class - handles monitor managment for a large tree...
+ *
+ *
+ * This
+ *
+ * usage :
+ * x = new Monitor({
+ change : function () {
+ * ....
+ *}
+ }
+ * x.add('/somepath')
+ * x.stop() // stops all scanning.
+ * x.play(); // starts the scanning
+ *
+ *
+ *
+ *
+ */
+
+function Monitor(cfg){
+ for (var i in cfg) {
+ this[i] = cfg[i];
+ }
+
+
+ this.monitors = [];
+
+ this.top = [];
+
+}
+
+Monitor.prototype = {
+
+ monitors : false, // Array of GioFileMonitors
+ top : false, // list of top level directories..
+ paused : false,
+ /**
+ * add a directory or file to monitor
+ */
+ add : function(add)
+ {
+ this.top.push(add);
+ },
+ /**
+ * start monitoring
+ */
+ start : function()
+ {
+ for(var i =0;i < this.top.length; i++) {
+ this.monitor(this.top[i]);
+ }
+ },
+ /**
+ * stop / pause monitoring
+ *
+ */
+ stop : function()
+ {
+
+ for(var i =0;i < this.monitors.length; i++) {
+ this.monitors[i].cancel();
+ }
+ this.monitors = [];
+ },
+ /**
+ * pause monitoring - without changing what's monitored
+ */
+ pause : function()
+ {
+ this.paused = true;
+ },
+ /**
+ * resume monitoring - without changing what's monitored
+ */
+ resume : function()
+ {
+ this.paused = false;
+ },
+ /**
+ * monitor a file or directory (privatish)
+ *
+ * initially called with ~/gitlive null 0 (effectvely)
+ *
+ *
+ */
+ monitor : function(path, fn, depth)
+ {
+ var _this = this;
+
+ // print("ADD: " + path)
+
+ depth = typeof(depth) == 'number' ? depth *1 : 0;
+
+
+ fn = fn || function (fm, f, of, event_type, uh) {
+ _this.onEvent(fm, f, of, event_type, uh);
+ }
+
+
+ var f = Gio.file_new_for_path(path);
+ //var cancel = new Gio.Cancellable ();
+ if (depth > 0) {
+
+ var fm = f.monitor(2,null); //Gio.FileMonitorFlags.SEND_MOVED
+
+
+
+ XObject.isSeed ? fm.signal.changed.connect(fn) : fm.connect('changed',fn);
+ this.monitors.push(fm);
+ // print("ADD path " + depth + ' ' + path);
+ }
+ // iterate children?
+ // - this is not used.
+ //if (GLib.file_test(path + '/.git' , GLib.FileTest.IS_DIR) && this.initRepo) {
+
+ // this.initRepo(path);
+ //}
+
+ var file_enum = f.enumerate_children(
+ Gio.FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME + ','+
+ Gio.FILE_ATTRIBUTE_STANDARD_TYPE,
+ Gio.FileQueryInfoFlags.NONE,
+ null);
+
+ var next_file;
+
+ while ((next_file = file_enum.next_file(null)) != null) {
+
+ //print("got a file " + next_file.sudo () + '?=' + Gio.FileType.DIRECTORY);
+
+ if (next_file.get_file_type() != Gio.FileType.DIRECTORY) {
+ next_file = null;
+ continue;
+ }
+
+ if (next_file.get_file_type() == Gio.FileType.SYMBOLIC_LINK) {
+ next_file = null;
+ continue;
+ }
+
+ if (next_file.get_display_name()[0] == '.') {
+ next_file = null;
+ continue;
+ }
+ var sp = path+'/'+next_file.get_display_name();
+ // skip modules.
+ //print("got a file : " + sp);
+
+ next_file = null;
+
+
+
+ this.monitor(sp, fn, depth + 1);
+
+ }
+
+ file_enum.close(null);
+ },
+
+
+
+ realpath : function(file)
+ {
+ if (!file) {
+ return file;
+ }
+
+ if (GLib.file_test(file.get_path(), GLib.FileTest.EXISTS)) {
+ var rp = File.realpath(file.get_path());
+ return Gio.file_new_for_path(rp);
+
+ }
+ // file does not currently exist..
+ // check parent.
+ var bn = file.get_basename();
+ var ar = file.get_path().split('/');
+ ar.pop();
+ var dirname = ar.join('/');
+ var rp = File.realpath(dirname);
+ return Gio.file_new_for_path(rp + '/' + bn);
+
+ },
+
+
+
+
+
+ onEvent : function(fm, f_orig, of_orig, event_type, uh)
+ {
+ if (this.paused) {
+ return;
+ }
+
+ var f = this.realpath(f_orig);
+
+ var of = this.realpath(of_orig);
+
+ var src = {
+ name : f.get_basename(),
+ path : f.get_path(),
+ dir : GLib.path_get_dirname(f.get_path())
+ };
+
+ var dest = false;
+
+ if (of) {
+
+ dest = {
+ name : of.get_basename(),
+ path : of.get_path(),
+ dir : GLib.path_get_dirname(of.get_path())
+ }
+ }
+ var event_name = 'UKNOWN';;
+
+ for(var i in Gio.FileMonitorEvent) {
+ if (Gio.FileMonitorEvent[i] == event_type) {
+ event_name = i;
+ }
+ }
+
+ //print (JSON.stringify([event_name , f.get_path(), of ? of.get_path() : false ] ));
+ //print ("got src: " + src.toString());
+ //print ("got event: " + src.toString());
+ try {
+
+ switch(event_type) {
+ case Gio.FileMonitorEvent.CHANGED:
+ this.onChanged(src);
+ return; // ingore thise?? -wait for changes_done_htin?
+
+ case Gio.FileMonitorEvent.CHANGES_DONE_HINT:
+ this.onChangesDoneHint(src);
+ return;
+
+ case Gio.FileMonitorEvent.DELETED:
+ this.onDeleted(src);
+ return;
+
+ case Gio.FileMonitorEvent.CREATED:
+ this.onCreated(src);
+ return;
+
+ case Gio.FileMonitorEvent.ATTRIBUTE_CHANGED: // eg. chmod/chatt
+ this.onAttributeChanged(src);
+ return;
+
+ case Gio.FileMonitorEvent.MOVED: // eg. chmod/chatt
+ this.onMoved(src,dest);
+ return;
+
+ // rest are mount related - not really relivant.. maybe add later..
+ }
+ } catch(e) {
+ print(e);
+ }
+
+ },
+
+ /** override these to do stuff.. */
+ initRepo : function(src) { }, // called on startup at the top level repo dir.
+ onChanged : function(src) { },
+ onChangesDoneHint : function(src) { },
+ onDeleted : function(src) { },
+ onCreated : function(src) { },
+ onAttributeChanged : function(src) { },
+ onMoved : function(src) { }
+
+
+}
+
+
+
+
+
+
+
--- /dev/null
+const GLib = imports.gi.GLib;
+
+const File = imports.File.File;
+
+/**
+ * usage:
+ * var cfg = Netrc.forHost('www.google.com');
+ * var uname = cfg.login
+ * var pass = cfg.password
+ *
+ *
+ */
+Netrc = {
+
+ forHost: function(name)
+ {
+ try {
+ return this._data[name];
+ } catch(e) {
+ throw "Host " + name + " was not found in netrc file (or parser could not read file..)\n";
+ }
+
+ },
+
+ _data : {},
+ /**
+ * private - called at the bottom..
+ */
+ _load : function()
+ {
+
+ var netrc = File.read(GLib.get_home_dir() + "/.netrc");
+ var authdata = {};
+ netrc.split("\n").forEach(function(nl) {
+ var line = {};
+ var k = false
+
+ nl.replace(/\s+$/,'').replace(/^\s+/,'').split(/\s+/).forEach(function(kv) {
+
+ if (!k) {
+ k = kv;
+ return
+ }
+ line[k] = kv
+ k = false;
+ });
+
+ authdata[line.machine] = line;
+
+ });
+ this._data = authdata;
+
+ }
+
+
+
+
+}
+// load the file up.
+Netrc._load();
\ No newline at end of file
--- /dev/null
+
+XObject = imports.XObject.XObject;
+XMLHttpRequest = imports.XMLHttpRequest.XMLHttpRequest;
+Netrc = imports.Netrc.Netrc;
+Date = imports.Date.Date;
+/**
+ *
+ * Projects -
+ *
+ *
+ *
+ */
+
+Projects = {
+
+ list : [],
+
+ // called on startup..??
+ // clear list, and call again to refresh..
+
+ fetch: function(callback)
+ {
+ // have we got the status in the last 15 mins..
+ // we should not need to get it again... - it's probably not changed.
+
+ if (this.list.length) {
+ callback( this.list);
+ }
+
+ _this = this;
+ // do the request to get the task..
+ var r = new XMLHttpRequest({
+ onreadystatechange : function() {
+ print("Got result.");
+ if (this.status != 4) {
+ return;
+ }
+
+
+ var res = JSON.parse(this.responseText);
+
+ //print(JSON.stringify(res,null,4))
+ //print([ res.success , res.data.length ]);
+ if (!res.success || !res.data.length) {
+ print("NO tasks returned");
+ Projects.list = []; //res.data;
+ return;
+ }
+ Projects.list = res.data;
+
+ //print("Current task:" + JSON.stringify(_this.curTask,null,4));
+ callback(res.data);
+ }
+
+ });
+ var netrc = Netrc.forHost('git.roojs.com');
+
+ r.open('GET',
+ "http://roojs.com/admin.php/Roo/Projects?sort=code&dir=ASC&active=1&limit=999"
+ ,true, netrc.login, netrc.password );
+ // print("Getting current task: " + "http://roojs.com/admin.php/Roo/mtrack_ticket?repo_shortname=" + repo.name);
+ r.send();
+
+ },
+
+
+
+
+
+};
+
+
+
+
+//-------------- testing
+/*
+Gtk = imports.gi.Gtk;
+Gtk.init(Seed.argv);
+Projects.fetch( function(list) { print(JSON.stringify(list,null,4)); } );
+Gtk.main();
+ */
\ No newline at end of file
--- /dev/null
+Gtk = imports.gi.Gtk;
+Gdk = imports.gi.Gdk;
+Pango = imports.gi.Pango;
+GLib = imports.gi.GLib;
+Gio = imports.gi.Gio;
+GObject = imports.gi.GObject;
+GtkSource = imports.gi.GtkSource;
+WebKit = imports.gi.WebKit;
+Vte = imports.gi.Vte;
+console = imports.console;
+XObject = imports.XObject.XObject;
+RemoteEdit=new XObject({
+ xtype: Gtk.Dialog,
+ listeners : {
+ destroy_event : function (self, event) {
+ this.el.hide();
+ return false;
+ },
+ response : function (self, id) {
+ // hide
+ //if (id < 1) {
+ this.el.hide();
+ return;
+ //}
+ if (typeof(this.get('bug').getValue()) != 'object') {
+ print("ERROR");
+ return;
+ }
+
+ this.el.hide();
+
+ //var val = this.get('bug').getValue();
+ // Seed.print(val);
+ }
+ },
+ ' modal' : true,
+ border_width : 3,
+ default_height : 150,
+ default_width : 500,
+ title : "Remotes",
+ deletable : true,
+ modal : true,
+ show : function(c) {
+
+ if (!this.el) {
+ this.init();
+ }
+ var _this = this;
+ //this.get('/remotesStore').load();
+ this.get('/remoteURL').el.get_child().set_text('');
+ this.get('/remoteName').el.set_text('');
+
+
+ this.el.show_all();
+
+ var run_ret = this.el.run();
+ if (run_ret < 1 ) {
+ return false;
+ }
+ var ret= {
+ url : this.get('/remoteURL').el.get_child().get_text(),
+ name : this.get('/remoteName').el.get_text()
+ };
+
+ return ret;
+
+
+
+ },
+ items : [
+ {
+ xtype: Gtk.VBox,
+ pack : function(p,e) {
+ p.el.get_content_area().pack_start(e.el,true,true,10);
+ },
+ items : [
+ {
+ xtype: Gtk.HBox,
+ pack : "pack_start,false,true,10",
+ items : [
+ {
+ xtype: Gtk.Label,
+ label : "URL :",
+ pack : "pack_start,false,false,10",
+ width_request : 50
+ },
+ {
+ xtype: Gtk.ComboBox,
+ listeners : {
+ changed : function (self) {
+ var val = this.el.get_child().get_text();
+ print(JSON.stringify(val));
+ if (!val.length) {
+ return;
+ }
+
+ var name = this.get('/remoteName').el.get_text();
+ if (name.length) {
+ return;
+ }
+ // fill in name
+ var val = imports.Scm.Git.Repo.Repo.parseURL(val);
+ if ((typeof(val.host) != 'undefined') && val.host.length) {
+ var host = val.host;
+ // need to add github owner...
+ if (host.match(/github.com$/)) {
+ host += '.' + val.path.split('/').shift();
+ }
+
+
+ this.get('/remoteName').el.set_text(host);
+ }
+
+
+ }
+ },
+ id : "remoteURL",
+ init : function() {
+ this.el = new Gtk.ComboBox.with_entry();
+
+
+ this.model = new XObject(this.model);
+ this.model.init();
+ this.el.set_model(this.model.el);
+ this.el.set_entry_text_column (0);
+ XObject.prototype.init.call(this);
+
+ },
+ load : function(tr)
+ {
+ //this.insert(citer,iter,0);
+ this.model.el.clear();
+
+ var master = false;
+ var working = false;
+
+ for(var i =0 ; i < tr.length; i++) {
+ var ret = { };
+ this.model.el.append(ret);
+ //print(JSON.stringify(ret,null,4));
+ if (tr[i].name == 'master') {
+ master = i;
+ }
+ if (tr[i].name == 'working') {
+ working = i;
+ }
+ this.model.el.set_value(ret.iter, 0, '' + tr[i].name );
+ this.model.el.set_value(ret.iter, 1, '' + tr[i].rev );
+
+
+ }
+ if (master !== false) {
+ this.el.set_active(master);
+ }
+ if (working !== false) {
+ this.el.set_active(working);
+ }
+
+ },
+ model : {
+ xtype: Gtk.ListStore,
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.set_column_types ( 3, [
+ GObject.TYPE_STRING, // file
+ GObject.TYPE_STRING, // added
+ GObject.TYPE_STRING, // removed
+ ] );
+ }
+ }
+ }
+ ]
+ },
+ {
+ xtype: Gtk.HBox,
+ pack : "pack_start,false,true,10",
+ items : [
+ {
+ xtype: Gtk.Label,
+ label : "Name : ",
+ pack : "pack_start,false,false,10",
+ width_request : 50,
+ xalign : 1
+ },
+ {
+ xtype: Gtk.Entry,
+ id : "remoteName"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ xtype: Gtk.Button,
+ label : "Cancel",
+ pack : "add_action_widget,0"
+ },
+ {
+ xtype: Gtk.Button,
+ id : "ok_button",
+ label : "Add",
+ pack : "add_action_widget,1"
+ }
+ ]
+});
+RemoteEdit.init();
+XObject.cache['/RemoteEdit'] = RemoteEdit;
--- /dev/null
+Gtk = imports.gi.Gtk;
+Gdk = imports.gi.Gdk;
+Pango = imports.gi.Pango;
+GLib = imports.gi.GLib;
+Gio = imports.gi.Gio;
+GObject = imports.gi.GObject;
+GtkSource = imports.gi.GtkSource;
+WebKit = imports.gi.WebKit;
+Vte = imports.gi.Vte;
+console = imports.console;
+XObject = imports.XObject.XObject;
+Remotes=new XObject({
+ xtype: Gtk.Dialog,
+ listeners : {
+ destroy_event : function (self, event) {
+ this.el.hide();
+ return false;
+ },
+ response : function (self, id) {
+ // hide
+ //if (id < 1) {
+ this.el.hide();
+ return;
+ //}
+ if (typeof(this.get('bug').getValue()) != 'object') {
+ print("ERROR");
+ return;
+ }
+
+ this.el.hide();
+
+ //var val = this.get('bug').getValue();
+ // Seed.print(val);
+ }
+ },
+ ' modal' : true,
+ border_width : 3,
+ default_height : 300,
+ default_width : 500,
+ title : "Remotes",
+ deletable : true,
+ modal : true,
+ show : function(c) {
+
+ if (!this.el) {
+ this.init();
+ }
+ var _this = this;
+ this.get('/remotesStore').load();
+ this.el.show_all();
+
+ var run_ret = this.el.run();
+ if (run_ret < 1 ) {
+ return "DONE";
+ }
+ print("RUN RETURN : " + run_ret);
+ return "DONE";
+
+ },
+ items : [
+ {
+ xtype: Gtk.VBox,
+ pack : function(p,e) {
+ p.el.get_content_area().pack_start(e.el,true,true,0)
+ },
+ items : [
+ {
+ xtype: Gtk.HBox,
+ pack : "pack_start,false,true",
+ items : [
+ {
+ xtype: Gtk.Button,
+ listeners : {
+ clicked : function (self) {
+
+
+ var RemoteEdit= imports.RemoteEdit.RemoteEdit
+ RemoteEdit.repo = Remotes.repo;
+ RemoteEdit.el.set_transient_for(Remotes.el);
+
+ var res = RemoteEdit.show();
+
+ if (res != false) {
+ Remotes.repo.remotes(res);
+ }
+
+ this.get('/remotesStore').load();
+
+
+ }
+ },
+ label : "Add",
+ pack : "add"
+ }
+ ]
+ },
+ {
+ xtype: Gtk.ScrolledWindow,
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.set_policy (Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
+ },
+ items : [
+ {
+ xtype: Gtk.TreeView,
+ listeners : {
+ cursor_changed : function (self)
+ {
+
+ return;
+ // SEE SELECTION.CHANGED
+ if (this.el.get_selection().count_selected_rows() < 1) {
+ //nothing? - clea it?
+ return;
+ }
+ var ret = {};
+ var model = this.get('/changedFilesStore');
+
+ var s = this.el.get_selection();
+ var files = [];
+ s.selected_foreach(function(model,p,iter) {
+
+ files.push( model.get_value(iter, 0).value.get_string());
+
+ });
+ this.get('/patchview').showDiff(files);
+ //var value = ''+ ret.model.get_value(ret.iter, 1).value.get_string();
+ //print("OUT?" + value);// id..
+ // load the list in the right grid..
+
+ return true;
+
+ }
+ },
+ id : "remotesView",
+ pack : "add",
+ init : function() {
+ XObject.prototype.init.call(this);
+ var description = new Pango.FontDescription.c_new();
+ description.set_size(8000);
+ this.el.modify_font(description);
+
+ this.selection = this.el.get_selection();
+ this.selection.set_mode( Gtk.SelectionMode.MULTIPLE);
+ var _this = this;
+ this.selection.signal['changed'].connect(function() {
+ _this.listeners.cursor_changed.apply(
+ _this, [ _this, '']
+ );
+ });
+ },
+ items : [
+ {
+ xtype: Gtk.ListStore,
+ id : "remotesStore",
+ pack : "set_model",
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.set_column_types ( 3, [
+ GObject.TYPE_STRING, // file
+ GObject.TYPE_STRING, // added
+ GObject.TYPE_STRING, // removed
+ ] );
+ },
+ load : function(tr)
+ {
+ //this.insert(citer,iter,0);
+ this.el.clear();
+
+ var tr = Remotes.repo.remotes();
+
+
+ for(var i =0 ; i < tr.length; i++) {
+ var ret = { };
+
+ this.el.append(ret);
+
+ //print(JSON.stringify(ret,null,4));
+
+
+ this.el.set_value(ret.iter, 0, '' + tr[i].name );
+ this.el.set_value(ret.iter, 1, '' + tr[i].url );
+ this.el.set_value(ret.iter, 2, '' + tr[i].type );
+
+
+ }
+ }
+ },
+ {
+ xtype: Gtk.TreeViewColumn,
+ min_width : 70,
+ pack : "append_column",
+ resizable : true,
+ title : "Name",
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.add_attribute(this.items[0].el , 'markup', 0 );
+
+ },
+ items : [
+ {
+ xtype: Gtk.CellRendererText,
+ pack : "pack_start"
+ }
+ ]
+ },
+ {
+ xtype: Gtk.TreeViewColumn,
+ min_width : 70,
+ pack : "append_column",
+ resizable : true,
+ title : "Type",
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.add_attribute(this.items[0].el , 'markup', 2 );
+
+ },
+ items : [
+ {
+ xtype: Gtk.CellRendererText,
+ pack : "pack_start"
+ }
+ ]
+ },
+ {
+ xtype: Gtk.TreeViewColumn,
+ min_width : 200,
+ pack : "append_column",
+ title : "URL",
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.add_attribute(this.items[0].el , 'markup', 1 );
+
+ },
+ items : [
+ {
+ xtype: Gtk.CellRendererText,
+ pack : "pack_start"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ xtype: Gtk.TreeView,
+ pack : false,
+ items : [
+ {
+ xtype: Gtk.ListStore,
+ pack : false
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ xtype: Gtk.Button,
+ label : "Cancel",
+ pack : "add_action_widget,0"
+ },
+ {
+ xtype: Gtk.Button,
+ id : "ok_button",
+ label : "OK",
+ pack : "add_action_widget,1"
+ }
+ ]
+});
+Remotes.init();
+XObject.cache['/Remotes'] = Remotes;
--- /dev/null
+/**
+ * a generic simple api for requests...
+ *
+ * new Request({
+ url :
+ params : {}
+ method : ?? not yet
+ success : function() { ... }
+
+ });
+ *
+ *
+ */
+
+
+XMLHttpRequest = imports.XMLHttpRequest.XMLHttpRequest;
+Netrc = imports.Netrc.Netrc;
+
+Request = function(opts) {
+
+
+ _this = this;
+ // do the request to get the task..
+ var r = new XMLHttpRequest({
+
+ onreadystatechange : function()
+ {
+ print("Got result.");
+ if (this.status != 4) {
+ return;
+ }
+
+
+ var res = JSON.parse(this.responseText);
+
+ //print(JSON.stringify(res,null,4))
+ //print([ res.success , res.data.length ]);
+ if (!res.success || !res.data.length) {
+ print("NO tasks returned");
+ callback([]);
+ return;
+ }
+
+ //print("Current task:" + JSON.stringify(_this.curTask,null,4));
+ if (opts.success) {
+ opts.success.call(opts.scope || this, res.data);
+ }
+ }
+
+ });
+
+
+ var netrc = Netrc.forHost('git.roojs.com');
+
+
+
+ r.open('GET',
+ 'http://roojs.com/admin.php' + opts.url + '?' + r.urlEncode(opts.params)
+ ,true, netrc.login, netrc.password );
+ print("Getting current task: " +
+ 'http://roojs.com/admin.php' + opts.url + '?' + r.urlEncode(opts.params)
+ );
+ r.send();
+
+}
+
+
+
+
--- /dev/null
+///<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' },
+* }
+* });
+*
+*
+*
+
+*
+*
+* CRITICAL - needs this change to gir in GLib-2.0.gir g_spawn_async_with_pipes
+* Fixed in Ubuntu 12.10
+ <parameter name="argv" transfer-ownership="none">
+ <array c:type="gchar**">
+ <type name="utf8"/>
+ </array>
+ </parameter>
+ <parameter name="envp" transfer-ownership="none" allow-none="1">
+ <array c:type="gchar**">
+ <type name="utf8"/>
+ </array>
+ </parameter>
+*
+* ALSO in GLib-2.0.gir
+
+<method name="read_line"
+ c:identifier="g_io_channel_read_line"
+ throws="1">
+ <return-value transfer-ownership="none">
+ <type name="IOStatus" c:type="GIOStatus"/>
+ </return-value>
+ <parameters>
+ <parameter name="str_return" transfer-ownership="full" direction="out">
+ <type name="utf8" c:type="gchar**"/>
+ </parameter>
+ <parameter name="length" transfer-ownership="none" direction="out">
+ <type name="gsize" c:type="gsize*"/>
+ </parameter>
+ <parameter name="terminator_pos" transfer-ownership="none" direction="out">
+ <type name="gsize" c:type="gsize*"/>
+ </parameter>
+ </parameters>
+ </method>
+*
+* run g-ir-compile -o /usr/lib/girepostitory-1.0/GLib-2.0.typelib GLib-2.0.gir
+*
+*
+*/
+
+
+/**
+ * @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 = {
+
+ ctx : false, // the mainloop ctx.
+ 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.
+ * result is applied to object properties (eg. 'output' or 'stderr')
+ * @returns {Object} self.
+ */
+ run : function()
+ {
+
+ var _this = this;
+
+ var err_src = false;
+ var out_src = false;
+ var ret = {};
+
+ if (this.debug) {
+ print("cd " + this.cwd +";" + this.args.join(" "));
+ }
+
+ var gret = GLib.spawn_async_with_pipes(this.cwd, this.args, this.env,
+ GLib.SpawnFlags.DO_NOT_REAP_CHILD + GLib.SpawnFlags.SEARCH_PATH ,
+ null, null, ret);
+
+ var isSeed = true;
+ if (typeof(Seed) == 'undefined') {
+ ret = {
+ child_pid : gret[1],
+ standard_input : gret[2],
+ standard_output: gret[3],
+ standard_error: gret[4]
+ };
+ isSeed = false;
+ }
+
+ //print(JSON.stringify(gret));
+ this.pid = ret.child_pid;
+
+ if (this.debug) {
+ print("PID: " + this.pid);
+ }
+
+
+
+ GLib.child_watch_add(GLib.PRIORITY_DEFAULT, this.pid, function(pid, result) {
+ _this.result = result;
+ if (_this.debug) {
+ print("child_watch_add : result: " + result);
+ }
+ _this.read(_this.out_ch);
+ _this.read(_this.err_ch);
+
+
+ GLib.spawn_close_pid(_this.pid);
+ _this.pid = false;
+ if (_this.ctx) {
+ _this.ctx.quit();
+ }
+ tidyup();
+ //print("DONE TIDYUP");
+ if (_this.listeners.finish) {
+ _this.listeners.finish.call(this, _this.result);
+ }
+ });
+
+ 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;
+
+ }
+
+
+ this.in_ch = new GLib.IOChannel.unix_new(ret.standard_input);
+ this.out_ch = new GLib.IOChannel.unix_new(ret.standard_output);
+ this.err_ch = new GLib.IOChannel.unix_new(ret.standard_error);
+
+ // make everything non-blocking!
+
+
+
+ // using NONBLOCKING only works if io_add_watch
+ //returns true/false in right conditions
+ 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 + GLib.IOCondition.HUP + GLib.IOCondition.ERR,
+ function() {
+
+ return _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 + GLib.IOCondition.HUP,
+ function()
+ {
+ return _this.read(_this.err_ch);
+
+ });
+
+
+
+ // call input..
+ if (this.pid !== false) {
+ // child can exit before 1we get this far..
+ if (this.listeners.input) {
+ print("Trying to call listeners");
+ try {
+ this.write(this.listeners.input.call(this));
+ // this probably needs to be a bit smarter...
+ //but... let's close input now..
+ this.in_ch.close();
+ _this.in_ch = false;
+
+
+
+
+
+ } 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");
+ }
+
+ this.ctx = isSeed ? new GLib.MainLoop.c_new (null, false) : GLib.MainLoop.new (null, false);;
+ this.ctx.run(false); // wait fore exit?
+
+ //print("main_loop done!");
+ } 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
+ }
+ //print("write: " + str);
+ // NEEDS GIR FIX! for return value.. let's ignore for the time being..
+ //var ret = {};
+ //var res = this.in_ch.write_chars(str, str.length, ret);
+ var res = this.in_ch.write_chars(str, str.length);
+
+ //print("write_char retunred:" + JSON.stringify(res) + ' ' +JSON.stringify(ret) );
+
+ if (res != GLib.IOStatus.NORMAL) {
+ throw "Write failed";
+ }
+ //return ret.value;
+ return str.length;
+
+ },
+
+ /**
+ * 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';
+ // print("prop: " + prop);
+ var _this = this;
+
+
+ //print(JSON.stringify(ch, null,4));
+ while (true) {
+
+ var x = {};
+ var status = ch.read_line( x);
+ // print('status: ' +JSON.stringify(status));
+ // print(JSON.stringify(x));
+ switch(status) {
+ case GLib.IOStatus.NORMAL:
+
+ //write(fn, x.str);
+ if (this.listeners[prop]) {
+ this.listeners[prop].call(this, x.str_return);
+ }
+ _this[prop] += x.str_return;
+ if (_this.debug) {
+ print(prop + ':' + x.str_return.replace(/\n/, ''));
+ }
+ if (this.async) {
+ try {
+ if (imports.gi.Gtk.events_pending()) {
+ imports.gi.Gtk.main_iteration();
+ }
+ } catch(e) {
+
+ }
+ }
+
+ //this.ctx.iteration(true);
+ continue;
+ case GLib.IOStatus.AGAIN:
+ //print("Should be called again.. waiting for more data..");
+ return true;
+ break;
+ case GLib.IOStatus.ERROR:
+ case GLib.IOStatus.EOF:
+ return false;
+ break;
+
+ }
+ break;
+ }
+
+ //print("RETURNING");
+ return false; // allow it to be called again..
+ }
+
+};
+/**
+ * @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
+try {
+ Seed.print(run({
+ args: ['ls', '/tmp'],
+ debug : true
+ }));
+} catch (e) { print(JSON.stringify(e)); }
+
+var secs = (new Date()).getSeconds()
+
+try {
+Seed.print(run({
+ args: ['/bin/touch', '/tmp/spawntest-' + secs ],
+ debug : true
+}));
+} catch (e) { print( 'Error: ' + JSON.stringify(e)); }
+
+
+ */
+
--- /dev/null
+/**
+ * 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 XObject = imports.XObject.XObject;
+
+//var gitlive = imports.gitlive;
+
+
+var StatusIcon = new XObject({
+
+ paused : false, // on!
+ xtype : Gtk.StatusIcon,
+ title : 'gitlive',
+ stock : Gtk.STOCK_REFRESH,
+ tooltip_text : 'GitLive',
+ init : function() {
+ XObject.prototype.init.call(this);
+ this.el.set_name('gitlive');
+ },
+ listeners : {
+ //'popup-menu' : function( w, event, event_time) {
+ 'activate' : function( w, event, event_time) {
+ print(Array.prototype.slice.call(arguments).join(','));
+
+ var menu = this.get('menu');
+
+ menu.el.show_all();
+
+ this.get(!this.paused ? 'resume' : 'pause' ).el.hide();
+ print("MENU EL: " + menu.el);
+ print("POPUP: " + typeof(menu.el.popup));
+
+ var isSeed = typeof(Seed) != 'undefined';
+ /* if (isSeed) {
+
+ //print(JSON.stringify([null, null, Gtk.StatusIcon.position_menu , this.el , 1, Gtk.get_current_event_time()]));
+ print( Gtk.get_current_event_time());
+ 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;
+ }
+ */
+ Gtk.get_current_event_device ()
+ menu.el.popup_for_device(
+ Gtk.get_current_event_device (),
+ null, null,null, null, null,
+ 1, Gtk.get_current_event_time());
+
+
+ //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);
+ menu.el.get_toplevel().move(10,10);
+
+ }
+ },
+ items : [
+ {
+ xtype: Gtk.Menu,
+ id : 'menu',
+ pack: false,
+ items : [
+ {
+ init : function() {
+
+ this.el = XObject.isSeed ?
+ new Gtk.ImageMenuItem.from_stock(Gtk.STOCK_MEDIA_PAUSE)
+ : new Gtk.ImageMenuItem.new_from_stock(Gtk.STOCK_MEDIA_PAUSE, null);
+ 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.GitMonitor.GitMonitor.stop();
+ // this.el.label = status ? 'Resume' : 'Pause';
+ this.parent.parent.el.set_from_stock( Gtk.STOCK_MEDIA_PAUSE );
+
+ }
+ }
+ },
+
+ {
+ init : function() {
+ this.el = XObject.isSeed ?
+ new Gtk.ImageMenuItem.from_stock(Gtk.STOCK_MEDIA_PLAY)
+ : new Gtk.ImageMenuItem.new_from_stock(Gtk.STOCK_MEDIA_PLAY, null);
+ 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.GitMonitor.GitMonitor.start();
+ //var status = this.el.label == 'Pause' ? 1 : 0
+ // this.el.label = status ? 'Resume' : 'Pause';
+
+
+ }
+ }
+ },
+
+ {
+ init : function() {
+ this.el = XObject.isSeed ?
+ new Gtk.ImageMenuItem.from_stock(Gtk.STOCK_FULLSCREEN)
+ : new Gtk.ImageMenuItem.new_from_stock(Gtk.STOCK_FULLSCREEN, null);
+
+ XObject.prototype.init.call(this);
+ },
+ label: 'Pull (Refresh) All',
+ always_show_image : true,
+ accel_group : null,
+ //label: 'Pause',
+ pack: 'append',
+ listeners : {
+ activate : function () {
+ imports.GitMonitor.GitMonitor.stop();
+
+
+ var tr = imports.Scm.Repo.Repo.list();
+ for (var i= 0; i< tr.length;i++) {
+ this.parent.parent.el.set_from_stock( i%2 ? Gtk.STOCK_FULLSCREEN : Gtk.STOCK_LEAVE_FULLSCREEN );
+
+ var repo = tr[i];
+ if (!repo.autocommit()) {
+ //??? should we ignore ones not on autocommit..
+ continue;
+ }
+ try {
+ this.parent.parent.el.set_tooltip_text("pull: " + repo.name);
+
+ var str = repo.pull();
+ // do not care if it's already in sycn..
+ if (str.match(/Already up-to-date/)) {
+ continue;
+ }
+ var notification = new Notify.Notification({
+ summary: "Updated " + repo.name,
+ body : str
+ });
+ notification.set_timeout(20);
+ notification.show();
+
+ } catch(e) {
+ this.parent.parent.el.set_from_stock( Gtk.STOCK_MEDIA_RECORD );
+ print(JSON.stringify(e));
+ print("notification or push errror- probably to many in queue..");
+ imports.gitlive.errorDialog(e.message);
+
+ }
+ }
+ this.parent.parent.el.set_tooltip_text(this.parent.parent.tooltip_text);
+
+
+
+
+ imports.GitMonitor.GitMonitor.start();
+ }
+ }
+ },
+ {
+ init : function() {
+ this.el = XObject.isSeed ?
+ new Gtk.ImageMenuItem.from_stock(Gtk.STOCK_SAVE)
+ : new Gtk.ImageMenuItem.new_from_stock(Gtk.STOCK_SAVE, null);
+
+ XObject.prototype.init.call(this);
+ },
+ label: 'Update Timesheet',
+ always_show_image : true,
+ accel_group : null,
+
+ //label: 'Pause',
+ pack: 'append',
+ listeners : {
+ activate : function () {
+ var ret = imports.FixBug.FixBug.show();
+
+ }
+ }
+ },
+
+
+ {
+ init : function() {
+ this.el = XObject.isSeed ?
+ new Gtk.ImageMenuItem.from_stock(Gtk.STOCK_FULLSCREEN)
+ : new Gtk.ImageMenuItem.new_from_stock(Gtk.STOCK_FULLSCREEN, null);
+ XObject.prototype.init.call(this);
+ },
+ label: 'Manage Clones',
+ always_show_image : true,
+ accel_group : null,
+
+ //label: 'Pause',
+ pack: 'append',
+ listeners : {
+ activate : function () {
+ var ret = imports.Clones.Clones.show();
+
+ }
+ }
+ },
+
+
+
+
+ {
+ init : function() {
+ this.el = XObject.isSeed ?
+ new Gtk.ImageMenuItem.from_stock(Gtk.STOCK_ABOUT)
+ : new Gtk.ImageMenuItem.new_from_stock(Gtk.STOCK_ABOUT, null);
+
+ XObject.prototype.init.call(this);
+ },
+ label: 'About GitLive',
+ pack: 'append',
+ listeners : {
+ activate : function () {
+ var msg = new Gtk.AboutDialog({
+ program_name : "Git Live",
+ version: '0.3',
+ website: 'http://www.roojs.org/index.php/projects/gitlive.html',
+ website_label: 'RooJS Consulting',
+ license : 'LGPL'
+ });
+ msg.set_authors([ "Alan Knowles <alan@roojs.com>" ]);
+ msg.run();
+ msg.destroy();
+ }
+ }
+ },
+
+ {
+ init : function() {
+
+ this.el = XObject.isSeed ?
+ new Gtk.ImageMenuItem.from_stock(Gtk.STOCK_QUIT)
+ : new Gtk.ImageMenuItem.new_from_stock(Gtk.STOCK_QUIT, null);
+
+ XObject.prototype.init.call(this);
+ },
+ label: 'Quit',
+ pack: 'append',
+ listeners : {
+ activate : function () {
+ Seed.quit();
+ }
+ }
+ }
+
+
+ ]
+ }
+ ]
+
+});
+
+
--- /dev/null
+
+XObject = imports.XObject.XObject;
+XMLHttpRequest = imports.XMLHttpRequest.XMLHttpRequest;
+Netrc = imports.Netrc.Netrc;
+Date = imports.Date.Date;
+/**
+ *
+ * Tasks
+ *
+ * Flow
+ *
+ * Commit
+ * => Tasks.notify(commit)
+ *
+ *
+ *
+ *
+ */
+
+Tasks = {
+
+ curTask : false,
+ commitRepo : false, // the DB version of repo info..
+ lastCommit : false,
+
+ nextPrompt : false, // time when the system last prompted a confirmation that a task is being worked on.
+
+
+ notifyIdle : function()
+ {
+
+ },
+
+ notify : function(commit)
+ {
+ if (this.inQuery && this.inQuery > (new Date())) {
+ // ignore the notification.. we are currently checking what the current
+ // status is.
+
+ // we need to handle a WTF situation where something below failed... so
+
+ return;
+ }
+ this.inQuery = (new Date()).add(Date.MINUTE, 5);
+ this.lastCommit = commit;
+ this.commitRepo = false;
+ this.curTask = false;
+ this.fetchTask();
+ },
+
+
+
+ fetchTask: function()
+ {
+ // have we got the status in the last 15 mins..
+ // we should not need to get it again... - it's probably not changed.
+ if (this.curTask && !this.curTask.hasExpired()) {
+ this.fetchRepo();
+ }
+ _this = this;
+ // do the request to get the task..
+ var r = new XMLHttpRequest({
+ onreadystatechange : function() {
+ print("Got result.");
+ if (this.status != 4) {
+ return;
+ }
+
+
+ var res = JSON.parse(this.responseText);
+
+ //print(JSON.stringify(res,null,4))
+ //print([ res.success , res.data.length ]);
+ _this.curTask = (res.success && res.data.length) ? (new Task(res.data[0])) : false;
+
+ print("Current task:" + JSON.stringify(_this.curTask,null,4));
+ _this.fetchRepo();
+ }
+
+ });
+ var netrc = Netrc.forHost('git.roojs.com');
+
+ r.open('GET',
+ "http://roojs.com/admin.php/Roo/cash_invoice_entry?_current_task=1"
+ ,true, netrc.login, netrc.password );
+ print("Getting current task: " + "http://roojs.com/admin.php/Roo/cash_invoice_entry?_current_task=1");
+ r.send();
+
+ },
+
+
+
+ list: function(repo, callback)
+ {
+ // have we got the status in the last 15 mins..
+ // we should not need to get it again... - it's probably not changed.
+
+
+ this.query({repo_shortname : repo.name }, callback);
+ },
+
+
+ query : function(params , callback)
+ {
+
+ _this = this;
+ // do the request to get the task..
+ var r = new XMLHttpRequest({
+ onreadystatechange : function() {
+ print("Got result.");
+ if (this.status != 4) {
+ return;
+ }
+
+
+ var res = JSON.parse(this.responseText);
+
+ //print(JSON.stringify(res,null,4))
+ //print([ res.success , res.data.length ]);
+ if (!res.success || !res.data.length) {
+ print("NO tasks returned");
+ callback([]);
+ return;
+ }
+
+ //print("Current task:" + JSON.stringify(_this.curTask,null,4));
+ callback(res.data);
+ }
+
+ });
+ var netrc = Netrc.forHost('git.roojs.com');
+
+
+
+ r.open('GET',
+ "http://roojs.com/admin.php/Roo/mtrack_ticket?" + r.urlEncode(params)
+ ,true, netrc.login, netrc.password );
+ print("Getting current task: " +
+
+ "http://roojs.com/admin.php/Roo/mtrack_ticket?" + r.urlEncode(params));
+ r.send();
+
+ },
+
+
+
+
+ fetchRepo: function()
+ {
+
+ var repo = this.lastCommit.repo;
+
+ _this = this;
+ var r = new XMLHttpRequest({
+ onreadystatechange : function() {
+ print("Got result.");
+ if (this.status != 4) {
+ return;
+ }
+
+
+ var res = JSON.parse(this.responseText);
+
+ print(JSON.stringify(res,null,4))
+ //print([ res.success , res.data.length ]);
+ _this.commitRepo = (res.success && res.data.length) ? res.data[0] : false;
+ print(JSON.stringify(_this.commitRepo))
+ _this.verifyCommit();
+ }
+
+ });
+ var netrc = Netrc.forHost('git.roojs.com');
+
+ r.open('GET',
+ "http://roojs.com/admin.php/Roo/mtrack_repos?shortname=" + repo.name
+ ,true, netrc.login, netrc.password );
+ //print("SEding request");
+ r.send();
+
+
+ },
+
+ //---------- end fetching - now verifying..
+
+
+
+ verifyCommit : function()
+ {
+ // using curTask + lastCommit decide what to do.
+ this.inQuery = 0;
+ //tests:::
+
+ // check to see if current task is being planned for too long..
+ // you should only enter task, and allow it to span over an hour.
+ // if you do the whole day on a task, then it will need to verify with you every so often that you
+ // need to confirm that you are still working on it..
+
+ /*
+
+ Example:
+
+ Start at 10am, marked working on it till 3pm.
+
+ So:
+ at 11am, the system will pop up a warning - are you still working on it?
+ -> if yes pressed, then next warning will be at 11pm
+
+
+ */
+
+ if (!this.currTask) {
+ this.promptForTask();
+ return;
+ }
+
+ if (!this.currTask.project_id) {
+ this.promptForTask();
+ return;
+ }
+
+ // are we working on the same project!!!!
+ if (this.currTask.project_id != this.commitRepo.project_id) {
+ this.promptForTask();
+ return;
+ }
+
+ // has the ticket been closed...
+
+ var is_project= this.curTask.project_id_code[0] != '*' ;
+ // is there a ticket?
+ if (is_project && !this.currTask.ticket_id) {
+ this.promptForTask();
+ return;
+ }
+ if (is_project && this.currTask.ticket_status) {
+ //TODO - if status is closed.. then we need to prompt..
+
+
+ }
+
+
+ // we now working on same project..
+
+
+ var now = new Date();
+
+ print(JSON.stringify(this.curTask));
+
+ var endoftask = this.curTask.action_datetime.add(Date.HOUR, this.curTask.qtyvalue);
+ print("END OF TASK: " + endoftask);
+
+ var max_stretch = now.add(Date.HOUR, 1);
+ print("Max stretch: " + max_stretch);
+ if (endoftask > max_stretch) {
+ this.fixEndCurrTask(); //
+
+ }
+ // still needs to be verified..
+
+
+
+
+
+
+ if (!this.nextPrompt && this.curTask) {
+ //var use_start = this.curTask.action_datetime < now ? now :
+ // if we have a task, then the next verification should be 1 hour after it started.
+ // even if we have only just seen it.. so we could already need verification.
+ this.nextPrompt = this.curTask.action_datetime; // the start time recorded in the database.
+ }
+
+
+ if (!this.nextPrompt || (this.nextPrompt < (new Date()))) {
+
+ this.promptForTask();
+ return;
+
+ }
+
+ // ok verified basic time...
+ //let's check to see if project matches..'
+
+
+
+
+ },
+
+
+
+
+ //---------- end verifying - now prompting..
+
+
+ fixEndCurrTask: function()
+ {
+ // set the end time of the current task to be now + 1 hours at most...
+ var now = new Date();
+ var eot = now.add(Date.HOUR, 1);
+ // now round it down to nearest 15 minutes..
+ var min = Math.round((eot.format('i')*1) / 15) * 15;
+ var reot = Date.parseDate(eot.format('Y-m-d H:') + (min ? min : '00') + ':00', 'Y-m-d H:i:s');
+
+ print("REAL END TIME" + reot.format('Y-m-d H:i:s'))
+ print("Current start time" + this.curTask.action_datetime.format('Y-m-d H:i:s'))
+
+ // how long between start and reot...
+ var hours = (reot - this.curTask.action_datetime) / (60*60 * 1000 );
+ var rounded = Math.round(hours * 4) / 4.0;
+ print("Rounded : " + rounded);
+ //return;
+ this.updateTask({ qtyvalue : rounded });
+ this.curTask.qtyvalue = rounded;
+
+ },
+
+ promptForTask : function()
+ {
+ /// fixme...
+ this.nextPrompt = (new Date()).add(Date.MINUTE, 60);
+
+
+ },
+
+ updateTask: function(setv)
+ {
+ var args = {};
+ XObject.extend(args,setv);
+ args.id = _this.curTask.id;
+
+
+ //print(JSON.stringify(args));
+ //return;
+
+
+ _this = this;
+ // do the request to get the task..
+ var r = new XMLHttpRequest({
+ onreadystatechange : function() {
+ print("Got result.");
+ if (this.status != 4) {
+ return;
+ }
+
+ print( this.responseText)
+
+ var res = JSON.parse(this.responseText);
+
+ print(JSON.stringify(res,null,4))
+ //print([ res.success , res.data.length ]);
+ }
+
+ });
+ var netrc = Netrc.forHost('git.roojs.com');
+
+ r.open('POST',
+ "http://roojs.com/admin.php/Roo/cash_invoice_entry?_current_task=1"
+ ,true, netrc.login, netrc.password );
+ //print("SEding request");
+ r.send(args);
+
+
+
+
+ }
+
+};
+
+
+
+
+
+Task = XObject.define(
+ function(cfg) {
+ // cal parent?
+ if (typeof(cfg) != 'object') {
+ print("CFG not oboject?");
+ return;
+ }
+ XObject.extend(this,cfg);
+
+ // fix up the values.
+ this.action_datetime = Date.parseDate(this.action_dt,'Y-m-d H:i:s');
+ // print("ACT DT: " + this.action_dt);
+
+ },
+ Object,
+ {
+ /**
+ * This is similar to the cash_invoice_entry data..
+ *
+ */
+ action_dt: '', //"2012-11-23 11:00:00"
+ description: '', //"QA on new site"
+ qtyvalue: 0, //"2.25"
+
+ hasExpired : function()
+ {
+
+ var exp = this.action_datetime.add(Date.HOUR, this.qtyvalue);
+ return (new Date()) > exp;
+
+ }
+ }
+);
+
+
+
+
+
+
+
+
+
+
+//-------------- testing
+/*
+Gtk = imports.gi.Gtk;
+Gtk.init(Seed.argv);
+Tasks.notify( { repo : imports.Scm.Repo.Repo.get('gitlive') } );
+Gtk.main();
+*/
\ No newline at end of file
--- /dev/null
+//<script type="text/javascript">
+/**
+ * log desktop actions..
+ *
+ * a potential add-on to gitlive....
+ * - basically tracks what applications are being worked on when, allowing you to
+ * use it to generate time tracking (eg. invoices...) later..
+ *
+ *
+ * apt-get install gir1.2-wnck-3.0
+ * -- needs latest seed (HEAD as of 30nov2011) with the xorg module built in..
+ *
+ */
+
+
+
+
+const Wnck = imports.gi.Wnck;
+const Gtk = imports.gi.Gtk ;
+const Spawn = imports.Spawn;
+const File = imports.File.File;
+const GLib = imports.gi.GLib;
+const Gio = imports.gi.Gio;
+
+//Gtk.init(Seed.argv);
+const xDate = imports.Date;
+const xorg = typeof(Seed) != 'undefined' ? imports.xorg : false;
+
+WindowLog = {
+
+ win : false,
+ screen : false,
+
+ start : function()
+ {
+
+ this.outdir = GLib.get_home_dir() + "/.gitlog";
+ this.screen = Wnck.Screen.get_default();
+ //
+ GLib.timeout_add(GLib.PRIORITY_LOW, 5000, function() {
+ return WindowLog.getStatus()
+ } );
+ //Roo.log("Windowlog start");
+ this.screen.signal.active_window_changed.connect(function() {
+ WindowLog.windowChanged();
+ });
+ },
+
+
+
+
+ getStatus : function()
+ {
+
+
+ var output = xorg.screensaverinfo_get_idletime();
+ //print(output);
+ // more that 10 seconds?? - report idle..
+ if (output * 1 > 10000) {
+ if (this.win != false) {
+ print( (xDate.newDate()).format("Y-m-d H:i:s") + " IDLE");
+ this.write(false, "IDLE");
+ }
+ this.win = false;
+ return true;
+ }
+ return true;
+ },
+ windowChanged : function()
+ {
+ this.screen.force_update();
+ // print("window changeD");
+ var aw = this.screen.get_active_window();
+ if (aw) {
+ var win = aw.get_name();
+ var app = aw.get_application();
+ var pid = app.get_pid();
+ //print("PID " + pid);
+ //var cmd = File.realpath('/proc/'+ pid + '/exe');
+ var cmd = pid ? File.read('/proc/'+ pid + '/cmdline') : 'UNKNOWN';
+
+ if (!this.win || (this.win && win != this.win)) {
+
+ print((xDate.newDate()).format("Y-m-d H:i:s") + " " + win + ' - '+ cmd );
+ this.write(cmd, win);
+ this.win=win;
+ }
+ }
+
+
+ return true;
+ },
+ lastdir : false,
+
+
+
+
+ write : function (cmd , str)
+ {
+
+ var dir = this.outdir + (xDate.newDate()).format("/Y/m");
+ if (!this.lastdir || this.lastdir != dir) {
+ if (!File.isDirectory(dir)) {
+ File.mkdir(dir,true);
+ }
+ this.lastdir = dir;
+ }
+ var ctime = xDate.newDate();
+ var fname = ctime.format("/d") + ".log";
+ var path = dir + '/' + fname;
+ var time = ctime.format("H:i:s ")
+
+ File.append (path, "\n" +time + str + ' ' + cmd );
+
+
+ // copy to gitlive/gitlog (each user should check out their own gitlog!?
+ if (this.lastcopy && this.lastcopy > ctime.add(xDate.Date.HOUR, -1)) {
+ return;
+ }
+ this.lastcopy = ctime;
+ var cpdir = imports.GitMonitor.GitMonitor.gitlive +
+ '/gitlog' + (xDate.newDate()).format("/Y/m");
+
+ if (!File.isDirectory(cpdir)) {
+ File.mkdir(cpdir,true);
+ }
+ File.copy(path, cpdir + fname, Gio.FileCopyFlags.OVERWRITE );
+
+
+ }
+
+}
+
+
+
--- /dev/null
+XObject = imports.XObject.XObject;
+
+Soup = imports.gi.Soup;
+
+var XMLHttpRequest = function (cfg) {
+ if (typeof(cfg) == 'object') {
+ for(var i in cfg) {
+ this[i] = cfg[i];
+ }
+ }
+
+}
+
+XMLHttpRequest.prototype = {
+ // event handlers
+ //onreadystatechange;
+ //onloadstart;
+ //onprogress;
+ //onabort;
+ //onerror;
+ //onload;
+ //ontimeout;
+ //onloadend;
+
+ timeout : 0,
+ withCredentials : false,
+
+ // states
+ UNSENT : 0,
+ OPENED : 1,
+ HEADERS_RECEIVED : 2,
+ LOADING : 3,
+ DONE : 4,
+
+ // readonly..
+ readyState : 0,
+ upload: null,
+
+
+ _message : false,
+ _session : false,
+ _async : false,
+
+ // request
+ open : function ( method, url, async, user, password)
+ {
+ async = async || false;
+ user = user || false;
+ password = password || false;
+
+ this._session = async ? new Soup.SessionAsync() : new Soup.SessionSync();
+
+ var uri = new Soup.URI.c_new(url);
+ this._message = new Soup.Message({method: method, uri:uri});
+ this._async = async;
+
+ if (user || password) {
+ user = user || '';
+ password = password || '';
+ var auth = new Soup.Auth.c_new(
+ Soup.AuthBasic.type,
+ this._message,
+ "Basic realm=\"Test\"");
+
+
+
+ auth.authenticate(user,password);
+ var authmsg = auth.get_authorization(this._message);
+ //print(authmsg);
+ this._message.request_headers.append(
+ 'Authorization', authmsg);
+ }
+
+
+
+ },
+
+ setRequestHeader : function ( header, value)
+ {
+ _this.message.request_headers.append(headers, value)
+
+ },
+ overrideMimeType : function ( mime)
+ {
+
+ },
+ send : function(data)
+ {
+ data = data|| false;
+
+ if (typeof(data) == 'object') {
+ // params..
+ data = this.urlEncode(data);
+ }
+
+ if (data) {
+ this._message.set_request('application/x-www-form-urlencoded', Soup.MemoryUse.COPY, data, data.length)
+ }
+ var _t = this;
+ if (this._async) {
+ this._session.queue_message(this._message, function(ses, msg) {
+ // doc's say we get here after we have sent the data..
+
+ //print("got queue callback");
+ //_t._session.unpause_message(this._message);
+ //print("queue message");
+ //print(_t._message.response_body.data)
+ _t.responseText = _t._message.response_body.data;
+ _t.status = 4;
+
+ if (_t.onreadystatechange) {
+ _t.onreadystatechange();
+ }
+
+
+ });
+ return false;
+
+ }
+ var status = this._session.send_message(this._message);
+ this.responseText = this._message.response_body.data;
+ this.status = 4;
+ if (_t.onreadystatechange) {
+ _t.onreadystatechange();
+ }
+ return status;
+
+ },
+ abort : function()
+ {
+
+ },
+
+ // response (all readonly...)
+ status : false,
+ statusText : false,
+ //readonly attribute any response
+ responseText : false,
+ responseXML : false,
+ responseType : false,
+
+ // response - read
+ getResponseHeader : function( header)
+ {
+
+ },
+ getAllResponseHeaders : function ()
+ {
+
+ },
+ urlEncode : function(o){
+ if(!o){
+ return "";
+ }
+ var buf = [];
+ for(var key in o){
+ var ov = o[key], k = encodeURIComponent(key);
+ var type = typeof ov;
+ if(type == 'undefined'){
+ buf.push(k, "=&");
+ }else if(type != "function" && type != "object"){
+ buf.push(k, "=", encodeURIComponent(ov), "&");
+ }else if(ov instanceof Array){
+ if (ov.length) {
+ for(var i = 0, len = ov.length; i < len; i++) {
+ buf.push(k, "=", encodeURIComponent(ov[i] === undefined ? '' : ov[i]), "&");
+ }
+ } else {
+ buf.push(k, "=&");
+ }
+ }
+ }
+ buf.pop();
+ return buf.join("");
+ },
+
+};
--- /dev/null
+//<script type="text/javascript">
+const GIRepository = imports.gi.GIRepository;
+const GObject = imports.gi.GObject;
+/**
+ * XObject
+ * Yet another attempt to create a usable object construction library for seed..
+ *
+ * Why is this useful?
+ * A) It turns rather messy code into a tree structure, making it easy to find code relating to
+ * an interface element
+ * B) In theory it should be gjs/Seed compatible..
+ * C) It provides getElementById style lookups for elements.
+ * D) It provides classic OO constructors for Javascript (extend/define)
+ * E) It does not modify any buildin prototypes..
+ *
+ * Extend this.. to use it's wonderful features..
+ *
+ * normal usage:
+ * XObject = imports.XObject.XObject;
+ *
+ * Xyz = new XObject({
+ * xtype: Gtk.Window,
+ * id : 'window',
+ * items : [
+ *
+ * ]
+ * });
+ * Xyz.init(); // create and show.
+ *
+ *
+ * use XObject.debug = 1 to turn on debugging
+ *
+ * If XObjectBase/[xns]/[xtype].js exists, it will use this to override properties..
+ *
+ *
+ * He's some questions.
+ * - should we have a special property to use as the constructor / gobject.properties rather
+ * than sending all basic types to this?
+ *
+ * @cfg xtype {String|Function} constructor or string.
+ * @cfg id {String} (optional) id for registry
+ * @cfg xns {String|Object} (optional) namespace eg. Gtk or 'Gtk' - used with xtype.
+ * @cfg items {Array} (optional) list of child elements which will be constructed.. using XObject
+ * @cfg listeners {Object} (optional) map Gobject signals to functions
+ * @cfg pack {Function|String|Array} (optional) how this object gets added to it's parent
+ * @cfg el {Object} (optional) premade GObject
+ *
+ */
+
+function XObject (cfg) {
+ // first apply cfg if set.
+ //print("new XOBJECT!!!");
+
+ //print ("XObject ctr");
+
+ this.config = {}; // used to initialize GObject
+
+ this.cfg = XObject.extend({}, cfg); // used to store original configuration.. for referencing..
+
+ // used by baseobject to create fake child elements on init..
+ if (cfg.el) {
+ this.el = cfg.el;
+ }
+
+ // we could use this to determine if
+ // we are actually inside a inherited class...
+ // as define() should actually set this up..
+
+ if (!this.constructor) {
+
+ this.constructor = XObject;
+ var base = XObject.baseXObject(cfg);
+ if (base) {
+ XObject.extend(this, base.prototype);
+ }
+
+ }
+
+ // copy down all elements into self..
+ // make an extra copy in this.config?? - which is the one used in the constructor later
+
+ for (var i in cfg) {
+ this[i] = cfg[i];
+ if (typeof(cfg[i]) == 'function') { // do we skip objects.
+ continue;
+ }
+ // these properties are not copied to cfg.
+ if ( i == 'pack' ||
+ i == 'items' ||
+ i == 'id' ||
+ i == 'xtype' ||
+ i == 'xdebug' ||
+ i == 'xns') {
+ continue;
+ }
+
+
+ this.config[i] = cfg[i];
+ }
+
+
+ this.items = this.items || [];
+
+
+ // pack can be false!
+ if (typeof(this.pack) == 'undefined') {
+
+ this.pack = [ 'add' ]
+ /*
+ var Gtk = imports.gi.Gtk;
+ switch (true) {
+ // any others!!
+ case (this.xtype == Gtk.MenuItem): this.pack = [ 'append' ]; break;
+
+ }
+ */
+
+ }
+
+ // interesting question should we call constructor on items here...
+ // as the real work is done in init anyway..
+ var _this= this;
+
+ var items = []
+ for(var i = 0; i < this.items.length;i++) {
+ items.push(this.items[i]);
+ }
+
+
+
+ this.items = [];
+ // create XObject for all the children.
+ for(var i = 0; i < items.length;i++) {
+
+ var base = XObject.baseXObject(items[i]);
+ base = base || XObject;
+ var item = (items[i].constructor == XObject) ? items[i] : new base(items[i]);
+ item.parent = _this;
+ _this.items.push(item);
+ //_this.addItem(i);
+ };
+
+
+}
+
+
+
+XObject.prototype = {
+ /**
+ * @property el {GObject} the Gtk / etc. element.
+ */
+ el : false,
+ /*
+ * @property items {Array} list of sub elements
+ */
+ /**
+ * @property parent {XObject} parent Element
+ */
+
+ /**
+ * @property config {Object} the construction configuration.
+ */
+ /**
+ * @method init
+ * Initializes the Element (el) hooks up all the listeners
+ * and packs the children.
+ * you can override this, in child objects, then
+ * do this to do thi initaliztion.
+ *
+ * XObject.prototype.init.call(this);
+ *
+ */
+ init : function(parent)
+ {
+
+ // var items = [];
+ //this.items.forEach(function(i) {
+ // items.push(i);
+ //});
+ // remove items.
+ this.listeners = this.listeners || {};
+ //this.items = [];
+
+ // do we need to call 'beforeInit here?'
+
+ // handle include?
+ //if ((this.xtype == 'Include')) {
+ // o = this.pre_registry[cls];
+ //}
+ var isSeed = typeof(Seed) != 'undefined';
+
+ // xtype= Gtk.Menu ?? what about c_new stuff?
+ XObject.log("init: ID:"+ this.id +" typeof(xtype): " + typeof(this.xtype));
+
+ var xtypeof = isSeed ? typeof(this.xtype) :
+ // oterhwise it's gjs, which case ctors are functions, not objects...
+ ( typeof(this.xtype) == 'function' ? 'object' : typeof(this.xtype) );
+
+ if (!this.el && xtypeof == 'function') {
+ XObject.log("func?" + XObject.keys(this.config).join(','));
+ this.el = this.xtype(this.config);
+
+ }
+ if (!this.el && xtypeof == 'object') {
+ XObject.log(this.xtype.toString());
+
+ XObject.log("obj?" + XObject.keys(this.config).join(','));
+ try {
+ if (!isSeed) {
+ // gjs does not like properties that do not exist..
+
+ this.el = new (this.xtype)({});
+ XObject.extend(this.el, this.config);
+
+ } else {
+
+ this.el = new (this.xtype)(this.config);
+ }
+ } catch(e) {
+ print(JSON.stringify(e,null,4));
+ print(JSON.stringify(this.config,null,4));
+ print(e.stack);
+
+ throw {
+ name: "ArgumentError",
+ message :"Error creating object from xtype(object)"
+ };
+ }
+
+
+ }
+ //print(this.el);
+ if (!this.el && this.xns) {
+
+ var NS = imports.gi[this.xns];
+ if (!NS) {
+ XObject.error('Invalid xns: ' + this.xns, true);
+ }
+ constructor = NS[this.xtype];
+ if (!constructor) {
+ XObject.error('Invalid xtype: ' + this.xns + '.' + this.xtype);
+ }
+ this.el = isSeed ? new constructor(this.config) : new constructor();
+
+ }
+ XObject.log("init: ID:"+ this.id +" typeof(el):" + this.el);
+
+ // always overlay props..
+ // check for 'write' on object..
+ /*
+ if (typeof(XObject.writeablePropsCache[this.xtype.type]) == 'undefined') {
+
+ var gi = GIRepository.IRepository.get_default();
+ var ty = gi.find_by_gtype(this.xtype.type);
+ var write = [];
+ for (var i =0; i < GIRepository.object_info_get_n_properties(ty);i++) {
+ var p = GIRepository.object_info_get_property(ty,i);
+ if (GIRepository.property_info_get_flags(p) & 2) {
+ write.push(GIRepository.base_info_get_name(p));
+ }
+ }
+ XObject.writeablePropsCache[this.xtype.type] = write;
+ print(write.join(", "));
+ }
+
+ */
+
+
+ for (var i in this.config) {
+ if (i == 'type') { // problem with Gtk.Window... - not decided on a better way to handle this.
+ continue;
+ }
+ if (i == 'buttons') { // problem with Gtk.MessageDialog..
+ continue;
+ }
+ if (i[0] == '.') { // parent? -
+ continue;
+ }
+ this.el[i] = this.config[i];
+ }
+
+ // register it!
+ //if (o.xnsid && o.id) {
+ // XObject.registry = XObject.registry || { };
+ // XObject.registry[o.xnsid] = XObject.registry[o.xnsid] || {};
+ // XObject.registry[o.xnsid][o.id] = this;
+ //}
+
+ var type = this.xtype && this.xtype.type ? GObject.type_name(this.xtype.type) : '';
+ XObject.log("add children to " + type);
+
+ var _this=this;
+ for (var i = 0; i < this.items.length;i++) {
+ _this.addItem(this.items[i],i);
+ }
+
+
+ for (var i in this.listeners) {
+ this.addListener(i, this.listeners[i]);
+ }
+
+ this.init = XObject.emptyFn;
+
+ // delete this.listeners ?
+ // do again so child props work!
+
+ // do we need to call 'init here?'
+ },
+
+
+ /**
+ * Adds an item to the object using a new XObject
+ * uses pack property to determine how to add it.
+ * @arg cfg {Object} same as XObject constructor.
+ */
+ addItem : function(item, pos)
+ {
+
+ if (typeof(item) == 'undefined') {
+ XObject.error("Invalid Item added to this!");
+ imports.console.dump(this.cfg);
+ Seed.quit();
+ }
+ // what about extended items!?!?!?
+
+ item.init(this);
+ //print("CTR:PROTO:" + ( item.id ? item.id : '??'));
+ // print("addItem - call init [" + item.pack.join(',') + ']');
+ if (!item.el) {
+ XObject.error("NO EL!");
+ imports.console.dump(item);
+ Seed.quit();
+ }
+ XObject.log(XObject.type(this.xtype) + ":pack=" + item.pack);
+
+ if (item.pack===false) { // no packing.. various items have this ..
+ return;
+ }
+
+ if (typeof(item.pack) == 'function') { // pack is a function..
+ // parent, child
+ item.pack.apply(item, [ this , item ]);
+ item.parent = this;
+ return;
+ }
+
+ // pack = 'add,x,y'
+ var args = [];
+ var pack_m = false;
+ if (typeof(item.pack) == 'string') {
+
+ item.pack.split(',').forEach(function(e, i) {
+
+ if (e == 'false') { args.push( false); return; }
+ if (e == 'true') { args.push( true); return; }
+ if (!isNaN(parseInt(e))) { args.push( parseInt(e)); return; }
+ args.push(e);
+ });
+ //print(args.join(","));
+
+ pack_m = args.shift();
+ } else {
+ pack_m = item.pack.shift();
+ args = item.pack;
+ }
+
+ // handle error.
+ if (pack_m && typeof(this.el[pack_m]) == 'undefined') {
+
+ throw {
+ name: "ArgumentError",
+ message : 'pack method not available : ' + this.id + " : " + this.xtype + '.' + pack_m + " ADDING " + item.el
+
+ }
+
+ return;
+ }
+
+
+ // finally call the pack method
+ //Seed.print('Pack ' + this.el + '.'+ pack_m + '(' + item.el + ')');
+
+ args.unshift(item.el);
+
+
+
+
+
+ XObject.log(pack_m + '[' + args.join(',') +']');
+ //Seed.print('args: ' + args.length);
+ if (pack_m) {
+ this.el[pack_m].apply(this.el, args);
+ }
+
+
+
+ },
+ /**
+ * Connects a method to a signal. (gjs/Seed aware)
+ *
+ * @param {String} sig name of signal
+ * @param {Function} fn handler.
+ */
+ addListener : function(sig, fn)
+ {
+
+ XObject.log("Add signal " + sig);
+ fn.id= sig;
+ var _li = XObject.createDelegate(fn,this);
+ // private listeners that are not copied to GTk.
+
+ if (!this.el) {
+ print('missing el?');
+ print(fn);
+ print(JSON.stringify(this.cfg));
+ }
+
+
+ if (typeof(Seed) != 'undefined') {
+ // Seed.print(typeof(_li));
+ this.el.signal[sig].connect(_li);
+ } else {
+ this.el.connect( sig, _li);
+ }
+
+
+ },
+ /**
+ * @method get
+ * Finds an object in the child elements using xid of object.
+ * prefix with '.' to look up the tree..
+ * prefix with multiple '..' to look further up..
+ * prefix with '/' to look from the top, eg. '^LeftTree.model'
+ *
+ * @param {String} name name of signal
+ * @return {XObject|false} the object if found.
+ */
+ get : function(xid)
+ {
+ XObject.log("SEARCH FOR " + xid + " in " + this.id);
+ var ret= false;
+ var oid = '' + xid;
+ if (!xid.length) {
+ throw {
+ name: "ArgumentError",
+ message : "ID not found : empty id"
+ }
+ }
+
+ if (xid[0] == '.') {
+ return this.parent.get(xid.substring(1));
+ }
+ if (xid[0] == '/') {
+
+ if (typeof(XObject.cache[xid]) != 'undefined') {
+ return XObject.cache[xid];
+ }
+ if (xid.indexOf('.') > -1) {
+
+ var child = xid.split('.');
+ var nxid = child.shift();
+
+ child = child.join('.');
+ if (typeof(XObject.cache[nxid]) != 'undefined') {
+ return XObject.cache[nxid].get(child);
+ }
+
+
+ }
+ var e = this;
+ while (e.parent) {
+ e = e.parent;
+ }
+
+ try {
+ ret = e.get(xid.substring(1));
+ } catch (ex) { }
+
+ if (!ret) {
+ throw {
+ name: "ArgumentError",
+ message : "ID not found : " + oid
+ }
+ }
+ XObject.cache[xid] = ret;
+ return XObject.cache[xid];
+ }
+ var child = false;
+
+ if (xid.indexOf('.') > -1) {
+ child = xid.split('.');
+ xid = child.shift();
+
+ child = child.join('.');
+
+ }
+ if (xid == this.id) {
+ try {
+ return child === false ? this : this.get(child);
+ } catch (ex) {
+ throw {
+ name: "ArgumentError",
+ message : "ID not found : " + oid
+ }
+ }
+
+ }
+
+
+ this.items.forEach(function(ch) {
+ if (ret) {
+ return;
+ }
+ if (ch.id == xid) {
+ ret = ch;
+ }
+ })
+ if (ret) {
+ try {
+ return child === false ? ret : ret.get(child);
+ } catch (ex) {
+ throw {
+ name: "ArgumentError",
+ message : "ID not found : " + oid
+ }
+ }
+
+ }
+ // iterate children.
+ var _this = this;
+ this.items.forEach(function(ch) {
+ if (ret) {
+ return;
+ }
+ if (!ch.get) {
+ XObject.error("invalid item...");
+ imports.console.dump(_this);
+ Seed.quit();
+ }
+ try {
+ ret = ch.get(xid);
+ } catch (ex) { }
+
+
+ });
+ if (!ret) {
+ throw {
+ name: "ArgumentError",
+ message : "ID not found : " + oid
+ }
+ }
+ try {
+ return child === false ? ret : ret.get(child);
+ } catch (ex) {
+ throw {
+ name: "ArgumentError",
+ message : "ID not found : " + oid
+ }
+ }
+ }
+
+
+}
+
+
+/**
+ * Copies all the properties of config to obj.
+ *
+ * Pretty much the same as JQuery/Prototype.. or Roo.apply
+ * @param {Object} obj The receiver of the properties
+ * @param {Object} config The source of the properties
+ * @param {Object} defaults A different object that will also be applied for default values
+ * @return {Object} returns obj
+ * @member XObject extend
+ */
+
+
+XObject.extend = function(o, c, defaults){
+ if(defaults){
+ // no "this" reference for friendly out of scope calls
+ XObject.extend(o, defaults);
+ }
+ if(o && c && typeof c == 'object'){
+ for(var p in c){
+ o[p] = c[p];
+ }
+ }
+ return o;
+};
+
+XObject.extend(XObject,
+{
+
+ /**
+ * @property {Boolean} debug XObject debugging. - set to true to debug.
+ *
+ */
+ debug : true,
+ /**
+ * @property {Object} cache - cache of object ids
+ *
+ */
+ cache: { },
+ /**
+ * Empty function
+ *
+ */
+ emptyFn : function () { },
+
+
+
+ /**
+ * Debug Logging
+ * @param {String|Object} output String to print.
+ */
+ log : function(output)
+ {
+ if (!this.debug) {
+ return;
+ }
+ print("LOG:" + output);
+ },
+
+ /**
+ * Error Logging
+ * @param {String|Object} output String to print.
+ */
+ error : function(output)
+ {
+ print("ERROR: " + output);
+ },
+ /**
+ * fatal error
+ * @param {String|Object} output String to print.
+ */
+ fatal : function(output)
+ {
+
+ throw {
+ name: "ArgumentError",
+ message : output
+
+ }
+ },
+ /**
+ * usefull for compatibilyt.
+ *
+ */
+ isSeed : typeof(Seed) != 'undefined',
+ /**
+ * Copies all the properties of config to obj, if the do not exist.
+ * @param {Object} obj The receiver of the properties
+ * @param {Object} config The source of the properties
+ * @return {Object} returns obj
+ * @member Object extendIf
+ */
+
+
+ extendIf : function(o, c)
+ {
+
+ if(!o || !c || typeof c != 'object'){
+ return o;
+ }
+ for(var p in c){
+ if (typeof(o[p]) != 'undefined') {
+ continue;
+ }
+ o[p] = c[p];
+ }
+ return o;
+ },
+
+
+
+ /**
+ * Extends one class with another class and optionally overrides members with the passed literal. This class
+ * also adds the function "override()" to the class that can be used to override
+ * members on an instance.
+ *
+ * usage:
+ * MyObject = Object.define(
+ * function(...) {
+ * ....
+ * },
+ * parentClass, // or Object
+ * {
+ * ... methods and properties.
+ * }
+ * });
+ * @param {Function} constructor The class inheriting the functionality
+ * @param {Object} superclass The class being extended
+ * @param {Object} overrides (optional) A literal with members
+ * @return {Function} constructor (eg. class
+ * @method define
+ */
+ define : function()
+ {
+ // inline overrides
+ var io = function(o){
+ for(var m in o){
+ this[m] = o[m];
+ }
+ };
+ return function(constructor, parentClass, overrides) {
+ if (typeof(parentClass) == 'undefined') {
+ XObject.error("XObject.define: Missing parentClass: when applying: " );
+ XObject.error(new String(constructor));
+ Seed.quit();
+ }
+ if (typeof(parentClass.prototype) == 'undefined') {
+ XObject.error("Missing protype: when applying: " );
+ XObject.error(new String(constructor));
+ XObject.error(new String(parentClass));
+ Seed.quit();
+ }
+ var F = function(){};
+ var sbp;
+ var spp = parentClass.prototype;
+
+ F.prototype = spp;
+ sbp = constructor.prototype = new F();
+ sbp.constructor=constructor;
+ constructor.superclass=spp;
+
+ // extends Object.
+ if(spp.constructor == Object.prototype.constructor){
+ spp.constructor=parentClass;
+ }
+
+ constructor.override = function(o){
+ Object.extend(constructor.prototype, o);
+ };
+ sbp.override = io;
+ XObject.extend(constructor.prototype, overrides);
+ return constructor;
+ };
+ }(),
+
+
+ /**
+ * returns a list of keys of the object.
+ * @param {Object} obj object to inspect
+ * @return {Array} returns list of kyes
+ * @member XObject keys
+ */
+ keys : function(o)
+ {
+ var ret = [];
+ for(var i in o) {
+ ret.push(i);
+ }
+ return ret;
+ },
+ /**
+ * return the Gobject name of a constructor - does not appear to work on structs..
+ * @param {Object} gobject ctr
+ * @return {String} returns name
+ * @member XObject type
+ */
+ type : function(o)
+ {
+ if (typeof(o) == 'object') {
+ return GObject.type_name(o.type);
+ // print("GNAME:" +gname + " GTYPE:"+cfg.xtype.type);
+ }
+ return 'unknown';
+ },
+ /**
+ * return the XObjectBase class for a cfg (which includes an xtype)
+ * @param {Object} configuration.
+ * @return {function} constructor
+ * @member XObject baseXObject
+ */
+ baseXObject : function(cfg)
+ {
+ try {
+ // loocks for XObject/Gtk/TreeView.js [ TreeView = { .... } ]
+ // xns is not a string!!!?
+ var gname = false;
+ if (typeof(cfg.xtype) == 'object') {
+ gname = XObject.type(cfg.xtype);
+
+ }
+ if (typeof(cfg.xtype) == 'string') {
+ gname = cfg.xtype;
+ }
+
+ XObject.log("TRYING BASE OBJECT : " + gname);
+
+ // in the situation where we have been called and there is a base object
+ // defining the behavior..
+ // then we should copy the prototypes from the base object into this..
+
+ // see if file exists???
+
+ var base = gname ? imports.XObjectBase[gname][gname] : false;
+ return base;
+
+ } catch (e) {
+ // if debug?
+ XObject.log("error finding " + gname + " - " + e.toString());
+ return false;
+ }
+
+
+ },
+
+ /**
+ * @member XObject createDelegate
+ * creates a delage metdhod
+ * @param {Function} method to wrap
+ * @param {Object} scope
+ * @param {Array} args to add
+ * @param {Boolean|Number} append arguments or replace after N arguments.
+ * @return {Function} returns the delegate
+ */
+
+ createDelegate : function(method, obj, args, appendArgs){
+
+ return function() {
+ XObject.log("CALL: " + obj.id + ':'+ method.id);
+
+ var callArgs = args || arguments;
+ if(appendArgs === true){
+ callArgs = Array.prototype.slice.call(arguments, 0);
+ callArgs = callArgs.concat(args);
+ }else if(typeof appendArgs == "number"){
+ callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first
+ var applyArgs = [appendArgs, 0].concat(args); // create method call params
+ Array.prototype.splice.apply(callArgs, applyArgs); // splice them in
+ }
+ return method.apply(obj || window, callArgs);
+ };
+ }
+
+});
--- /dev/null
+
+
+idea:
+
+- local version of merger -
+* it basically shows the difference between two branches,
+as a tree, then as a list of changed files, then diff view
+
+- to do this.
+
+A) select repo
+ current directory (eg.) 'Repo' Class
+B) get history
+ ....
+C) get diff etc...
+
+Lets' start with the Repo directory.
+
+
+Design
+
+Top bar:
+- select repo (done by manage repos)
+- select "Release Branch"
+- select "Working Branch"
+
+
+
+
+
+
+----
+Other dialogs
+
+Manage Repos
+-> list of repo's
+
+Actions:
+-> Merger
+-> Pull branches (from remote)
+-> Add?
+-> Flag 'auto-commit'
+-> Flag 'auto-push'
+-> Switch Branch
\ No newline at end of file
--- /dev/null
+#!/usr/bin/seed
+///<script type="text/javascript">
+/**
+* Git Live
+*
+* inotify hooks for ~/gitlive
+* that commit and push any changes made.
+* Bit like a revision controled backed up file system!?
+*
+*
+*/
+
+GIRepository = imports.gi.GIRepository
+GLib = imports.gi.GLib;
+
+//print(JSON.stringify(GI, null,4));
+// we add this in, as it appears to get lost sometimes if we set it using the ENV. variable in builder.sh
+// see the install instructions on how to override the default gir's
+//GIRepository.Repository.prepend_search_path(GLib.get_home_dir() + '/.Builder/girepository-1.2');
+
+var Gio = imports.gi.Gio;
+var Gtk = imports.gi.Gtk;
+var Notify = imports.gi.Notify;
+
+
+var StatusIcon = imports.StatusIcon.StatusIcon;
+var Monitor = imports.Monitor.Monitor;
+var GitMonitor = imports.GitMonitor.GitMonitor;
+var WindowLog = imports.WindowLog.WindowLog;
+
+
+Gtk.init (null, null);
+
+// sanity check...
+
+// where is everything..
+GitMonitor.gitlive = GLib.get_home_dir() + "/gitlive";
+
+if (!GLib.file_test(GitMonitor.gitlive, GLib.FileTest.IS_DIR)) {
+ var msg = new Gtk.MessageDialog({message_type:
+ Gtk.MessageType.INFO, buttons : Gtk.ButtonsType.OK, text: "GIT Live - ~/gitlive does not exist."});
+ msg.run();
+ msg.destroy();
+ Seed.quit();
+}
+
+// I'm lost...
+
+function errorDialog(data) {
+ var msg = new Gtk.MessageDialog({
+ message_type: Gtk.MessageType.ERROR,
+ buttons : Gtk.ButtonsType.OK,
+ text: data
+ });
+ msg.run();
+ msg.destroy();
+}
+
+
+
+//
+// need a better icon...
+
+
+StatusIcon.init();
+
+
+Notify.init("gitlive");
+
+GLib.timeout_add(GLib.PRIORITY_LOW, 500, function() {
+ // this should start after we have shown the icon...
+ GitMonitor.add(GitMonitor.gitlive);
+ GitMonitor.start();
+
+ WindowLog.start();
+});
+
+Gtk.main();
+//icon.signal["activate"].connect(on_left_click);
+
--- /dev/null
+#!/usr/bin/seed
+//<Script type="text/javascript">
+/**
+ * runtime file
+ * takes a gtk project directory, and turns it into an application!
+ * by compling the files into JS files..
+ *
+ * Initially developed for runtime testing. (the vte runner)
+ *
+ * Might be the way to go for full runtime
+ *
+ *
+ * Usage: (call with wrapper to set up directories..)
+ * sh builder.sh
+ *
+ * Concepts..
+ * a) load dependancies.. (eg. gi's..) - derived later?
+ * Gtk.init()
+ *
+ * loop the files (find .bjs)
+ * - comple to js (if not exist // or force enabled..)
+ * b) load all the files
+ *
+ * Gtk.main();
+ *
+ */
+// autogen?
+
+// sort out import path - this is a bit of a mess..
+GIRepository = imports.gi.GIRepository;
+GLib = imports.gi.GLib;
+
+// we add this in, as it appears to get lost sometimes if we set it using the ENV. variable in builder.sh
+GIRepository.IRepository.prepend_search_path(GLib.get_home_dir() + '/.Builder/girepository-1.1');
+//print(JSON.stringify(GIRepository.IRepository.get_search_path()));
+
+Gtk = imports.gi.Gtk;
+Gdk = imports.gi.Gdk;
+Pango = imports.gi.Pango;
+
+Gio = imports.gi.Gio;
+GObject = imports.gi.GObject;
+GtkSource = imports.gi.GtkSource;
+WebKit = imports.gi.WebKit;
+Vte = imports.gi.Vte;
+
+Gdl = imports.gi.Gdl;
+
+GtkClutter = imports.gi.GtkClutter;
+
+if (GtkClutter) {
+ GtkClutter.init(Seed.argv);
+}
+
+File = imports.File.File;
+
+XObject = imports.XObject.XObject;
+//XObject.debug = true;
+Gtk.init(Seed.argv);
+
+
+imports.searchPath.push('/'); // allow global paths..
+// error checking todo..
+
+var ret = imports.FixBug.FixBug.show();
+print("show returned\n");
+print(JSON.stringify(ret,null, 4));
+
+
+
+Gtk.main();
+
--- /dev/null
+#!/usr/bin/seed
+//<Script type="text/javascript">
+/**
+ * runtime file
+ * takes a gtk project directory, and turns it into an application!
+ * by compling the files into JS files..
+ *
+ * Initially developed for runtime testing. (the vte runner)
+ *
+ * Might be the way to go for full runtime
+ *
+ *
+ * Usage: (call with wrapper to set up directories..)
+ * sh builder.sh
+ *
+ * Concepts..
+ * a) load dependancies.. (eg. gi's..) - derived later?
+ * Gtk.init()
+ *
+ * loop the files (find .bjs)
+ * - comple to js (if not exist // or force enabled..)
+ * b) load all the files
+ *
+ * Gtk.main();
+ *
+ */
+// autogen?
+
+// sort out import path - this is a bit of a mess..
+GIRepository = imports.gi.GIRepository;
+GLib = imports.gi.GLib;
+
+// we add this in, as it appears to get lost sometimes if we set it using the ENV. variable in builder.sh
+//GIRepository.Repository.prepend_search_path(GLib.get_home_dir() + '/.Builder/girepository-1.2');
+//print(JSON.stringify(GIRepository.IRepository.get_search_path()));
+
+Gtk = imports.gi.Gtk;
+Gdk = imports.gi.Gdk;
+Pango = imports.gi.Pango;
+
+Gio = imports.gi.Gio;
+GObject = imports.gi.GObject;
+GtkSource = imports.gi.GtkSource;
+WebKit = imports.gi.WebKit;
+Vte = imports.gi.Vte;
+
+
+
+
+File = imports.File.File;
+
+XObject = imports.XObject.XObject;
+//XObject.debug = true;
+Gtk.init(Seed.argv);
+
+
+imports.searchPath.push('/'); // allow global paths..
+// error checking todo..
+var ret = imports.FixBug.FixBug.show();
+print("show returned\n");
+print(JSON.stringify(ret,null, 4));
+
+
+
+Gtk.main();
+
--- /dev/null
+var Gtk = imports.gi.Gtk;
+
+var Repo = imports.Scm.Git.Repo.Repo;
+
+
+Gtk.init(Seed.argv);
+
+File = imports.File.File;
+
+var repo = new Repo({ repopath : '/home/alan/gitlive/gitlive' });
+
+repo.applyPatch(File.read('/tmp/test1.txt'));
+
+//var hist = repo.history('/', false, 'rev', 'github..master');
+//var hist = repo.getBranches();
+
+//var hist = repo.changedFiles('/', 'rev', 'github..master');
+
+
+print(JSON.stringify(hist,null,4));
+
+//Gtk.main();
\ No newline at end of file
--- /dev/null
+#!/usr/bin/seed
+//<Script type="text/javascript">
+/**
+ * runtime file
+ * takes a gtk project directory, and turns it into an application!
+ * by compling the files into JS files..
+ *
+ * Initially developed for runtime testing. (the vte runner)
+ *
+ * Might be the way to go for full runtime
+ *
+ *
+ * Usage: (call with wrapper to set up directories..)
+ * sh builder.sh
+ *
+ * Concepts..
+ * a) load dependancies.. (eg. gi's..) - derived later?
+ * Gtk.init()
+ *
+ * loop the files (find .bjs)
+ * - comple to js (if not exist // or force enabled..)
+ * b) load all the files
+ *
+ * Gtk.main();
+ *
+ */
+// autogen?
+
+// sort out import path - this is a bit of a mess..
+GIRepository = imports.gi.GIRepository;
+GLib = imports.gi.GLib;
+
+// we add this in, as it appears to get lost sometimes if we set it using the ENV. variable in builder.sh
+GIRepository.Repository.prepend_search_path(GLib.get_home_dir() + '/.Builder/girepository-1.2');
+//print(JSON.stringify(GIRepository.IRepository.get_search_path()));
+
+Gtk = imports.gi.Gtk;
+Gdk = imports.gi.Gdk;
+Pango = imports.gi.Pango;
+
+Gio = imports.gi.Gio;
+GObject = imports.gi.GObject;
+GtkSource = imports.gi.GtkSource;
+WebKit = imports.gi.WebKit;
+Vte = imports.gi.Vte;
+
+
+
+
+File = imports.File.File;
+
+XObject = imports.XObject.XObject;
+//XObject.debug = true;
+Gtk.init(Seed.argv);
+
+
+imports.searchPath.push('/'); // allow global paths..
+// error checking todo..
+ var ret = imports.Clones.Clones.show();
+ //imports.Merger.Merger.repo = new imports.Scm.Git.Repo.Repo('/home/alan/gitlive/roojs1');
+var ret = imports.Merger.Merger.show();
+
+print("show returned\n");
+print(JSON.stringify(ret,null, 4));
+
+
+
+//Gtk.main();
+