sync
authorAlan Knowles <alan@roojs.com>
Fri, 11 Aug 2017 05:04:20 +0000 (13:04 +0800)
committerAlan Knowles <alan@roojs.com>
Fri, 11 Aug 2017 05:04:20 +0000 (13:04 +0800)
old_seed_version/INSTALL.txt [new file with mode: 0644]
old_seed_version/Scm/Git/Event.js [new file with mode: 0644]
old_seed_version/Scm/Git/Repo.js [new file with mode: 0644]
old_seed_version/Scm/Git/Repo.vala [new file with mode: 0644]
old_seed_version/Scm/Repo.js [new file with mode: 0644]
old_seed_version/install1.2.sh [new file with mode: 0644]

diff --git a/old_seed_version/INSTALL.txt b/old_seed_version/INSTALL.txt
new file mode 100644 (file)
index 0000000..41964de
--- /dev/null
@@ -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 (file)
index 0000000..d2393ca
--- /dev/null
@@ -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 (file)
index 0000000..a946bfe
--- /dev/null
@@ -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 '<PRE>';echo $line ."\n</PRE>";
+                $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 '<PRE>';print_r($args);echo '</PRE>';
+            
+            
+            
+            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 '<PRE>';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 (file)
index 0000000..a50ddff
--- /dev/null
@@ -0,0 +1,231 @@
+
+/**
+ * @class Scm.Git.Repo
+ *
+ * @extends Scm.Repo
+ * 
+ *
+ *
+ */
+class GitRepo : Object
+{
+    
+
+
+    /**
+    * index of.. matching gitpath..
+    */
+     public static int indexOfAdd( Array<GitRepo> repos, string gitpath) {
+            for(var i =0; i < repos.length; i++) {
+                if (reos.index(i).gitpath == add) {
+                    return i;
+                }
+            }
+            return -1;
+        }
+    }
+
+
+
+     Array<GitMontitorQueue> 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<GitMontitorQueue> ();
+        //Repo.superclass.constructor.call(this,cfg);
+        
+    } 
+    /**
+     * add:
+     * add files to track.
+     *
+     * @argument {Array} files the files to add.
+     */
+    public string add ( Array<GitMontitorQueue> 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<GitMontitorQueue> 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<GitMontitorQueue> 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 (file)
index 0000000..06022bc
--- /dev/null
@@ -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 (file)
index 0000000..63dd28a
--- /dev/null
@@ -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/