From 73626b8ded22465767a986e68cf47f45cf1fa6f3 Mon Sep 17 00:00:00 2001 From: FrozenCow Date: Mon, 19 Aug 2013 21:38:17 +0200 Subject: [PATCH 1/8] Added CreateBlobFromDisk to Repository. Based on http://libgit2.github.com/libgit2/#v0.18.0/group/blob/git_blob_create_fromdisk CreateBlobFromDisk reads a file specified by its path and creates a blob. The Result of this function is the oid of the blob and not a blob object. This is to circumvent reading the bytes of the blob into memory. --- src/repository.cc | 47 +++++++++++++++++++++++++++++++++++++++++++++++ src/repository.h | 3 +++ 2 files changed, 50 insertions(+) diff --git a/src/repository.cc b/src/repository.cc index 86f1a39..9c56f8c 100644 --- a/src/repository.cc +++ b/src/repository.cc @@ -171,6 +171,13 @@ class CreateRemoteBaton : public RepositoryBaton { CreateRemoteBaton(Repository *r) : RepositoryBaton(r) { } }; +class CreateBlobFromDiskBaton : public RepositoryBaton { +public: + string path; + git_oid id; + CreateBlobFromDiskBaton(Repository *r) : RepositoryBaton(r) { } +}; + Persistent Repository::constructor_template; Repository::Repository() { @@ -242,6 +249,7 @@ void Repository::Init(Handle target) { NODE_SET_PROTOTYPE_METHOD(t, "createSymReference", CreateSymReference); NODE_SET_PROTOTYPE_METHOD(t, "remote", GetRemote); NODE_SET_PROTOTYPE_METHOD(t, "createRemote", CreateRemote); + NODE_SET_PROTOTYPE_METHOD(t, "createBlobFromDisk", CreateBlobFromDisk); NODE_SET_METHOD(target, "openRepository", OpenRepository); NODE_SET_METHOD(target, "initRepository", InitRepository); @@ -696,6 +704,45 @@ void Repository::AsyncAfterCreateRemote(uv_work_t *req) { delete baton; } +Handle Repository::CreateBlobFromDisk(const Arguments &args) { + HandleScope scope; + Repository *repository = ObjectWrap::Unwrap(args.This()); + + CreateBlobFromDiskBaton *baton = new CreateBlobFromDiskBaton(repository); + baton->path = CastFromJS(args[0]); + baton->setCallback(args[1]); + + uv_queue_work(uv_default_loop(), &baton->req, AsyncCreateBlobFromDisk, + NODE_094_UV_AFTER_WORK_CAST(AsyncAfterCreateBlobFromDisk)); + + return Undefined(); +} + +void Repository::AsyncCreateBlobFromDisk(uv_work_t *req) { + CreateBlobFromDiskBaton *baton = GetBaton(req); + + if(AsyncLibCall(git_blob_create_fromdisk(&baton->id, baton->repo->repo_, + baton->path.c_str()), baton)) { + } +} + +void Repository::AsyncAfterCreateBlobFromDisk(uv_work_t *req) { + HandleScope scope; + CreateBlobFromDiskBaton *baton = GetBaton(req); + + if(baton->isErrored()) { + Handle argv[] = { baton->createV8Error() }; + FireCallback(baton->callback, 1, argv); + } + else { + Handle id = CastToJS(baton->id); + Handle argv[] = { Null(), id }; + FireCallback(baton->callback, 2, argv); + } + + delete baton; +} + Handle Repository::Exists(const Arguments& args) { HandleScope scope; Repository *repo = ObjectWrap::Unwrap(args.This()); diff --git a/src/repository.h b/src/repository.h index d94f002..4db6c25 100644 --- a/src/repository.h +++ b/src/repository.h @@ -40,6 +40,7 @@ class Repository : public ObjectWrap { static Handle GetRemote(const Arguments&); static Handle Exists(const Arguments&); static Handle CreateRemote(const Arguments&); + static Handle CreateBlobFromDisk(const Arguments&); void close(); @@ -61,6 +62,8 @@ class Repository : public ObjectWrap { static void AsyncAfterGetRemote(uv_work_t*); static void AsyncCreateRemote(uv_work_t*); static void AsyncAfterCreateRemote(uv_work_t*); + static void AsyncCreateBlobFromDisk(uv_work_t*); + static void AsyncAfterCreateBlobFromDisk(uv_work_t*); static Handle CreateReferenceObject(git_reference*); From fb34968ed672c16bcc2a75a04e6906bff4518255 Mon Sep 17 00:00:00 2001 From: FrozenCow Date: Mon, 19 Aug 2013 21:45:27 +0200 Subject: [PATCH 2/8] Added CreateTree to Repository. CreateTree will create a tree object from an array of TreeEntry. A TreeEntry should follow have: * name: the name/path of the file * id: the id of the blob object * mode: the mode of the file (as described here: http://libgit2.github.com/libgit2/#v0.18.0/group/treebuilder/git_treebuilder_insert) This makes use of git_treebuilder_* of libgit2 to create the tree. --- src/repository.cc | 81 +++++++++++++++++++++++++++++++++++++++++++++++ src/repository.h | 3 ++ 2 files changed, 84 insertions(+) diff --git a/src/repository.cc b/src/repository.cc index 9c56f8c..978e115 100644 --- a/src/repository.cc +++ b/src/repository.cc @@ -52,6 +52,9 @@ static Persistent ref_target_symbol; static Persistent object_id_symbol; static Persistent object_type_symbol; +static Persistent tree_entry_name_symbol; +static Persistent tree_entry_mode_symbol; + class OpenRepoBaton : public Baton { public: string path ; @@ -178,6 +181,19 @@ class CreateBlobFromDiskBaton : public RepositoryBaton { CreateBlobFromDiskBaton(Repository *r) : RepositoryBaton(r) { } }; +class TreeEntry { +public: + string filename; + git_oid blobid; + git_filemode_t filemode; +}; +class CreateTreeBaton : public RepositoryBaton { +public: + list entries; + git_oid treeid; + CreateTreeBaton(Repository *r) : RepositoryBaton(r), entries() { } +}; + Persistent Repository::constructor_template; Repository::Repository() { @@ -237,6 +253,10 @@ void Repository::Init(Handle target) { object_id_symbol = NODE_PSYMBOL("id"); object_type_symbol = NODE_PSYMBOL("_type"); + // Tree Entry symbols + tree_entry_name_symbol = NODE_PSYMBOL("name"); + tree_entry_mode_symbol = NODE_PSYMBOL("mode"); + Local t = FunctionTemplate::New(New); constructor_template = Persistent::New(t); constructor_template->SetClassName(repo_class_symbol); @@ -250,6 +270,7 @@ void Repository::Init(Handle target) { NODE_SET_PROTOTYPE_METHOD(t, "remote", GetRemote); NODE_SET_PROTOTYPE_METHOD(t, "createRemote", CreateRemote); NODE_SET_PROTOTYPE_METHOD(t, "createBlobFromDisk", CreateBlobFromDisk); + NODE_SET_PROTOTYPE_METHOD(t, "createTree", CreateTree); NODE_SET_METHOD(target, "openRepository", OpenRepository); NODE_SET_METHOD(target, "initRepository", InitRepository); @@ -743,6 +764,66 @@ void Repository::AsyncAfterCreateBlobFromDisk(uv_work_t *req) { delete baton; } +Handle Repository::CreateTree(const Arguments &args) { + HandleScope scope; + Repository *repository = ObjectWrap::Unwrap(args.This()); + + CreateTreeBaton *baton = new CreateTreeBaton(repository); + Handle jsentries = args[0].As(); + for(unsigned int i=0;iLength();i++) { + TreeEntry entry; + Handle jsentry = jsentries->Get(i)->ToObject(); + entry.filename = CastFromJS(jsentry->Get(tree_entry_name_symbol)); + entry.blobid = CastFromJS(jsentry->Get(object_id_symbol)); + entry.filemode = (git_filemode_t)CastFromJS(jsentry->Get(tree_entry_mode_symbol)); + baton->entries.push_back(entry); + } + baton->setCallback(args[1]); + + uv_queue_work(uv_default_loop(), &baton->req, AsyncCreateTree, + NODE_094_UV_AFTER_WORK_CAST(AsyncAfterCreateTree)); + + return Undefined(); +} + +void Repository::AsyncCreateTree(uv_work_t *req) { + CreateTreeBaton *baton = GetBaton(req); + git_treebuilder *treebuilder; + if(AsyncLibCall(git_treebuilder_create(&treebuilder, NULL), baton)) { + for(list::iterator i = baton->entries.begin(); + i != baton->entries.end(); ++i) { + if(!AsyncLibCall(git_treebuilder_insert(NULL, treebuilder, + i->filename.c_str(), &i->blobid, i->filemode), baton)) { + break; + } + } + if (git_treebuilder_entrycount(treebuilder) == baton->entries.size()) { + AsyncLibCall(git_treebuilder_write(&baton->treeid,baton->repo->repo_, + treebuilder), baton); + } + + } + + git_treebuilder_free(treebuilder); +} + +void Repository::AsyncAfterCreateTree(uv_work_t *req) { + HandleScope scope; + CreateTreeBaton *baton = GetBaton(req); + + if(baton->isErrored()) { + Handle argv[] = { baton->createV8Error() }; + FireCallback(baton->callback, 1, argv); + } + else { + Handle treeid = CastToJS(baton->treeid); + Handle argv[] = { Null(), treeid }; + FireCallback(baton->callback, 2, argv); + } + + delete baton; +} + Handle Repository::Exists(const Arguments& args) { HandleScope scope; Repository *repo = ObjectWrap::Unwrap(args.This()); diff --git a/src/repository.h b/src/repository.h index 4db6c25..5f8c79f 100644 --- a/src/repository.h +++ b/src/repository.h @@ -41,6 +41,7 @@ class Repository : public ObjectWrap { static Handle Exists(const Arguments&); static Handle CreateRemote(const Arguments&); static Handle CreateBlobFromDisk(const Arguments&); + static Handle CreateTree(const Arguments&); void close(); @@ -64,6 +65,8 @@ class Repository : public ObjectWrap { static void AsyncAfterCreateRemote(uv_work_t*); static void AsyncCreateBlobFromDisk(uv_work_t*); static void AsyncAfterCreateBlobFromDisk(uv_work_t*); + static void AsyncCreateTree(uv_work_t*); + static void AsyncAfterCreateTree(uv_work_t*); static Handle CreateReferenceObject(git_reference*); From bda45da1095db7dee351d2114ce45f8e7cc39eda Mon Sep 17 00:00:00 2001 From: FrozenCow Date: Mon, 19 Aug 2013 22:45:21 +0200 Subject: [PATCH 3/8] Added CreateCommit to Repository. CreateCommit is based on http://libgit2.github.com/libgit2/#v0.18.0/group/commit/git_commit_create. CreateCommit results in the oid of the commit that was created. CreateCommit is called with the following keys: * updateref: maps to update_ref and can be unused. (optional) * author: a signature of the author (optional, committer is used) * committer: a signature of the committer * message: the message of the commit * tree: the id of a tree object * parents: an array of parents A signature has the following keys: * name: the name of the author/committer * email: the email of the author/committer * time: the time of the commit (optional) * offset: timezone offset of the commit-time (optional) --- src/repository.cc | 150 ++++++++++++++++++++++++++++++++++++++++++++++ src/repository.h | 3 + 2 files changed, 153 insertions(+) diff --git a/src/repository.cc b/src/repository.cc index 978e115..2371e1c 100644 --- a/src/repository.cc +++ b/src/repository.cc @@ -55,6 +55,18 @@ static Persistent object_type_symbol; static Persistent tree_entry_name_symbol; static Persistent tree_entry_mode_symbol; +static Persistent signature_name_symbol; +static Persistent signature_email_symbol; +static Persistent signature_time_symbol; +static Persistent signature_offset_symbol; + +static Persistent commit_updateref_symbol; +static Persistent commit_author_symbol; +static Persistent commit_committer_symbol; +static Persistent commit_message_symbol; +static Persistent commit_parents_symbol; +static Persistent commit_tree_symbol; + class OpenRepoBaton : public Baton { public: string path ; @@ -194,6 +206,25 @@ class CreateTreeBaton : public RepositoryBaton { CreateTreeBaton(Repository *r) : RepositoryBaton(r), entries() { } }; +class CommitSignature { +public: + string name; + string email; + git_time_t time; + int offset; +}; +class CreateCommitBaton : public RepositoryBaton { +public: + string update_ref; + CommitSignature author; + CommitSignature committer; + string message; + list parents; + git_oid treeid; + git_oid commitid; + CreateCommitBaton(Repository *r) : RepositoryBaton(r) { } +}; + Persistent Repository::constructor_template; Repository::Repository() { @@ -257,6 +288,20 @@ void Repository::Init(Handle target) { tree_entry_name_symbol = NODE_PSYMBOL("name"); tree_entry_mode_symbol = NODE_PSYMBOL("mode"); + // Signature symbols + signature_name_symbol = NODE_PSYMBOL("name"); + signature_email_symbol = NODE_PSYMBOL("email"); + signature_time_symbol = NODE_PSYMBOL("time"); + signature_offset_symbol = NODE_PSYMBOL("offset"); + + // Commit symbols + commit_updateref_symbol = NODE_PSYMBOL("updateref"); + commit_author_symbol = NODE_PSYMBOL("author"); + commit_committer_symbol = NODE_PSYMBOL("committer"); + commit_message_symbol = NODE_PSYMBOL("message"); + commit_parents_symbol = NODE_PSYMBOL("parents"); + commit_tree_symbol = NODE_PSYMBOL("tree"); + Local t = FunctionTemplate::New(New); constructor_template = Persistent::New(t); constructor_template->SetClassName(repo_class_symbol); @@ -271,6 +316,7 @@ void Repository::Init(Handle target) { NODE_SET_PROTOTYPE_METHOD(t, "createRemote", CreateRemote); NODE_SET_PROTOTYPE_METHOD(t, "createBlobFromDisk", CreateBlobFromDisk); NODE_SET_PROTOTYPE_METHOD(t, "createTree", CreateTree); + NODE_SET_PROTOTYPE_METHOD(t, "createCommit", CreateCommit); NODE_SET_METHOD(target, "openRepository", OpenRepository); NODE_SET_METHOD(target, "initRepository", InitRepository); @@ -824,6 +870,110 @@ void Repository::AsyncAfterCreateTree(uv_work_t *req) { delete baton; } +Handle Repository::CreateCommit(const Arguments &args) { + HandleScope scope; + Repository *repository = ObjectWrap::Unwrap(args.This()); + + CreateCommitBaton *baton = new CreateCommitBaton(repository); + Handle options = args[0].As(); + + baton->update_ref = options->Has(commit_updateref_symbol) + ? CastFromJS(options->Get(commit_updateref_symbol)) + : ""; + + Handle committer = options->Get(commit_committer_symbol).As(); + baton->committer.name = CastFromJS(committer->Get(signature_name_symbol)); + baton->committer.email = CastFromJS(committer->Get(signature_email_symbol)); + baton->committer.time = CastFromJS(committer->Get(signature_time_symbol)); + baton->committer.offset = CastFromJS(committer->Get(signature_offset_symbol)); + + if (options->Has(commit_author_symbol)) { + Handle author = options->Get(commit_author_symbol).As(); + baton->author.name = CastFromJS(author->Get(signature_name_symbol)); + baton->author.email = CastFromJS(author->Get(signature_email_symbol)); + baton->author.time = CastFromJS(author->Get(signature_time_symbol)); + baton->author.offset = CastFromJS(author->Get(signature_offset_symbol)); + } else { + baton->author = baton->committer; + } + + baton->message = CastFromJS(options->Get(commit_message_symbol)); + if (options->Has(commit_parents_symbol)) { + baton->parents = CastFromJS< list >(options->Get(commit_parents_symbol)); + } + baton->treeid = CastFromJS(options->Get(commit_tree_symbol)); + baton->setCallback(args[1]); + + uv_queue_work(uv_default_loop(), &baton->req, AsyncCreateCommit, + NODE_094_UV_AFTER_WORK_CAST(AsyncAfterCreateCommit)); + + return Undefined(); +} + +void Repository::AsyncCreateCommit(uv_work_t *req) { + CreateCommitBaton *baton = GetBaton(req); + + git_tree *tree; + std::vector parents; + for(list::iterator i = baton->parents.begin(); + i != baton->parents.end(); ++i) { + git_commit *commit; + if (AsyncLibCall(git_commit_lookup(&commit, baton->repo->repo_, + &(*i)), baton)) { + parents.push_back(commit); + } else { + break; + } + } + + if(parents.size() == baton->parents.size()) { + git_signature *committer; + if (AsyncLibCall(baton->committer.time == 0 + ? git_signature_now(&committer, baton->committer.name.c_str(), baton->committer.email.c_str()) + : git_signature_new(&committer, baton->committer.name.c_str(), baton->committer.email.c_str(), + baton->committer.time, baton->committer.offset), baton)) { + git_signature *author; + if (AsyncLibCall(baton->author.time == 0 + ? git_signature_now(&author, baton->author.name.c_str(), baton->author.email.c_str()) + : git_signature_new(&author, baton->author.name.c_str(), baton->author.email.c_str(), + baton->author.time, baton->author.offset), baton)) { + if(AsyncLibCall(git_tree_lookup(&tree,baton->repo->repo_, + &baton->treeid), baton)) { + if(AsyncLibCall(git_commit_create(&baton->commitid,baton->repo->repo_, + baton->update_ref.empty() ? NULL : baton->update_ref.c_str(), + author, committer, NULL, baton->message.c_str(), tree, + parents.size(), (const git_commit**)&(parents[0])), baton)) { + + } + } + git_signature_free(author); + } + git_signature_free(committer); + } + } + + for(std::vector::iterator i = parents.begin(); i != parents.end(); ++i) { + git_commit_free(*i); + } +} + +void Repository::AsyncAfterCreateCommit(uv_work_t *req) { + HandleScope scope; + CreateCommitBaton *baton = GetBaton(req); + + if(baton->isErrored()) { + Handle argv[] = { baton->createV8Error() }; + FireCallback(baton->callback, 1, argv); + } + else { + Handle commitid = CastToJS(baton->commitid); + Handle argv[] = { Null(), commitid }; + FireCallback(baton->callback, 2, argv); + } + + delete baton; +} + Handle Repository::Exists(const Arguments& args) { HandleScope scope; Repository *repo = ObjectWrap::Unwrap(args.This()); diff --git a/src/repository.h b/src/repository.h index 5f8c79f..8ca1ae1 100644 --- a/src/repository.h +++ b/src/repository.h @@ -42,6 +42,7 @@ class Repository : public ObjectWrap { static Handle CreateRemote(const Arguments&); static Handle CreateBlobFromDisk(const Arguments&); static Handle CreateTree(const Arguments&); + static Handle CreateCommit(const Arguments&); void close(); @@ -67,6 +68,8 @@ class Repository : public ObjectWrap { static void AsyncAfterCreateBlobFromDisk(uv_work_t*); static void AsyncCreateTree(uv_work_t*); static void AsyncAfterCreateTree(uv_work_t*); + static void AsyncCreateCommit(uv_work_t*); + static void AsyncAfterCreateCommit(uv_work_t*); static Handle CreateReferenceObject(git_reference*); From 2243320e141291ae1911ab77a5acee2350e5532d Mon Sep 17 00:00:00 2001 From: FrozenCow Date: Tue, 20 Aug 2013 11:43:00 +0200 Subject: [PATCH 4/8] Updated documentation to match createCommit, createTree and createBlob. --- lib/bindings/bindings.js | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/lib/bindings/bindings.js b/lib/bindings/bindings.js index 1d86fcc..6ebf237 100644 --- a/lib/bindings/bindings.js +++ b/lib/bindings/bindings.js @@ -186,10 +186,9 @@ Gitteh.error.GIT_ENOTIMPLEMENTED = undefined; Repository.prototype.getCommit = function(sha1, callback) {}; /** - * Creates a new Commit and immediately stores it in the Repository. - * @param {Object} data The data for the commit. Should be the same properties that a {@link Commit} contains. - * @param {Function} [callback] If provided, the Commit will be created asynchronously, and the newly created Commit object returned to the callback. - * @throws If Commit couldn't be created. + * Creates a new {@link Commit} and immediately stores it in the Repository. + * @param {Object} data The data for the commit. Should be the same properties that a {@link Commit} contains, but without id. + * @param {Function} [callback] The id of the newly created Commit is returned to the callback. */ Repository.prototype.createCommit = function(data, callback) {}; @@ -203,12 +202,11 @@ Repository.prototype.createCommit = function(data, callback) {}; Repository.prototype.getTree = function(sha1, callback) {}; /** - * Creates a new {@link Tree} in the Repository with the given data. NOTE: - * this is currently unimplemented. - * @param {Object} data - * @param {Function} [callback] + * Creates a new {@link Tree} in the Repository with the given entries. + * @param {Array} entries A list of file-entries from which to create the tree. Each entry should have a name, id (of the blob object) and mode. The mode should be any of the values 0040000, 0100644, 0100755, 0120000 or 0160000. + * @param {Function} [callback] The id of the newly created Tree is returned to the callback. */ -Repository.prototype.createTree = function(data, callback) {}; +Repository.prototype.createTree = function(entries, callback) {}; /** * Retrieves a {@link Reference} from the Repository with the given name. @@ -307,6 +305,13 @@ Repository.prototype.getTag = function(sha1, callback) {}; */ Repository.prototype.createBlob = function(data, callback) {}; +/** + * Creates a new {@link Blob} in the Repository. + * @param {String} path The path to a file from which data will be made into the Blob. + * @param {Function} [callback] The id of the newly created Blob is returned to the callback. + */ +Repository.prototype.createBlobFromDisk = function(path, callback) {}; + /** * Retrieves a Blob from the Repository with given id. * @param {String} sha1 The sha1 hash id of the blob. From dbd1b33c71de0cd85ecab727c5280d66d02e88f9 Mon Sep 17 00:00:00 2001 From: FrozenCow Date: Fri, 23 Aug 2013 13:33:26 +0200 Subject: [PATCH 5/8] Added createBlobFromDisk, createTree and createCommit to gitteh.coffee --- src/args.coffee | 8 +++++++- src/gitteh.coffee | 52 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/src/args.coffee b/src/args.coffee index 8ebe3aa..0eeaa6c 100644 --- a/src/args.coffee +++ b/src/args.coffee @@ -71,4 +71,10 @@ fn.validators = return objectTypes.indexOf val > -1 remoteDir: (val) -> - return remoteDirs.indexOf val > -1 \ No newline at end of file + return remoteDirs.indexOf val > -1 + + array: (val) -> + return val instanceof Array + + object: (val) -> + return typeof val is "object" \ No newline at end of file diff --git a/src/gitteh.coffee b/src/gitteh.coffee index fb8bf41..c8dc32e 100644 --- a/src/gitteh.coffee +++ b/src/gitteh.coffee @@ -580,6 +580,58 @@ Gitteh.Repository = class Repository _priv.native.createRemote name, url, _wrapCallback cb, (remote) => return cb null, new Remote @, remote + createBlobFromDisk: -> + ### + Creates a new Blob for this repository from the file-content loaded + from `path`. Calls `cb` when the operation has completed. + ### + _priv = _getPrivate @ + [path, cb] = args + path: type: "string" + cb: type: "function" + _priv.native.createBlobFromDisk path, _wrapCallback cb, (blob) => + return cb null, blob + + createTree: -> + ### + Creates a new Tree for this repository from the `entities` + that contain the content (as a blob), the name and the filemode + of the tree-entities that will be in the new Tree. + Calls `cb` when the operation has completed. + ### + _priv = _getPrivate @ + [entities, cb] = args + entities: type: "array" + cb: type: "function" + _priv.native.createTree entities, _wrapCallback cb, (tree) => + return cb null, tree + + createCommit: -> + ### + Creates a new Commit for this repository from `data`. + `data` should contain the following keys: + + * **updateref**: updates this reference to the new commit. (optional, default: do not update any refs) + * **author**: a signature of the author (optional, default: committer is used) + * **committer**: a signature of the committer + * **message**: the message of the commit + * **tree**: the id of a tree object + * **parents**: an array of parents. + + A signature has the following keys: + + * **name**: the name of the author/committer + * **email**: the email of the author/committer + * **time**: the time of the commit (optional) + * **offset**: timezone offset of the commit-time (optional) + ### + _priv = _getPrivate @ + [data, cb] = args + data: type: "object" + cb: type: "function" + _priv.native.createCommit data, _wrapCallback cb, (commit) => + return cb null, commit + ###* * Alias of {@link #reference}. * @param {String} oid id of reference to be fetched. From ab02afe401b9c826039d788658beaa9ef6f619ce Mon Sep 17 00:00:00 2001 From: FrozenCow Date: Thu, 29 Aug 2013 21:28:25 +0200 Subject: [PATCH 6/8] Renamed 'attributes' of tree-entry to 'filemode'. This should unify the naming convention. --- src/gitteh.coffee | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gitteh.coffee b/src/gitteh.coffee index c8dc32e..9f6351c 100644 --- a/src/gitteh.coffee +++ b/src/gitteh.coffee @@ -188,7 +188,7 @@ Gitteh.Tree = class Tree * **id**: *(String)* OID this entry points to. * **name**: *(String)* file name of this entry. * **type**: *(String)* kind of object pointed to by this entry - * **attributes**: *(Number)* UNIX file attributes for this entry. + * **filemode**: *(Number)* UNIX file filemode for this entry. ### constructor: (@repository, obj) -> @@ -200,7 +200,7 @@ Gitteh.Tree = class Tree .set("id") .set("name") .set("type") - .set("attributes") + .set("filemode") _immutable(@, obj) .set("id") .set("entries") @@ -743,7 +743,7 @@ Gitteh.clone = => else if entry.type is "blob" repo.blob entry.id, _wrapCallback cb, (blob) -> file = fs.createWriteStream _path.join(dest, entry.name), - mode: entry.attributes + mode: entry.filemode file.write blob.data file.end() cb() From 150bd6d270d6f59cf9eae0041146d416dda5ec06 Mon Sep 17 00:00:00 2001 From: FrozenCow Date: Thu, 29 Aug 2013 21:29:46 +0200 Subject: [PATCH 7/8] Unified naming of tree-entries in createTree. This allows the use of repo.tree to be passed to createTree. --- src/repository.cc | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/repository.cc b/src/repository.cc index 2371e1c..9adbe88 100644 --- a/src/repository.cc +++ b/src/repository.cc @@ -52,8 +52,9 @@ static Persistent ref_target_symbol; static Persistent object_id_symbol; static Persistent object_type_symbol; +static Persistent tree_entry_id_symbol; static Persistent tree_entry_name_symbol; -static Persistent tree_entry_mode_symbol; +static Persistent tree_entry_filemode_symbol; static Persistent signature_name_symbol; static Persistent signature_email_symbol; @@ -195,8 +196,8 @@ class CreateBlobFromDiskBaton : public RepositoryBaton { class TreeEntry { public: - string filename; - git_oid blobid; + git_oid id; + string name; git_filemode_t filemode; }; class CreateTreeBaton : public RepositoryBaton { @@ -285,8 +286,9 @@ void Repository::Init(Handle target) { object_type_symbol = NODE_PSYMBOL("_type"); // Tree Entry symbols + tree_entry_id_symbol = NODE_PSYMBOL("id"); tree_entry_name_symbol = NODE_PSYMBOL("name"); - tree_entry_mode_symbol = NODE_PSYMBOL("mode"); + tree_entry_filemode_symbol = NODE_PSYMBOL("filemode"); // Signature symbols signature_name_symbol = NODE_PSYMBOL("name"); @@ -819,9 +821,9 @@ Handle Repository::CreateTree(const Arguments &args) { for(unsigned int i=0;iLength();i++) { TreeEntry entry; Handle jsentry = jsentries->Get(i)->ToObject(); - entry.filename = CastFromJS(jsentry->Get(tree_entry_name_symbol)); - entry.blobid = CastFromJS(jsentry->Get(object_id_symbol)); - entry.filemode = (git_filemode_t)CastFromJS(jsentry->Get(tree_entry_mode_symbol)); + entry.id = CastFromJS(jsentry->Get(tree_entry_id_symbol)); + entry.name = CastFromJS(jsentry->Get(tree_entry_name_symbol)); + entry.filemode = (git_filemode_t)CastFromJS(jsentry->Get(tree_entry_filemode_symbol)); baton->entries.push_back(entry); } baton->setCallback(args[1]); @@ -839,7 +841,7 @@ void Repository::AsyncCreateTree(uv_work_t *req) { for(list::iterator i = baton->entries.begin(); i != baton->entries.end(); ++i) { if(!AsyncLibCall(git_treebuilder_insert(NULL, treebuilder, - i->filename.c_str(), &i->blobid, i->filemode), baton)) { + i->name.c_str(), &i->id, i->filemode), baton)) { break; } } From 097236a0009d34c93a311e54015bfcff2f9c9abe Mon Sep 17 00:00:00 2001 From: FrozenCow Date: Fri, 30 Aug 2013 00:50:49 +0200 Subject: [PATCH 8/8] Added createBlobFromBuffer to Repository. Based on http://libgit2.github.com/libgit2/#v0.18.0/group/blob/git_blob_create_frombuffer --- src/gitteh.coffee | 12 ++++++++++++ src/repository.cc | 49 +++++++++++++++++++++++++++++++++++++++++++++++ src/repository.h | 3 +++ 3 files changed, 64 insertions(+) diff --git a/src/gitteh.coffee b/src/gitteh.coffee index 9f6351c..41b5173 100644 --- a/src/gitteh.coffee +++ b/src/gitteh.coffee @@ -592,6 +592,18 @@ Gitteh.Repository = class Repository _priv.native.createBlobFromDisk path, _wrapCallback cb, (blob) => return cb null, blob + createBlobFromBuffer: -> + ### + Creates a new Blob for this repository from the data supplied + as `buffer`. Calls `cb` when the operation has completed. + ### + _priv = _getPrivate @ + [buffer, cb] = args + buffer: type: "object" + cb: type: "function" + _priv.native.createBlobFromBuffer buffer, _wrapCallback cb, (blob) => + return cb null, blob + createTree: -> ### Creates a new Tree for this repository from the `entities` diff --git a/src/repository.cc b/src/repository.cc index 9adbe88..f969b0f 100644 --- a/src/repository.cc +++ b/src/repository.cc @@ -194,6 +194,14 @@ class CreateBlobFromDiskBaton : public RepositoryBaton { CreateBlobFromDiskBaton(Repository *r) : RepositoryBaton(r) { } }; +class CreateBlobFromBufferBaton : public RepositoryBaton { +public: + void *data; + int length; + git_oid id; + CreateBlobFromBufferBaton(Repository *r) : RepositoryBaton(r) { } +}; + class TreeEntry { public: git_oid id; @@ -317,6 +325,7 @@ void Repository::Init(Handle target) { NODE_SET_PROTOTYPE_METHOD(t, "remote", GetRemote); NODE_SET_PROTOTYPE_METHOD(t, "createRemote", CreateRemote); NODE_SET_PROTOTYPE_METHOD(t, "createBlobFromDisk", CreateBlobFromDisk); + NODE_SET_PROTOTYPE_METHOD(t, "createBlobFromBuffer", CreateBlobFromBuffer); NODE_SET_PROTOTYPE_METHOD(t, "createTree", CreateTree); NODE_SET_PROTOTYPE_METHOD(t, "createCommit", CreateCommit); @@ -812,6 +821,46 @@ void Repository::AsyncAfterCreateBlobFromDisk(uv_work_t *req) { delete baton; } +Handle Repository::CreateBlobFromBuffer(const Arguments &args) { + HandleScope scope; + Repository *repository = ObjectWrap::Unwrap(args.This()); + + CreateBlobFromBufferBaton *baton = new CreateBlobFromBufferBaton(repository); + baton->data = Buffer::Data(args[0]); + baton->length = Buffer::Length(args[0]); + baton->setCallback(args[1]); + + uv_queue_work(uv_default_loop(), &baton->req, AsyncCreateBlobFromBuffer, + NODE_094_UV_AFTER_WORK_CAST(AsyncAfterCreateBlobFromBuffer)); + + return Undefined(); +} + +void Repository::AsyncCreateBlobFromBuffer(uv_work_t *req) { + CreateBlobFromBufferBaton *baton = GetBaton(req); + + if(AsyncLibCall(git_blob_create_frombuffer(&baton->id, baton->repo->repo_, + baton->data, baton->length), baton)) { + } +} + +void Repository::AsyncAfterCreateBlobFromBuffer(uv_work_t *req) { + HandleScope scope; + CreateBlobFromBufferBaton *baton = GetBaton(req); + + if(baton->isErrored()) { + Handle argv[] = { baton->createV8Error() }; + FireCallback(baton->callback, 1, argv); + } + else { + Handle id = CastToJS(baton->id); + Handle argv[] = { Null(), id }; + FireCallback(baton->callback, 2, argv); + } + + delete baton; +} + Handle Repository::CreateTree(const Arguments &args) { HandleScope scope; Repository *repository = ObjectWrap::Unwrap(args.This()); diff --git a/src/repository.h b/src/repository.h index 8ca1ae1..36d8940 100644 --- a/src/repository.h +++ b/src/repository.h @@ -41,6 +41,7 @@ class Repository : public ObjectWrap { static Handle Exists(const Arguments&); static Handle CreateRemote(const Arguments&); static Handle CreateBlobFromDisk(const Arguments&); + static Handle CreateBlobFromBuffer(const Arguments&); static Handle CreateTree(const Arguments&); static Handle CreateCommit(const Arguments&); @@ -66,6 +67,8 @@ class Repository : public ObjectWrap { static void AsyncAfterCreateRemote(uv_work_t*); static void AsyncCreateBlobFromDisk(uv_work_t*); static void AsyncAfterCreateBlobFromDisk(uv_work_t*); + static void AsyncCreateBlobFromBuffer(uv_work_t*); + static void AsyncAfterCreateBlobFromBuffer(uv_work_t*); static void AsyncCreateTree(uv_work_t*); static void AsyncAfterCreateTree(uv_work_t*); static void AsyncCreateCommit(uv_work_t*);