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 Gee.HashMap<string,GitBranch> branches; // accessed in GitBranch..
public RooTicket? activeTicket;
-
+ public Gee.HashMap<string,GitRepo> cache;
+
+
+
public static GitRepo singleton()
{
if (_GitRepo == null) {
}
return _GitRepo;
}
-
+
/**
* index of.. matching gitpath..
*/
}
- public Gee.HashMap<string,GitRepo> cache;
+
}
return list_cache;
-
-
}
public static GitRepo get(string path)
if ( !cache.has_key(path) ) {
cache.set( path, this);
}
+
+ var r = this.git({ "remote" , "get-url" , "--push" , "origin"});
+ var uri = new Soup.URI(r);
+ this.host = uri.get_host();
+
+
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.currentBranch.name == "master" || this.currentBranch.name == "roojs";
}
- public bool is_autocommit ()
+ public bool is_managed()
{
+ // is it a roojs origin?
+
+ if (this.host != "git.roojs.com") { // we can only push to this url. -- unless we have forced it to be managed.
+ return FileUtils.test(this.gitdir + "/.gitlive-managed" , FileTest.EXISTS);
+ }
+ // otherwise see if unmanaged is set to disable it..
+ return !FileUtils.test(this.gitdir + "/.gitlive-unmanaged" , FileTest.EXISTS);
+
+ }
+
+
+ public bool is_autocommit ()
+ {
return !FileUtils.test(this.gitdir + "/.gitlive-disable-autocommit" , FileTest.EXISTS);
}
+ public void set_autocommit(bool val)
+ {
+
+ var cur = this.is_autocommit();
+ GLib.debug("SET auto commit : %s <= %s", val ? "ON" : "OFF", cur ? "ON" : "OFF");
+ if (cur == val) {
+ return; // no change..
+ }
+ if (!val) {
+ FileUtils.set_contents(this.gitdir + "/.gitlive-disable-autocommit" , "x");
+ } else {
+ // it exists...
+ FileUtils.remove(this.gitdir + "/.gitlive-disable-autocommit" );
+ }
+
+ }
+
+ public bool is_auto_branch ()
+ {
+ if (this.name == "gitlog") {
+ return false;
+ }
+ // check remote...
+ if (this.is_managed()) {
+ return true;
+ }
+ return false;
+
+
+ }
+
+ public void set_auto_branch(bool val)
+ {
+
+ var cur = this.is_auto_branch();
+ GLib.debug("SET auto branch : %s <= %s", val ? "ON" : "OFF", cur ? "ON" : "OFF");
+
+ if (cur == val) {
+ return; // no change..
+ }
+ if (val) {
+ FileUtils.set_contents(this.gitdir + "/.gitlive-enable-auto-branch" , "x");
+ } else {
+ // it exists...
+ FileUtils.remove(this.gitdir + "/.gitlive-enable-auto-branch" );
+ }
+
+ }
public bool is_autopush ()
{
return !FileUtils.test(this.gitdir + "/.gitlive-disable-autopush" , FileTest.EXISTS);
+ }
+ public void set_autopush(bool val)
+ {
+
+ var cur = this.is_autopush();
+ GLib.debug("SET auto push : %s <= %s", val ? "ON" : "OFF", cur ? "ON" : "OFF");
+ if (cur == val) {
+ return; // no change..
+ }
+ if (!val) {
+ FileUtils.set_contents(this.gitdir + "/.gitlive-disable-autopush" , "");
+ } else {
+ // it exists...
+ FileUtils.remove(this.gitdir + "/.gitlive-disable-autopush" );
+ }
+
}
- Gee.HashMap<string,GitBranch> branches;
+
+ public void loadStatus()
+ {
+ 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" : "");
+
+
+ this.git_diff = this.git({ "diff" , "HEAD", "--no-color" });
+ }
+
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);
}
if (br.name == "") {
continue;
}
- ret += ret.length > 0 ? "," : "";
+ ret += ret.length > 0 ? "\n" : "";
ret += br.name;
}
}
GitMonitor.gitmonitor.start();
}
-
-
-
+
public bool doMerge(string action, string ticket_id, string commit_message)
{
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.currentBranch.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(
+ var notification = new Notify.Notification(
"Merged branch %s to master".printf(oldbranch),
"",
"dialog-information"
}
return false;
}
+
+ public void loadActiveTicket()
+ {
+ this.activeTicket = null;
+ if (!FileUtils.test(this.gitdir + "/.gitlive-active-ticket" , FileTest.EXISTS)) {
+ return;
+ }
+ string ticket_id;
+ FileUtils.get_contents(this.gitdir + "/.gitlive-active-ticket" , out ticket_id);
+ 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)
{
if (!this.createBranchNamed(branchname)) {
return false;
}
- FileUtils.set_contents(this.gitdir + "/.gitlive-active-ticket" , ticket.id);
+ if (ticket != null) {
+ FileUtils.set_contents(this.gitdir + "/.gitlive-active-ticket" , ticket.id);
+ } else {
+ FileUtils.remove(this.gitdir + "/.gitlive-active-ticket" );
+ }
this.activeTicket = ticket;
return true;
}
if (this.branches.has_key(branchname)) {
- // this is where it get's tricky...
- try {
- 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);
- } catch(Error e) {
- GitMonitor.gitmonitor.pauseError(e.message);
- return false;
-
- }
- try {
- cmd = { "merge", "master" };
- this.git(cmd);
- } catch(Error e) {
- try {
- cmd = { "mergetool" };
- this.git(cmd);
- cmd = { "commit" "-m" "Fix merge conflicts from master" };
- this.git(cmd);
- } catch(Error ee) {
- GitMonitor.gitmonitor.pauseError(ee.message);
- return false;
- }
- }
- try {
- cmd = { "stash", "pop" };
- if (stash) { this.git(cmd); }
- } catch(Error ee) {
- GitMonitor.gitmonitor.pauseError(ee.message);
- return false;
- }
-
+ this.switchToExistingBranchNamed(branchname);
} else {
- try {
-
- string[] cmd = { "checkout", "-b" , branchname };
- this.git(cmd);
- } catch(Error ee) {
- GitMonitor.gitmonitor.pauseError(ee.message);
- return false;
- }
+ this.createNewBranchNamed(branchname);
}
var notification = new Notify.Notification(
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 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 void pull_async(GitAsyncCallback cb)
{
- string[] cmd = { "pull" , "--no-edit" };
+ string[] cmd = { "pull" , "--no-edit" };
this.git_async( cmd , cb);
public string push () throws Error, SpawnError
{
// should
- return this.git({ "push", "origin", "HEAD" });
+ return this.git({ "push" });
}
//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);
+ // 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;
}
}
+
+
+
+
+ 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);
+ }
+
+ }
+ public static void updateAllCallback(GitRepo repo, int err, string res)
+ {
+ repo.loadBranches();
+ repo.loadStatus();
+
+ update_all_total--;
+ if (update_all_total > 0 ) {
+ return;
+ }
+ switch (update_all_after) {
+ case "show_clones":
+ Clones.singleton().show();
+ break;
+ default:
+ break;
+ }
+ return;
+ }
+
+
+
}