X-Git-Url: http://git.roojs.org/?p=gitlive;a=blobdiff_plain;f=GitRepo.vala;h=4e018e547b12347508e44dcf9b9e84cfab574443;hp=1dd9edc1d1afc08983c7367f9fe3acee33a1012a;hb=265adcf86cbf103f51c08f6a02ba486633b148b0;hpb=f11d232709e74414262867a2a062a5e4c3690490 diff --git a/GitRepo.vala b/GitRepo.vala index 1dd9edc1..4e018e54 100644 --- a/GitRepo.vala +++ b/GitRepo.vala @@ -7,30 +7,138 @@ * * */ +static GitRepo _GitRepo; + public class GitRepo : Object { - + public Array cmds; - + public string name; public string gitdir; + public string git_working_dir; public bool debug = false; + + public Gee.HashMap ignore_files; + public GitBranch currentBranch; + + + public static GitRepo singleton() + { + if (_GitRepo == null) { + _GitRepo = new GitRepo(); + _GitRepo.cache = new Gee.HashMap(); + } + return _GitRepo; + } /** * index of.. matching gitpath.. */ - public static int indexOfAdd( Array repos, string gitpath) { + public static int indexOf( Array repos, string gitpath) { + // make a fake object to compare against.. + var test_repo = GitRepo.get(gitpath); + for(var i =0; i < repos.length; i++) { - if (repos.index(i).gitdir == gitpath) { + if (repos.index(i).gitdir == test_repo.gitdir) { return i; } } return -1; } + + public Gee.HashMap cache; + + + + public static Array list() + { - - + //if (GitRepo.list_cache != null) { + // unowned Array ret = GitRepo.list_cache; + // return ret; + //} + var cache = GitRepo.singleton().cache; + var list_cache = new Array(); + + var dir = Environment.get_home_dir() + "/gitlive"; + + var f = File.new_for_path(dir); + FileEnumerator file_enum; + try { + file_enum = f.enumerate_children( + FileAttribute.STANDARD_DISPLAY_NAME + ","+ + FileAttribute.STANDARD_TYPE, + FileQueryInfoFlags.NONE, + null); + } catch (Error e) { + + return list_cache; + + } + + FileInfo next_file; + + while (true) { + + try { + next_file = file_enum.next_file(null); + if (next_file == null) { + break; + } + + } catch (Error e) { + GLib.debug("Error: %s",e.message); + break; + } + + //print("got a file " + next_file.sudo () + '?=' + Gio.FileType.DIRECTORY); + + if (next_file.get_file_type() != FileType.DIRECTORY) { + next_file = null; + continue; + } + + if (next_file.get_file_type() == FileType.SYMBOLIC_LINK) { + next_file = null; + continue; + } + + if (next_file.get_display_name()[0] == '.') { + next_file = null; + continue; + } + var sp = dir+"/"+next_file.get_display_name(); + + var gitdir = dir + "/" + next_file.get_display_name() + "/.git"; + + if (!FileUtils.test(gitdir, FileTest.IS_DIR)) { + continue; + } + + var rep = GitRepo.get( sp ); + list_cache.append_val(rep); + + } + + return list_cache; + + + + } + + public static GitRepo get(string path) + { + var cache = GitRepo.singleton().cache; + if (cache.has_key(path)) { + return cache.get(path); + } + return new GitRepo(path); + } + + + /** * constructor: @@ -40,28 +148,101 @@ public class GitRepo : Object * */ - public GitRepo(string path) { + private GitRepo(string path) { // cal parent? + this.name = File.new_for_path(path).get_basename(); + this.ignore_files = new Gee.HashMap(); + this.git_working_dir = path; this.gitdir = path + "/.git"; if (!FileUtils.test(this.gitdir , FileTest.IS_DIR)) { this.gitdir = path; // naked... } this.cmds = new Array (); - //Repo.superclass.constructor.call(this,cfg); + var cache = GitRepo.singleton().cache; + //Repo.superclass.constructor.call(this,cfg); + if ( !cache.has_key(path) ) { + cache.set( path, this); + } } + + + public bool is_autocommit () + { + return !FileUtils.test(this.gitdir + "/.gitlive-disable-autocommit" , FileTest.EXISTS); + } + public bool is_autopush () + { + return !FileUtils.test(this.gitdir + "/.gitlive-disable-autopush" , FileTest.EXISTS); + } + + Gee.HashMap branches; + + public void loadBranches() + { + this.branches = new Gee.HashMap(); + + 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; + } + } + + } + public string branchesToString() + { + var ret = ""; + foreach( var br in this.branches.values) { + if (br.name == "") { + continue; + } + ret += ret.length > 0 ? "," : ""; + ret += br.name; + + } + return ret; + + } + RooTicket? ticket = null; + + public void setActiveTicket(RooTicket ticket, string branchname) + { + this.createBranchNamed(branchname); + FileUtils.set_contents(this.gitdir + "/.gitlive-active-ticket" , ticket.id); + this.activeTicket = ticket; + } + + public void createBranchNamed(string branchname) + { + string[] cmd = { "checkout", "-b" , branchname }; + this.git(cmd); + this.loadBranches(); // update branch list... + } + + /** * add: * add files to track. * * @argument {Array} files the files to add. */ - public string add ( Array files ) + public string add ( Array files ) throws Error, SpawnError { // should really find out if these are untracked files each.. // we run multiple versions to make sure that if one failes, it does not ignore the whole lot.. // not sure if that is how git works.. but just be certian. + var ret = ""; for (var i = 0; i < files.length;i++) { var f = files.index(i).vname; try { @@ -72,7 +253,30 @@ public class GitRepo : Object } } + return ret; } + + public bool is_ignore(string fname) throws Error, SpawnError + { + if (fname == ".gitignore") { + this.ignore_files.clear(); + } + + if (this.ignore_files.has_key(fname)) { + return this.ignore_files.get(fname); + } + + try { + var ret = this.git( { "check-ignore" , fname } ); + this.ignore_files.set(fname, ret.length > 0); + return ret.length > 0; + } catch (SpawnError e) { + this.ignore_files.set(fname, false); + return false; + } + + } + /** * remove: @@ -80,7 +284,7 @@ public class GitRepo : Object * * @argument {Array} files the files to add. */ - public string remove ( Array files ) + public string remove ( Array files ) throws Error, SpawnError { // this may fail if files do not exist.. // should really find out if these are untracked files each.. @@ -102,6 +306,7 @@ public class GitRepo : Object } + /** * commit: * perform a commit. @@ -116,7 +321,7 @@ public class GitRepo : Object * */ - public string commit ( string message, Array files ) + public string commit ( string message, Array files ) throws Error, SpawnError { @@ -138,8 +343,8 @@ public class GitRepo : Object } */ - string[] args = { "commit", "-m", }; - arg += (message.length > 0 ? message : "Changed" ); + string[] args = { "commit", "-m" }; + args += (message.length > 0 ? message : "Changed" ); for (var i = 0; i< files.length ; i++ ) { args += files.index(i).vname; // full path? } @@ -155,15 +360,25 @@ public class GitRepo : Object * -- maybe later it will have a few options and do more stuff.. * */ - public string pull () + public string pull () throws Error, SpawnError { // should probably hand error conditions better... - string[] cmd = { "pull" }; + string[] cmd = { "pull" , "--no-edit" }; return this.git( cmd ); - } + + public delegate void GitAsyncCallback (GitRepo repo, int err, string str); + public void pull_async(GitAsyncCallback cb) + { + + string[] cmd = { "pull" , "--no-edit" }; + this.git_async( cmd , cb); + + + } + /** * push: * Send local changes to remote repo(s) @@ -172,12 +387,15 @@ public class GitRepo : Object * -- maybe later it will have a few options and do more stuff.. * */ - public string push () + public string push () throws Error, SpawnError { // should - return this.git({ "push" }); + return this.git({ "push", "origin", "HEAD" }); } + + + /** * git: * The meaty part.. run spawn.. with git.. @@ -185,20 +403,16 @@ public class GitRepo : Object * */ - public string git(string[] args_in, ?string[] env) throws Error, SpawnError + public string git(string[] args_in ) throws Error, SpawnError { // convert arguments. - string[] args = { "git" }; - args += "--git-dir"; - args += this.gitdir; + //args += "--git-dir"; + //args += this.gitdir; args += "--no-pager"; - - if (env == null) { - env = {}; - } - + + //if (this.gitdir != this.repopath) { // args += "--work-tree"; // args += this.repopath; @@ -208,10 +422,12 @@ public class GitRepo : Object } //this.lastCmd = args.join(" "); - if(this.debug) { - - print( string.joinv (", ", args)); - } + //if(this.debug) { + GLib.debug( "CWD=%s", this.git_working_dir ); + GLib.debug( "cmd: %s", string.joinv (" ", args)); + //} + + string[] env = {}; string home = "HOME=" + Environment.get_home_dir() ; env += home ; // do not need to set gitpath.. @@ -220,15 +436,72 @@ public class GitRepo : Object //} - var cfg = new SpawnConfig(this.gitdir, args , env); + var cfg = new SpawnConfig(this.git_working_dir , args , env); // may throw error... var sp = new Spawn(cfg); - - //print("GOT: " + output) + + + GLib.debug( "GOT: %s" , sp.output); // parse output for some commands ? return sp.output; } + + unowned GitAsyncCallback git_async_on_callback; + public void git_async( string[] args_in, GitAsyncCallback cb ) throws Error, SpawnError + { + // convert arguments. + this.git_async_on_callback = cb; + string[] args = { "git" }; + //args += "--git-dir"; + //args += this.gitdir; + args += "--no-pager"; + + + //if (this.gitdir != this.repopath) { + // args += "--work-tree"; + // args += this.repopath; + //} + for (var i = 0; i < args_in.length;i++) { + args += args_in[i]; + } + + //this.lastCmd = args.join(" "); + //if(this.debug) { + GLib.debug( "CWD=%s", this.git_working_dir ); + //print( "cmd: %s\n", string.joinv (" ", args)); + //} + + string[] env = {}; + string home = "HOME=" + Environment.get_home_dir() ; + env += home ; + // do not need to set gitpath.. + //if (File.exists(this.repo + '/.git/config')) { + //env.push("GITPATH=" + this.repo ); + //} + + + var cfg = new SpawnConfig(this.git_working_dir , args , env); + cfg.async = true; + + // may throw error... + var sp = new Spawn(cfg); + //sp.ref(); + //this.ref(); + sp.run(this.git_async_on_complete); + + } + + void git_async_on_complete(int err, string output) + { + GLib.debug("GOT %d : %s", err, output); + this.git_async_on_callback(this, err, output); +// this.unref(); + // sp.unref(); + + + } + }