revert code that did not affect memory
[gitlive] / GitRepo.vala
index b1bb25f..a4d1bfd 100644 (file)
@@ -18,12 +18,36 @@ public class GitRepo : Object
     public string gitdir;
     public string git_working_dir;
     public bool debug = false;
+    public bool has_local_changes = false;
+    public string host = "";
+    public string git_status;    
+    public string git_diff;        
+    public string ahead_or_behind = "";
     
     public Gee.HashMap<string,bool> ignore_files;
-    public GitBranch currentBranch;
+     
+    public GitBranch  _currentBranch;
+    public GitBranch  getCurrentBranch() {
+       if (this._currentBranch == null) {
+               Posix.usleep(100); // try and slow down branch loading          
+               this.loadBranches();
 
+       }
+       if (this._currentBranch == null) {      
+               GLib.error("could not work out current branch? : %s ",this.git_working_dir );
+               }
+               return this._currentBranch;
+    }
+    
+    
+    public Gee.HashMap<string,GitBranch> branches; // accessed in GitBranch..
        public RooTicket? activeTicket;
-
+    public Gee.HashMap<string,GitRepo> cache;
+    public Gee.HashMap<string,string> config_cache;
+    
+    public Ggit.Repository repo;
+    public Ggit.RemoteHead[]                           remote_heads = null;
+    
        public static GitRepo singleton()
     {
         if (_GitRepo == null) {
@@ -32,13 +56,13 @@ public class GitRepo : Object
         }
         return _GitRepo;
     }
-
     /**
     * index of.. matching gitpath..
     */
     public static int indexOf( Array<GitRepo> repos, string gitpath) {
         // make a fake object to compare against..
-        var test_repo = GitRepo.get(gitpath);
+        var test_repo = GitRepo.get_sync(gitpath);
         
         for(var i =0; i < repos.length; i++) {
             if (repos.index(i).gitdir == test_repo.gitdir) {
@@ -49,7 +73,7 @@ public class GitRepo : Object
     
     }
     
-    public  Gee.HashMap<string,GitRepo> cache;
+
     
     
     
@@ -118,24 +142,48 @@ public class GitRepo : Object
                 continue;
             }
             
-               var rep =  GitRepo.get(  sp );
+               var rep =  GitRepo.get_sync(  sp );
                list_cache.append_val(rep);             
             
         }
     
         return list_cache;
-        
          
-          
        }
        
-       public static GitRepo get(string path) 
+       public  static GitRepo get_sync(string path) 
        {
+               GitRepo ret;
                var cache = GitRepo.singleton().cache;
                if (cache.has_key(path)) {
-                       return cache.get(path);
+                       ret =  cache.get(path);
+               } else {
+                       ret =  new GitRepo(path);
                }
-               return new GitRepo(path);
+               return ret;
+       }
+        
+       public static  async  GitRepo? get(string path) 
+       {
+               
+               SourceFunc callback = GitRepo.get.callback;
+               GitRepo ret = null;
+               ThreadFunc<bool> run = () => {
+                       
+                       var cache = GitRepo.singleton().cache;
+                       if (cache.has_key(path)) {
+                               ret =  cache.get(path);
+                       } else {
+                               ret =  new GitRepo(path);
+                       }
+                       Idle.add((owned) callback);
+               return true;
+                       
+               };
+               new Thread<bool>("thread-new-gitrepo-" + path, run);
+               yield;
+               return ret;
+               
        }
        
     private GitRepo.single() {
@@ -149,7 +197,8 @@ public class GitRepo : Object
      *
      */
      
-    private GitRepo(string path) {
+    private GitRepo(string path) 
+    {
         // cal parent?
         this.name =   File.new_for_path(path).get_basename();
         this.ignore_files = new Gee.HashMap<string,bool>();
@@ -166,50 +215,155 @@ public class GitRepo : Object
                if ( !cache.has_key(path) ) {
                        cache.set( path, this);
        }
+       
+       this.repo =  Ggit.Repository.open(GLib.File.new_for_path(path));
+       
+       var r = this.repo.lookup_remote("origin");
+       
+       
+       //var r = this.git({ "remote" , "get-url" , "--push" , "origin"});
+       var uri = new Soup.URI(r.get_url());            
+       this.host = uri.get_host();
+               this.init_config();
+       
        this.loadBranches();
+       this.loadActiveTicket();
+       this.loadStatus();
     } 
     
-    public bool is_wip_branch()
+    public bool is_master_branch()
     {
-       return this.currentBranch.name.has_prefix("wip_");
+       // special branches that do not allow autopushing now...
+       return this.getCurrentBranch().name == "master" || this.getCurrentBranch().name == "roojs";
                
     }
+    public void init_config()
+    {
+       this.config_cache = new Gee.HashMap<string,string>();
+       // managed = 
+       if (this.get_config("managed") == "") {
+               this.set_config("managed", this.host == "git.roojs.com" ? "1" : "0");
+               }
+       if (this.get_config("autocommit") == "") {
+               this.set_config("autocommit", this.host == "git.roojs.com" ? "1" : "0");
+               }
+       if (this.get_config("autopush") == "") {
+               this.set_config("autopush", this.host == "git.roojs.com" ? "1" : "0");
+               }
+               
+    }
+    
+    
+    
+    public string get_config(string key) 
+    {
+    
+       if (this.config_cache.has_key(key)) {
+               //GLib.debug("get_config %s = '%s'", key, this.config_cache.get(key));
+               return this.config_cache.get(key);
+               }
+       try {
+               var cfg = this.repo.get_config().snapshot();
+               var ret = cfg.get_string("gitlive." + key).strip();
+               return ret;
+       } catch (Error e) {
+               this.repo.get_config().set_string("gitlive." + key, "");
+               //this.config_cache.set(key, "");
+               //GLib.debug("get_config (fail) %s = '%s'", key, "");
+               return ""; // happens when there is nothing set...
+       }
+
+       }
+    public void set_config(string key, string value) 
+    {
+       this.repo.get_config().set_string("gitlive." + key, value);
+       //this.git({ "config" , "gitlive." + key, value });
+       //this.config_cache.set(key,value);
+       }
+    
+    public bool is_managed()
+    {
+       return this.get_config("managed") == "1";
+    }
+    
     
     public bool is_autocommit ()
+    {          
+       return this.get_config("autocommit") == "1";            
+    }
+    
+    public void set_autocommit(bool val)
+    {
+               this.set_config("autocommit", val ? "1" : "0");
+    
+    }
+    
+    public bool is_auto_branch ()
     {
-       return !FileUtils.test(this.gitdir + "/.gitlive-disable-autocommit" , FileTest.EXISTS);
+       if (this.name == "gitlog") {
+               return false;
+               }
+               // check remote...
+       if (this.is_managed()) {
+               return true;
+               }
+       return false;
+       
+    }
+    
+    public void set_auto_branch(bool val)
+    {
+               if (this.name == "gitlog") {
+               return;
+               }
+               this.set_config("managed", val ? "1" : "0");
+    
     }
     public bool is_autopush ()
     {
-       return !FileUtils.test(this.gitdir + "/.gitlive-disable-autopush" , FileTest.EXISTS);
+       return this.get_config("autopush") == "1";
     }
+    public void set_autopush(bool val)
+    {
+               this.set_config("autopush", val ? "1" : "0");
+    }
+    
     
-    Gee.HashMap<string,GitBranch> branches;
+       public void loadStatus()
+       {
+               // status??/ 
+               var r = this.git({ "status" , "--porcelain" });
+               this.git_status = r;
+               this.has_local_changes = r.length > 0;
+               
+               //var rs = this.git({ "status" , "-sb" });
+               var cb = this.getCurrentBranch();
+                 
+               this.ahead_or_behind = cb.ahead > 0 ?  "A" : (cb.behind > 0  ? "B" : "");
+               
+               
+               this.git_diff  = this.diffWorking();
+       }    
+
     
     public void loadBranches()
     {
-       this.branches = new Gee.HashMap<string,GitBranch>();
-       
-       string[] cmd = { "branch",   "--no-color", "--verbose", "--no-abbrev" , "-a"  };
-        var res = this.git( cmd );
-        var lines = res.split("\n");
-        for (var i = 0; i < lines.length ; i++) {
-               var br = new GitBranch(this);
-               if (!br.parseBranchListItem(lines[i])) {
-                       continue;
-               }
-               GLib.debug("add branch %s", br.realName());
-                
-               branches.set(br.realName(), br);
-               if (br.active) {
-                       this.currentBranch = br;
-               }
-        }
-    
+
+       GitBranch.loadBranches(this);
     }
      
     
-    
+    public bool hasBranchCalled(string name)
+    {
+       foreach( var br in this.branches.values) {
+                       if (br.name == name) {
+                               return true;
+                       }
+
+               }
+               return false;
+    }
     
     public string branchesToString()
     {
@@ -218,8 +372,9 @@ public class GitRepo : Object
                        if (br.name == "") {
                                continue; 
                        }
-                       ret += ret.length > 0 ? ","  : "";
-                       ret += br.name;
+                       var col = /hours/.match(br.age) ? "#ff851b" : "#ffdc00"; // orange or yellow
+                       ret += ret.length > 0 ? "\n"  : "";
+                       ret += br.name + " <span background=\"" + col + "\">" + br.age + "</span>";
                
                }
                return ret;
@@ -239,7 +394,7 @@ public class GitRepo : Object
                                continue;
                        }
                        commitrevs += commitrevs.length > 0 ? " " : "";
-                       commitrevs += repo.currentBranch.lastrev;
+                       commitrevs += repo.getCurrentBranch().lastrev;
                }
        }
        if (sucess && action == "CLOSE") {
@@ -247,29 +402,29 @@ public class GitRepo : Object
        }
        GitMonitor.gitmonitor.start();
     }
-    
-
-
+      
 
     public bool doMerge(string action, string ticket_id, string commit_message)
     {
        // in theory we should check to see if other repo's have got the same branch and merge all them at the same time.
        // also need to decide which branch we will merge into?
+                       var master = this.hasBranchCalled("roojs") ? "roojs" : "master";
+       
                   var ret = "";
                   if (action == "CLOSE" || action == "LEAVE") {
                                   
                try {
-                       var oldbranch = this.currentBranch.name;
-                       this.setActiveTicket(null, "master");
-               string [] cmd = { "merge",   "--squash",  oldbranch };
-               this.git( cmd );
-                cmd = { "commit",   "--m",  commit_message };
-               this.git( cmd );
-               this.loadBranches(); // updates lastrev..
+                   var oldbranch = this.getCurrentBranch().name;
+                   this.setActiveTicket(null, master);
+                          string [] cmd = { "merge",   "--squash",  oldbranch };
+                          this.git( cmd );
+                          cmd = { "commit",   "-a" , "-m",  commit_message };
+                          this.git( cmd );
+                          this.push();
+                          this.loadBranches(); // updates lastrev..
                
-               var notification = new Notify.Notification(
-                               "Merged branch %s to master".printf(oldbranch),
+                      var notification = new Notify.Notification(
+                               "Merged branch %s to %s".printf(oldbranch, master),
                                "",
                                 "dialog-information"
                                
@@ -292,10 +447,10 @@ public class GitRepo : Object
        if (action == "MASTER") {
                // merge master into ours..
                        try {
-                       string[] cmd = { "merge",  "master" };
+                       string[] cmd = { "merge", master};
                        this.git( cmd );
                        var notification = new Notify.Notification(
-                                       "Merged code from master to %s".printf(this.currentBranch.name),
+                                       "Merged code from %s to %s".printf(master,this.getCurrentBranch().name),
                                        "",
                                         "dialog-information"
                                        
@@ -311,8 +466,8 @@ public class GitRepo : Object
            }
        if (action == "EXIT") {
                        try {
-                       var oldbranch  = this.currentBranch.name;
-                         this.setActiveTicket(null, "master");
+                       var oldbranch  = this.getCurrentBranch().name;
+                         this.setActiveTicket(null, master);
                        this.loadBranches();
                        var notification = new Notify.Notification(
                                        "Left branch %s".printf(oldbranch),
@@ -334,46 +489,43 @@ public class GitRepo : Object
        }
        return false;
     }
+        
+    public void loadActiveTicket()
+    {
+       this.activeTicket = null;
+               var ticket_id = this.get_config("ticket");
+       
+       if (ticket_id.length < 1) {
+               return;
+               }
+               this.activeTicket = RooTicket.singleton().getById(ticket_id.strip());
+       
+       
+    }
+    
     
     
-    public bool setActiveTicket(RooTicket ticket, string branchname)
+    public bool setActiveTicket(RooTicket? ticket, string branchname)
     {
+       this.set_config("ticket", "");
        if (!this.createBranchNamed(branchname)) {
                return false;
                }
-       FileUtils.set_contents(this.gitdir + "/.gitlive-active-ticket" , ticket.id);
+               this.set_config("ticket", ticket == null ? "": ticket.id);
        this.activeTicket = ticket;
        return true;
     }
     
     public bool createBranchNamed(string branchname)
-    {
-               
-               try {
+    {  
+               
+
                     if (this.branches.has_key(branchname)) {
-                       // this is where it get's tricky...
-                       
-                       string[] cmd = { "ls-files" ,  "-m" };                   // list the modified files..
-                   var ret = this.git(cmd);
-                   var stash = ret.length> 1 ;
-                   
-                       
-                   cmd = { "stash" };                  
-                   if (stash) { this.git(cmd); }
-                   
-                   cmd = { "checkout", branchname  };
-                   this.git(cmd);
-                   
-                   cmd = { "merge", "master"  };
-                   this.git(cmd);
-                   
-                   cmd = { "stash", "pop"  };
-                   if (stash) { this.git(cmd); }
-                   
+                       this.switchToExistingBranchNamed(branchname);
                    
                    } else {
-                           string[] cmd = { "checkout", "-b" , branchname  };
-                           this.git(cmd);
+                                this.createNewBranchNamed(branchname); 
+                           
                    }
                       var notification = new Notify.Notification(
                        "Changed to branch %s".printf(branchname),
@@ -385,16 +537,179 @@ public class GitRepo : Object
                notification.set_timeout(5);
                notification.show();   
        
-                   
-           } catch(Error e) {
-               GitMonitor.gitmonitor.pauseError(e.message);
-        return false;          
-           
-           }
+        
         this.loadBranches(); // update branch list...
-        GitMonitor.gitmonitor.runQueue(); // commit any outstanding...
+        //GitMonitor.gitmonitor.runQueue(); // no point - we have hidden the queue..
         return true;
     }
+     bool switchToExistingBranchNamed(string branchname)
+     {
+               var master = this.hasBranchCalled("roojs") ? "roojs" : "master";
+               var stash = false;
+               // this is where it get's tricky...
+               string files = "";
+               try {                   
+                               string[] cmd = { "ls-files" ,  "-m" };                   // list the modified files..
+                               files = this.git(cmd);
+                               stash = files.length> 1 ;
+                               
+                               
+                               cmd = { "stash" };                      
+                               if (stash) { this.git(cmd); }
+                               
+                               this.pull();
+                               
+                               cmd = { "checkout", branchname  };
+                               this.git(cmd);
+                 } catch(Error e) {
+                               GitMonitor.gitmonitor.pauseError(e.message);
+                               return false;           
+                 }
+               try {
+                  if (branchname != master) {
+                      string[] cmd = { "merge", master };
+                           this.git(cmd);
+                           this.push();
+                      
+                   }
+                   
+               } catch(Error e) {
+                   string[] cmd = { "checkout", master  };
+                   this.git(cmd);
+                       GitMonitor.gitmonitor.pauseError(
+                               "Use\n\na) git checkout %s\nb) git mergetool\nc) git commit\nd) git push\n d) stash pop \ne) start gitlive again\n".printf(
+                                       branchname)
+                                + e.message
+                       );
+                       return false;           
+                
+               }
+               try {                                   
+                   string[]  cmd = { "stash", "pop"  };
+                   if (stash) { 
+                       this.git(cmd); 
+                       var fl = files.split("\n");
+                       cmd = { "commit", "-m" , "Changed " + string.joinv("",fl) };
+                       foreach(var f in fl) {
+                               if (f.length < 1) continue;
+                               cmd += f;
+                       }
+                       this.git(cmd);                              
+               }
+            
+
+                  
+               } catch(Error ee) {
+                       GitMonitor.gitmonitor.pauseError(ee.message);
+                       return false;           
+               }
+       this.push();
+       return true;                            
+                
+     }
+    
+    
+    
+     bool createNewBranchNamed(string branchname)
+     {
+               var stash = false;
+                try {                                  
+                               string[] cmd = { "ls-files" ,  "-m" };                   // list the modified files..
+                               var files = this.git(cmd);
+                               stash = files.length> 1 ;
+                       
+                        cmd = { "checkout", "-b" , branchname  };
+                       this.git(cmd);
+
+               cmd = { "push", "-u" , "origin" ,"HEAD"  };
+                       this.git(cmd);
+                               if (stash) { 
+
+                               var fl = files.split("\n");
+                               cmd = { "commit", "-m" , "Changed " + string.joinv("",fl) };
+                               foreach(var f in fl) {
+                                       if (f.length < 1) continue;
+                                       cmd += f;
+                               }
+                               this.git(cmd);  
+                               this.push();                        
+                       }
+
+             
+               } catch(Error ee) {
+                               GitMonitor.gitmonitor.pauseError(ee.message);
+                               return false;           
+                       }
+                       return true;
+     
+     }
+     
+     public static string previewMerges(string ticket_id)
+    {
+       var ret = "";
+       foreach(var  repo in GitRepo.singleton().cache.values) {
+           if (repo.activeTicket == null || repo.activeTicket.id != ticket_id) {
+                       continue;
+               }
+                       ret += repo.previewMerge() + "\n\n";
+
+       }
+       return ret;
+
+    }
+     
+     
+     
+     public string previewMerge()
+     {
+        try {                                  
+                       var master = this.hasBranchCalled("roojs") ? "roojs" : "master";
+                       var lines = this.git({"log", master + "...",  "--pretty=format:%H %P" }).split("\n");;
+                       var head = this.git({"log", "-1",  "--pretty=format:%H %P" });
+                       var start = head.split(" ")[0];
+                       var end = "";
+                       for (var i = 0; i < lines.length; i++) {
+                               var cols = lines[i].split(" ");
+                               if (cols.length > 2) {
+                                       end = cols[0];
+                                       break;
+                               }
+                       }
+                       if (end == "") {
+                               var last = lines.length > 0 ? lines[lines.length-1] : "";
+                               end = last.split(" ")[1];                               
+                       }
+
+                       return this.git({ "diff" , (end+".."+start), "--no-color" });
+               }  catch(Error ee) {
+                       GitMonitor.gitmonitor.pauseError(ee.message);
+                       return "Error getting diff";            
+               }
+         
+     }
+    
+    
+    public string diffWorking()
+    {
+       var cb = this.getCurrentBranch();
+       GLib.debug("Calling diff working");
+       var diff = new Ggit.Diff.tree_to_workdir(this.repo, cb.getTree(), new Ggit.DiffOptions());
+       var ret = "";
+       diff.print(Ggit.DiffFormatType.PATCH, (delta, hunk, line) => {
+               switch(line.get_origin()) {
+                       case Ggit.DiffLineType.ADDITION: ret+="+"; break;
+                               case Ggit.DiffLineType.DELETION: ret+="-";break;
+                               case Ggit.DiffLineType.CONTEXT:  ret+=" ";break;
+                               case Ggit.DiffLineType.HUNK_HDR: break;                                 
+                               case Ggit.DiffLineType.FILE_HDR: break;
+                               default: ret+=" ";break;
+                       }
+               ret += " " + line.get_text() ;
+               return 0;
+       });
+       //GLib.debug("returning %s", ret);
+       return ret;
+    }    
     
     
     /**
@@ -539,7 +854,7 @@ public class GitRepo : Object
     public void pull_async(GitAsyncCallback cb) 
     {
     
-        string[] cmd = { "pull" , "--no-edit" };
+         string[] cmd = { "pull" , "--no-edit" };
          this.git_async( cmd , cb);
          
     
@@ -556,7 +871,7 @@ public class GitRepo : Object
     public string push () throws Error, SpawnError
     {
         // should 
-        return this.git({ "push", "origin", "HEAD" });
+        return this.git({ "push"  });
         
     }
     
@@ -600,16 +915,19 @@ public class GitRepo : Object
         //if (File.exists(this.repo + '/.git/config')) {
             //env.push("GITPATH=" + this.repo );
         //}
-        
-
+          
         var cfg = new SpawnConfig(this.git_working_dir , args , env);
-        
+        //cfg.debug = true;
 
        // may throw error...
         var sp = new Spawn(cfg);
       
-
-        GLib.debug( "GOT: %s" , sp.output);
+            //GLib.debug( "GOT result: %d" , sp.result);
+      
+       // diff output is a bit big..
+               if (args_in[0] != "diff") {
+               GLib.debug( "GOT: %s" , sp.output);
+        }
         // parse output for some commands ?
         return sp.output;
     }
@@ -670,4 +988,158 @@ public class GitRepo : Object
     
     }
     
+    
+    public async void doUpdate()
+    {
+       SourceFunc callback = this.doUpdate.callback;
+               GitRepo ret = null;
+               ThreadFunc<bool> run = () => {
+                       
+                       
+               // update the branches..
+                       this.loadBranches();
+
+                       //GLib.debug("connecting '%s'", r.get_url());
+                       string[] far = {};
+                       foreach(var br in this.branches.values) {
+                               if (br.remote == "" || br.remoterev == br.lastrev) {
+                                       continue;
+                               }
+                               far +=  ("+refs/heads/" + br.name + ":refs/remotes/" + br.remote);
+                       }
+                       if (far.length > 0) {
+                               GLib.debug("PUlling %s", this.name);
+                               var r = this.repo.lookup_remote("origin");
+                               r.connect(Ggit.Direction.FETCH, new GitCallbacks(this), null, null);
+                               var options = new Ggit.FetchOptions();
+                               options.set_remote_callbacks( new GitCallbacks(this));
+                               r.download(far, options);
+                               r.disconnect();
+                       }
+                       this.loadStatus();
+                        
+               
+                       Idle.add((owned) callback);
+               return true;
+                       
+               };
+               new Thread<bool>("thread-new-gitpull-" + this.name, run);
+               yield;
+                  
+       
+    }
+    
+       
+       public static void updateAllAsync(string after)
+       {
+               
+               var doing = new  Gee.HashMap<string,bool>();;
+               
+               var tr =  GitRepo.singleton().cache;
+        
+       var update_all_total = tr.size;
+       foreach(var repo  in tr.values) {
+               if (!repo.is_managed()) {
+                       update_all_total--;                     
+                               continue;
+                       }
+                       doing.set(repo.name, true);
+                       repo.doUpdate.begin((obj, res) => {
+                               repo.doUpdate.end(res);
+                               doing.set(repo.name, false);
+                                
+                               foreach(var b in doing.keys) {
+                                       if (doing.get(b)) {
+                                               GLib.debug("pending: %s", b);
+                                               return;
+                                       }
+                               }
+                       
+                               
+                               switch (after) {
+                                       case "show_clones":
+                                               Clones.singleton().show();
+                                               break;
+                                       default:
+                                               GLib.debug("Unkown call after load = %s", update_all_after);            
+                                               break;
+                               }
+                       });
+               }
+
+       
+       }
+       
+        
+    
+    public void update_async(GitAsyncCallback cb) 
+    {
+         string[] cmd = { "fetch" , "--all" };
+         this.git_async( cmd , cb);
+         
+    }
+    
+    
+    static uint update_all_total = 0;
+    static string update_all_after = "";
+     
+    public static void updateAll(string after)
+    {
+               update_all_after = after;
+               var tr =  GitRepo.singleton().cache;
+            
+        
+       update_all_total = tr.size;
+       foreach(var repo  in tr.values) {
+                       if (!repo.is_managed()) {
+                       update_all_total--;                     
+                               continue;
+                       }
+           repo.update_async(updateAllCallback); 
+        } 
+               GLib.debug("calls total = %d", (int) update_all_total);
+    }
+    
+    
+    
+    public static void  updateAllCallback(GitRepo repo, int err, string res)
+    {
+       repo.loadBranches();
+       repo.loadStatus();
+       
+       update_all_total--;
+               GLib.debug("calls remaining = %d", (int)update_all_total);      
+       if (update_all_total > 0 ) {
+
+               return;
+               }
+               GLib.debug("call after load = %s", update_all_after);    
+               
+               switch (update_all_after) {
+                       case "show_clones":
+                               Clones.singleton().show();
+                               break;
+                       default:
+                               GLib.debug("Unkown call after load = %s", update_all_after);            
+                               break;
+               }
+               return;
+    }
+    
+    public void loadRemoteHeads(bool force = false)
+       {
+               
+               if (!force && this.remote_heads != null) {
+                       return;
+               }
+               var r = this.repo.lookup_remote("origin");
+               var cb = new GitCallbacks(this);
+               r.connect(Ggit.Direction.FETCH, cb, null, null);
+               this.remote_heads = r.list();
+               r.disconnect();
+       
+       }
+    
 }