#import "git.h" #import "include/git2.h" #import namespace v8_extensions { class GitRepository : public CefBase { private: bool exists; git_repository *repo; public: GitRepository(const char *pathInRepo) { exists = git_repository_open_ext(&repo, pathInRepo, 0, NULL) == GIT_OK; } ~GitRepository() { if (repo) git_repository_free(repo); } CefRefPtr GetPath() { if (exists) return CefV8Value::CreateString(git_repository_path(repo)); else return CefV8Value::CreateNull(); } CefRefPtr GetHead() { if (!exists) return CefV8Value::CreateNull(); git_reference *head; if (git_repository_head(&head, repo) == GIT_OK) { if (git_repository_head_detached(repo) == 1) { const git_oid* sha = git_reference_oid(head); if (sha) { char oid[GIT_OID_HEXSZ + 1]; git_oid_tostr(oid, GIT_OID_HEXSZ + 1, sha); return CefV8Value::CreateString(oid); } } return CefV8Value::CreateString(git_reference_name(head)); } return CefV8Value::CreateNull(); } CefRefPtr IsIgnored(const char *path) { if (!exists) { return CefV8Value::CreateBool(false); } int ignored; if (git_ignore_path_is_ignored(&ignored, repo, path) == GIT_OK) { return CefV8Value::CreateBool(ignored == 1); } else { return CefV8Value::CreateBool(false); } } CefRefPtr GetStatus(const char *path) { if (!exists) { return CefV8Value::CreateInt(0); } git_index* index; if (git_repository_index(&index, repo) == GIT_OK) { git_index_read(index); git_index_free(index); } unsigned int status = 0; if (git_status_file(&status, repo, path) == GIT_OK) { return CefV8Value::CreateInt(status); } else { return CefV8Value::CreateInt(0); } } CefRefPtr CheckoutHead(const char *path) { if (!exists) { return CefV8Value::CreateBool(false); } char *copiedPath = (char *)malloc(sizeof(char) * (strlen(path) + 1)); strcpy(copiedPath, path); git_checkout_opts options; memset(&options, 0, sizeof(options)); options.checkout_strategy = GIT_CHECKOUT_OVERWRITE_MODIFIED; git_strarray paths; paths.count = 1; paths.strings = &copiedPath; options.paths = paths; int result = git_checkout_head(repo, &options); free(copiedPath); if (result == GIT_OK) { return CefV8Value::CreateBool(true); } else { return CefV8Value::CreateBool(false); } } IMPLEMENT_REFCOUNTING(GitRepository); }; Git::Git() : CefV8Handler() { NSString *filePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"v8_extensions/git.js"]; NSString *extensionCode = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; CefRegisterExtension("v8/git", [extensionCode UTF8String], this); } bool Git::Execute(const CefString& name, CefRefPtr object, const CefV8ValueList& arguments, CefRefPtr& retval, CefString& exception) { if (name == "getRepository") { CefRefPtr userData = new GitRepository(arguments[0]->GetStringValue().ToString().c_str()); retval = CefV8Value::CreateObject(NULL); retval->SetUserData(userData); return true; } if (name == "getHead") { GitRepository *userData = (GitRepository *)object->GetUserData().get(); retval = userData->GetHead(); return true; } if (name == "getPath") { GitRepository *userData = (GitRepository *)object->GetUserData().get(); retval = userData->GetPath(); return true; } if (name == "isIgnored") { GitRepository *userData = (GitRepository *)object->GetUserData().get(); retval = userData->IsIgnored(arguments[0]->GetStringValue().ToString().c_str()); return true; } if (name == "getStatus") { GitRepository *userData = (GitRepository *)object->GetUserData().get(); retval = userData->GetStatus(arguments[0]->GetStringValue().ToString().c_str()); return true; } if (name == "checkoutHead") { GitRepository *userData = (GitRepository *)object->GetUserData().get(); retval = userData->CheckoutHead(arguments[0]->GetStringValue().ToString().c_str()); return true; } return false; } }