Partial Fix #5782 - messing around with libgit2-glib
[gitlive] / GitRepo.vala
index d1ee645..9cb29f6 100644 (file)
@@ -25,13 +25,26 @@ public class GitRepo : Object
     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) {
+               this.loadBranches();
+       }
+       if (this._currentBranch == null) {      
+               GLib.error("could not work out current branch?");
+               }
+               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 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()
     {
@@ -47,7 +60,7 @@ public class GitRepo : Object
     */
     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) {
@@ -127,7 +140,7 @@ public class GitRepo : Object
                 continue;
             }
             
-               var rep =  GitRepo.get(  sp );
+               var rep =  GitRepo.get_sync(  sp );
                list_cache.append_val(rep);             
             
         }
@@ -136,13 +149,39 @@ public class GitRepo : Object
          
        }
        
-       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() {
@@ -175,8 +214,13 @@ public class GitRepo : Object
                        cache.set( path, this);
        }
        
-       var r = this.git({ "remote" , "get-url" , "--push" , "origin"});
-       var uri = new Soup.URI(r);      
+       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();
        
@@ -188,7 +232,7 @@ public class GitRepo : Object
     public bool is_master_branch()
     {
        // special branches that do not allow autopushing now...
-       return this.currentBranch.name == "master" || this.currentBranch.name == "roojs";
+       return this.getCurrentBranch().name == "master" || this.getCurrentBranch().name == "roojs";
                
     }
     public void init_config()
@@ -209,27 +253,30 @@ public class GitRepo : Object
     
     
     
-    public string get_config(string key) {
+    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 ret =   this.git({ "config" , "gitlive." + key }).strip();
-               this.config_cache.set(key, ret);
-               //GLib.debug("get_config %s = '%s'", key, ret);
+               var cfg = this.repo.get_config().snapshot();
+               var ret = cfg.get_string("gitlive." + key).strip();
                return ret;
        } catch (Error e) {
-               this.config_cache.set(key, "");
+               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.git({ "config" , "gitlive." + key, value });
-       this.config_cache.set(key,value);
+    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()
@@ -283,16 +330,18 @@ public class GitRepo : Object
     
        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" });
-
-               this.ahead_or_behind = rs.contains("[ahead") ? "A" : (rs.contains("[behind") ? "B" : "");
+               //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.git({ "diff" , "HEAD", "--no-color" });
+               this.git_diff  = this.diffWorking();
        }    
 
     
@@ -343,7 +392,7 @@ public class GitRepo : Object
                                continue;
                        }
                        commitrevs += commitrevs.length > 0 ? " " : "";
-                       commitrevs += repo.currentBranch.lastrev;
+                       commitrevs += repo.getCurrentBranch().lastrev;
                }
        }
        if (sucess && action == "CLOSE") {
@@ -363,7 +412,7 @@ public class GitRepo : Object
                   if (action == "CLOSE" || action == "LEAVE") {
                                   
                try {
-                   var oldbranch = this.currentBranch.name;
+                   var oldbranch = this.getCurrentBranch().name;
                    this.setActiveTicket(null, master);
                           string [] cmd = { "merge",   "--squash",  oldbranch };
                           this.git( cmd );
@@ -399,7 +448,7 @@ public class GitRepo : Object
                        string[] cmd = { "merge", master};
                        this.git( cmd );
                        var notification = new Notify.Notification(
-                                       "Merged code from %s to %s".printf(master,this.currentBranch.name),
+                                       "Merged code from %s to %s".printf(master,this.getCurrentBranch().name),
                                        "",
                                         "dialog-information"
                                        
@@ -415,7 +464,7 @@ public class GitRepo : Object
            }
        if (action == "EXIT") {
                        try {
-                       var oldbranch  = this.currentBranch.name;
+                       var oldbranch  = this.getCurrentBranch().name;
                          this.setActiveTicket(null, master);
                        this.loadBranches();
                        var notification = new Notify.Notification(
@@ -634,11 +683,32 @@ public class GitRepo : Object
                        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;
+    }    
+    
     
     /**
      * add:
@@ -916,7 +986,88 @@ 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);
+                       }
+                       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;
+                               }
+                       });
+               }
+
+       
+       }
+       
         
     
  
@@ -947,6 +1098,9 @@ public class GitRepo : Object
         } 
                GLib.debug("calls total = %d", (int) update_all_total);
     }
+    
+    
+    
     public static void  updateAllCallback(GitRepo repo, int err, string res)
     {
        repo.loadBranches();
@@ -971,6 +1125,17 @@ public class GitRepo : Object
                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();
+       
+       }
     
 }