Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Big rewrite of the JS bridge stuff. Removed that silly prototype wrap…

…ping, instead I'm totally encapsulating the bindings and native objects and exposing pure JS constructors. Wrote an argument marshalling/validating lib to do strict checking on args coming into JS bridge.
  • Loading branch information...
commit f5b0efd5e14ac8d0ae83964cb437b8988f10c5e8 1 parent 375fdb3
@samcday samcday authored
View
1  .gitignore
@@ -1,3 +1,4 @@
build/
node_modules/
lib/gitteh.js
+lib/args.js
View
65 coffee/args.coffee
@@ -0,0 +1,65 @@
+module.exports = fn = (params) ->
+ paramList = for own name, param of params
+ param.name = name
+ param
+ ret = []
+
+ numRequired = 0
+ leftRequired = for param in paramList
+ break if param.hasOwnProperty("default")
+ numRequired++
+ param
+ paramList.splice 0, leftRequired.length
+ rightRequired = for param in paramList.slice(0).reverse()
+ break if param.hasOwnProperty("default")
+ numRequired++
+ param
+ rightRequired = rightRequired.reverse()
+ paramList.splice -rightRequired.length
+
+ args = Array.prototype.slice.call fn.caller.arguments
+ throw new Error("Not enough arguments.") if args.length < numRequired
+
+ left = args.splice 0, leftRequired.length
+ right = args.splice -rightRequired.length
+
+ argn = 0
+ for arg, i in left
+ argn++
+ param = leftRequired[i]
+ if not fn.validators[param.type] arg
+ throw new TypeError "#{param.name} (#{argn}) is not a valid #{param.type}"
+ ret.push arg
+
+ for param, i in paramList
+ argn++
+ if args.length > i
+ arg = args[i]
+ if not fn.validators[param.type] arg
+ throw new TypeError "#{param.name} (#{argn}) is not a valid #{param.type}"
+ ret.push arg
+ else ret.push param.default
+ for arg, i in right
+ argn++
+ param = rightRequired[i]
+ if not fn.validators[param.type] arg
+ throw new TypeError "#{param.name} (#{argn}) is not a valid #{param.type}"
+ ret.push arg
+ return ret
+fn.validators =
+ string: (val) ->
+ return typeof val is "string"
+ function: (val) -> return typeof val is "function"
+ bool: (val) ->
+ return typeof val is "boolean"
+
+###
+myfn = ->
+ [path, bare, cb] = fn
+ path: type: "string"
+ bare: type: "bool", default: false
+ cb: type: "function"
+ console.log path, bare, cb
+
+myfn "awesome", "zzz"
+###
View
131 coffee/gitteh.coffee
@@ -1,5 +1,8 @@
-module.exports = Gitteh = require "../build/Debug/gitteh"
-{Repository} = Gitteh
+bindings = require "../build/Debug/gitteh"
+{minOidLength, types, NativeRepository} = bindings
+args = require "./args"
+
+module.exports = Gitteh = {}
immutable = (obj, src) ->
return o = {
@@ -73,66 +76,80 @@ Gitteh.Tag = Tag = (@repository, obj) ->
@target = (cb) =>
@repository.object @targetId, @type, cb
return @
+
oidRegex = /^[a-zA-Z0-9]{0,40}$/
+args.validators.oid = (val) ->
+ return false if typeof val isnt "string"
+ return false if not oidRegex.test val
+ return false if val.length < minOidLength
+ return true
+
+objectTypes = ["any", "blob", "commit", "tag", "tree"]
+args.validators.objectType = (val) ->
+ return objectTypes.indexOf val > -1
+
checkOid = (str, allowLookup = true) ->
throw new TypeError "OID should be a string" if typeof str isnt "string"
throw new TypeError "Invalid OID" if not oidRegex.test str
throw new Error "OID is too short" if str.length < Gitteh.minOidLength
throw new TypeError "Invalid OID" if not allowLookup and str.length isnt 40
-wrap = (clazz, fn, prototype, newFn) ->
- override = if prototype then clazz.prototype else clazz
- orig = override[fn]
-
- override[fn] = ->
- shadowed = if prototype then orig.bind @ else orig
- newFn.apply @, [shadowed].concat Array.prototype.slice.call arguments
-
-wrap Gitteh, "openRepository", false, (shadowed, path, cb) ->
- shadowed path, cb
-
-wrap Gitteh, "initRepository", false, (shadowed, path, bare, cb) ->
- if typeof bare is "function"
- cb = bare
- bare = false
-
- shadowed path, bare, cb
-
-wrap Repository, "exists", true, (shadowed, oid, cb) ->
- checkOid oid, false
- shadowed oid, cb
-
-wrap Repository, "object", true, (shadowed, args..., cb) ->
- [oid, type] = args
- type = "any" if not type
- checkOid oid
- shadowed oid, type, (err, object) =>
- return cb err if err?
- clazz = switch object._type
- when Gitteh.types.commit then Commit
- when Gitteh.types.tree then Tree
- when Gitteh.types.blob then Blob
- when Gitteh.types.tag then Tag
- else undefined
- return cb new TypeError("Unexpected object type") if clazz is undefined
- return cb null, new clazz @, object
-
-Repository.prototype.commit = (oid, cb) ->
- @object oid, "commit", cb
-
-Repository.prototype.tree = (oid, cb) ->
- @object oid, "tree", cb
-
-Repository.prototype.blob = (oid, cb) ->
- @object oid, "blob", cb
-
-Repository.prototype.tag = (oid, cb) ->
- @object oid, "tag", cb
-
-wrap Repository, "reference", true, (shadowed, name, resolve, cb) ->
- if typeof resolve is "function"
- cb = resolve
- resolve = false
- shadowed name, resolve, cb
+wrapCallback = (orig, cb) ->
+ return (err) ->
+ return orig err if err?
+ cb.apply null, Array.prototype.slice.call arguments, 1
+
+module.exports.Repository = Repository = (nativeRepo) ->
+ if nativeRepo not instanceof NativeRepository
+ throw new Error "Don't construct me, see gitteh.(open|init)Repository"
+
+ immutable(@, nativeRepo)
+ .set("bare")
+ .set("path")
+ .set("workDir", "workingDirectory")
+ @exists = =>
+ [oid, cb] = args
+ oid: type: "oid"
+ cb: type: "function"
+ nativeRepo.exists oid, cb
+ @object = =>
+ [oid, type, cb] = args
+ oid: type: "oid"
+ type: type: "objectType", default: "any"
+ cb: type: "function"
+ nativeRepo.object oid, type, wrapCallback cb, (object) =>
+ clazz = switch object._type
+ when types.commit then Commit
+ when types.tree then Tree
+ when types.blob then Blob
+ when types.tag then Tag
+ else undefined
+ return cb new TypeError("Unexpected object type") if clazz is undefined
+ return cb null, new clazz @, object
+ @blob = (oid, cb) => @object oid, "blob", cb
+ @commit = (oid, cb) => @object oid, "commit", cb
+ @tag = (oid, cb) => @object oid, "tag", cb
+ @tree = (oid, cb) => @object oid, "tree", cb
+ @reference = =>
+ [name, resolve, cb] = args
+ name: type: "string"
+ resolve: type: "bool"
+ cb: type: "function"
+ nativeRepo.reference name, resolve, cb
+ @ref = @reference
+ return @
-Repository.prototype.ref = Repository.prototype.reference
+Gitteh.openRepository = ->
+ [path, cb] = args
+ path: type: "string"
+ cb: type: "function"
+ bindings.openRepository path, wrapCallback cb, (repo) ->
+ cb null, new Repository repo
+
+Gitteh.initRepository = () ->
+ [path, bare, cb] = args
+ path: type: "string"
+ bare: type: "bool", default: false
+ cb: type: "function"
+ bindings.initRepository path, bare, wrapCallback cb, (repo) ->
+ cb null, new Repository repo
View
4 src/repository.cc
@@ -33,7 +33,6 @@ static Persistent<String> repo_class_symbol;
static Persistent<String> path_symbol;
static Persistent<String> bare_symbol;
-static Persistent<String> git_dir_symbol;
static Persistent<String> object_dir_symbol;
static Persistent<String> index_file_symbol;
static Persistent<String> work_dir_symbol;
@@ -134,10 +133,9 @@ Repository::~Repository() {
void Repository::Init(Handle<Object> target) {
HandleScope scope;
- repo_class_symbol = NODE_PSYMBOL("Repository");
+ repo_class_symbol = NODE_PSYMBOL("NativeRepository");
path_symbol = NODE_PSYMBOL("path");
bare_symbol = NODE_PSYMBOL("bare");
- git_dir_symbol = NODE_PSYMBOL("gitDirectory");
object_dir_symbol = NODE_PSYMBOL("objectDirectory");
index_file_symbol = NODE_PSYMBOL("indexFile");
work_dir_symbol = NODE_PSYMBOL("workDir");
View
8 test/test.repository.coffee
@@ -27,14 +27,14 @@ describe "Repository", ->
repo.path.should.equal fixtures.projectRepo.gitPath
delete repo.path
repo.path.should.equal fixtures.projectRepo.gitPath
- describe "#workDir", ->
+ describe "#workingDirectory", ->
it "should point to #{fixtures.projectRepo.path}", ->
- repo.workDir.should.equal fixtures.projectRepo.path
+ repo.workingDirectory.should.equal fixtures.projectRepo.path
it "should be immutable", ->
repo.path = "foo"
- repo.workDir.should.equal fixtures.projectRepo.path
+ repo.workingDirectory.should.equal fixtures.projectRepo.path
delete repo.path
- repo.workDir.should.equal fixtures.projectRepo.path
+ repo.workingDirectory.should.equal fixtures.projectRepo.path
describe "#exists()", ->
it "should return true for first commit in repo :)", (done) ->
repo.exists "1f4425ce2a14f21b96b9c8dde5bcfd3733467b14", (err, exists) ->
Please sign in to comment.
Something went wrong with that request. Please try again.