sync
authorAlan Knowles <alan@roojs.com>
Wed, 20 Mar 2019 06:37:20 +0000 (14:37 +0800)
committerAlan Knowles <alan@roojs.com>
Wed, 20 Mar 2019 06:37:20 +0000 (14:37 +0800)
1  2 
Git.vala
GitRepo.vala

diff --cc Git.vala
index b4cc84c,0000000..6207008
mode 100644,000000..100644
--- /dev/null
+++ b/Git.vala
@@@ -1,619 -1,0 +1,619 @@@
-       
-                       
-                       
 +
 +// valac -o /tmp/ggit Git.vala --pkg libgit2-glib-1.0 --pkg libsoup-2.4 --pkg gee-0.8 -g
 +
 +
 +
 +void main()
 +{
 +       GLib.Log.set_handler(null, 
 +            GLib.LogLevelFlags.LEVEL_DEBUG | GLib.LogLevelFlags.LEVEL_WARNING | GLib.LogLevelFlags.LEVEL_INFO, 
 +            (dom, lvl, msg) => {
 +                                      
 +                                      
 +               // should we debug..
 +                                      
 +                              
 +               print("%s\n", msg);
 +            }
 +         ); 
 +
 +      Ggit.init();
 +      
 +      var a = new GitLive.Repo("/home/alan/gitlive/gitlive");
 +      a.mergeMasterIntoHead();
 +      //a.walkDiff();
 +      return;
 +      a.is_managed();
 +      a.is_autocommit();
 +      a.loadLocalBranches();
 +      a.loadRemoteHeads();
 +      a.fetchAll();
 +      //
 +      /*
 +      var a = new GitLive.Repo("/home/alan/git/test1-clone");
 +      //a.fetchAll();
 +      var str = (new GLib.DateTime.now_utc()).format("%Y-%m-%d %H:%M:%S");
 +      GLib.FileUtils.set_contents("/home/alan/git/test1-clone/test1",  str); 
 +      
 +      var ix = a.repo.get_index();
 +      ix.add_path("test1");
 +      ix.write();
 +      var treeoid = ix.write_tree();
 +
 +      var head = a.repo.get_head();
 +      var parent = head.lookup() as Ggit.Commit;
 +      Ggit.Commit[] parents = (parent == null) ? 
 +              new Ggit.Commit[] {} :
 +              new Ggit.Commit[] { parent };
 +
 +      var tree = a.repo.lookup(treeoid,typeof (Ggit.Tree))  as   Ggit.Tree;// odd format.. 
 +      
 +      var sig = new Ggit.Signature.now("Alan Knowles", "alan@roojs.com");
 +      a.repo.create_commit("HEAD", sig, sig, null, "test commit " + str, tree, parents);
 +      */
 +      // mmh.. no git add/commit in library...
 +//    string[] spawn_args = {"git", "commit", "-m", "test", "-a"};
 +      //string[] spawn_env = Environ.get ();
 +//    Process.spawn_sync ("/home/alan/git/test1-clone", spawn_args, spawn_env, SpawnFlags.SEARCH_PATH, null);
 + 
 +      a.pushAll();
 +}
 + 
 +
 +namespace  GitLive {
 +
 +      public class Repo : Object {
 +
 +              string name = "";
 +              public Ggit.Repository  repo;
 +              Callbacks callbacks;
 +
 +              public Repo(string path)
 +              {
 +                      this.name = GLib.Path.get_basename(path);
 +                      this.repo = Ggit.Repository.open(GLib.File.new_for_path(path));
 +                      this.callbacks = new Callbacks(this);
 +              
 +              }
 +              Ggit.Branch                                             head = null;
 +          Gee.ArrayList<Ggit.Branch>          branches = null;
 +          Ggit.RemoteHead[]                           remote_heads = null;
 +              public void loadLocalBranches(bool force = false)
 +              {
 +                      if (!force && this.branches != null) {
 +                              return;
 +                      }
 +                      
 +                      this.branches =  new Gee.ArrayList<Ggit.Branch>();
 +                      var r = this.repo.enumerate_branches(Ggit.BranchType.LOCAL);
 +                      while (r.next()) {
 +                              var br = r.get() as Ggit.Branch;
 +                              //var head = this.repo.revparse("refs/heads/" + br.get_name() ).get_id();
 +                              //var rhead = this.repo.revparse(br.get_upstream().get_name() ).get_id();
 +                              //GLib.debug("got branch: name = %s upstream = %s oid = %s ", 
 +                              //              br.get_name(), br.get_upstream().get_name(), 
 +                              //              head.to_string());
 +                              this.branches.add(br);
 +                              if (br.is_head()) {
 +                                      GLib.debug("HEAD= %s", br.get_name());
 +                                      this.head = br;
 +                              }
 +                              
 +                      }
 +                      
 +                      
 +              }
 +               
 +              public bool is_managed()
 +              {
 +                      GLib.debug("is_managed: %d", this.repo.get_config().get_int32("gitlive.managed"));
 +                      return this.repo.get_config().get_int32("gitlive.managed") == 1;
 +              }
 +              
 +              
 +              public bool is_autocommit ()
 +              {       
 +                      GLib.debug("is_autocommit: %d", this.repo.get_config().get_int32("gitlive.autocommit"));
 +                      return this.repo.get_config().get_int32("gitlive.autocommit") == 1;
 +              }
 +              public void set_autocommit(bool val)
 +              {
 +                      this.repo.get_config().set_int32("gitlive.autocommit", val ? 1 : 0);
 +              
 +              }
 +               
 +              public void walkDiff()
 +              {
 +                      this.loadLocalBranches();
 +                      
 +                      
 +                      
 +                      var oid =  this.repo.revparse(this.head.get_name() ).get_id()  ;
 +                      var moid =  this.repo.revparse("refs/heads/master" ).get_id()  ;
 +                      
 +                      var a = new Ggit.RevisionWalker(this.repo);
 +                      a.set_sort_mode(Ggit.SortMode.TOPOLOGICAL);
 +                      a.push(oid);
 +                      a.hide(moid);
 +                      var last = oid;
 +                      for (var noid = a.next(); noid != null; noid= a.next()) {
 +                              //var commit = this.repo.lookup(noid, typeof(Ggit.Commit)) as Ggit.Commit;
 +                              GLib.debug("rev: %s",
 +                                      noid.to_string()
 +                              );
 +                              last = noid;
 +                      }
 +                      var commit = this.repo.lookup(last, typeof(Ggit.Commit)) as Ggit.Commit;
 +                      var parent = commit.get_parents();
 +                      GLib.debug("parent = %s", parent.get_id(0).to_string());
 +                      var master_rev =  parent.get_id(0);
 +                      var master_commit  = this.repo.lookup_commit(master_rev);;
 +                      
 +                      var head_commit = this.repo.lookup_commit(oid);
 +                      
 +                      var master_tree = master_commit.get_tree();
 +                      var head_tree = head_commit.get_tree();
 +                      
 +                      var diff = new Ggit.Diff.tree_to_tree(this.repo, master_tree, head_tree, new Ggit.DiffOptions());
 +                      
 +                      diff.print(Ggit.DiffFormatType.PATCH, ( delta,  hunk,  line) => {
 +                              GLib.debug("%d: %s, %s", line.get_new_lineno(), line.get_origin().to_string(), line.get_text());
 +                              return 0;
 +                      });
 +                      // let's try a merge..
 +                      var mo = new Ggit.MergeOptions();
 +                      mo.set_file_favor(Ggit.MergeFileFavor.THEIRS);
 +                      var ix = this.repo.merge_trees(master_tree, master_tree, head_tree, mo);
 +                      
 +                      if (ix.has_conflicts()) {
 +                              GLib.debug("merge has conflicts");
 +                              return;
 +                      }
 +                       var treeoid = ix.write_tree();
 +                       
 +                       
 +                        
 +                      var parents =   new Ggit.Commit[] { master_commit };
 +
 +
 +                      var new_tree = this.repo.lookup(treeoid,typeof (Ggit.Tree))  as   Ggit.Tree;
 +                      
 +                      var sig = new Ggit.Signature.now(
 +                                      this.repo.get_config().get_string("user.name"),
 +                                      this.repo.get_config().get_string("user.email")
 +                      );
 +                      
 +                      
 +                      
 +                      this.repo.create_commit("HEAD", sig, sig, null, "Test Merge", new_tree, parents);
-                                       this.repo.get_config().get_string("user.name"),
-                                       this.repo.get_config().get_string("user.email")
++       
 +                      
 +                      
 +              }
 +              public void mergeMasterIntoHead()
 +              {
 +                      // assumes head is not master...
 +                      this.loadLocalBranches();
 +                      GLib.debug("head rev = %s", this.head.get_name());
 +                      var head_oid =  this.repo.revparse(this.head.get_name() ).get_id()  ;
 +                      //var master_oid =  this.repo.revparse("refs/heads/master" ).get_id()  ;
 +                      var master_oid =  this.repo.revparse("HEAD" ).get_id()  ;
 +
 +                      var master_commit  = this.repo.lookup_commit(master_oid);;
 +                      var head_commit = this.repo.lookup_commit(head_oid);
 +                       
 +              
 +                      var anc_oid = this.repo.merge_base(master_commit.get_id(), head_commit.get_id());
 +                      
 +                      var anc_commit = this.repo.lookup_commit(anc_oid);
 +                      var anc_tree = anc_commit.get_tree();
 +                      
 +                      var mo = new Ggit.MergeOptions();
 +                      var co = new Ggit.CheckoutOptions();
 +                      var the_ref = this.repo.lookup_reference_dwim("refs/heads/master");
 +
 +                  var ac = new Ggit.AnnotatedCommit.from_ref(this.repo, the_ref);
 +                      
 +                      var commits =   new Ggit.AnnotatedCommit[] { ac };
 +                      
 +                      this.repo.merge(commits, mo, co);
++                      
++                      var cfg = this.repo.get_config().snapshot();
++                      
 +                  var sig = new Ggit.Signature.now(
-                       this.repo.create_commit(this.head.get_name(), sig, sig, null, "Test Merge", new_tree, parents);
++                                      cfg.get_string("user.name"),
++                                      cfg.get_string("user.email")
 +                      );
 +                      var new_head = this.repo.get_head();
 +                      var oid = new_head.get_target();
 +
 +                      var ix = this.repo.get_index();
 + 
 +                      ix.write();
 +                      var treeoid = ix.write_tree();
 +
 +                      var new_tree = this.repo.lookup(treeoid,typeof (Ggit.Tree))  as   Ggit.Tree;
 +                      
 +                      var parent = new_head.lookup() as Ggit.Commit;
 +                      Ggit.Commit[] parents =  new Ggit.Commit[] { parent };
 +                      
-               
++                      this.repo.create_commit("refs/heads/" + this.head.get_name(), sig, sig, null, "Test Merge", new_tree, parents);
 +       
 +              }
 +              
 +              
 +              /*
 +              public bool doMergeClose(string commit_message)
 +              {
 +                      this.loadLocalBranches(true);
 +                      var oldbranch = this.head.get_name();
 +            // going to asume this is merge trees..
 +                         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 %s".printf(oldbranch, master),
 +                               "",
 +                                "dialog-information"
 +                               
 +                       );
 +
 +                       notification.set_timeout(5);
 +                       notification.show();   
 +               
 +              
 +              }
 +              */
 +              
 +              
 +              public bool is_auto_branch ()
 +              {
 +                      if (this.name == "gitlog") {
 +                              return false;
 +                      }
 +                      // check remote...
 +                      if (this.is_managed()) {
 +                              return true;
 +                      }
 +                      return false;
 +                      
 +       
 +              }
 +              
 +              public void loadRemoteHeads(bool force = false)
 +              {
 +                      
 +                      if (!force && this.remote_heads != null) {
 +                              return;
 +                      }
 +                      var r = this.repo.lookup_remote("origin");
 +                      r.connect(Ggit.Direction.FETCH, this.callbacks, null, null);
 +                      this.remote_heads = r.list();
 +              
 +              }
 +              
 +              
 +              
 +              Ggit.Branch? getBranch(string remote_name, string remote_branch_name)
 +              {
 +                       //GLib.debug("bn=%s",remote_branch_name);
 +                       if (remote_branch_name.has_prefix("refs/remotes/")) {
 +                               return null;
 +                       }
 +
 +                       var target = remote_branch_name.replace("refs/heads/", remote_name+"/") .replace("refs/remotes/", "");
 +                      if (target == "HEAD") {
 +                              target = remote_name +"/master";
 +                      }
 +                       
 +                      foreach(var br in this.branches) {
 +                      //      GLib.debug("test:%s=%s", br.get_upstream().get_shorthand() , target);
 +                              if ( br.get_upstream().get_shorthand() == target) {
 +                                      return br;
 +                              }
 +                              
 +                      }
 +                      //GLib.debug("missing %s", remote_branch_name);                 
 +                      return null;
 +              
 +              }
 +               
 +              
 +              public void fetchAll()
 +              {
 +                      this.loadLocalBranches();
 +                      this.loadRemoteHeads();
 +                      
 +                      // remotes probably will not work with http auth..
 +                      //var ar = this.repo.list_remotes();
 +                      //foreach(var n in ar) {
 +                      var n = "origin"; 
 +                      
 +                              GLib.debug("got remote '%s'", n);
 +                              var r = this.repo.lookup_remote(n);
 +                              GLib.debug("connecting '%s'", r.get_url());
 +                               
 +                              try {
 +                                      string[] h = { "a = 1" };
 +                                      r.connect(Ggit.Direction.FETCH, this.callbacks, null, null);
 +                                      
 +                              } catch (Error e) {
 +                                      GLib.debug("Got Error Message: %s", e.message);
 +                                      return;
 +                              }
 +                              string[] far = {};
 +
 +                              foreach(var rh in this.remote_heads) {
 +                                      if (rh.get_name().has_prefix("refs/remotes/")) {
 +                                                 continue;
 +                                       }
 +                              
 +                                      var br = this.getBranch(n, rh.get_name());
 +                               
 +                                      /*GLib.debug("got heads: name=%s   rev=%s  localrev=%s",
 +                                              rh.get_name(), 
 +                                              rh.get_oid().to_string(),
 +                                              br == null ? "?": this.repo.revparse(br.get_name() ).get_id().to_string()
 +                                      );
 +                                      */
 +                                      var loc_oid = this.repo.revparse(br.get_name() ).get_id();
 +                                      size_t ahead, behind;
 +                                      this.repo.get_ahead_behind(
 +                                              loc_oid,
 +                                              rh.get_oid(),
 +                                              out ahead,
 +                                              out behind
 +                                      );
 +                                      
 +                                      if (rh.get_oid().to_string() == this.repo.revparse(br.get_name() ).get_id().to_string()) {
 +                                              continue;
 +                                      }
 +                                      if (ahead > 0) {
 +                                              continue;
 +                                      }
 +                                      far += ("+refs/heads/" + br.get_name()) + ":refs/remotes/" + n + "/" + rh.get_name().replace("refs/heads/","");
 +                              } 
 +                              
 +                              if (far.length < 1) {
 +                                      GLib.debug("no fetch required.. it's uptodate");
 +                                      r.disconnect();
 +                                      return;
 +                              }
 +                              
 +                              GLib.debug("getting remote specs '%s', %d", n, far.length);
 +                              
 +/*
 +                              var far = r.get_fetch_specs();
 +                              */
 +                              foreach(var rs in far) {
 +                                      GLib.debug("got remote spec: %s", rs);
 +                                      
 +                              }
 +
 +                              var options = new Ggit.FetchOptions();
 +                              options.set_remote_callbacks(this.callbacks);
 +                              //yield Async.thread(() => {
 +      
 +                                      r.download(far, options);
 +                              //});
 +                              r.disconnect();
 +                              
 +                              //r.download(
 +                       
 +              
 +              }
 +              
 +              
 +              
 +              public void pushAll()
 +              {
 +                      
 +                      this.loadLocalBranches();
 +                      this.loadRemoteHeads();
 +                      // remotes probably will not work with http auth..
 +                      //var ar = this.repo.list_remotes();
 +                      var n = "origin";
 +                      
 +                              GLib.debug("got remote '%s'", n);
 +                              var r = this.repo.lookup_remote(n);
 +                              GLib.debug("connecting '%s'", r.get_url());
 +                               
 +                              r.connect(Ggit.Direction.PUSH, this.callbacks, null, null);
 +                              
 +                              //GLib.debug("getting specs '%s'", n);
 +                              /* 
 +                              
 +                              this.repo.add_remote_push(
 +                                      "origin",
 +                                      "+%s:%s".printf(head.get_shorthand(),head.get_name())
 +                              );
 + */
 + 
 +                              string[] far = {};
 +                              var heads = r.list();
 +                              foreach(var rh in heads) {
 +                                      if (rh.get_name().has_prefix("refs/remotes/")) {
 +                                                 continue;
 +                                       }
 +                              
 +                                      var br = this.getBranch(n, rh.get_name());
 +                                      /*
 +                                      GLib.debug("got heads: name=%s   rev=%s  localrev=%s",
 +                                              rh.get_name(), 
 +                                              rh.get_oid().to_string(),
 +                                              br == null ? "?": this.repo.revparse(br.get_name() ).get_id().to_string()
 +                                      );*/
 +                                      var loc_oid = this.repo.revparse(br.get_name() ).get_id();
 +                                      size_t ahead, behind;
 +                                      this.repo.get_ahead_behind(
 +                                              loc_oid,
 +                                              rh.get_oid(),
 +                                              out ahead,
 +                                              out behind
 +                                      );
 +                                      
 +                                      if (rh.get_oid().to_string() == this.repo.revparse(br.get_name() ).get_id().to_string()) {
 +                                              continue;
 +                                      }
 +                                      if (behind > 0) {
 +                                              continue;
 +                                      }
 +                                      far += ("+refs/heads/" + br.get_name()) + ":"+ rh.get_name();
 +                              }  
 +                              
 +                              if (far.length < 1) {
 +                                      GLib.debug("no push required.. it's uptodate");
 +                                      r.disconnect();
 +                                      return;
 +                              }
 + 
 +                              /*var head = this.repo.get_head();
 +                              string[] far = {};
 +                              far += "+%s:%s".printf(head.get_name(),head.get_name());
 +                              */
 +                              foreach(var rs in far) {
 +                                      GLib.debug("got remote spec: %s", rs);
 +                                      
 +                              }
 +                                      
 +                              var popts = new Ggit.PushOptions();
 +                               popts.callbacks = this.callbacks;
 +                              GLib.debug("Push?");
 +                              r.upload(far,popts);
 +                              GLib.debug("Push done?");
 +                              r.disconnect();
 +                              
 +                              
 +                              //r.download(
 +                       
 +              
 +              }
 +              
 +               
 +
 +      }
 +      
 +      private class Callbacks : Ggit.RemoteCallbacks
 +      {
 +              //private Remote d_remote;
 +              private Ggit.RemoteCallbacks? d_proxy = null;
 +
 +              public delegate void TransferProgress(Ggit.TransferProgress stats);
 +              //private TransferProgress? d_transfer_progress;
 +
 +              public Callbacks( Repo repo)  //, Ggit.RemoteCallbacks? proxy) //,Remote remote, owned TransferProgress? transfer_progress)
 +              {
 +                      //d_remote = remote;
 +                      //d_proxy = proxy;
 +                      //d_transfer_progress = (owned)transfer_progress;
 +              }
 +
 +              protected override void progress(string message)
 +              {
 +                      GLib.debug("progress: %s", message);
 +                      if (d_proxy != null)
 +                      {
 +                              d_proxy.progress(message);
 +                      }
 +              }
 +
 +              protected override void transfer_progress(Ggit.TransferProgress stats)
 +              {
 +                      GLib.debug("transfer_progress");
 +                      /*
 +                      if (d_transfer_progress != null)
 +                      {
 +                              d_transfer_progress(stats);
 +                      }
 +
 +                      if (d_proxy != null)
 +                      {
 +                              d_proxy.transfer_progress(stats);
 +                      }
 +                      */
 +              }
 +
 +              protected override void update_tips(string refname, Ggit.OId a, Ggit.OId b)
 +              {
 +                      GLib.debug("update_tips");
 +                      //d_remote.tip_updated(refname, a, b);
 +
 +                      if (d_proxy != null)
 +                      {
 +                              d_proxy.update_tips(refname, a, b);
 +                      }
 +              }
 +
 +              protected override void completion(Ggit.RemoteCompletionType type)
 +              {
 +                      GLib.debug("completion");
 +                      if (d_proxy != null)
 +                      {
 +                              d_proxy.completion(type);
 +                      }
 +              }
 +
 +              protected override Ggit.Cred? credentials(string url, string? username_from_url, Ggit.Credtype allowed_types) throws Error
 +              {
 + 
 +                      GLib.debug("get credentials %s  UN=%s", url, username_from_url);
 +                      var uri = new Soup.URI(url);
 +
 +                      if (uri != null) {
 +                              var ret = this.netrc(uri.get_host());
 +                              if (ret != null) {
 +                                      return ret;
 +                              }
 +                              
 +                              //return new Ggit.CredPlaintext(username_from_url, "test");
 +                      }
 +                      return null;
 +                      /*var provider = d_remote.credentials_provider;
 +
 +                      if (provider != null)
 +                      {
 +                              ret = provider.credentials(url, username_from_url, allowed_types);
 +                      }
 +
 +                      if (ret == null && d_proxy != null)
 +                      {
 +                              ret = d_proxy.credentials(url, username_from_url, allowed_types);
 +                      }
 +                      
 +                      return ret;
 +                      */
 +              }
 +              public  Ggit.Cred netrc(string domain) 
 +              {
 +                      string str;
 +                      GLib.FileUtils.get_contents(GLib.Environment.get_home_dir() + "/.netrc", out str);
 +                      var lines = str.split("\n");
 +                      for(var i=0; i< lines.length; i++) {
 +                              // assumes one line per entry.. if not we are buggered...
 +                              //GLib.debug("got %s" , lines[i]);
 +                      
 +                              var bits =  Regex.split_simple ("[ \t]+", lines[i].strip());
 +                              if (bits.length < 6 || bits[0] != "machine" || bits[1] != domain) {
 +                                      continue;
 +                              }
 +                              GLib.debug("found password?");
 +                              // we are gussing.... 
 +                              return new Ggit.CredPlaintext(bits[3], bits[5]);
 +
 +                      }
 +                      return null;
 +
 +
 +              
 +              
 +              }
 +              
 +      }
 +      
 +      
 +
 +}
diff --cc GitRepo.vala
@@@ -28,10 -28,10 +28,10 @@@ public class GitRepo : Objec
      public GitBranch 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;
      
++    private Ggit.Repository repo;
      
        public static GitRepo singleton()
      {
                        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();
        
      
      
      
--    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()
      
        public void loadStatus()
        {
++              // status??/ 
                var r = this.git({ "status" , "--porcelain" });
                this.git_status = r;
                this.has_local_changes = r.length > 0;