From 4e21946b4e27ba5df96da35a46ffc76fc548e301 Mon Sep 17 00:00:00 2001 From: Alan Knowles Date: Fri, 11 Aug 2017 13:04:20 +0800 Subject: [PATCH] sync --- old_seed_version/INSTALL.txt | 16 + old_seed_version/Scm/Git/Event.js | 166 +++++ old_seed_version/Scm/Git/Repo.js | 939 +++++++++++++++++++++++++++++ old_seed_version/Scm/Git/Repo.vala | 231 +++++++ old_seed_version/Scm/Repo.js | 342 +++++++++++ old_seed_version/install1.2.sh | 16 + 6 files changed, 1710 insertions(+) create mode 100644 old_seed_version/INSTALL.txt create mode 100644 old_seed_version/Scm/Git/Event.js create mode 100644 old_seed_version/Scm/Git/Repo.js create mode 100644 old_seed_version/Scm/Git/Repo.vala create mode 100644 old_seed_version/Scm/Repo.js create mode 100644 old_seed_version/install1.2.sh diff --git a/old_seed_version/INSTALL.txt b/old_seed_version/INSTALL.txt new file mode 100644 index 00000000..41964de2 --- /dev/null +++ b/old_seed_version/INSTALL.txt @@ -0,0 +1,16 @@ + +GTK3 + +git clone git://github.com/roojs/gitlive.git +cd gitlive +git clone git://github.com/roojs/gir-1.2-gtk-3.0.git gir-1.2 +sh install1.2.sh + +# - since GLib still has a few bugs.. +sudo cp ~/.Builder/girepository-1.2/GLib-2.0.gir /usr/lib/girepository-1.0/ + +seed gitlive.js + + + + diff --git a/old_seed_version/Scm/Git/Event.js b/old_seed_version/Scm/Git/Event.js new file mode 100644 index 00000000..d2393ca9 --- /dev/null +++ b/old_seed_version/Scm/Git/Event.js @@ -0,0 +1,166 @@ +var XObject = imports.XObject.XObject; + + +Event = XObject.define( + function (cfg) { + // do nothing?? universal ctr ? + XObject.extend(this,cfg); + if (this.commit.length) { + this.parseCommit(); + } + //print(JSON.stringify(this, null,4)); Seed.quit(); + }, + Object, + { + + + + repo : false, + /** Revision or changeset identifier for this particular file */ + rev : false, + + /** commit message associated with this revision */ + changelog : false, + + /** who committed this revision */ + changeby : false, + + /** when this revision was committed */ + ctime : false, + + /** files affected in this event; may be null, but otherwise + * will be an array of MTrackSCMFileEvent */ + files : false, + + commit : false, + + + + + parseCommit : function() + { + + var ent = this; + + this.branches = []; // FIXME + this.tags = []; // FIXME + this.files = {}; + + + + var lines = this.commit.split("\n"); + + // print ('--->'+ lines.join("\n")); + + var line = lines.shift(); + if (!line.match(/^commit\s+(\S+)/)) { + throw "Invalid commit line"; + } + this.rev = line.replace(/^commit\s+/,''); + + while (lines.length) { + line = lines.shift(); + if (!line.length) { + break; // empty line = STOP? + } + if (line.match(/^(\S+):\s+(.*)\s*/)) { + var k,v + line.replace(/^(\S+):\s+(.*)\s*/, function(m,ma,mb) { + k = ma; + v = mb; + }) + + switch (k) { + case 'Author': + this.changeby = v; + break; + + case 'Date': + //var ts = strtotime(v); + + var Date = imports.Date.Date; + //var pd = imports.Date.Date.pqqqarseDate; + this.changed_raw = v; + this.changed = Date.parseDate(v, "Y-m-d h:i:s O"); + this.cday = this.changed.format("Y-m-d"); + this.ctime = this.changed.format("H:i:s"); + break; + } + }1 + } + + this.changelog = ""; + + if (lines[0] == '') { + lines.shift(); + } + + while ( lines.length ) { + line = lines.shift(); + if (!line.match(/^ /)) { + lines.unshift( line ); + break; + } + line = line.substring( 4); + this.changelog += line + "\n"; + } + + if (lines[0] == '') { + lines.shift(); + } + var info; + + + // this should only be the last set of lines.. + lines.forEach(function(line) { + if (!line.length) { + return; + } + + if (line.match(/^:/)) { + // it's our stat line..: + // :100755 100755 fde93abd1a71accd3aa7e97b29c1eecfb43095d7 + // 3d71edf6512035846d8164c3b28818de0062335a M web/MTrackWeb/DataObjects/Changes.php + var lr = line.split(/\t/); + var info = lr[0].substring(1).split(/\s+/); + + + // print_r(info); + var f = {}; //new MTrackSCMFileEvent; //generic.. + + f.oldperm = info.shift(); + f.newperm = info.shift(); + f.oldver = info.shift(); + f.newver = info.shift();; + f.status = info.shift(); + f.name = lr[1]; // not the right way to do this!!! - does not handle names correclty. + ent.files[f.name] = f; + + return; + } + + var info = line.substring(1).split(/\t/); // 3 only.. + //print_r(info); + var added = info.shift(); + var removed = info.shift(); + + var name = info.join("\t"); + + ent.files[name] = XObject.extend( + typeof(ent.files[name]) == 'undefined' ? {} : ent.files[name], + { + added : added, + removed : removed + } + ); + }); + // fixme.. + if (!this.branches.length) { + this.branches.push( 'master' ); + } + + } + } +); + + \ No newline at end of file diff --git a/old_seed_version/Scm/Git/Repo.js b/old_seed_version/Scm/Git/Repo.js new file mode 100644 index 00000000..a946bfec --- /dev/null +++ b/old_seed_version/Scm/Git/Repo.js @@ -0,0 +1,939 @@ + +const GLib = imports.gi.GLib; + +const XObject = imports.XObject.XObject; +const Event = imports.Scm.Git.Event.Event; +const Spawn = imports.Spawn.Spawn; +const File = imports.File.File; + +/** + * @class Scm.Git.Repo + * + * @extends Scm.Repo + * + * + * + */ +Repo = XObject.define( + /** + * constructor: + * + * @param {Object} cfg - Configuration + * (basically repopath is currently only critical one.) + * + */ + + function(cfg) { + // cal parent? + XObject.extend(this,cfg); + this.gitdir = cfg.repopath + "/.git"; + + if (!File.isDirectory(this.gitdir)) { + this.gitdir = this.repopath; + } + //Repo.superclass.constructor.call(this,cfg); + + }, + imports.Scm.Repo.Repo, // or Object + { + branches : false, + currentBranch : false, + tags : false, + gitdir : false, + debug : true, + lastCmd : false, + hasLocalChanges : false, + localChanges : false, + + getMetaData : function() { + return { + name : 'Git', + tool : ['git' ] + + }; + }, + + + getStatus : function() + { + //git status --porcelain + // find out if we are up-to-date. + //git ls-remote origin -h refs/heads/master + var bl = this.git([ 'status', { + 'porcelain' : true + }]); + print(JSON.stringify(bl.length)); + this.hasLocalChanges = bl.length > 0 ? true : false; + this.localChanges = bl; + + + }, + + + getBranches : function() + { + if (this.branches !== false) { + return this.branches; + } + this.branches = []; + + var bl = this.git([ 'branch', { + 'no-color' : true, + 'verbose' : true, + 'no-abbrev' : true, + 'a' : true + }]).split("\n"); + var bmap = {}; + var _this=this; + + var local = []; + var remotes = []; + + bl.forEach(function(line) { + // * master 61e7e7d oneliner + var active = line[0]=='*'; + if (!line.length) { + return; + } + line = line.substring(2); + + //print(JSON.stringify(line)); + var parts = line.split(/\s+/); + if (parts[1] == '->') { + return; // it's an alias like remotes/origin/HEAD -> origin/master + } + var br = { + lastrev : parts[1], + name : '', + remote : '', + remoterev : '' + }; + if (parts[0].match(/^remotes\//)) { + br.remote = parts[0]; + bmap[br.remote] = br; + remotes.push(br); + } else { + br.name = parts[0]; + bmap[br.name] = br; + local.push(br); + } + + if (active) { + _this.currentBranch = br; + } + }); + + //print(JSON.stringify(local)); + //print(JSON.stringify(remotes)); + //print(JSON.stringify(bmap,null,4)); + + + // overlay tracking informaion + bl = this.git([ + 'for-each-ref', + { format : '%(refname:short):remotes/%(upstream:short)' }, + 'refs/heads' + ]).split("\n"); + //print(this.lastCmd); + + //print(JSON.stringify(bl,null,4)); + + bl.forEach(function(line) { + if (!line.length) { + return; + } + var ar = line.split(':remotes/'); + + var lname= ar[0]; + var rname = 'remotes/' + ar[1]; + //print(rname); + // we should always have a local version of it. + bmap[lname].remote = rname; + if (typeof(bmap[rname]) == 'undefined') { + return; + } + bmap[lname].remoterev = bmap[rname].lastrev; + // flag it for not adding.. + + bmap[rname].name = lname; + }); + var _this =this; + + + + // add any remotes that do not have name.. + remotes.forEach(function(r) { + if (r.name.length) { + return; + } + + // create a tracking branch.. + var name = r.remote.replace(/^remotes\//, '' ).replace(/^origin\//,'').replace('/', '.'); + + + + if (typeof(bmap[name]) != 'undefined') { + // already got aremote of that name. + // skip it... + r.remoterev = r.lastrev; + r.lastrev = ''; + local.push(r); + return; + } + + + _this.git([ + 'branch', + { + f : true, + track : true + }, + name, + r.remote + ]); + + r.remoterev = r.lastrev; + r.name = name; + local.push(r); + }); + + this.branches = local; + // print(JSON.stringify(local,null,4)); + + + return this.branches; + }, + _remotes : false, + + remotes: function(cfg) + { + + if (cfg) { + this._remotes = false; // reset so we can query it.. + + var url = Repo.parseURL(cfg.url); + if ((url.scheme == 'http://' || url.scheme == 'https://' ) + && url.user.length) { + // remove username - as it confuses netrc.. + cfg.url = url.scheme + url.host + '/' +url.path; + + } + + + this.git([ + 'remote', + 'add', + cfg.name, + cfg.url + ]); + this.branches = false; + + this.git([ + 'fetch', + cfg.name, + { 'a' : true } + ]); + + + + //print(this.lastCmd); + + } + + + if (this._remotes!== false) { + return this._remotes; + } + this._remotes = []; + + var bl = this.git([ 'remote', { + // 'no-color' : true, + 'verbose' : true + }]).split("\n"); + + var _this=this; + bl.forEach(function(line) { + if (!line.length) { + return; + // * master 61e7e7d oneliner + } + // print(JSON.stringify( line)); + var parts = line.split(/\t/); + var type = false; + parts[1] = parts[1].replace(/\([a-z]+\)$/, function( a) { + type = a.substr(1,a.length-2); + return ''; + }); + + _this._remotes.push( { + name: parts[0], + url : parts[1], + type: type + }); + + }); + return this._remotes; + }, + + + + lastupdated: function() { + return 'tbc'; + }, + autocommit: function(val) { + if (typeof(val) == 'undefined') { + + if (File.exists(this.gitdir + '/.gitlive-disable-autocommit')) { + return false; + } + + return true; + } + if (val == this.autocommit()) { + return val; + } + if (!val) { // turn off + File.write(this.gitdir + '/.gitlive-disable-autocommit', '.'); + } else { + File.remove(this.gitdir + '/.gitlive-disable-autocommit'); + } + return val; + + }, + + + + autopush: function(val) { + + if (typeof(val) == 'undefined') { + + if (File.exists(this.gitdir + '/.gitlive-disable-autopush')) { + return false; + } + + return true; + } + if (val == this.autocommit()) { + return val; + } + if (!val) { // turn off + File.write(this.gitdir + '/.gitlive-disable-autopush', '.'); + } else { + File.remove(this.gitdir + '/.gitlive-disable-autopush'); + } + return val; + }, + /* + + public function getTags() + { + if ($this->tags !== null) { + return $this->tags; + } + $this->tags = array(); + $fp = $this->git('tag'); + while ($line = fgets($fp)) { + $line = trim($line); + $this->tags[$line] = $line; + } + $fp = null; + return $this->tags; + } + + public function readdir($path, $object = null, $ident = null) + { + $res = array(); + + if ($object === null) { + $object = 'branch'; + $ident = 'master'; + } + $rev = $this->resolveRevision(null, $object, $ident); + + if (strlen($path)) { + $path = rtrim($path, '/') . '/'; + } + + $fp = $this->git('ls-tree', $rev, $path); + + $dirs = array(); + require_once 'MTrack/SCM/Git/File.php'; + while ($line = fgets($fp)) { + // blob = file, tree = dir.. + list($mode, $type, $hash, $name) = preg_split("/\s+/", $line); + //echo '
';echo $line ."\n
"; + $res[] = new MTrack_SCM_Git_File($this, "$name", $rev, $type == 'tree', $hash); + } + return $res; + } + + public function file($path, $object = null, $ident = null) + { + if ($object == null) { + $branches = $this->getBranches(); + if (isset($branches['master'])) { + $object = 'branch'; + $ident = 'master'; + } else { + // fresh/empty repo + return null; + } + } + $rev = $this->resolveRevision(null, $object, $ident); + require_once 'MTrack/SCM/Git/File.php'; + return new MTrack_SCM_Git_File($this, $path, $rev); + } + */ + /** + * history: + * Get the log/history about repo or specific file(s) + * + * @param string path (can be empty - eg. '') + * @param {number|date} limit how many to fetch + * @param {string} object = eg. rev|tag|branch (use 'rev' here and ident=HASH to retrieve a speific revision + * @param {string} ident = + * + * Example: + * - fetch on revision?: '.',1,'rev','xxxxxxxxxx' + * + * + * range... object ='rev' ident ='master..release' + * + */ + history: function(path, limit , object, ident) + { + limit = limit || false; + object = object || false; + ident = ident || false; + var res = []; + var args = [ 'log' ]; + + + if (object !== false) { + rev = this.resolveRevision(false, object, ident); // from scm... + args.push( '' + rev); + } else { + args.push( "master" ); + } + + var arg = { + "no-color" : true, + //args.push("--name-status"; + "raw" : true, + + "numstat" : true, + "date" : 'iso8601' + }; + if (limit !== false) { + if (typeof(limit) == 'number') { + arg['max-count'] = limit; + } else if (typeof(limit) == 'object') { + arg.skip= limit[0]; + arg['max-count']= limit[1]; + + } else { + arg.since = limit; + } + } + + args.push(arg); + + + + + + //echo '
';print_r($args);echo '
'; + + + + args.push({ '' : true }); + if (typeof(path) == 'string') { + path = path[0] == '/' ? path.substring(1) : path; + args.push(path); + } else { + path.forEach(function(p) { + args.push(p); + }) + } + + + // print_R(array($args, '--' ,$path));exit; + var fp = this.git(args).split("\n"); + + var commits = []; + var commit = false; + while (fp.length) { + var line = fp.shift() + "\n"; + + if (line.match(/^commit/)) { + if (commit !== false) { + commits.push( commit ); + } + commit = line; + continue; + } + commit += line ; + } + + if (commit !== false) { + commits.push( commit ); + } + var res = []; + //print(JSON.stringify(commits,null,4)); + + var _t = this; + commits.forEach( function(c) { + // print(typeof(Event)); print(JSON.stringify(c)); + var ev = new Event( {commit : c, repo: _t }); + res.push(ev); + + }); + // close 'fp' + return res; + }, + diff : function(path, from, to) + { + to = to || false; + from = from || false; + + + + + /* + if ($path instanceof MTrackSCMFile) { + if ($from === null) { + $from = $path->rev; + } + $path = $path->name; + + } + // if it's a file event.. we are even lucker.. + if ($path instanceof MTrackSCMFileEvent) { + return $this->git('log', '--max-count=1', '--format=format:', '--patch', $from, '--', $path->name); + + } + */ + // diff ignoring white space.. + args = [ 'diff' , { 'w' : true} ] + + if (to == false) { + to = from; + from = from + '^'; + } + + args.push(from+'..'+to); + args.push( { '' : true }); + if (typeof(path) != 'string') { + path.forEach(function(p) { args.push(p); }) + } + return this.git(args); + }, + + + + dayTree: function (path, limit , object, ident) + { + + var ar = this.history(path, limit , object, ident); + + // the point of this is to extract all the revisions, and group them. + + + + //echo '
';print_R($ar);
+            
+            // need to get a 2 dimensional array of
+            // files along top, and commints down.
+            var cfiles = []
+            var rows = [];
+            
+            var days = {};
+            
+            ar.forEach(function( commit) {
+                
+                var files = commit.files;
+                var day = commit.cday;
+                if (typeof(days[day]) == 'undefined') { 
+                    days[day] = {
+                        'text' : day,
+                        'rev' : day,
+                        'children' : {}
+                    }
+                }
+                var time= commit.ctime;
+                if (typeof(days[day]['children'][time]) == 'undefined' ) { 
+                    days[day]['children'][time] = {
+                        'text' : time,
+                        'rev' : day + ' ' + time,
+                        'children' : [] 
+                    };
+                }
+                days[day]['children'][time]['children'].push( {
+                    'text' : commit.changelog,
+                    'rev' : commit.rev,
+                    'leaf' :  true
+                });
+            });
+            var out = [];
+            
+            for(var d in days) {
+                var dr = days[d];
+                dcn = dr['children'];
+                dr['children'] = [];
+                for(var t in dcn) {
+                    var to = dcn[t];
+                    to['rev']  = to['children'][0]['rev'];
+                    dr['children'].push( to);
+                }
+                dr['rev'] = dr['children'][0]['rev'];
+                out.push( dr);
+            }
+            
+            return out;            
+             
+            
+        },
+        
+        
+    
+    
+        changedFiles :function(path,  object, ident)
+        {
+             object = object || false;
+            ident = ident || false; 
+            var res = [];
+            var args = [ 'diff', { 'numstat' : true}  , { 'w' : true } ];
+             
+            
+            if (object !== false) {
+                rev = this.resolveRevision(false, object, ident); // from scm...
+                args.push( '' + rev);  
+            } else {
+                args.push( "master" );
+            }
+            path = path[0] == '/' ? path.substring(1) : path; 
+            
+            args.push({ '' : true });
+            args.push(path);
+              // in theory you could click a number of them and only merge those changes..
+            // need to do a git diff.. and just get a list of files..
+            var rows = [];
+            var res = this.git(args).split("\n"); 
+            res.forEach( function(line) {
+                
+                
+                
+                var ar = line.split("\t"); 
+                if (ar.length !=3 ) {
+                    return;
+                }
+                rows.push({ 
+                    'added' : ar[0],
+                    'removed' : ar[1],
+                    'filename' : ar[2]
+                });
+                
+                
+            });
+            return rows;  
+    
+        },
+        
+        
+        checkout : function(branch)
+        {
+            this.git(['checkout', branch ]);
+        },
+        /**
+         * stash:
+         * Very basic stash the current changes (normally so you can checkout
+         * another branch..)
+         */
+        stash: function()
+        {
+            this.git(['stash' ]);
+        },
+        
+        
+            
+        applyPatch : function( diff )
+        {
+            var sp = new Spawn({
+                cwd : this.repopath,
+                args : [ 'patch' , '-p1' , '-f' ] ,
+                env :  [  "HOME=" + GLib.get_home_dir() ],
+                debug: true,
+                exceptions : false,
+                async : false,
+                listeners : {
+                    input : function() {
+                        print("sedning patch!");
+                        return diff;
+                    }
+                }
+            });
+            sp.run();
+            return sp.output;
+        } ,
+        /**
+         * add:
+         * add files to track.
+         *
+         * @argument {Array} files the files to add.
+         */
+        add : function ( files )
+        {
+            // should really find out if these are untracked files each..
+            // we run multiple versions to make sure that if one failes, it does not ignore the whole lot..
+            // not sure if that is how git works.. but just be certian.
+            var _t = this;
+            files.forEach(function(f) {
+                try { 
+                    _t.git([ 'add', { '': true }, f ]);
+                } catch(e) {} // ignore errors..
+            });  
+        },
+        
+          /**
+         * remove:
+         * remove files to track.
+         *
+         * @argument {Array} files the files to add.
+         */
+        remove : function ( files )
+        {
+            // this may fail if files do not exist..
+            // should really find out if these are untracked files each..
+            // we run multiple versions to make sure that if one failes, it does not ignore the whole lot..
+            // not sure if that is how git works.. but just be certian.
+            var _t = this;
+            files.forEach(function(f) {
+                try {
+                    _t.git([ 'rm', { f: true } , { '': true }, f ]);
+                } catch(e) {} // ignore errors..
+            });  
+        },
+        
+        /**
+         * commit:
+         * perform a commit.
+         *
+         * @argument {Object} cfg commit configuration
+         * 
+         * @property {String} name (optional)
+         * @property {String} email (optional)
+         * @property {String} changed (date) (optional)
+         * @property {String} reason (optional)
+         * @property {Array} files - the files that have changed. 
+         * 
+         */
+         
+        commit : function( cfg )
+        {
+            
+            var args= [  'commit'  ];
+            var env = [];
+            
+            if (typeof(cfg.name) != 'undefined') {
+                args.push( {
+                    'author' : cfg.name + ' <' + cfg.email + '>'
+                });
+                env.push(
+                    "GIT_COMMITTER_NAME" + cfg.name,
+                    "GIT_COMMITTER_EMAIL" + cfg.email
+                );
+            }
+            if (typeof(cfg.changed) != 'undefined') {
+                env.push("GIT_AUTHOR_DATE= " + cfg.changed )
+                
+            }
+            args.push( 
+                { 'm' : (cfg.reason ? cfg.reason : 'Changed') },
+                { '': true }
+            );
+            
+            cfg.files.forEach(function(f) { args.push(f); })
+             
+            return this.git(args, env);
+        },
+        
+        /**
+         * pull:
+         * Fetch and merge remote repo changes into current branch..
+         *
+         * At present we just need this to update the current working branch..
+         * -- maybe later it will have a few options and do more stuff..
+         *
+         */
+        pull : function ()
+        {
+            // should probably hand error conditions better... 
+            return this.git([ 'pull' ]);
+            
+            
+        },
+        /**
+         * push:
+         * Send local changes to remote repo(s)
+         *
+         * At present we just need this to push the current branch.
+         * -- maybe later it will have a few options and do more stuff..
+         *
+         */
+        push : function ()
+        {
+            // should 
+            return this.git([ 'push' ]);
+            
+        },
+        
+    /*
+        public function getWorkingCopy()
+        {
+            require_once 'MTrack/SCM/Git/WorkingCopy.php';
+            return new MTrack_SCM_Git_WorkingCopy($this);
+        }
+    
+      public function getRelatedChanges($revision) // pretty nasty.. could end up with 1000's of changes..
+      {
+        $parents = array();
+        $kids = array();
+    
+        $fp = $this->git('rev-parse', "$revision^");
+        while (($line = fgets($fp)) !== false) {
+          $parents[] = trim($line);
+        }
+    
+        // Ugh!: http://stackoverflow.com/questions/1761825/referencing-the-child-of-a-commit-in-git
+        $fp = $this->git('rev-list', '--all', '--parents');
+        while (($line = fgets($fp)) !== false) {
+          $hashes = preg_split("/\s+/", $line);
+          $kid = array_shift($hashes);
+          if (in_array($revision, $hashes)) {
+            $kids[] = $kid;
+          }
+        }
+    
+        return array($parents, $kids);
+      } */
+    
+        
+         
+        
+        git: function(args_in,env)
+        {
+            // convert arguments.
+            
+            //print(JSON.stringify(args_in,null,4));
+            args_in.unshift( {
+                'git-dir' : this.gitdir,
+                'no-pager' : true 
+            });
+            var args = ['git' ];
+            
+            if (this.gitdir != this.repopath) {
+                args_in.unshift( { "work-tree" :  this.repopath } ); 
+            }
+            
+            args_in.forEach(function(arg) { 
+                 if (typeof(arg) == 'string') {
+                    args.push(arg);
+                    return;
+                }
+                if (typeof(arg) == 'object') {
+                    for(var k in arg) {
+                        var v = arg[k];
+                        
+                        args.push(k.length != 1 ? ('--' + k) : ('-' + k));
+                        
+                        if (v === true) {
+                            continue;;
+                        }
+                        args.push(v);
+                    }
+                }
+            });
+            this.lastCmd = args.join(" ");
+            if(this.debug) {
+               
+                print( args.join(" ")); 
+            }
+            env = env || [];
+            env.push(  "HOME=" + GLib.get_home_dir() );
+            // do not need to set gitpath..
+            //if (File.exists(this.repo + '/.git/config')) {
+                //env.push("GITPATH=" + this.repo );
+            //}
+            
+            //print(JSON.stringify(args,null,4));  Seed.quit();
+            var sp = new Spawn({
+                cwd : this.repopath,
+                args : args,
+                env : env, // optional
+                debug: this.debug,
+                exceptions : false,
+                async : false
+            });
+            sp.run();
+            
+            if (sp.result) {
+                print(JSON.stringify(sp.result));
+                
+                print(JSON.stringify(sp.args));
+                print(JSON.stringify(sp.stderr));
+                
+                throw {
+                    name    : "RepoSpawnError",
+                    message : sp.stderr,
+                    spawn   : sp
+                };                
+            }
+             
+            //print("GOT: " + output)
+            // parse output for some commands ?
+            return sp.output;
+        },
+        /**
+         * parseAuthor:
+         * break author string with name and email into parts
+         * @argument {String} author
+         * @returns {Object} with 'name' and 'email' properties.
+         */ 
+        parseAuthor : function(author)
+        {
+            var lp = author.indexOf('<');
+             
+            return {
+                name : author.substring(0, lp-1).replace(/\s+$/,''),
+                email : author.substring(0, author.length-1).substring(lp+1)
+            };
+            
+        }
+          
+});
+
+Repo.parseURL = function(url)
+{
+    
+    // git : git://github.com/roojs/roojs1.git
+    // http https://roojs@github.com/roojs/roojs1.git
+    // ssh  git@github.com:roojs/roojs1.git
+    var ret = {
+       scheme : 'ssh://'
+    }
+    url = url.replace(/^[a-z]+:\/\//, function(v) {
+        ret.scheme = v;
+        return '';
+    });
+    var parts = url.split(ret.scheme == 'ssh://' ? ':' : "/");
+    var login_host  = parts.shift().split('@');
+    var user_pass  = (login_host.length == 2 ? login_host.shift() : '').split(':');
+    ret.user = user_pass[0];
+    ret.pass = user_pass.length == 2 ? user_pass[1] : ''; 
+    
+    ret.host = login_host.shift();
+    ret.path = parts.join('/');
+    return ret;
+    
+    
+}
\ No newline at end of file
diff --git a/old_seed_version/Scm/Git/Repo.vala b/old_seed_version/Scm/Git/Repo.vala
new file mode 100644
index 00000000..a50ddff2
--- /dev/null
+++ b/old_seed_version/Scm/Git/Repo.vala
@@ -0,0 +1,231 @@
+
+/**
+ * @class Scm.Git.Repo
+ *
+ * @extends Scm.Repo
+ * 
+ *
+ *
+ */
+class GitRepo : Object
+{
+    
+
+
+    /**
+    * index of.. matching gitpath..
+    */
+     public static int indexOfAdd( Array repos, string gitpath) {
+            for(var i =0; i < repos.length; i++) {
+                if (reos.index(i).gitpath == add) {
+                    return i;
+                }
+            }
+            return -1;
+        }
+    }
+
+
+
+     Array cmds;
+
+
+     public string gitdir;
+    /**
+     * constructor:
+     * 
+     * @param {Object} cfg - Configuration
+     *     (basically repopath is currently only critical one.)
+     *
+     */
+     
+    public GitRepo(path) {
+        // cal parent?
+        
+        this.gitdir = path + "/.git";
+        if (!GLib.file_test(this.gitdir , GLib.FileTest.IS_DIR)) {
+            this.gitdir = path; // naked...
+        }
+        this.cmds = new  Array ();
+        //Repo.superclass.constructor.call(this,cfg);
+        
+    } 
+    /**
+     * add:
+     * add files to track.
+     *
+     * @argument {Array} files the files to add.
+     */
+    public string add ( Array files )
+    {
+        // should really find out if these are untracked files each..
+        // we run multiple versions to make sure that if one failes, it does not ignore the whole lot..
+        // not sure if that is how git works.. but just be certian.
+        for (var i = 0; i < files.length;i++) {
+            var f = files.item(i);
+            
+            if (!GLib.FileUtils.test(this.repopath +"/" + f, GLib.FileTest.EXISTS)) {
+                continue;
+            }
+            printf("Checked %s - exists\n", this.repopath +"/" + f);
+            try {
+                this.git( { "add",   f });
+            } catch (Error e) {
+                ret += e.message  + "\n";
+            }        
+
+        }
+    }
+    
+      /**
+     * remove:
+     * remove files to track.
+     *
+     * @argument {Array} files the files to add.
+     */
+    public string remove : function ( Array files )
+    {
+        // this may fail if files do not exist..
+        // should really find out if these are untracked files each..
+        // we run multiple versions to make sure that if one failes, it does not ignore the whole lot..
+        // not sure if that is how git works.. but just be certian.
+        var ret = "";
+
+        for (var i = 0; i < files.length;i++) {
+            var f = files.item(i);
+            try {
+                this.git( { "rm",  "-f" ,  f });
+            } catch (Error e) {
+                ret += e.message  + "\n";
+            }        
+        }
+
+        return ret;
+
+    },
+    
+    /**
+     * commit:
+     * perform a commit.
+     *
+     * @argument {Object} cfg commit configuration
+     * 
+     * @property {String} name (optional)
+     * @property {String} email (optional)
+     * @property {String} changed (date) (optional)
+     * @property {String} reason (optional)
+     * @property {Array} files - the files that have changed. 
+     * 
+     */
+     
+    public string commit ( string message, Array files  )
+    {
+        
+
+        /*
+        var env = [];
+
+        if (typeof(cfg.name) != 'undefined') {
+            args.push( {
+                'author' : cfg.name + ' <' + cfg.email + '>'
+            });
+            env.push(
+                "GIT_COMMITTER_NAME" + cfg.name,
+                "GIT_COMMITTER_EMAIL" + cfg.email
+            );
+        }
+
+        if (typeof(cfg.changed) != 'undefined') {
+            env.push("GIT_AUTHOR_DATE= " + cfg.changed )
+            
+        }
+        */
+        var args = { "commit", "-m", message.length ? message : "Changed" }
+        for (var i = i< files.length ; i++ ) {
+            args += files.items(i).path; // full path?
+        }
+         
+        return this.git(args, env);
+    },
+    
+    /**
+     * pull:
+     * Fetch and merge remote repo changes into current branch..
+     *
+     * At present we just need this to update the current working branch..
+     * -- maybe later it will have a few options and do more stuff..
+     *
+     */
+    pull : function ()
+    {
+        // should probably hand error conditions better... 
+        return this.git({ "pull" });
+        
+        
+    },
+    /**
+     * push:
+     * Send local changes to remote repo(s)
+     *
+     * At present we just need this to push the current branch.
+     * -- maybe later it will have a few options and do more stuff..
+     *
+     */
+    push : function ()
+    {
+        // should 
+        return this.git({ "push" });
+        
+    },
+     /**
+     * git:
+     * The meaty part.. run spawn.. with git..
+     *
+     *
+     */
+    
+    git: function(string[] args_in, string[] env = {})
+    {
+        // convert arguments.
+        
+
+        var args = {
+           "git", 
+            "--git-dir", this.gitdir,
+            "--no-pager",
+        }; 
+
+
+        if (this.gitdir != this.repopath) {
+            args +=   "--work-tree"
+            args += this.repopath; 
+        }
+        for (var i = i; i < args_in.length;i++) {
+            args += args_in[i];
+        }            
+
+        //this.lastCmd = args.join(" ");
+        if(this.debug) {
+         
+            print(  string.joinv (", ", args_list);); 
+        }
+        
+        env +=  ("HOME=" + GLib.get_home_dir() );
+        // do not need to set gitpath..
+        //if (File.exists(this.repo + '/.git/config')) {
+            //env.push("GITPATH=" + this.repo );
+        //}
+        
+
+        var cfg = new SpawnConfig(this.repopath, args , env);
+        
+
+       // may throw error...
+        var sp = new Spawn(cfg);
+                
+        //print("GOT: " + output)
+        // parse output for some commands ?
+        return sp.output;
+    }
+
+}
diff --git a/old_seed_version/Scm/Repo.js b/old_seed_version/Scm/Repo.js
new file mode 100644
index 00000000..06022bc4
--- /dev/null
+++ b/old_seed_version/Scm/Repo.js
@@ -0,0 +1,342 @@
+var XObject = imports.XObject.XObject;
+
+var GLib  = imports.gi.GLib;
+var File = imports.File.File;
+// mix of SCM and Repo class from mtrack.
+
+//var SCM = imports.SCM.SCM;
+
+_abstract = function() {
+    throw "abstract function not implemented";
+}
+
+Repo = XObject.define(
+    function(cfg) {
+        // cal parent?
+        if (typeof(cfg) != 'object') {
+            return;
+        } 
+        XObject.extend(cfg);
+         
+    },
+    Object,
+    {
+            
+        id : null,
+        scmtype : null,
+         browserurl : null,
+        browsertype : null,
+        description : null,
+        parent : '',
+        clonedfrom : null,
+        serverurl : null,
+
+    
+        links_to_add : false,
+        links_to_remove : false,
+        links : false,
+        
+        
+        repopath : '',
+        
+       
+        /** Returns an array keyed by possible branch names.
+        * The data associated with the branches is implementation
+        * defined.
+        * If the SCM does not have a concept of first-class branch
+        * objects, this function returns null */
+        getBranches : _abstract,
+        
+        /** Returns an array keyed by possible tag names.
+        * The data associated with the tags is implementation
+        * defined.
+        * If the SCM does not have a concept of first-class tag
+        * objects, this function returns null */
+        getTags : _abstract,
+        
+        /** Enumerates the files/dirs that are present in the specified
+        * location of the repository that match the specified revision,
+        * branch or tag information.  If no revision, branch or tag is
+        * specified, then the appropriate default is assumed.
+        *
+        * The second and third parameters are optional; the second
+        * parameter is one of 'rev', 'branch', or 'tag', and if specifed
+        * the third parameter must be the corresponding revision, branch
+        * or tag identifier.
+        *
+        * The return value is an array of MTrackSCMFile objects present
+        * at that location/revision of the repository.
+        */
+        readdir : _abstract,
+        
+        /** Queries information on a specific file in the repository.
+        *
+        * Parameters are as for readdir() above.
+        *
+        * This function returns a single MTrackSCMFile for the location
+        * in question.
+        */
+        file : _abstract,
+        
+        /** Queries history for a particular location in the repo.
+        *
+        * Parameters are as for readdir() above, except that path can be
+        * left unspecified to query the history for the entire repo.
+        *
+        * The limit parameter limits the number of entries returned; it it is
+        * a number, it specifies the number of events, otherwise it is assumed
+        * to be a date in the past; only events since that date will be returned.
+        *
+        * Returns an array of MTrackSCMEvent objects.
+        */
+        history : _abstract,
+        
+        /** Obtain the diff text representing a change to a file.
+        *
+        * You may optionally provide one or two revisions as context.
+        *
+        * If no revisions are passed in, then the change associated
+        * with the location will be assumed.
+        *
+        * If one revision is passed, then the change associated with
+        * that event will be assumed.
+        *
+        * If two revisions are passed, then the difference between
+        * the two events will be assumed.
+        */
+        diff : _abstract,
+        
+        /** Determine the next and previous revisions for a given
+        * changeset.
+        *
+        * Returns an array: the 0th element is an array of prior revisions,
+        * and the 1st element is an array of successor revisions.
+        *
+        * There will usually be one prior and one successor revision for a
+        * given change, but some SCMs will return multiples in the case of
+        * merges.
+        */
+        getRelatedChanges : _abstract,
+        
+        /** Returns a working copy object for the repo
+        *
+        * The intended purpose is to support wiki page modifications, and
+        * as such, is not meant to be an especially efficient means to do so.
+        */
+        getWorkingCopy : _abstract,
+        
+        /** Returns meta information about the SCM type; this is used in the
+        * UI and tooling to let the user know their options.
+        *
+        * Returns an array with the following keys:
+        * 'name' => 'Mercurial', // human displayable name
+        * 'tools' => array('hg'), // list of tools to find during setup
+        */
+        getSCMMetaData : _abstract,
+        
+        /** Returns the default 'root' location in the repository.
+        * For SCMs that have a concept of branches, this is the empty string.
+        * For SCMs like SVN, this is the trunk dir */
+        getDefaultRoot : function() {
+             return '';
+        },
+
+        
+          
+        
+        /* takes an MTrackSCM as a parameter because in some bootstrapping
+         * cases, we're actually MTrack_Repo and not the end-class.
+         * MTrack_Repo calls the end-class method and passes itself in for
+         * context */
+        reconcileRepoSettings  : _abstract,
+        
+        
+        
+        
+        getBrowseRootName   : _abstract, 
+        /***
+         *
+         * resolve Revision
+         *
+         * @param {string} rev - a fixed revision - always returns this if it is not false;
+         * @param {string} object [rev|branch|tag]- object type
+         * @param {ident} object id (eg. rev nun, branch name, tag name)
+         *
+         *
+         */
+        resolveRevision :function(rev, object, ident)
+        {
+            if (rev !== false) {
+                return rev;
+            }
+            
+            if (object === false) {
+                return false;
+            }
+            
+            switch (object) {
+                case 'rev':
+                    rev = ident;
+                    break;
+                
+                case 'branch':
+                    
+                    // technically we should check it exists..
+                    rev = ident;
+                    break;
+                    //var branches = this.getBranches();
+                    // branches is now an array - not a map.
+                     
+                    //rev = typeof(branches[ident]) == 'undefined' ? false : branches[ident];
+                    //break;
+                
+                case 'tag':
+                    tags = this.getTags();
+                    rev = typeof(tags[ident]) == 'undefined' ? false : tags[ident];
+                    break;
+            }
+            if (rev === false) {
+                throw   "don't know which revision to use (rev,object,ident) got" + object;
+            }
+            return rev;
+        }
+        
+    
+     /*
+    
+    function reconcileRepoSettings()
+    {
+        $c = self::Factory(array('scmtype'=>$this->scmtype));
+        $s->reconcileRepoSettings($this);
+    }
+    
+    function getServerURL()
+    {
+        if ($this->serverurl) {
+            return $this->serverurl;
+        }
+        
+        return null;
+    }
+
+    function getCheckoutCommand() {
+        $url = $this->getServerURL();
+        if (strlen($url)) {
+          return $this->scmtype . ' clone ' . $this->getServerURL();
+        }
+        return null;
+    }
+
+    function canFork() {
+        return false;
+    }
+
+    function getWorkingCopy() {
+         throw new Exception("cannot getWorkingCopy from a generic repo object");
+    }
+    /*
+    function deleteRepo(MTrackChangeset $CS) {
+        MTrackDB::q('delete from repos where repoid = ?', $this->repoid);
+        mtrack_rmdir($this->repopath);
+    }
+     
+  
+
+// these are needed just to implement the abstract interface..
+    function getBranches() {}
+    function getTags() {}
+    function readdir($path, $object = null, $ident = null) {}
+    function file($path, $object = null, $ident = null) {}
+    function history($path, $limit = null, $object = null, $ident = null){}
+    function diff($path, $from = null, $to = null) {}
+    function getRelatedChanges($revision) {}
+    function getSCMMetaData() { return null; }
+    /**
+     *  converts a commit log message (cached locally into a working object..)
+     *  see Browse.php
+     */
+    /*
+    function commitLogToEvent($str) {
+        throw new Exception("no implementation for commitLogToEvent");
+    }
+    */
+});
+
+
+/*
+ 
+    static $scms = array();
+    static function factory($ar)
+    {
+        //print_r($ar);
+        $type = ucfirst($ar['scmtype']);
+        $fn = 'MTrack/SCM/'.$type .'/Repo.php';
+        $cls = 'MTrack_SCM_'.$type .'_Repo';
+        require_once $fn;
+        
+        $ret = new $cls($ar);
+        
+        return $ret;
+        
+    }
+    
+ 
+    static function getAvailableSCMs()
+    {
+        $ret = array();
+        $ar = scandir(dirname(__FILE__).'/SCM');
+        
+        foreach($ar as $a) {
+            if (empty($a) || $a[0] == '.') {
+                continue;
+            }
+            $fn = dirname(__FILE__).'/SCM/'.$a.'/Repo.php';
+            if (!file_exists($fn)) {
+                continue;
+            } 
+            $ret[$a] = MTrack_Repo::factory(array('scmtype'=> $a));
+            
+        }
+        return $ret;
+    }  
+*/
+
+Repo._list  = false;
+Repo.list = function()
+{
+    
+    if (Repo._list !== false) {
+        return Repo._list;
+    }
+    Repo._list  = [];
+    var dir = GLib.get_home_dir() + '/gitlive';
+    var ar = File.list(dir );
+    print(JSON.stringify(ar));
+    ar.forEach(function(f) {
+        if (File.exists(dir + '/' + f +'/.git')) {
+            Repo._list.push(new imports.Scm.Git.Repo.Repo(  {
+                repopath : dir  +'/' + f,
+                name : f
+            }))
+        }
+    });
+    
+    return Repo._list;
+      
+}
+Repo.get = function(path_or_name)
+{
+    var tr = Repo.list();
+    for (var i =0;i < tr.length; i++) {
+        if (tr[i].name == path_or_name) {
+            return tr[i];
+        }
+        
+        if (tr[i].repopath == path_or_name) {
+            return tr[i];
+        }
+        
+    }
+    return false;
+    
+}
diff --git a/old_seed_version/install1.2.sh b/old_seed_version/install1.2.sh
new file mode 100644
index 00000000..63dd28a4
--- /dev/null
+++ b/old_seed_version/install1.2.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+# installs the working girs!
+#git clone git://github.com/roojs/gir-1.2-gtk-3.0.git gir-1.2
+
+#// compile GIR's
+mkdir -p ~/.Builder/girepository-1.2 || false
+ 
+ 
+ls gir-1.2 | sed s/.gir// | awk \
+    '{ print "g-ir-compiler  gir-1.2/" $1 ".gir --includedir=gir-1.2 -o  ~/.Builder/girepository-1.2/" $1 ".typelib" }' \
+    | sh -x
+
+
+
+cp ~/.Builder/girepository-1.2/GLib-2.0.typelib /usr/lib/girepository-1.0/
-- 
2.39.2