X-Git-Url: http://git.roojs.org/?p=gitlive;a=blobdiff_plain;f=GitRepo.vala;h=fa5ce1a7c17332072d2ae81d70e7035a78f57913;hp=6954437cd13cc3971096b4128846e211125717ef;hb=HEAD;hpb=72a4edfbda67d0bf3eb93a91c28c4084945ddae5 diff --git a/GitRepo.vala b/GitRepo.vala index 6954437c..a4d1bfd3 100644 --- a/GitRepo.vala +++ b/GitRepo.vala @@ -25,13 +25,28 @@ public class GitRepo : Object public string ahead_or_behind = ""; public Gee.HashMap 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 branches; // accessed in GitBranch.. public RooTicket? activeTicket; - public Gee.HashMap cache; - public Gee.HashMap config_cache; - + public Gee.HashMap cache; + public Gee.HashMap config_cache; + public Ggit.Repository repo; + public Ggit.RemoteHead[] remote_heads = null; public static GitRepo singleton() { @@ -47,7 +62,7 @@ public class GitRepo : Object */ public static int indexOf( Array 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 +142,7 @@ public class GitRepo : Object continue; } - var rep = GitRepo.get( sp ); + var rep = GitRepo.get_sync( sp ); list_cache.append_val(rep); } @@ -136,13 +151,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 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("thread-new-gitrepo-" + path, run); + yield; + return ret; + } private GitRepo.single() { @@ -175,8 +216,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 +234,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 +255,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 +332,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(); } @@ -303,7 +354,16 @@ public class GitRepo : Object } - + public bool hasBranchCalled(string name) + { + foreach( var br in this.branches.values) { + if (br.name == name) { + return true; + } + + } + return false; + } public string branchesToString() { @@ -312,8 +372,9 @@ public class GitRepo : Object if (br.name == "") { continue; } + var col = /hours/.match(br.age) ? "#ff851b" : "#ffdc00"; // orange or yellow ret += ret.length > 0 ? "\n" : ""; - ret += br.name; + ret += br.name + " " + br.age + ""; } return ret; @@ -333,7 +394,7 @@ public class GitRepo : Object continue; } commitrevs += commitrevs.length > 0 ? " " : ""; - commitrevs += repo.currentBranch.lastrev; + commitrevs += repo.getCurrentBranch().lastrev; } } if (sucess && action == "CLOSE") { @@ -341,18 +402,20 @@ 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"); + var oldbranch = this.getCurrentBranch().name; + this.setActiveTicket(null, master); string [] cmd = { "merge", "--squash", oldbranch }; this.git( cmd ); cmd = { "commit", "-a" , "-m", commit_message }; @@ -361,7 +424,7 @@ public class GitRepo : Object this.loadBranches(); // updates lastrev.. var notification = new Notify.Notification( - "Merged branch %s to master".printf(oldbranch), + "Merged branch %s to %s".printf(oldbranch, master), "", "dialog-information" @@ -384,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" @@ -403,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), @@ -481,8 +544,9 @@ public class GitRepo : Object } bool switchToExistingBranchNamed(string branchname) { + var master = this.hasBranchCalled("roojs") ? "roojs" : "master"; var stash = false; - // this is where it get's tricky... + // this is where it get's tricky... string files = ""; try { string[] cmd = { "ls-files" , "-m" }; // list the modified files.. @@ -502,15 +566,15 @@ public class GitRepo : Object return false; } try { - if (branchname != "master") { - string[] cmd = { "merge", "master" }; + if (branchname != master) { + string[] cmd = { "merge", master }; this.git(cmd); this.push(); } } catch(Error e) { - string[] cmd = { "checkout", "master" }; + 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( @@ -579,8 +643,74 @@ public class GitRepo : Object 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; + } + /** * add: @@ -858,7 +988,89 @@ public class GitRepo : Object } + + public async void doUpdate() + { + SourceFunc callback = this.doUpdate.callback; + GitRepo ret = null; + ThreadFunc 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("thread-new-gitpull-" + this.name, run); + yield; + + + } + + + public static void updateAllAsync(string after) + { + + var doing = new Gee.HashMap();; + + 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; + } + }); + } + + + } + @@ -889,6 +1101,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(); @@ -913,6 +1128,18 @@ 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(); + r.disconnect(); + + } }